读书人

运用GameCanvas制作星空效果

发布时间: 2012-09-20 09:36:50 作者: rapoo

使用GameCanvas制作星空效果
http://www.3geye.net/bbs/thread-164-1-1.html

MIDP2.0中提供了游戏开发专用的API,比如GameCanvas等类。他们位于javax.microedition.lcdui.game包内。本文介绍GameCanvas的基本使用方法并实现一种滚动星空的效果。您可以参考Game Canvas Basic获得更详细的信息。

??? GameCanvas是Canvas的子类,因此他同样继承了Canvas类的一些特性,比如showNotify()方法会在Canvas被显示在屏幕 的时候调用,而hideNotify()会在Canvas离开屏幕的时候被调用。我们可以把他们当作{8}来使用,用于初始化和销毁资源。比如
??? // 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;
??? }
}

读书人网 >移动开发

热点推荐