package com.slinw.gamecanvas; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.game.GameCanvas; /** * http://ajava.org/readbook/J2ME/3d/4327.html * @author 章伟 * GameCanvas 类的主要功能:提供屏幕缓冲绘制机制,并能直接得到设备键盘的物理状态。 * GameCanvas方法说明: * getGraphics() : 获得画布 * flushGraphics( ):刷新画布 * getKeyStates():得到当前按键状态 * flushGraphics(int x, int y, int width, int height): 局部刷新,意思是作者知道下次帧和上次帧图像的区别只是某个局部 *为了将缓冲区中的内容刷新到屏幕上,所需要做的只是先调用getGraphics()方法,获得用来绘制缓冲区的Graphics对象。 *刚创建的Graphics对象具有以下默认属性。 n 绘制目标是这个GameCanvas的缓冲区。 n 绘制区域覆盖整个缓冲区。 n 当前颜色是黑色。 n 字体和调用Font.getDefaultFont()返回的相同。 n 绘图模式为SOLID。 n 坐标系统的原点定位在缓冲区的左上角。 返回的Graphics对象将用于绘制属于这个GameCanvas的后备屏幕缓冲区(off-screen buffer),但是绘制后的结果不会立即显示出来, 直到调用flushGraphics()方法,将缓冲区中的内容一起绘制到屏幕上去。 3.2.4 获取键盘状态 前面已经提到,GameCanvas和Canvas的按键状态的响应是不一样的。在Canvas时代,如果想知道按键状态, 必须实现keyPressed()/keyReleased()/keyRepeated(),每当有按键被按下时,这个方法就被调用, 而在GameCanvas时代,如果要检查特定的按键是否被按下,只需要将getKeyStates()返回的值与这些键值进行按位与(&), 并根据计算结果来判断即可。 getKeyStates()返回的bit数据分别代表了不同的按键(例如Up、Down、Fire等)。当按下某个物理键盘时,其对应的位设置为1, 否则将被设置为0,这样做的好处是,无论游戏主循环执行得多慢,键盘事件都不会被忽略。 每一次getKeyStates()方法的调用都会清除当前键盘缓冲区,因此理论上说,连续调用两次getKeyStates(),前一次会清除之前锁定的键盘状态,而后一次会得到反映当前键盘状态的理想值。 当然getKeyStates()的返回值会在另外一个线程中被更新,所以在游戏主循环中最好稍微等一会儿,以保证这个值被更新。GameCanvas中获得用户输入的代码: protected void input() { int keyState = getKeyStates(); //获得键盘状态 if ((keyState & LEFT_PRESSED) != 0) { //如果左键被按下 // do something } if ((keyState & RIGHT_PRESSED) != 0) { //如果右键被按下 // do something } if ((keyState & FIRE_PRESSED) != 0) { //如果确定键被按下 // do something } } */ public class WGameCanvas extends GameCanvas implements Runnable{ private Graphics g = null; private boolean isPlay; // Game Loop runs when isPlay is true private long delay; // To give thread consistency private int currentX, currentY; // To hold current position of the 'X' private int width; // To hold screen width private int height; // To hold screen height // Constructor and initialization public WGameCanvas() { super(true); width = getWidth(); height = getHeight(); currentX = width / 2; currentY = height / 2; delay = 20; g = getGraphics(); } // Automatically start thread for game loop public void start() { isPlay = true; new Thread(this).start(); } public void stop() { isPlay = false; } // Main Game Loop public void run() { while (isPlay) { keyEventInput(); drawScreen(g); try { Thread.sleep(delay); } catch (InterruptedException ie) {} } } // Method to Handle User Inputs private void keyEventInput() { int keyStates = getKeyStates(); // Left if ((keyStates & LEFT_PRESSED) != 0) { currentX = Math.max(0, currentX - 1); } // Right if ((keyStates & RIGHT_PRESSED) != 0) { if (currentX + 5 < width) { currentX = Math.min(width, currentX + 1); } } // Up if ((keyStates & UP_PRESSED) != 0) { currentY = Math.max(0, currentY - 1); } // Down if ((keyStates & DOWN_PRESSED) != 0) { if (currentY + 10 < height) { currentY = Math.min(height, currentY + 1); } } } // Method to Display Graphics private void drawScreen(Graphics g) { g.setColor(0xffffff); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(0x0000ff); g.drawString("X", currentX, currentY, Graphics.TOP | Graphics.LEFT); flushGraphics(); } }