文章来源:J2ME开发网
MIDP2.0中推出了Game开发包,为开发者提供了游戏开发的便利。javax.microedition.lcdui.game包内总共有五各类,分别是GameCanvas、Layer、Sprite、TiledLayer和LayerManager。其中Sprite和TiledLayer是Layer的子类,作用是构建游戏中的两个重要的元素,Sprite代表游戏中运动的主题,比如动作游戏中的坦克,而TiledLayer主要是为游戏提供背景。LayerManager方便对游戏中的各个层进行管理。GameCanvas是继承了Canvas类的,针对游戏开发特别定制的。如果使用Canvas类开发游戏的时候代码的结构通常如下,
public class MicroTankCanvas extends Canvas
implements Runnable
{
public void run()
{
while (true)
{
// Update the game state.
repaint();
// Delay one time step.
}
}
public void paint(Graphics g)
{
// Painting code goes here.
}
protected void keyPressed(int keyCode)
{
// Respond to key presses here.
}
}
这样的结构存在一些问题,事件处理、游戏绘制的动作放在不同的线程内处理,对游戏可能产生不可预料的影响。GameCanvas的出现很好的解决了这个问题,你可以在应用程序的线程中获得Graphics对象,这时候系统会在off-screen的缓冲区内进行绘制,当你调用flushGraphics()的时候会马上绘制到手机屏幕上去。只有当屏幕被更新后者个方法才会返回,而调用repaint()的话,方法马上就返回你就不知道什么时候paint()才被调用。另外GameCanvas通过getKeyStates()方法来判断用户的输入事件。这样你就不用等待系统调用keyPressed()方法了,getKeyStates()可以马上得到现在按键的状态。
如果我们采用GameCanvas做游戏的时候,通常游戏的结构如下:
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
public class SimpleGameCanvas extends GameCanvas implements Runnable
{
private volatile boolean mTrucking;
private long mFrameDelay;
private int mX, mY;
private int mState;
public SimpleGameCanvas()
{
super(true);
mX = getWidth() / 2;
mY = getHeight() / 2;
mState = 0;
mFrameDelay = 20;
}
public void start()
{
mTrucking = true;
Thread t = new Thread(this);
t.start();
}
public void stop()
{
mTrucking = false;
}
public void run()
{
Graphics g = getGraphics();
while (mTrucking == true)
{
tick();
input();
render(g);
try
{
Thread.sleep(mFrameDelay);//这里我们也可以通过定义每桢的时间来处理,更合理些。
} catch (InterruptedException ie)
{
stop();
}
}
}
private void tick()
{
mState = (mState + 1) % 20;
}