j2me学习六_翻译教程-牧羊犬游戏2

来源:互联网 发布:三角函数矩阵的幂次方 编辑:程序博客网 时间:2024/05/16 00:47
 

四.搭建游戏环境

1.新建Field类

2.引入类

// unnamed package

import javax.microedition.lcdui.*;

import javax.microedition.lcdui.game.*;

3.继承TiledField类

TieldField对象是一个能由多个小图片组成的网格,这个类允许使用小的图像来绘制大的场景

class Field

    extends TiledLayer

{

//为游戏创建背景

    private static final int WIDTH_IN_TILES = 12;

    private static final int HEIGHT_IN_TILES = 12;

    private static final int TILE_WIDTH = 16;

    private static final int TILE_HEIGHT = 16;

 

    private static int[][] cellTiles =

        {{-3, -2, -3, -1, -2, -1, -3, -1, -2, -3, -1, -2},

         {-2,  3,  4,  3,  1,  2,  3,  2,  1,  5,  2, -3},

         {-1,  2,  1,  2,  3,  4,  5,  3,  2,  4,  3, -1},

         {-2,  1,  4,  9,  9,  9,  9,  4,  5,  2,  1, -2},

         {-3,  3,  5,  9, 10, 10, 10,  2,  1,  3,  5, -1},

         {-2,  2,  3,  9, 10, 10, 10,  5,  4,  2,  1, -3},

         {-1,  4,  2,  9,  9,  9,  9,  3,  1,  3,  2, -2},

         {-3,  2,  5,  1,  3,  1,  4,  2,  5,  4,  3, -3},

         {-2,  1,  4,  2,  5,  2,  3,  4,  2,  1,  2, -1},

         {-1,  5,  1,  4,  3,  4,  1,  2,  3,  4,  1, -2},

         {-3,  2,  4,  5,  2,  3,  2,  4,  1,  2,  3, -3},

         {-2, -3, -2, -1, -2, -1, -3, -2, -1, -3, -1, -2}};

    private static int FOLD_TILE = 10;

    private static int FENCE_TILE = 9;

    private static int[][] waterFrames = {{6, 7, 8}, {7, 8, 6}, {8, 6, 7}};

private int tickCount = 0;

5.创建生成背景的方法

用到了createAnimatedTilesetCell方法,前者用于创建动态单元,后者用于填充背景

    Field()

    {

        super(WIDTH_IN_TILES,

              HEIGHT_IN_TILES,

              SheepdogMIDlet.createImage("/field.png"),

              TILE_WIDTH,

              TILE_HEIGHT);

        createAnimatedTile(waterFrames[0][0]);      // tile -1

        createAnimatedTile(waterFrames[1][0]);      // tile -2

        createAnimatedTile(waterFrames[2][0]);      // tile -3

        for (int row = 0; row < HEIGHT_IN_TILES; ++row)

        {

            for (int column = 0; column < WIDTH_IN_TILES; ++column)

            {

                setCell(column, row, cellTiles[row][column]);

            }

        }

    }

5.创建方法,设置牧羊犬的初始地点和设置记录速度

int getSheepdogStartX()

    {

        return getWidth() - 50;

    }

 

    int getSheepdogStartY()

    {

        return getHeight() - 50;

    }

 

    void tick()

    {

        int tickState = (tickCount++ >> 3);   // slow down x8

        int tile = tickState % 3;

        setAnimatedTile(-1 - tile, waterFrames[tile][(tickState % 9) / 3]);

}

6.检测到不能达到的区域的通道

// return true if any part of the rectangle overlaps a water tile

    // or the fence

    boolean containsImpassableArea(int x, int y, int width, int height)

    {

        int rowMin = y / TILE_HEIGHT;

        int rowMax = (y + height - 1) / TILE_HEIGHT;

        int columnMin = x / TILE_WIDTH;

        int columnMax = (x + width - 1) / TILE_WIDTH;

        for (int row = rowMin; row <= rowMax; ++row)

        {

            for (int column = columnMin; column <= columnMax; ++column)

            {

                int cell = getCell(column, row);

                if ((cell < 0) || (cell == FENCE_TILE))

                {

                    return true;

                }

            }

        }

        return false;

    }

7.检测绵羊是否进入特定区域

    boolean inFold(Sprite s)

    {

        // we can assume that the sprite's reference pixel is unchanged

        int rowMin = s.getY() / TILE_HEIGHT;

        int rowMax = (s.getY() + s.getHeight() - 1) / TILE_HEIGHT;

        int columnMin = s.getX() / TILE_WIDTH;

        int columnMax = (s.getX() + s.getWidth() - 1) / TILE_WIDTH;

        for (int row = rowMin; row <= rowMax; ++row)

        {

            for (int column = columnMin; column <= columnMax; ++column)

            {

                if (getCell(column, row) != FOLD_TILE)

                {

                    return false;

                }

            }

        }

        return true;

    }

}

五.创建游戏角色

Sheepdog class

创建sheepdog的sprite,注意它没有面向右边的帧,当要让它面向右边的时候,使用图像的变换方法TRANS_MIRROR.

1.     创建Sheepdog类

2.     引入类

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

3.     继承Sprite

class Sheepdog
    extends Sprite
{

4.     创建参数

static final int WIDTH = 15;

    static final int HEIGHT = 15;

    static final int VIBRATION_MILLIS = 200;

    private final SheepdogCanvas canvas;

    private boolean barking = false;

    private int[][][] animations = {{{0},                // stand up

                                     {1, 2, 3, 4}},      // run up

                                    {{5},                // stand left

                                     {6, 7, 8, 9}},      // run left

                                    {{10},               // stand down

                                     {11, 12, 13, 14}}}; // run down

    private int animationTick = 0;

    private static final int STAND = 0;

    private static final int RUN = 1;

private int currentDirection = SheepdogCanvas.LEFT;

 

5.  在SheepdogCanvas中初始化Sheepdog对象并且载入dog的图像,defineCollisionRectangle用于设定用于检测碰撞的边界,defineReferencePixel用于设定Sprite的像素引用。

   Sheepdog(SheepdogCanvas canvas)
    {
        super(SheepdogMIDlet.createImage("/dog.png"), WIDTH, HEIGHT);
        defineCollisionRectangle(2, 2, WIDTH-4, WIDTH-4);
        defineReferencePixel(WIDTH/2, HEIGHT/2);
        
        this.canvas = canvas;
    }

 

6.     创建Sheepdog的动作,移动,犬吠

void tick(int direction, boolean bark)

    {

        animationTick++;

 

        Field field = canvas.getField();

        boolean moving = false;;

        switch (direction)

        {

        case SheepdogCanvas.UP:

            currentDirection = direction;

            if ((getY() > 0) &&

                !field.containsImpassableArea(getX(),

                                              getY() - 1,

                                              getWidth(),

                                              1) &&

                moveSuccessfully(0, -1))

            {

                moving = true;

            }

            else

            {

                canvas.vibrate(VIBRATION_MILLIS);

            }

            break;

        case SheepdogCanvas.LEFT:

            currentDirection = direction;

            if ((getX() > 0) &&

                !field.containsImpassableArea(getX() - 1,

                                              getY(),

                                              1,

                                              getHeight()) &&

                moveSuccessfully(-1, 0))

            {

                moving = true;

            }

            else

            {

                canvas.vibrate(VIBRATION_MILLIS);

            }

            break;

        case SheepdogCanvas.DOWN:

            currentDirection = direction;

            if ((getY() + getHeight() < field.getWidth()) &&

                !field.containsImpassableArea(getX(),

                                              getY() + getHeight(),

                                              getWidth(),

                                              1) &&

                moveSuccessfully(0, 1))

            {

                moving = true;

            }

            else

            {

                canvas.vibrate(VIBRATION_MILLIS);

            }

            break;

        case SheepdogCanvas.RIGHT:

            currentDirection = direction;

            if ((getX() + getWidth() < field.getWidth()) &&

                !field.containsImpassableArea(getX() + getWidth(),

                                              getY(),

                                              1,

                                              getHeight()) &&

                moveSuccessfully(1, 0))

            {

                moving = true;

            }

            else

            {

                canvas.vibrate(VIBRATION_MILLIS);

            }

            break;

        default:  // must be NONE

            break;

        }

        if (moving)

        {

            advanceRunningAnimation();

        }

        else

        {

            setStandingAnimation();

        }

        // implement a toggle, so bark only happens once per click

        // (will therefore not register very rapid multiple-clicks)

 

        if (bark)

        {

            if (!barking)

            {

                SoundEffects.getInstance().startDogSound();

                barking = true;

                canvas.handleDogBark();

            }

        }

        else

        {

            barking = false;

        }

}

7.  创建用于检测Sheepdog的胜利,用到了move方法

private boolean moveSuccessfully(int dx, int dy)
    {
        move(dx, dy);
        if (canvas.overlapsSheep(this))
        {
            move(-dx, -dy);
            return false;
        }
        else
        {
            return true;
        }
    }

8.  创建Sheepdog的动作,用到了setTransform和setFrame方法,前者用于图像的变换,后者用于设定图像序列的帧

private void advanceRunningAnimation()

    {

        int[] sequence;

        if (currentDirection == SheepdogCanvas.RIGHT)

        {

            sequence = animations[SheepdogCanvas.LEFT][RUN];

            setTransform(TRANS_MIRROR);

        }

        else

        {

            sequence = animations[currentDirection][RUN];

            setTransform(TRANS_NONE);

        }

        setFrame(sequence[(animationTick >> 1) % sequence.length]);

    }

 

    private void setStandingAnimation()

    {

        if (currentDirection == SheepdogCanvas.RIGHT)

        {

            setFrame(animations[SheepdogCanvas.LEFT][STAND][0]);

            setTransform(TRANS_MIRROR);

        }

        else

        {

            setFrame(animations[currentDirection][STAND][0]);

            setTransform(TRANS_NONE);

        }

    }

}

Sheep class

 

原理和Sheepdog class 差不多,直接上代码

// unnamed package

import javax.microedition.lcdui.*;

import javax.microedition.lcdui.game.*;

import java.util.*;

 

Set Sheep to extend Sprite.

 

class Sheep

    extends Sprite

{

//创建参数

 

    static final int WIDTH = 15;

    static final int HEIGHT = 15;

    private final SheepdogCanvas canvas;

    private int[][][] animations = {{{0},                // stand up

                                     {1, 2, 3, 4}},      // run up

                                    {{5},                // stand left

                                     {6, 7, 8, 9}},      // run left

                                    {{10},               // stand down

                                     {11, 12, 13, 14}}}; // run down

    private int animationTick;

    private static int numSheep = 0;

    private static final int STAND = 0;

    private static final int RUN = 1;

    private int currentDirection = SheepdogCanvas.DOWN;

 

    private final int flockFactor;

    private final int minDogFactor;

    private final int maxDogFactor;

    private int dogFactor;

 

//初始化sheep对象

 

    Sheep(SheepdogCanvas canvas)

    {

        super(SheepdogMIDlet.createImage("/sheep.png"), WIDTH, HEIGHT);

        defineCollisionRectangle(2, 2, WIDTH-4, WIDTH-4);

        defineReferencePixel(WIDTH/2, HEIGHT/2);

 

        this.canvas = canvas;

        animationTick = numSheep++;

 

        flockFactor = 100 + SheepdogMIDlet.random(100);

        minDogFactor = SheepdogMIDlet.random(20);

        maxDogFactor = minDogFactor + 10;

        dogFactor = minDogFactor;

    }

 

.

 

    void tick()

    {

        // sheep are 4x as slow as dogs

        if ((animationTick++ % 4) != 0)

        {

            return;

        }

//创建羊的人工智能

 

        // adjust dog factor

        adjustDogFactor();

 

        // ARTIFICIAL INTELLIGENCE SECTION

        // - wants to move away from dog, if dog is close

        // - wants to move closer to flock (average position of other

        //   sheep) if they are close

        // - if preferred direction is diagonal and major direction is

        //   blocked, take minor direction

        // - each sheep varies in how much it's scared of the dog, and

        //   how much it wants to flock

        // We do this by calculating a weighted direction vector

 

        // First calculate dog effect

        Sheepdog sheepdog = canvas.getSheepdog();

        int dx = getX() - sheepdog.getX();

        int dy = getY() - sheepdog.getY();

        int sumsq = dx * dx + dy * dy;

        Field field = canvas.getField();

        int dogEffectX =

            dogFactor * dx * field.getWidth() * field.getWidth() / sumsq;

        int dogEffectY =

            dogFactor * dy * field.getHeight() * field.getHeight() / sumsq;

 

        // Next calculate flock effect

        int flockDx = 0;

        int flockDy = 0;

        Vector sheep = canvas.getSheep();

        for (int i = 0; i < sheep.size(); ++i)

        {

            Sheep sh = (Sheep)(sheep.elementAt(i));

            if (sh != this)

            {

                flockDx += getX() - sh.getX();

                flockDy += getY() - sh.getY();

            }

        }

        int flockEffectX = (flockDx * flockFactor) / (sheep.size() - 1);

        int flockEffectY = (flockDy * flockFactor) / (sheep.size() - 1);

 

        // Now calculate total effect

        int totalEffectX = dogEffectX - flockEffectX;

        int totalEffectY = dogEffectY - flockEffectY;

 

        // Determine preferred directions

        int firstDirection;

        int secondDirection;

        int thirdDirection;

        if (Math.abs(totalEffectY) > Math.abs(totalEffectX))

        {

            // Prefer to move vertically

            if (totalEffectY > 0)

            {

                firstDirection = SheepdogCanvas.DOWN;

            }

            else

            {

                firstDirection = SheepdogCanvas.UP;

            }

            if (totalEffectX > 0)

            {

                secondDirection = SheepdogCanvas.RIGHT;

                thirdDirection = SheepdogCanvas.NONE;

            }

            else if (totalEffectX < 0)

            {

                secondDirection = SheepdogCanvas.LEFT;

                thirdDirection = SheepdogCanvas.NONE;

            }

            else  // totalEffectX == 0

            {

                if (SheepdogMIDlet.random(2) == 0)

                {

                    secondDirection = SheepdogCanvas.LEFT;

                    thirdDirection = SheepdogCanvas.RIGHT;

                }

                else

                {

                    secondDirection = SheepdogCanvas.RIGHT;

                    thirdDirection = SheepdogCanvas.LEFT;

                }

            }

        }

        else

        {

            // Prefer to move horizontally

            if (totalEffectX > 0)

            {

                firstDirection = SheepdogCanvas.RIGHT;

            }

            else

            {

                firstDirection = SheepdogCanvas.LEFT;

            }

            if (totalEffectY > 0)

            {

                secondDirection = SheepdogCanvas.DOWN;

                thirdDirection = SheepdogCanvas.NONE;

            }

            else if (totalEffectY < 0)

            {

                secondDirection = SheepdogCanvas.UP;

                thirdDirection = SheepdogCanvas.NONE;

            }

            else  // totalEffectY == 0

            {

                if (SheepdogMIDlet.random(2) == 0)

                {

                    secondDirection = SheepdogCanvas.UP;

                    thirdDirection = SheepdogCanvas.DOWN;

                }

                else

                {

                    secondDirection = SheepdogCanvas.DOWN;

                    thirdDirection = SheepdogCanvas.UP;

                }

            }

        }

 

        // if we can move in the preferred directions, do so, else

        // stand facing the dog

        if (tryMove(firstDirection) ||

            tryMove(secondDirection) ||

            ((thirdDirection != SheepdogCanvas.NONE) &&

             tryMove(thirdDirection)))

        {

            advanceRunningAnimation();

        }

        else

        {

            if (Math.abs(dx) > Math.abs(dy))

            {

                if (dx > 0)

                {

                    currentDirection = SheepdogCanvas.LEFT;

                }

                else

                {

                    currentDirection = SheepdogCanvas.RIGHT;

                }

            }

            else

            {

                if (dy > 0)

                {

                    currentDirection = SheepdogCanvas.UP;

                }

                else

                {

                    currentDirection = SheepdogCanvas.DOWN;

                }

            }

            setStandingAnimation();

        }

 

        // Will baa occasionally if dog is close. Dog distance ranges from

        // about 11 minimum to double width of field

        int dogDistance = Math.abs(dx) + Math.abs(dy);

        if (SheepdogMIDlet.random(dogDistance - 10) == 0)

        {

            SoundEffects.getInstance().startSheepSound();

        }

    }

 

 

 

    private void adjustDogFactor()

    {

        dogFactor += SheepdogMIDlet.random(4) - 2;  // -2..1

        if (dogFactor < minDogFactor)

        {

            dogFactor = minDogFactor;

        }

        else if (dogFactor > maxDogFactor)

        {

            dogFactor = maxDogFactor;

        }

    }

//创建检测羊的行动路线

 

    private boolean tryMove(int direction)

    {

        Field field = canvas.getField();

        boolean blocked = true;

        int dx = 0;

        int dy = 0;

        switch (direction)

        {

        case SheepdogCanvas.UP:

            if ((getY() > 0) &&

                !field.containsImpassableArea(getX(),

                                              getY() - 1,

                                              getWidth(),

                                              1))

            {

                blocked = false;

                dy = -1;

            }

            break;

        case SheepdogCanvas.LEFT:

            if ((getX() > 0) &&

                !field.containsImpassableArea(getX() - 1,

                                              getY(),

                                              1,

                                              getHeight()))

            {

                blocked = false;

                dx = -1;

            }

            break;

        case SheepdogCanvas.DOWN:

            if ((getY() + getHeight() - 1 < field.getWidth()) &&

                !field.containsImpassableArea(getX(),

                                              getY() + getHeight(),

                                              getWidth(),

                                              1))

            {

                blocked = false;

                dy = 1;

            }

            break;

        case SheepdogCanvas.RIGHT:

            if ((getX() + getWidth() - 1 < field.getWidth()) &&

                !field.containsImpassableArea(getX() + getWidth(),

                                              getY(),

                                              1,

                                              getHeight()))

            {

                blocked = false;

                dx = 1;

            }

            break;

        default:

            // can't happen

            break;

        }

        boolean success = false;

        if (!blocked)

        {

            boolean wasInFold = field.inFold(this);

            move(dx, dy);

            if (canvas.overlapsOtherSheep(this) ||

                canvas.overlapsSheepdog(this) ||

                (wasInFold && !field.inFold(this)))

            {

                move(-dx, -dy);

            }

            else

            {

                currentDirection = direction;

                success = true;

            }

        }

        return success;

    }

 

//创建羊的两个动作形态

 

    private void advanceRunningAnimation()

    {

        int[] sequence;

        if (currentDirection == SheepdogCanvas.RIGHT)

        {

            sequence = animations[SheepdogCanvas.LEFT][RUN];

            setTransform(TRANS_MIRROR);

        }

        else

        {

            sequence = animations[currentDirection][RUN];

            setTransform(TRANS_NONE);

        }

        setFrame(sequence[(animationTick >> 2) % sequence.length]);

    }

 

    private void setStandingAnimation()

    {

        if (currentDirection == SheepdogCanvas.RIGHT)

        {

            setFrame(animations[SheepdogCanvas.LEFT][STAND][0]);

            setTransform(TRANS_MIRROR);

        }

        else

        {

            setFrame(animations[currentDirection][STAND][0]);

            setTransform(TRANS_NONE);

        }

    }

 

//创建当有犬吠时羊的反应

 

    void handleDogBark()

    {

        // sheep should get nervous

        dogFactor += 5;

        if (dogFactor > maxDogFactor)

        {

            dogFactor = maxDogFactor;

        }

    }

}

原创粉丝点击