现在我们来到了手机游戏的核心:游戏主流程类,这个类里自身的代码并不多,但它控制这个整个游戏的场景绘制,流程控制,键盘事件处理,并负责与主MIDlet通信。
它的原始形态应该是这样的,一个继承自GameCanvas的类,扩展Runnable,以下为框架,为了结构清晰,一些变量没有给出,也有一些函数体是空的:
public class GameLoop extends GameCanvas implements Runnable {
public GameLoop(Flight midlet) {
super(true);
}
public void start() { // 开始游戏
Thread t = new Thread(this); // 获得当前模块的线程
}
public void stop() { //停止游戏
}
public void run() { // 游戏主流程
Graphics g = getGraphics();
while (mTrucking == true) { // 这个boolean值指示游戏是在进行还是已停止
input(); // 处理输入
render(g); // 渲染场景
try {
Thread.sleep(mFrameDelay); // 线程休眠 mFrameDelay个毫秒,这个是相当有必要的,否则会导致手机失去响应,通常应不小于15ms.
} catch (InterruptedException ie) {
}
}
}
private void input() {
}
private void render(Graphics g) {
}
}
我想有了这个框架,再有前面的几个游戏相关类,现在怎么写应该是很清楚的了,我们把Terrain(场景类)和Helicopter的paint方法放到render(Graphics g)中调用,把Helicopter的moveto方法放到 input()中去调用,然后把碰撞检测加到run()函数中的render(g)后面,就可以判断什么时候该结束游戏了.
以下是我的实现:
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.Image;
import java.io.*;
public class GameLoop extends GameCanvas implements Runnable {
private boolean mTrucking;
private long mFrameDelay;
private int screenWidth,screenHeight,mX, mY;
private Image img;
private Terrain terrain;
private Helicopter player;
private Flight midlet;
private Command pauseCommand;
private Command resumeCommand;
private Command exitCommand;
public GameLoop(Flight midlet) {
super(true);
this.midlet = midlet;
screenWidth = getWidth();
screenHeight = getHeight();
mX = screenWidth / 2;
mY = screenHeight * 2 / 3;
mFrameDelay = 15;
player = new Helicopter();
try{ // I was so frustrated at the moment when i got to know
img = Image.createImage("/res/brick.png"); //i have no idea to avoid the ugly inintialize codes
}catch(IOException ioe){ // out of the constructor of the class Terrain
ioe.printStackTrace();
}
terrain = new Terrain(screenWidth/4 , screenHeight/12 + 2,img,4,12,player);
pauseCommand = new Command("PAUSE",Command.STOP,1);
resumeCommand = new Command("RESUME",Command.SCREEN,1);
exitCommand = new Command("EXIT",Command.EXIT,1);
}
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) {
input();
render(g);
if(terrain.collides() == true && player.dying == false)player.dying = true; //如果碰撞发生,直升飞机开始爆炸
if(player.alive == false){stop();midlet.addHighScore(getScore());} // 如果爆炸结束,游戏结束,如果是高分则出现添加高分的页面
try {
Thread.sleep(mFrameDelay);
} catch (InterruptedException ie) {
}
}
}
private void input() {
int keyStates = getKeyStates();
if ((keyStates & FIRE_PRESSED) != 0 )
mX = Math.max(0, mX - 1);
else mX = Math.min(getWidth()-10, mX + 1);
}
private void render(Graphics g) {
g.setColor(0x000000);
g.fillRect(0,0,screenWidth,screenHeight);
terrain.paint(g);
terrain.update(); // update the terrain seemly,i think that's the best way
player.moveto(mX,mY);
player.paint(g);
player.update();
g.setColor(0xff0000);
g.drawString(String.valueOf(terrain.milemeter),20,20,0);
flushGraphics();
}
public int getScore(){
return terrain.milemeter; // 返回玩家的成绩,即飞了多少米
}
}
它的原始形态应该是这样的,一个继承自GameCanvas的类,扩展Runnable,以下为框架,为了结构清晰,一些变量没有给出,也有一些函数体是空的:
public class GameLoop extends GameCanvas implements Runnable {
public GameLoop(Flight midlet) {
super(true);
}
public void start() { // 开始游戏
Thread t = new Thread(this); // 获得当前模块的线程
}
public void stop() { //停止游戏
}
public void run() { // 游戏主流程
Graphics g = getGraphics();
while (mTrucking == true) { // 这个boolean值指示游戏是在进行还是已停止
input(); // 处理输入
render(g); // 渲染场景
try {
Thread.sleep(mFrameDelay); // 线程休眠 mFrameDelay个毫秒,这个是相当有必要的,否则会导致手机失去响应,通常应不小于15ms.
} catch (InterruptedException ie) {
}
}
}
private void input() {
}
private void render(Graphics g) {
}
}
我想有了这个框架,再有前面的几个游戏相关类,现在怎么写应该是很清楚的了,我们把Terrain(场景类)和Helicopter的paint方法放到render(Graphics g)中调用,把Helicopter的moveto方法放到 input()中去调用,然后把碰撞检测加到run()函数中的render(g)后面,就可以判断什么时候该结束游戏了.
以下是我的实现:
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.lcdui.Image;
import java.io.*;
public class GameLoop extends GameCanvas implements Runnable {
private boolean mTrucking;
private long mFrameDelay;
private int screenWidth,screenHeight,mX, mY;
private Image img;
private Terrain terrain;
private Helicopter player;
private Flight midlet;
private Command pauseCommand;
private Command resumeCommand;
private Command exitCommand;
public GameLoop(Flight midlet) {
super(true);
this.midlet = midlet;
screenWidth = getWidth();
screenHeight = getHeight();
mX = screenWidth / 2;
mY = screenHeight * 2 / 3;
mFrameDelay = 15;
player = new Helicopter();
try{ // I was so frustrated at the moment when i got to know
img = Image.createImage("/res/brick.png"); //i have no idea to avoid the ugly inintialize codes
}catch(IOException ioe){ // out of the constructor of the class Terrain
ioe.printStackTrace();
}
terrain = new Terrain(screenWidth/4 , screenHeight/12 + 2,img,4,12,player);
pauseCommand = new Command("PAUSE",Command.STOP,1);
resumeCommand = new Command("RESUME",Command.SCREEN,1);
exitCommand = new Command("EXIT",Command.EXIT,1);
}
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) {
input();
render(g);
if(terrain.collides() == true && player.dying == false)player.dying = true; //如果碰撞发生,直升飞机开始爆炸
if(player.alive == false){stop();midlet.addHighScore(getScore());} // 如果爆炸结束,游戏结束,如果是高分则出现添加高分的页面
try {
Thread.sleep(mFrameDelay);
} catch (InterruptedException ie) {
}
}
}
private void input() {
int keyStates = getKeyStates();
if ((keyStates & FIRE_PRESSED) != 0 )
mX = Math.max(0, mX - 1);
else mX = Math.min(getWidth()-10, mX + 1);
}
private void render(Graphics g) {
g.setColor(0x000000);
g.fillRect(0,0,screenWidth,screenHeight);
terrain.paint(g);
terrain.update(); // update the terrain seemly,i think that's the best way
player.moveto(mX,mY);
player.paint(g);
player.update();
g.setColor(0xff0000);
g.drawString(String.valueOf(terrain.milemeter),20,20,0);
flushGraphics();
}
public int getScore(){
return terrain.milemeter; // 返回玩家的成绩,即飞了多少米
}
}