![]() |
|
|
MIDP2.0中提供了游戏开发专用的API,比如GameCanvas等类。他们位于javax.microedition.lcdui.game包内。本文介绍GameCanvas的基本使用方法并实现一种滚动星空的效果。您可以参考Game Canvas Basic获得更详细的信息。 GameCanvas是Canvas的子类,因此他同样继承了Canvas类的一些特性,比如showNotify()方法会在Canvas被显示在屏幕的时候调用,而hideNotify()会在Canvas离开屏幕的时候被调用。我们可以把他们当作监听器来使用,用于初始化和销毁资源。比如 // When the canvas is shown, start a thread to // run the game loop. protected void showNotify() { random = new Random(); thread = new Thread(this); thread.start(); } // When the game canvas is hidden, stop the thread. protected void hideNotify() { thread = null; } 在游戏开发中最重要的就是接受用户触发的事件然后重新绘制屏幕,通常我们使用getKeyStates()方法判断哪个键被按下了,然后绘制屏幕,调用flushGraphics()。在GameCanvas中,系统事实上已经为我们实现了双缓冲技术,因此每次我们绘制的时候就是在off-screen上绘制的。结束后通过flushGraphics把它复制到屏幕上去。下面是典型的接受事件、处理逻辑、绘制屏幕的代码。 // Get the Graphics object for the off-screen buffer Graphics g = getGraphics(); while (true) { // Check user input and update positions if necessary int keyState = getKeyStates(); if ((keyState & LEFT_PRESSED) != 0) { sprite.move(-1, 0); } else if ((keyState & RIGHT_PRESSED) != 0) { sprite.move(1, 0); } // Clear the background to white g.setColor(0xFFFFFF); g.fillRect(0,0,getWidth(), getHeight()); // Draw the Sprite sprite.paint(g); // Flush the off-screen buffer flushGraphics(); } 下面开始实现我们滚动星空的效果,其实设计的思想非常简单。我们启动一个线程,使用copyArea()方法把屏幕的内容往下复制一个像素的距离。然后绘画第一个空白的直线,随机的在直线上绘画点儿,这样看起来就像星空一样了。逻辑代码如下: // The game loop. public void run() { int w = getWidth(); int h = getHeight() - 1; while (thread == Thread.currentThread()) { // Increment or decrement the scrolling interval // based on key presses int state = getKeyStates(); if ((state & DOWN_PRESSED) != 0) { sleepTime += SLEEP_INCREMENT; if (sleepTime > SLEEP_MAX) sleepTime = SLEEP_MAX; } else if ((state & UP_PRESSED) != 0) { sleepTime -= SLEEP_INCREMENT; if (sleepTime < 0) sleepTime = 0; } // Repaint the screen by first scrolling the // existing starfield down one and painting in // new stars... graphics.copyArea(0, 0, w, h, 0, 1, Graphics.TOP | Graphics.LEFT); graphics.setColor(0, 0, 0); graphics.drawLine(0, 0, w, 0); graphics.setColor(255, 255, 255); for (int i = 0; i < w; ++i) { int test = Math.abs(random.nextInt()) % 100; if (test < 5) { graphics.drawLine(i, 0, i, 0); } } flushGraphics(); // Now wait... try { Thread.currentThread().sleep(sleepTime); } catch (InterruptedException e) { } } } 下面给出源代码 /* * License * * Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved. * */ import javax.microedition.lcdui.*; import javax.microedition.lcdui.game.*; import javax.microedition.midlet.*; public class GameCanvasTest extends MIDlet implements CommandListener { private Display display; public static final Command exitCommand = new Command("Exit", Command.EXIT, 1); public GameCanvasTest() { } public void commandAction(Command c, Displayable d) { if (c == exitCommand) { exitMIDlet(); } } protected void destroyApp(boolean unconditional) throws MIDletStateChangeException { exitMIDlet(); } public void exitMIDlet() { notifyDestroyed(); } public Display getDisplay() { return display; } protected void initMIDlet() { GameCanvas c = new StarField(); c.addCommand(exitCommand); c.setCommandListener(this); getDisplay().setCurrent(c); } protected void pauseApp() { } protected void startApp() throws MIDletStateChangeException { if (display == null) { display = Display.getDisplay(this); initMIDlet(); } } } /* * License * * Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved. */ import java.util.Random; import javax.microedition.lcdui.*; import javax.microedition.lcdui.game.GameCanvas; // A simple example of a game canvas that displays // a scrolling star field. Use the UP and DOWN keys // to speed up or slow down the rate of scrolling. public class StarField extends GameCanvas implements Runnable { private static final int SLEEP_INCREMENT = 10; private static final int SLEEP_INITIAL = 150; private static final int SLEEP_MAX = 300; private Graphics graphics; private Random random; private int sleepTime = SLEEP_INITIAL; private volatile Thread thread; public StarField() { super(true); graphics = getGraphics(); graphics.setColor(0, 0, 0); graphics.fillRect(0, 0, getWidth(), getHeight()); } // The game loop. public void run() { int w = getWidth(); int h = getHeight() - 1; while (thread == Thread.currentThread()) { // Increment or decrement the scrolling interval // based on key presses int state = getKeyStates(); if ((state & DOWN_PRESSED) != 0) { sleepTime += SLEEP_INCREMENT; if (sleepTime > SLEEP_MAX) sleepTime = SLEEP_MAX; } else if ((state & UP_PRESSED) != 0) { sleepTime -= SLEEP_INCREMENT; if (sleepTime < 0) sleepTime = 0; } // Repaint the screen by first scrolling the // existing starfield down one and painting in // new stars... graphics.copyArea(0, 0, w, h, 0, 1, Graphics.TOP | Graphics.LEFT); graphics.setColor(0, 0, 0); graphics.drawLine(0, 0, w, 0); graphics.setColor(255, 255, 255); for (int i = 0; i < w; ++i) { int test = Math.abs(random.nextInt()) % 100; if (test < 5) { graphics.drawLine(i, 0, i, 0); } } flushGraphics(); // Now wait... try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } } } // When the canvas is shown, start a thread to // run the game loop. protected void showNotify() { random = new Random(); thread = new Thread(this); thread.start(); } // When the game canvas is hidden, stop the thread. protected void hideNotify() { thread = null; } } www.j2mehome.com
|