四.搭建游戏环境
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.创建生成背景的方法
用到了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. 继承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;
}
}
}
分享到:
相关推荐
midp-2_0-src-windows-i686.rarmidp-2_0-src-windows-i686.rarmidp-2_0-src-windows-i686.rarmidp-2_0-src-windows-i686.rarmidp-2_0-src-windows-i686.rar
Java 2 Micro Edition (J2ME) 是一个用于开发小型设备和嵌入式系统的 Java 平台,如手机、智能电器、游戏机等。CLDC(Connected Limited Device Configuration)是 J2ME 的一部分,专为资源有限的设备设计。这个...
j2me_wireless_toolkit-2_2-windows 由于附件不能超过10M,只好分两部分发了
J2ME,全称Java 2 Micro Edition,是Java平台的一个子集,主要用于嵌入式设备和移动设备的开发。其中,CLDC(Connected Limited Device Configuration)是J2ME的一部分,主要针对内存和处理能力有限的设备,如早期的...
标题中的"midp-2_0-src-windows-i686 + j2me_cldc-1_0_4-src-winunix"提及了两个关键组件,即Midp 2.0和J2ME CLDC 1.0.4的源代码,分别针对Windows i686(Intel x86架构)和Unix平台。描述进一步确认了这些内容涉及...
J2ME,全称为Java 2 Micro Edition,是Java平台的一个子集,专为资源有限的嵌入式设备设计,如移动电话、智能卡和消费电子设备等。在J2ME体系中,Connected Limited Device Configuration(CLDC)是一个重要的组成...
Java 2 Micro Edition (J2ME) 是一种Java平台,专为嵌入式设备和移动设备设计,如手机、智能手表等。它提供了一个运行环境,使得开发者可以编写跨平台的应用程序,能够在不同的设备上运行。J2ME由两部分组成:KVM(K...
在标题"j2me_https.rar_ j2me-https_j2me_j2me htt_j2me htt_j2me https"中,重点在于讨论J2ME中实现HTTPS连接的方法。描述中提到提供了图文并茂的解释,这通常意味着教程或指南包含详细步骤和示例,便于开发者理解...
j2me_cldc-1_1-fcs-src-winunixj2me_cldc-1_1-fcs-src-winunixj2me_cldc-1_1-fcs-src-winunixj2me_cldc-1_1-fcs-src-winunixj2me_cldc-1_1-fcs-src-winunixj2me_cldc-1_1-fcs-src-winunix
"j2me_wireless_toolkit-2_0-zh.zip"这个压缩包包含了J2ME WTK的2.0中文版本,为开发者提供了全面的中文文档和资源,便于理解和使用。 一、J2ME无线工具包概述 J2ME WTK 2.0是一个强大的开发环境,它允许开发者创建...
**Java J2ME**,全称Java 2 Micro Edition,是Java平台的一个子集,主要用于嵌入式设备和移动设备的开发,特别是智能手机和平板电脑。J2ME为开发者提供了在小型设备上创建应用程序的框架,它具有轻量级、高效能的...
《J2ME飞机游戏开发详解》 J2ME(Java 2 Micro Edition)是Java平台的一个子集,专为移动设备、嵌入式系统等资源有限的环境设计。本篇文章将深入探讨如何利用J2ME技术开发一款简单的飞机游戏,以此帮助初学者理解...
在J2ME(Java 2 Micro Edition)平台上开发游戏时,地图的设计与绘制是至关重要的一个环节。J2ME作为一种轻量级的Java平台,广泛应用于移动设备,如早期的智能手机和平板电脑,用于实现各种应用程序,特别是游戏。本...
学习这个开源项目,开发者不仅可以提升J2ME编程技能,还能深入理解游戏开发的基本流程和技巧,例如如何处理输入事件、如何实现帧同步动画、如何实现碰撞检测算法以及如何有效利用内存。这对于那些想进入移动游戏开发...
J2ME_Loader-1.7.7-open-release.apk
J2ME(Java 2 Micro Edition)是Java平台的一个子集,专为资源有限的移动和嵌入式设备设计。其中,CLDC(Connected Limited Device Configuration)是J2ME的一个核心部分,用于在具有非常有限内存和处理能力的设备上...
这个压缩包文件"j2me游戏开发及其源码.rar"包含了关于J2ME游戏开发的详细资料,非常适合初学者学习和探索。 在J2ME游戏开发中,你需要了解以下几个核心知识点: 1. **基础环境配置**:首先,开发者需要安装Java ...
2 JAD.MF文件:增加游戏专用摇杆键盘配置 3 JAD.MF文件:增加屏幕尺寸配置 4 修改repaint()处理,模拟J2ME内部实现[在1.0中repaint()方法会强制刷新屏幕,1.1中参考了J2ME内部刷新实现不再会强制刷新] 5 集成...