2011211115班2011210420号李佳宁对已有程序——手机游戏潜艇大战的实现分析一、游戏介绍(1)利用方向键来改变军舰的运行方向;(2)确定键发射导弹,击中敌人得分,击中自己人扣分;(3)选项键可以更换背景和背景音乐。二、游戏的流程和类结构(1)游戏流程本游戏的基本运行流程是在MIDlet启动后把整个画布作为一个线程,随时准备响应用户按键操作的KeyPressed()方法,100ms扫描一次潜艇和水雷等物体的运行状态。在扫描潜艇和水雷运动时,执行各个物体画面的移动方法。程序并不为每隔新增潜艇和水雷开启一个新线程,太多线程会造成程序的性能直线下降;而是将每一个物体类型直接加入到画布中,每当一个新物体产生,将直接在画布上画出;当物体消除时,将直接在画布上被消除。这样就形成一种注册机制,所有游戏物体的产生和消除都需要画布注册,画布拥有不同类型物体的所有“名单”,所以,当执行移动命令是只需要遍历画布中所有游戏物体,依次执行每隔游戏物体中定义的移动方法即可。(2)游戏的类结构在本游戏的设计过程中,严格按照面向对象的程序设计思想对程序进行设计,主要显示类包括主界面类、游戏画布类、菜单类、选项类、音乐类、说明类和分别代表军舰、水雷和潜艇的各种实体类。●FIRMIDlet:是游戏的主类,控制着游戏的生命周期,在FIRMIDlet类中的startapp()方法中先载入游戏画面:在FIRMIDlet类中定义了一个static型的quitapp()方法,以方便在游戏过程中随时点击“退出”键来结束改游戏,和一个static型的setcurrent方法方便在其他类中调用不同的显示对象。startapp()方法当中,加载本游戏的选择菜单;quitapp()方法以结束midlet应用程序并释放内存;采用setcurrent()方法来设置display对象中要显示的屏幕画面。●FIRCanvas:画布类,负责绘制游戏中的各种游戏物体,并响应用户的按键操作。●Boat:军舰类,定义游戏中军舰的外观、移动和绘制方法。●Submariner:潜艇类,定义游戏中潜艇的外观、移动和绘制方法。2011211115班2011210420号李佳宁1●Bomb:水雷类。定义游戏中水雷的外观,移动,控制以及碰撞检测的方法。三、具体设计(1)游戏画布类FIRCanvas的实现FIRCanvas继承Canvas类,用来实现整个游戏的主界面。代码具体如下:publicFIRCanvas(){CMD_BG=newCommand(更改背景,8,2);CMD_SOUND=newCommand(切换声音,8,2);CMD_BACK=newCommand(退出,8,2);addCommand(CMD_BG);addCommand(CMD_SOUND);addCommand(CMD_BACK);setCommandListener(this);try{imgBack=Image.createImage(getWidth(),getHeight());gBack=imgBack.getGraphics();sound=SoundEffects.getInstance();boatImage[0]=Image.createImage(/res/ship0.png);boatImage[1]=Image.createImage(/res/ship1.png);bombImage=Image.createImage(/res/boom.png);sImage1[0]=Image.createImage(/res/q1.png);sImage1[1]=Image.createImage(/res/h2.png);sImage2[0]=Image.createImage(/res/r1.png);sImage2[1]=Image.createImage(/res/q2.png);boomImage[0]=Image.createImage(/res/b.png);boomImage[1]=Image.createImage(/res/f1.png);boomImage[2]=Image.createImage(/res/b2.png);}catch(Exceptione){屏幕坐标示意图2011211115班2011210420号李佳宁2e.printStackTrace();}width=this.getWidth();//获得屏幕宽度height=this.getHeight();//获得屏幕高度imgBack=Image.createImage(getWidth(),getHeight());gBack=imgBack.getGraphics();//创建次画面和次画笔offScreen=Image.createImage(width,height);offG=offScreen.getGraphics();boat=newBoat(boatImage,width);init(0);init(1);bomb=newBomb(bombImage,0,0,height);Threadt=newThread(this);t.start();playMusic();}privatevoidinit(intnum){if(num==0){submarine[0]=newSubmarine(sImage1,width,height,0,boomImage);}if(num==1){submarine[1]=newSubmarine(sImage2,width,height,1,boomImage);}}●类中声明了游戏中需要的各种对象,并载入游戏中的图片●在类中启动新线程,调用线程类得run()方法来运行程序protectedvoidpaint(Graphicsg){//清屏offG.setColor(0xffffff);offG.fillRect(0,0,width,height);offG.setColor(0);//绘制if(imgBack!=null){offG.drawImage(imgBack,0,0,Graphics.TOP|Graphics.LEFT);}boat.paint(offG);2011211115班2011210420号李佳宁3submarine[0].paint(offG);submarine[1].paint(offG);if(bomb.isDisplay){bomb.paint(offG);}//绘制得分offG.drawString(得分:+score,4,4,Graphics.TOP|Graphics.LEFT);//将次画面贴到主画面g.drawImage(offScreen,0,0,Graphics.TOP|Graphics.LEFT);}●Paint()方法用来游戏中的各种物体图片绘制到屏幕上publicvoidkeyPressed(intkeyCode){//转换为游戏动作intaction=this.getGameAction(keyCode);switch(action){caseCanvas.LEFT://向左isRepeated=true;boatDirection=Boat.BOAT_MOVE_LEFT;break;caseCanvas.RIGHT:isRepeated=true;boatDirection=Boat.BOAT_MOVE_RIGHT;break;caseCanvas.FIRE:if(!bomb.isDisplay){bomb.isDisplay=true;bomb.setX(boat.x+boat.getBoatImageWidth()/2-bomb.getImageWidth()/2);bomb.setY(boat.Y+boat.getBoatImageHeight()-bomb.getImageHeight());}//设置坐标break;}//重新绘制repaint();2011211115班2011210420号李佳宁4}●keyPressed()方法用来判断用户的按键,从而控制军舰的移动protectedvoiddrawBackground(Graphicsg){bytebX=0,bY=0;intimgWidth,imgHeight;Imageimage;if(back0){g.setColor(0x00AAAAFF);g.fillRect(0,0,CanvasWidth,CanvasHeight);}else{try{image=Image.createImage(BackArray[back]);imgWidth=image.getWidth();imgHeight=image.getHeight();while(bY*imgHeight=CanvasHeight){bX=0;while(bX*imgWidth=CanvasWidth){g.drawImage(image,bX*imgWidth,bY*imgHeight,Graphics.TOP|Graphics.LEFT);bX++;}bY++;}}catch(IOExceptionioe){System.out.println(Imgnotfound:+BackArray[back]);g.setColor(0x00AAAAFF);g.fillRect(0,0,CanvasWidth,CanvasHeight);}}}●drawBackground()方法用来绘制背景图片publicvoidrun(){2011211115班2011210420号李佳宁5while(isRunning){try{Thread.sleep(100);}catch(Exceptione){}if(isRepeated){boat.move(boatDirection);}if(!submarine[0].isIsBoom()){submarine[0].move();}else{//播放爆炸效果submarine[0].boom();}if(!submarine[1].isIsBoom()){submarine[1].move();}else{//播放爆炸效果submarine[1].boom();}if(bomb.isDisplay){bomb.move();if(bomb.collidesWith(submarine[0])){bomb.handlecollidesWith(submarine[0]);score-=10;}if(bomb.collidesWith(submarine[1])){bomb.handlecollidesWith(submarine[1]);score+=10;}}System.gc();repaint();}}●run()方法用来运行程序privatevoidplayMusic(){sound.stopMusic();switch(music){case0:2011211115班2011210420号李佳宁6break;case1:sound.playSpringMusic();break;case2:sound.playCityMusic();break;case3:sound.playFlowerMusic();break;default:break;}}●playMusic()方法用来执行音乐的选择和播放publicvoidcommandAction(Commandc,Displayabled){if(c==CMD_BACK){midlet.instructionsBack();}elseif(c==CMD_SOUND){music++;if(music==5)music=0;playMusic();}elseif(c==CMD_BG){back++;if(back==BackArray.length)back=0;dra