[译]使用Game API创建2D动作游戏(一)

MIDP 2.0的Game API可简化2D游戏编写,由javax.microedition.lcdui.game包中五个类组成,提供GameCanvas和layer API两种重要功能。GameCanvas能将游戏逻辑置于同一循环,可直接获取Graphics对象绘图,还能通过polling技术获取按键状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用Game API创建2D动作游戏

原文出处:http://developers.sun.com/techtopics/mobility/midp/articles/game/

作者: Jonathan Knudsen
2003 3
译者: clapton_xpAThotmailDOTcom
2004
7
源代码下载: [SimpleGame source code]  [muTank source code]

muTank 例子

MIDP 2.0 包含一组Game API,可以简化2D游戏的编写. 这组API很简洁,仅由javax.microedition.lcdui.game 包中的五个类组成. 这五个类提供两种重要功能:

  • 新的 GameCanvas 类可以在游戏的主体中进行绘制屏幕或响应输入,而不是依赖于系统的绘图和输入线程.
  • 强大而便捷的layer API可以简单高效地创建复杂的场景.

使用 GameCanvas 创建一个循环

GameCanvas 是一个有着更多功能的Canvas; 它提供立即绘图和监视设备按键的方法. 这些新的方法可以将游戏的所有功能包含在由一个线程控制的同一个循环中. 想想你是怎么用Canvas实现一个典型游戏的,就会发现这是多么牛X:


public void 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.

  }

}



这有点不爽. 在一个程序线程中跑的 run() 方法, 每隔一段时间更新游戏状态. 一般都是更新一个球或者飞船的坐标,以及进行人物或者车辆的动画. 每次循环中, repaint() 被调用并更新屏幕. 系统传送按键时间到keyPressed(), keyPressed()方法相应地更改游戏状态.

问题是上面的每件事都在一个不同的线程中,而代码“令人迷惑不解地”分散在三个不同的方法中.run()中的主动画循环调用repaint(),无法确切地知道系统何时调用paint()方法. 当系统调用keyPressed(), 也无法知道程序中的其它部分是在干什么. 如果你的keyPressed() 中的代码是要更新游戏状态,而同时屏幕正在被paint()方法进行绘制,画出来的屏幕看起来就会有不对的地方. 另外如果绘制屏幕的时间超过run()方法调用一次的时间,动画看起来也会跳动或者有不对的地方.

GameCanvas 可以让你抛开上面的绘图和按键机制,将所有的游戏逻辑放在同一个循环中. 首先, GameCanvas 可以让你通过直接调用getGraphics() 方法获得它的Graphics 对象. 所有对获得的Graphics 对象的绘制都会在一个offscreen(一个后台的屏幕)缓存中进行. 你可以用flushGraphics()方法将整个缓存复制到真正的屏幕上, 这个方法会在绘图真正结束时才返回. 这使你可以比原来那种调用repaint()更好地控制程序. 因为repaint() 方法会立即返回,而你并不知道什么时候屏幕才真正地被重绘了.

GameCanvas 还包含一个方法用来获取当前设备按键的状态, 这个技术被称作polling. 不同于等待系统调用keyPressed()的机制, 你现在可以通过调用GameCanvasgetKeyStates()方法马上知道哪些键被按下了.

典型的使用 GameCanvas 循环的代码如下所示:

public void MicroTankCanvas

    extends GameCanvas

    implements Runnable {

  public void run() {

    Graphics g = getGraphics();

    while (true) {

      // Update the game state.

      int keyState = getKeyStates();

      // Respond to key presses here.

      // Painting code goes here.

      flushGraphics();

      // Delay one time step.

    }

  }

}



下面的例子演示了一个基本的游戏循环. 它显示一个旋转的“叉”,你可以用方向键来在屏幕上移动它. run() 方法很简单, 这归功于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;

  }

 

  private void input() {

    int keyStates = getKeyStates();

    if ((keyStates & LEFT_PRESSED) != 0)

      mX = Math.max(0, mX - 1);

    if ((keyStates & RIGHT_PRESSED) != 0)

      mX = Math.min(getWidth(), mX + 1);

    if ((keyStates & UP_PRESSED) != 0)

      mY = Math.max(0, mY - 1);

    if ((keyStates & DOWN_PRESSED) != 0)

      mY = Math.min(getHeight(), mY + 1);

  }

 

  private void render(Graphics g) {

    g.setColor(0xffffff);

    g.fillRect(0, 0, getWidth(), getHeight());

   

    g.setColor(0x0000ff);

    g.drawLine(mX, mY, mX - 10 + mState, mY - 10);

    g.drawLine(mX, mY, mX + 10, mY - 10 + mState);

    g.drawLine(mX, mY, mX + 10 - mState, mY + 10);

    g.drawLine(mX, mY, mX - 10, mY + 10 - mState);

   

    flushGraphics();

  }

}



示例代码中包含了这个例子,试着运行SimpleGameMIDlet 来看看效果. 你会看见一个正在做健美操的海星 (尽管这可怜的海星可能缺了条腿儿 :P)


SimpleGameMIDlet 截屏

 

待续

clapton_xpAThotmailDOTcom

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值