[译]使用Game API创建2D动作游戏(一)
2004-07-21 11:48
519 查看
使用Game API创建2D动作游戏<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
原文出处:http://developers.sun.com/techtopics/mobility/midp/articles/game/
作者: Jonathan Knudsen
2003 年 3 月
译者: clapton_xpAThotmailDOTcom
2004 年 7 月
源代码下载: [SimpleGame source code] [muTank source code]
MIDP 2.0 包含一组Game API,可以简化2D游戏的编写. 这组API很简洁,仅由javax.microedition.lcdui.game 包中的五个类组成. 这五个类提供两种重要功能:
新的 GameCanvas 类可以在游戏的主体中进行绘制屏幕或响应输入,而不是依赖于系统的绘图和输入线程.
强大而便捷的layer API可以简单高效地创建复杂的场景.
使用GameCanvas 创建一个循环
GameCanvas 是一个有着更多功能的Canvas; 它提供立即绘图和监视设备按键的方法. 这些新的方法可以将游戏的所有功能包含在由一个线程控制的同一个循环中. 想想你是怎么用Canvas实现一个典型游戏的,就会发现这是多么牛X了:
这有点不爽. 在一个程序线程中跑的 run() 方法, 每隔一段时间更新游戏状态. 一般都是更新一个球或者飞船的坐标,以及进行人物或者车辆的动画. 每次循环中, repaint() 被调用并更新屏幕. 系统传送按键时间到keyPressed(), keyPressed()方法相应地更改游戏状态.
问题是上面的每件事都在一个不同的线程中,而代码“令人迷惑不解地”分散在三个不同的方法中.当run()中的主动画循环调用repaint(),无法确切地知道系统何时调用paint()方法. 当系统调用keyPressed(), 也无法知道程序中的其它部分是在干什么. 如果你的keyPressed() 中的代码是要更新游戏状态,而同时屏幕正在被paint()方法进行绘制,画出来的屏幕看起来就会有不对的地方. 另外如果绘制屏幕的时间超过run()方法调用一次的时间,动画看起来也会跳动或者有不对的地方.
GameCanvas 可以让你抛开上面的绘图和按键机制,将所有的游戏逻辑放在同一个循环中. 首先, GameCanvas 可以让你通过直接调用getGraphics() 方法获得它的Graphics 对象. 所有对获得的Graphics 对象的绘制都会在一个offscreen(一个后台的屏幕)缓存中进行. 你可以用flushGraphics()方法将整个缓存复制到真正的屏幕上, 这个方法会在绘图真正结束时才返回. 这使你可以比原来那种调用repaint()更好地控制程序. 因为repaint() 方法会立即返回,而你并不知道什么时候屏幕才真正地被重绘了.
GameCanvas 还包含一个方法用来获取当前设备按键的状态, 这个技术被称作polling. 不同于等待系统调用keyPressed()的机制, 你现在可以通过调用GameCanvas的getKeyStates()方法马上知道哪些键被按下了.
典型的使用 GameCanvas 循环的代码如下所示:
下面的例子演示了一个基本的游戏循环. 它显示一个旋转的“叉”,你可以用方向键来在屏幕上移动它. run() 方法很简单, 这归功于GameCanvas.
示例代码中包含了这个例子,试着运行SimpleGameMIDlet 来看看效果. 你会看见一个正在做健美操的海星 (尽管这可怜的海星可能缺了条腿儿 :P)
待续 clapton_xpAThotmailDOTcom
原文出处:http://developers.sun.com/techtopics/mobility/midp/articles/game/
作者: Jonathan Knudsen
2003 年 3 月
译者: clapton_xpAThotmailDOTcom
2004 年 7 月
源代码下载: [SimpleGame source code] [muTank source code]
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /> |
muTank 例子 |
新的 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(),无法确切地知道系统何时调用paint()方法. 当系统调用keyPressed(), 也无法知道程序中的其它部分是在干什么. 如果你的keyPressed() 中的代码是要更新游戏状态,而同时屏幕正在被paint()方法进行绘制,画出来的屏幕看起来就会有不对的地方. 另外如果绘制屏幕的时间超过run()方法调用一次的时间,动画看起来也会跳动或者有不对的地方.
GameCanvas 可以让你抛开上面的绘图和按键机制,将所有的游戏逻辑放在同一个循环中. 首先, GameCanvas 可以让你通过直接调用getGraphics() 方法获得它的Graphics 对象. 所有对获得的Graphics 对象的绘制都会在一个offscreen(一个后台的屏幕)缓存中进行. 你可以用flushGraphics()方法将整个缓存复制到真正的屏幕上, 这个方法会在绘图真正结束时才返回. 这使你可以比原来那种调用repaint()更好地控制程序. 因为repaint() 方法会立即返回,而你并不知道什么时候屏幕才真正地被重绘了.
GameCanvas 还包含一个方法用来获取当前设备按键的状态, 这个技术被称作polling. 不同于等待系统调用keyPressed()的机制, 你现在可以通过调用GameCanvas的getKeyStates()方法马上知道哪些键被按下了.
典型的使用 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. } } } |
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 截屏 |
相关文章推荐
- 我是运营,我没有假期
- ATL实现Connection Point的一种简单的方法
- javascript表单之间的数据传递!
- 今天很高兴!
- 人生感悟第二篇章
- 利用hook截获进程的API调用
- org.apache.commons.logging 介绍
- Servlet 2.3过滤器编程(二)
- Servlet 2.3过滤器编程
- 从java线程中获得运算结果
- 菜鸟学jsp(二)
- 翻译Sun帮助文件——javax.wireless.messaging(MessageListener)
- COM组件的多线程测试-Apartment模型(附录)
- COM组件的多线程测试-Single模型(附录)
- 分頁控制
- 如何在ASP中实现网络打印功能
- 如何学好VB
- 一个投票程序
- 如何用Socket实现客户端通信模块