********GameMID。Java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.*;
/**
* @author Administrator
*/
public class GameMID extends MIDlet {
private Display display;
private GameWorld gw=null;
public GameMID(){
display = Display.getDisplay(this); //获取Display
gw=new GameWorld(this); //创建游戏画布
display.setCurrent(gw); //设置游戏画布为当前显示画面
}
public void startApp() {
if(gw!=null){
gw.start(); //游戏开始执行
}
}
public void pauseApp() {
if(gw!=null){
gw.setPaused(true); //游戏暂停执行
}
}
public void destroyApp(boolean unconditional) {
}
/* 退出程序 */
public void exit(){
try{
destroyApp(false);
}catch(Exception e){}
notifyDestroyed();
}
}
**********GameWorld。Java
import java.io.IOException;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.game.TiledLayer;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author Administrator
*/
public class GameWorld extends GameCanvas implements Runnable{
GameMID mid; //游戏MIDlet
Thread MainThread; //游戏主线程
private final int MS_PER_FRAME=30; //设置一次游戏循环所需时间,单位为毫秒(ms),每秒游戏帧数约为1000/MS_PER_FRAME
private int cps; //游戏帧速
private boolean isPaused; //游戏暂停状态
private boolean running; //游戏运行状态
Graphics g; //游戏绘图对象
public static int ScreenWidth; //游戏屏幕宽度,设置为静态成员,方便外部访问
public static int ScreenHeight; //游戏屏幕高度
public static int GameState; //游戏状态,1为暂停,2为游戏进行中,3为游戏失败
public static int KeyState; //按键状态
private Image imgEnemy,imgBoy; //精灵图像
private Sprite sprEnemy; //定义敌人精灵
private MySprite sprBoy; //用扩展的精灵类来定义玩家精灵
//定义三个不同方向的玩家精灵帧序列,右方向可由左方向镜像变换得到
int LSequ[]={3,4,3,5}; //定义左方向精灵帧序列
int USequ[]={6,7,6,8}; //定义上方向精灵帧序列
int DSequ[]={0,1,0,2}; //定义下方向精灵帧序列
int enemyX,enemyY; //敌人精灵坐标
int enemySpeedX; //敌人精灵速度,这里设置为只能水平移动
boolean isColl; //碰撞标志
long CollTextTime; //碰撞文本显示时间
TiledBg tbg; //创建贴图层应用类
TiledLayer tl; //创建贴图层类
//定义字体
private Font largeFont=Font.getFont(Font.FACE_SYSTEM,Font.STYLE_BOLD, Font.SIZE_LARGE);
private Font mediumFont=Font.getFont(Font.FACE_SYSTEM,Font.STYLE_BOLD, Font.SIZE_MEDIUM);
public GameWorld(GameMID midlet)
{
super(true);
this.mid=midlet; //获取MIDlet
this.setFullScreenMode(true); //设置为全屏模式
ScreenWidth=getWidth(); //获取屏幕大小
ScreenHeight=getHeight();
g=this.getGraphics(); //获取绘图对象
running=false; //设置游戏运行状态
isPaused=false;
GameInit(); //游戏初始化
}
/* 游戏初始化 */
private void GameInit() {
try {
imgBoy = Image.createImage("/Boy.png");
imgEnemy=Image.createImage("/enemy.png");
} catch (IOException ex) {
ex.printStackTrace();
}
// 使用Image对象,帧宽度、帧高度,速度,限制范围矩形左上角的X坐标、Y坐标、高度和宽度来构造自定义精灵
sprBoy=new MySprite(imgBoy,32,48,3,0,0,ScreenWidth,ScreenHeight);
sprBoy.setFrameSequence(LSequ); //设置初始化时的精灵帧序列和方向
sprBoy.setDir( MySprite.LEFT); //设置初始化时精灵方向
sprBoy.defineReferencePixel(sprBoy.getWidth()/2, sprBoy.getHeight()/2); //设置参考点
sprBoy.setRefPixelPosition(ScreenWidth/2, ScreenHeight/2); //通过参考点定位精灵
int sw=sprBoy.getWidth();
int sh=sprBoy.getHeight();
sprBoy.defineCollisionRectangle(sw/10, sh/10, sw*8/10,sh*8/10); //重设精灵的碰撞矩形范围为原来的80%
//创建敌人精灵
sprEnemy=new Sprite(imgEnemy,imgEnemy.getWidth()/3,imgEnemy.getHeight()/3);
sprEnemy.setFrameSequence(LSequ); //设置精灵循环序列
enemyX=50; //设置敌人精灵的坐标
enemyY=200;
enemySpeedX=-2; //设置敌人精灵速度
tbg=new TiledBg(); //创建TiledBg对象
tl=tbg.getTiledbg(); //获取贴图层
}
/* 游戏运行 */
public void run(){
int cyclesThisSecond=0; //当前1秒内的循环次数
long cycleStartTime; //循环开始时间
long lastCPSTime=0; //上次计算帧速的时间
long cycleEndTime=0; //循环结束时间
long cycleTimes=0; //一次游戏循环热所花的时间
boolean bSkip = false; //游戏是否跳帧
cps=0;
System.out.println("游戏开始");//在控制台输出开始信息,可屏蔽
/* 游戏主循环 */
while(running){ //检查是否运行
cycleStartTime = System.currentTimeMillis();//记录游戏循环开始时间
// 下面语句用于处理游戏内容,如果游戏设置为跳帧,
// 则本次循环不处理游戏内容
if(!bSkip)
{
GameInput(); //处理输入消息
GameCycle(); //处理游戏逻辑
render(g); //渲染游戏画面
flushGraphics(); //更新画面
}
/* 下面语句用于计算游戏循环时间,并进行相应处理 */
cycleEndTime=System.currentTimeMillis(); //记录游戏循环结束时间
cycleTimes=cycleEndTime-cycleStartTime; //计算循环时间
//如果循环时间间隔小于MS_PER_FRAME,则通过休眠,使其不小于rate,
//并能让系统有空闲转去处理其他事务
if(cycleTimes bSkip = false; try { Thread.sleep(MS_PER_FRAME - cycleTimes); //休眠 } catch (InterruptedException ex) { ex.printStackTrace(); } } else{ //如果循环时间大于MS_PER_FRAME,则设置bSkip为true, //让程序跳过一次循环,以主动丢帧的方式换取游戏速度 bSkip = true; } //下面语句用于计算每秒的循环次数,即帧速,在游戏中如果不需要, //可将这部分语句及相关变量注释屏蔽 if (System.currentTimeMillis() - lastCPSTime > 1000){ //检查距上次计算帧数的 //时间是否经过1000ms lastCPSTime=System.currentTimeMillis(); //设定lastCPS为当前时间 cps = cyclesThisSecond; // System.out.println("cps:"+cps); //输出每秒的帧数 cyclesThisSecond = 0; //重置帧数 } else { cyclesThisSecond++; //帧数递增 } } System.out.println("游戏结束!"); release(); //释放资源 exit(); //退出游戏 } /* 启动游戏进程 */ public void start(){ //检查游戏循环是否处于运行状态,如果未运行,则创建线程并启动 //如果游戏处于运行状态,则表示是暂停后的继续执行,仅设置暂停状态即可 if(!running){ running=true; MainThread=new Thread(this); MainThread.start(); GameState=2; } else{ GameState=2; setPaused(false); } } //退出游戏 private void exit() { mid.exit(); //退出游戏 } /* 停止游戏 */ private void stop(){ running=false; //终止游戏循环 } /* 释放游戏资源 */ private void release(){ //此处为释放游戏资源的代码 imgEnemy=null; imgBoy=null; sprBoy=null; sprEnemy=null; tbg=null; tl=null; System.gc(); } /* 获取暂停状态 */ public boolean getPaused() { return isPaused; } /* 设置暂停状态 */ public void setPaused(boolean isPaused) { this.isPaused = isPaused; } /* 处理游戏输入信息 */ private void GameInput() { int keyStates = this.getKeyStates(); //获取按键状态 /* 下面是对按键事件的具体处理,应根据游戏需要进行修改*/ KeyState=0; //Fire if((keyStates & FIRE_PRESSED )!=0){ KeyState=FIRE_PRESSED; } // Left if ((keyStates & LEFT_PRESSED) != 0){ KeyState=LEFT_PRESSED; } // Right if ((keyStates & RIGHT_PRESSED) !=0 ){ KeyState=RIGHT_PRESSED; } // Up if ((keyStates & UP_PRESSED) != 0) { KeyState=UP_PRESSED; } // Down if ((keyStates & DOWN_PRESSED) !=0) { KeyState=DOWN_PRESSED; } //Game_A if((keyStates & GAME_A_PRESSED)!=0) { KeyState=GAME_A_PRESSED; } //Game_B if((keyStates & GAME_B_PRESSED)!=0){ KeyState=GAME_B_PRESSED; } //Game_C if((keyStates & GAME_C_PRESSED)!=0) { KeyState=GAME_C_PRESSED; } //Game_D if((keyStates & GAME_D_PRESSED)!=0){ KeyState=GAME_D_PRESSED; } } /* 渲染游戏画面 */ private void render(Graphics g) { /* 填充背景 */ g.setColor(0xffffff); g.fillRect(0, 0, ScreenWidth,ScreenHeight); /* 下面是对游戏渲染的具体处理,应根据游戏需要进行修改*/ tl.paint(g); //绘制贴图层 // g.drawImage(imgBuild,100, 50, Graphics.LEFT|Graphics.TOP); sprEnemy.paint(g); //绘制敌人精灵 sprBoy.paint(g); //绘制精灵 //当敌人精灵和玩家角色相碰撞时,绘制下面的内容 if(isColl){ g.setColor(0xccbbcc); g.fillRect(50, 0, 120, 20); g.setColor(0xffffff); g.setFont(largeFont); g.drawString("被敌人撞上啦!",60,0, Graphics.LEFT| Graphics.TOP); } } /* 游戏逻辑处理*/ private void GameCycle() { switch(GameState){ case 1: //游戏暂停状态时的处理 //根据按键状态执行相应功能 switch(KeyState){ case GAME_A_PRESSED: //按下GAME_A键时的处理 GameState=4; //设置游戏状态会结束程序 break; case FIRE_PRESSED: //按下FIRE键时的处理 if(getPaused()){ GameState=2; setPaused(false); } break; } break; case 2: //游戏处于运行状态时的处理 { //根据按键状态执行相应功能 //根据按键状态进行计算 switch(KeyState){ case FIRE_PRESSED: //按下Fire键时 GameState=1; //设置游戏状态为暂停 setPaused(true); //设置暂停 break; case GAME_A_PRESSED: //按下Game_A键时 GameState=4; //设置游戏状态为退出 break; case GAME_B_PRESSED: //按下Game_B键时 sprBoy.setFrame(2); break; default: update(); //更新数据 break; } } break; case 3: //游戏失败的处理 break; case 4: //游戏退出时的处理 stop(); //停止运行 break; } } /* 更新数据 */ private void update(){ //敌人的运动 enemyX+=enemySpeedX; //计算坐标 if(enemyX>=ScreenWidth+sprEnemy.getWidth() && enemySpeedX>0) { enemySpeedX=-enemySpeedX; //改变速度方向 sprEnemy.setTransform(Sprite.TRANS_NONE); } if(enemyX+sprEnemy.getWidth()<=0 && enemySpeedX<0 ) { enemySpeedX=-enemySpeedX; //改变速度方向 sprEnemy.setTransform(Sprite.TRANS_MIRROR); } sprEnemy.setRefPixelPosition(enemyX, enemyY); //设置敌人位置 sprEnemy.nextFrame(); //精灵动画移到后一帧 //检测玩家角色是否与敌人相碰撞,如果是,则后退 if( sprBoy.collidesWith(sprEnemy,false)){ //通过敌人的速度方向来检查是从哪个方向撞上的,并作相应动作 if(sprEnemy.getX()>sprBoy.getX()) { sprBoy.move(-sprBoy.getSpeed(), 0); //移动玩家角色精灵 sprEnemy.setTransform(Sprite.TRANS_MIRROR); //设置敌人精灵方向 enemyX+=sprEnemy.getWidth(); //重设敌人精灵坐标 enemySpeedX=2; //设置敌人精灵速度方向 } else{ sprBoy.move(sprBoy.getSpeed(), 0); //移动玩家角色精灵 sprEnemy.setTransform(Sprite.TRANS_NONE); //设置敌人精灵方向 enemyX-=sprEnemy.getWidth(); //重设敌人精灵坐标 enemySpeedX=-2; //设置敌人精灵速度方向 } sprEnemy.setRefPixelPosition(enemyX, enemyY); //重设敌人位置 isColl=true; //设置碰撞标志 CollTextTime=120; //设置碰撞文本显示时间 } else if(CollTextTime<=0){ isColl=false; } CollTextTime--; //设置碰撞文本显示时间递减 //根据按键状态计算玩家角色精灵与贴图层数据 switch(KeyState){ case LEFT_PRESSED: //按下Left键时 //检查原来是否为左方向的精灵帧序列,如果不是则设置为左方向精灵帧序列 if(sprBoy.getDir()!=MySprite.LEFT){ sprBoy.setFrameSequence(LSequ); //设置左方向精灵序列 sprBoy.setTransform(MySprite.TRANS_NONE); //设置为不变换 } if(sprBoy.move(MySprite.LEFT)){ //向左移动,如果到屏幕边缘则移动贴图层 tbg.move(sprBoy.getSpeed(), 0); } break; case RIGHT_PRESSED: //按下Right键时 //检查原来是否为右方向的精灵帧序列,如果不是则设置为右方向精灵帧序列 if(sprBoy.getDir()!=MySprite.RIGHT){ sprBoy.setFrameSequence(LSequ); //设置左方向精灵帧序列 sprBoy.setTransform(MySprite.TRANS_MIRROR); //设置为镜像变换 } //向右移动,如果到屏幕边缘则移动贴图层 if(sprBoy.move(MySprite.RIGHT)){ tbg.move(-sprBoy.getSpeed(), 0); } break; case UP_PRESSED: //按下Up键时 //检查原来是否为上方向的精灵帧序列,如果不是则设置为上方向精灵帧序列 if(sprBoy.getDir()!=MySprite.UP){ sprBoy.setFrameSequence(USequ); } //向上移动,如果到屏幕边缘则移动贴图层 if(sprBoy.move(MySprite. UP)){ tbg.move(0,sprBoy.getSpeed() ); } break; case DOWN_PRESSED: //按下Right键时 //检查原来是否为下方向的精灵帧序列,如果不是则设置为下方向精灵帧序列 if(sprBoy.getDir()!=MySprite.DOWN){ sprBoy.setFrameSequence(DSequ); } //向下移动,如果到屏幕边缘则移动贴图层 if( sprBoy.move(MySprite.DOWN)){ tbg.move(0,-sprBoy.getSpeed() ); } break; } tbg.update(); //更新动态贴图 } } ************MySprite.java import javax.microedition.lcdui.Image; import javax.microedition.lcdui.game.Sprite; /* * To change this template, choose Tools | Templates * and open the template in the editor. */ /** * * @author Administrator */ public class MySprite extends Sprite{ private int speed; //速度 private int dir; //方向 private int RoundX; //限制矩形范围的左上角坐标 private int RoundY; private int RoundWidth; //限制矩形范围宽度 private int RoundHeight; //限制矩形范围高度 //定义各方向静态常量 public final static int LEFT=1; //左 public final static int RIGHT=2; //右 public final static int UP=3; //上 public final static int DOWN=4; //下 /* 使用Image对象,帧宽度w和帧高度h构造精灵*/ public MySprite(Image img,int w,int h){ super(img,w,h); //使用基类(即Sprite)构造方法创建精灵 this.speed=1; //设置默认速度 setDir(DOWN); //设置默认方向 setRoundRect(0,0,240,309); //设置缺省时的限制矩形 } /* 使用Image对象,帧宽度w、帧高度h和速度speed构造精灵 */ public MySprite(Image img,int w,int h,int speed){ super(img,w,h); this.speed=speed; setDir(DOWN); //设置默认方向 } /* 使用Image对象,帧宽度、帧高度,速度,限制范围矩形左上角的X坐标、Y坐标、高度和宽度来构造精灵 */ public MySprite(Image img,int w,int h,int speed,int rx,int ry,int rw,int rh){ super(img,w,h); this.speed=speed; //设置速度 setDir(DOWN); //设置默认方向 setRoundRect(rx,ry,rw,rh); //设置限制范围矩形 } /* 设置限制范围矩形 */ public void setRoundRect(int rx,int ry,int rw,int rh){ setRoundX(rx); setRoundY(ry); setRoundWidth(rw); setRoundHeight(rh); } /* 向dir方向移动精灵,并返回是否已到达范围矩形边框*/ public boolean move(int dir){ boolean isRound; isRound=false; int moveX=0; int moveY=0; this.setDir(dir); //设置方向 switch(dir){ //通过方向,按设置的速度距离移动精灵 case LEFT: moveX=-getSpeed(); break; case RIGHT: moveX=getSpeed(); break; case UP: moveY=-getSpeed(); break; case DOWN: moveY=getSpeed(); break; } //下面语句用于将移动点在范围矩形内 if( getX()+moveX moveX=getRoundX()-getX(); isRound=true; } else if( getX()+moveX+getWidth()>getRoundX()+getRoundWidth()){ moveX=getRoundX()+getRoundWidth()-getX()-getWidth(); isRound=true; } if( getY()+moveY moveY=getRoundY()-getY(); isRound=true; } else if( getY()+moveY+getHeight()>getRoundY()+getRoundHeight()){ moveY=getRoundY()+getRoundHeight()-getY()-getHeight(); isRound=true; } super.nextFrame(); super.move(moveX, moveY); //调用基类方法移动精灵 return isRound; } /* 获取速度 */ public int getSpeed() { return speed; } /* 设置速度 */ public void setSpeed(int speed) { this.speed = speed; } /* 获取方向 */ public int getDir() { return dir; } /* 设置方向 */ public void setDir(int dir) { this.dir = dir; } /* 获取限制框X坐标 */ public int getRoundX() { return RoundX; } /* 设置限制框X坐标 */ public void setRoundX(int RoundX) { this.RoundX = RoundX; } /* 获取限制框Y坐标 */ public int getRoundY() { return RoundY; } /* 设置限制框Y坐标 */ public void setRoundY(int RoundY) { this.RoundY = RoundY; } /* 获取限制框宽度 */ public int getRoundWidth() { return RoundWidth; } /* 设置限制框宽度 */ public void setRoundWidth(int RoundWidth) { this.RoundWidth = RoundWidth; } /* 获取限制框高度 */ public int getRoundHeight() { return RoundHeight; } /* 设置限制框高度 */ public void setRoundHeight(int RoundHeight) { this.RoundHeight = RoundHeight; } } ***************TiledBg.java /* * To change this template, choose Tools | Templates * and open the template in the editor. */ import javax.microedition.lcdui.*; import javax.microedition.lcdui.game.*; import java.io.IOException; /** * @author Administrator */ public class TiledBg { private Image tiled; //贴图源图 private TiledLayer tiledbg; //定义贴图层 int AnimSeq[]={14,21,28}; //动态贴图序列 int AnimTiled; //动态贴图号 int AnimIndex; //记录当前动态贴图序号 int AnimTimes; //用于计算动态贴图时间间隔 public TiledBg(){ try { // write pre-init user code here tiled = Image.createImage("/tiled.png"); //获取源图 } catch (IOException ex) { ex.printStackTrace(); } AnimIndex=0; //初始化 AnimTimes=0; } /* 获取贴图源图像*/ public Image getTiled() { return this.tiled; } /* 更新动态贴图 */ public void update(){ //检测动态贴图时间间隔,每5次循环更新一次动态贴图 if(AnimTimes%5==0){ AnimIndex++; //动态贴图序号递增 if(AnimIndex>=AnimSeq.length){ //检查动态贴图序号是否超出下标范围 AnimIndex=0; //重置动态贴图序号 } //设置动态贴图 tiledbg.setAnimatedTile(AnimTiled, AnimSeq[AnimIndex]); } AnimTimes++; //动态贴图时间间隔递增 } /* 创建并返回动态贴图*/ public TiledLayer getTiledbg() { //检查贴图层是否已创建,如未创建则先创建 if (tiledbg == null) { tiledbg = new TiledLayer(20, 10, tiled, 32, 32); //创建贴图层 AnimTiled= tiledbg.createAnimatedTile(AnimSeq [0]); //定义贴图序号数组 int[][] tiles = { { 3, 3, 2, 2, 2, 2, 2, 15, 7, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2 }, { 2, 2, 2, 2, 2, 4, 2, 15, 2, 2, 2, 2, 2, 6, 2, 2, AnimTiled, 2, 3, 2 }, { 7, 2, 2, 26, 2, 2, 2, 17, 10, 9, 10, 9, 11, 2, 2, 2, 13, 2, 3, 7 }, { 9, 9, 9, 9, 11, 19, 2, 2, 2, 2, 2, 2, 15, 2, 12, 2, 8, 9, 9, 9 }, { 2, 2, 2, AnimTiled, 15, 2, 2, 2, 2, 7, 2, 20, 22, 2, 2, 2, 15, 2, 3, 2 }, { 4, 2, 2, 2, 17, 10, 9, 10, 9, 24, 10, 9, 18, 2, 2, 2, 15, 2, 3, 4 }, { 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 2, 2, 26, 19, 19, 2, 15, 2, 3, 2 }, { 2, 2, 13, 2, 2, 2, 2, 20, 2, 15, AnimTiled, 2, 2, 19, 19, 3, 15, 3, 3, 2 }, { 2, 2, 2, 2, 2, 8, 10, 9, 10, 16, 10, 9, 10, 9, 10, 9, 18, 3, 3, 2 }, { 4, 2, 2, 27, 7, 15, 2, 2, 2, 7, 2, AnimTiled, 2, 2, 4, 2, 2, 6, 3, 2 } }; //通过双重循环设置贴图 for (int row = 0; row < 10; row++) { for (int col = 0; col < 20; col++) { tiledbg.setCell(col, row, tiles[row][col]); //设置贴图 } } } return tiledbg; //返回贴图 } /* 移动贴图层 */ public void move(int x,int y){ //检查是否到达贴图层左边缘,如果是,则设置为紧贴左边缘 if(tiledbg.getX()>=0 && x>0){ tiledbg.setPosition(0, tiledbg.getY()); return; } //检查是否到达贴图层右边缘,如果是,则设置为紧贴右边缘 if(tiledbg.getX()<=GameWorld.ScreenWidth-tiledbg.getWidth() && x<0){ tiledbg.setPosition(GameWorld.ScreenWidth-tiledbg.getWidth(), tiledbg.getY()); return; } //检查是否到达贴图层上边缘,如果是,则设置为紧贴上边缘 if(tiledbg.getY()>=0 && y>0){ tiledbg.setPosition(tiledbg.getX(), 0); return; } //检查是否到达贴图层下边缘,如果是,则设置为紧贴下边缘 if( tiledbg.getY()<=GameWorld.ScreenHeight-tiledbg.getHeight() && y<0){ tiledbg.setPosition(tiledbg.getX(), GameWorld.ScreenHeight-tiledbg.getHeight()); return; } tiledbg.move(x,y); //移动贴图层 } }