********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); //移动贴图层
}
}