您的位置:首页 > 其它

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

2011-07-27 22:55 453 查看
 四.搭建游戏环境
1.新建Field类
2.引入类// unnamed packageimport 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.创建生成背景的方法
用到了
createAnimatedTile
setCell
方法,前者用于创建动态单元,后者用于填充背景
    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.     继承Spriteclass 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;
       }
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息