| 
				 5.子弹类 
子弹类TankBullet继承Sprite类并实现Runnable接口,每一个坦克对象创建一个子弹就重新创建了一个线程来实现子弹的运行、碰撞处理以及消除。在本设计中,每个坦克对象可以同时发射五颗子弹,也就是为每个坦克对象创建了一个数组容量为5的子弹数组,代码如下。 
public class TankBullet extends Sprite implements Runnable { 
public int Bullet_X,Bullet_Y,Bullet_Dir;  
public TankGameCanvas game; 
public Image bulletImage; 
public TankBullet(Image image, int frameWidth, int frameHeight) { 
    super(image, frameWidth, frameHeight);   
} 
    public void start(int Bullet_X,int Bullet_Y,int Bullet_Dir){ 
    this.Bullet_X = Bullet_X; 
    this.Bullet_Y = Bullet_Y; 
    this.Bullet_Dir = Bullet_Dir; 
    new Thread(this).start(); 
} 
public void run() { 
    while(Bullet_X>0 & Bullet_X<240 & Bullet_Y>0 &Bullet_Y<224){ 
    switch(Bullet_Dir)             //根据接收的参数定义子弹的发射方向 
    { 
      case 0: Bullet_Y--; break;  //子弹向上发射           
      case 1: Bullet_Y++; break;  //子弹向下发射 
      case 2: Bullet_X--; break;  //子弹向左发射 
      case 3: Bullet_X++;     //子弹向右发射 
  } 
    try{ 
        Thread.sleep(20);       //线程的间隔时间为20ms 
    }catch(Exception ie){} 
    setRefPixelPosition(Bullet_X, Bullet_Y); //设置子弹显示位置 
    if(this.collidesWith(TankGameCanvas.mBackground, true)||!this.isVisible()) 
        break; 
    } 
    setVisible(false);             //子弹状态为不可见,相当于子弹消失 
} 
} 
6.生成敌方坦克 
游戏画布创建时便生成了11个敌方坦克对象,并将其设为不可见,以便在玩家进入游戏后再将其慢慢地在不同位置显示出来,生成敌方坦克由TankGameCanvas类createETank方法实现,关键代码如下。 
    public void createETank(){ 
        long f_time = System.currentTimeMillis();//获取系统目前时间 
        long times = f_time - t1;   //计算两次显示敌方坦克的时间间隔    
        random = new Random();       //随机函数生成对象 
        if(times>1000){              //设置两次显示敌方坦克的时间最少为1s 
            for(int i=0;i<E_Tank.length;i++){ 
                if(!E_Tank[i].isVisible()){         
                    E_Tank[i].setVisible(true); 
                    int nX,nY,nDir; 
                    while(true){ 
                        nX = random.nextInt(15); //生成随机X坐标 
                        nY = random.nextInt(14); //生成随机Y坐标 
                        int x_dst = Math.abs(nX*16-curX); 
                        int y_dst = Math.abs(nY*16-curY); 
                        if(x_dst>48&y_dst>48&Map[nY*15+nX]==0)   //限制敌方坦克的生成位置 
                            break;                  //不得与主坦克位置太接近 
                    } 
                    nDir = random.nextInt(3);       //随机生成敌方坦克生成时方向 
                    E_Tank[i].setDir(nDir); 
                    E_Tank[i].setPosition(nX*16, nY*16); 
                    t1 = f_time; 
                    break; 
                } 
            } 
        } 
    } 
屏幕绘制模块里设置了画布的背景色,以及该背景色的显示区域,并将各图层按顺序添加到LayerManager对象,最后再利用flushGraphics()方法将所有内容显示在画布当中。在游戏界面下也会显示玩家的等级、生命值HP、所获得的经验值等信息,让玩家可以更加清楚自己的坦克的状态。屏幕绘制由TankGameCanvas类drawScreen方法实现,关键代码如下。 
private void drawScreen(Graphics g){ 
        g.setColor(0x996633);       //设置游戏画布背景色 
        g.fillRect(0,0,getWidth(),getHeight()-17);//背景色填充范围 
        g.setColor(0xffffff); 
        g.fillRect(0, 232, 240, 32); 
        //显示玩家等级、生命值HP、所获得的经验EXP等信息 
        String str ="LV"+M_lv+"  "+"HP"+"  "+Math.max(0,M_blood)+"/"+ 
                    (M_lv*25+25)+"  "+"EXP"+"  "+M_exp+"/"+M_mexp; 
        //设置显示字体 
        Font font = Font.getFont(Font.FACE_MONOSPACE, 
                Font.STYLE_BOLD|Font.STYLE_ITALIC,Font.SIZE_MEDIUM); 
        g.setFont(font);    g.setColor(0x996633); 
        g.drawString(str, 8, 248,g.BOTTOM|g.LEFT); 
        M_Tank.setPosition(curX, curY);       //设置主坦克显示位置  
        for(int i=0;i<E_Tank.length;i++){ 
            mlayerManager.append(E_Tank[i]); //添加敌方坦克图层到   
        }                                   //当前对象 
        mlayerManager.append(M_Tank);  
        mlayerManager.append(mBackground); 
        mlayerManager.append(mlayer); 
        mlayerManager.append(elayer); 
        for(int j=0;j<Bullet.length;j++){ 
            mlayerManager.append(Bullet[j]); 
        } 
        for(int m=0;m<M_Wall.length;m++){ 
            mlayerManager.append(M_Wall[m]); 
            mlayerManager.append(E_Wall[m]); 
        } 
        checkResult(); 
        mlayerManager.paint(g,0,0);   //绘制屏幕 
        flushGraphics();              //刷新缓冲区内容到当前画布显示 
    } 
在游戏中玩家与敌方均有自己输赢的标志“堡垒”,在整个游戏进行过程中只要自己的“堡垒”被攻破就算失败,游戏也就结束。因此,玩家只有在自己的“堡垒”被攻破之前攻破对方的“堡垒”才能获得胜利。然而,“堡垒”外层的“铁墙”并不是一下子就能摧毁的,玩家所控制的坦克等级越低,攻击力也就越低,攻破外层的“铁墙”所需要的时间也就越长。游戏输赢判断由TankGameCanvas类drawScreen方法实现,关键代码如下。 
   private void checkResult(){ 
        if(gameEnd==1){                   //*游戏战胜* 
            EndSprite.setFrame(0);        //精灵显示第一帧    
            mlayerManager.remove(elayer); //去掉原有图层 
            elayer.setCell(7, 0, 4);    elayer.setCell(7, 1, 5); 
            mlayerManager.append(elayer); //添加新图层 
            mlayerManager.append(EndSprite);//添加精灵图层 
            removeCommand(stopCommand);   //去掉“暂停”右软键 
            addCommand(restartCommand);   //添加“重新开始”右软件键 
            isPlay = false;              //中止主循环线程参数 
        } 
        if(gameEnd==2){                  //*游戏失败* 
            EndSprite.setFrame(1);       //精灵显示第二帧  
            mlayerManager.remove(mlayer);//去掉原有图层 
            mlayer.setCell(7, 27, 4);   mlayer.setCell(7, 28, 5); 
            mlayerManager.append(mlayer);//添加新图层 
            mlayerManager.append(EndSprite);//添加精灵图层 
            removeCommand(stopCommand);   //去掉“暂停”右软键 
            addCommand(restartCommand);   //添加“重新开始”右软件键 
            isPlay = false;              //中止主循环线程参数 
        } 
    } 
  
四、结语 
由于手机设备资源的限制,对程序代码的要求也相应提高。对于内存的局限,主要在图片的制作上进行高压缩处理,并将一些相同规格的图片压缩成一张,有效地减小了图片chunks的浪费;而对于处理器的限制,在程序设计中尽量避免多重循环语句的出现和复杂算法的使用。  
  
参考文献 
  
[1]陈刚编著.Eclipse从入门到精通.清华大学出版社. 
[2]Michael Morrison 著.J2ME手机游戏编程入门.人民邮电出版社. 
[3]郎锐,孙方 编著.J2ME手机程序Eclipse开发基础.机械工业出版社. 
[4]Martin J.Wells 著.J2ME游戏编程.清华大学出版社. 
[5]李振鹏,龚剑 编著.J2ME手机游戏开发技术详解.清华大学出版社. 			
				 |