第一讲-面向对象游戏设计_第1页
第一讲-面向对象游戏设计_第2页
第一讲-面向对象游戏设计_第3页
第一讲-面向对象游戏设计_第4页
第一讲-面向对象游戏设计_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1简单坦克游戏的面向对象实现2简单坦克游戏的面向对象实现本章的游戏例子涵盖了Java语言的众多特点,比如继承、封装、抽象方法、静态方法和静态变量等等,并结合Java画图机制、线程机制和Java网络通信三部分的知识点。本讲概要坦克游戏复习坦克游戏面向对象设计面向对象分析坦克的面向对象设计主窗体的设计坦克游戏复习坦克:圆心坐标:x、y半径大小:20坦克朝向:dir子弹:圆心坐标、半径、移动方向坦克的移动:使用键盘按键机制改变圆心坐标,改变之后刷新画面子弹的移动,使用线程机制控制面向对象分析分析坦克大战小游戏,如图1所示,一共有三种实体:坦克:Tank子弹:Bullet障碍物:Block除了这三种实体以外,我们还需要实体所在的场景类:场景:GameCanvas三种对象为了简单起见,暂不考虑障碍物。在上一讲中开发坦克大战的方法是传统的结构化的思想,本讲我们改用面向对象的方法来实现,可以针对坦克和子弹写各写一个类坦克的面向对象设计对于坦克,把类名设定为Tank,类是由属性和方法构成的,Tank类中的属性和方法如下表所示(代码见例1)Tank类的属性坦克圆心坐标(x,y)坦克半径radius坦克朝向dirTank类的方法坦克移动move()构造方法Tank()坦克射击shoot()例1:Tank类publicclassTank{

intx=100,y=100,dir=0,radius=20;publicTank(int

x,inty){this.x=x;this.y=y;}publicvoidmove(int

moveDir){

switch(moveDir) { case0:x=x-5;break;//0表示左

case1:y=y-5;break;//1表示上

case2:x=x+5;break;//2表示右

case3:y=y+5;break;//3表示下

}}}面向对象坦克绘制虽然实现了Tank类,但是这个实现有意义吗?接下来要考虑的是如何通过画图机制把坦克表现出来。若要画出坦克,必须要使用Frame类的paint()方法,每一次变动的时候调用repaint()方法重绘。paint()方法中画图的关键部分是Graphics对象g,该对象包含了与画图相关的所有方法,能不能把该对象“拿出来”,传给需要使用它的对象,在绘制图形的时候调用呢?答案是肯定的,Frame类提供了一个getGraphics()方法,该方法返回一个Graphics对象,使用这个返回的对象就能在任何地方进行绘图了。Frame类中在得到Graphics对象以后,只要传给Tank对象,Tank对象调用move()方法改变坦克位置以后就可以进行重绘了。面向对象坦克绘制若要画出坦克,必须要使用Frame类的paint()方法每一次变动的时候调用repaint()方法重绘。paint()方法中画图的关键部分是Graphics对象g,该对象包含了与画图相关的所有方法,能不能把该对象“拿出来”,传给需要使用它的对象,在绘制图形的时候调用呢?面向对象坦克绘制答案是肯定的,Frame类提供了一个getGraphics()方法,该方法返回一个Graphics对象,使用这个返回的对象就能在任何地方进行绘图了。Frame类中在得到Graphics对象以后,只要传给Tank对象,Tank对象调用move()方法改变坦克位置以后就可以进行重绘了。需要在Tank类的定义中增加一个Graphics对象和一个draw()方法,请看例2所示的代码

面向对象坦克绘制例2:增加绘制方法的Tank类importjava.awt.*;publicclassTank{

staticGraphicsg;

intx=100,y=100,dir=0,radius=20;publicTank(int

x,inty){this.x=x;this.y=y;}publicvoidmove(int

moveDir){

switch(moveDir){case0:x=x-5;break;//0表示左

case1:y=y-5;break;//1表示上

case2:x=x+5;break;//2表示右

case3:y=y+5;break;//3表示下

}draw();}publicvoiddraw(){

g.setColor(Color.blue);

g.fillOval(x,y,40,40);g.setColor(Color.red);

switch(dir){case0:g.drawLine(x,y,x-20,y);break;case1:g.drawLine(x,y,x,y-20);break;case2:g.drawLine(x+20,y,x,y);break;case3:g.drawLine(x,y,x,y+20);break;}}//坦克的射击方法

publicvoidshoot(){}}面向对象绘制的注意事项属性g是一个静态属性,需要从外面传进来,draw()方法使用g对象对坦克进行绘制。需要对上一讲的GameCanvas类做一定变动,在键盘按键事件中,直接调用player对象的move()方法,在move()方法中改变坦克的位置并进行重绘例10-3给出了GameCanvas的代码和运行结果GameCanvas类中调用画布的getGraphics()方法为g赋值。改造后的GameCanvas类importjava.awt.*;importjava.awt.event.*;publicclassGameCanvasextendsFrame{Tankplayer;publicGameCanvas(){player=newTank(100,100);classKLimplementsKeyListener{publicvoidkeyPressed(KeyEvente){}publicvoidkeyReleased(KeyEvente){}publicvoidkeyTyped(KeyEvente){switch(e.getKeyChar()){case'a':

player.dir=0;player.move(0);break;case'w':

player.dir=1;player.move(1);break;case'd':

player.dir=2;player.move(2);break;case's':

player.dir=3;player.move(3);break;}}}

addKeyListener(newKL());}publicvoidpaint(Graphicsg){Tank.g=this.getGraphics();

player.draw();}publicstaticvoidmain(String[]args){GameCanvasgame=newGameCanvas();game.setSize(600,400);

game.setVisible(true);}}注意这里的变化改造后的GameCanvas类运行效果坦克移动的尾巴从上图可以看到,坦克行动之后会留下一条长长的“尾巴”,这是我们不希望看到的,为了解决这个问题,我们必须在Tank类中设置两个变量oldX和oldY,用来记录坦克移动之前的坐标,在移动之后使用这两个值擦掉“尾巴”,具体如例10-4所示。修改Tank类,使坦克移动后不留下轨迹importjava.awt.*;publicclassTank{staticGraphicsg;

intx=100,y=100,dir=0,radius=20;

int

oldX,oldY;//保存移动前的坐标

publicTank(int

x,inty){this.x=x;this.y=y;}publicvoidmove(int

moveDir){oldX=x;oldY=y;

switch(moveDir){case0:x=x-5;break;//0表示左

case1:y=y-5;break;//1表示上

case2:x=x+5;break;//2表示右

case3:y=y+5;break;//3表示下

}draw();}

publicvoiddraw(){//擦除移动前的图形

g.setColor(Color.white);g.fillRect(oldX-20,oldY-20,40,40);

g.setColor(Color.blue);g.fillOval(x-20,y-20,40,40);

g.setColor(Color.red);

switch(dir){case0:g.drawLine(x,y,x-20,y);break;case1:g.drawLine(x,y,x,y-20);break;case2:g.drawLine(x+20,y,x,y);break;case3:g.drawLine(x,y,x,y+20);break;}}//坦克的射击方法

publicvoidshoot(){}}子弹射击的面向对象实现Tank类中的shoot()方法是坦克射击的方法,坦克射击的动作会产生一颗子弹,所以必须在实现子弹类后再来讨论这个方法的实现。右表列出了子弹类Bullet的属性和方法

Bullet类的属性子弹圆心坐标(x,y)移动前的圆心坐标(oldX,oldY)子弹方向dir子弹半径radius是否可以移动canMove绘图对象gBullet类的方法子弹移动move()绘图方法draw()子弹自动移动go()Bullet类的代码importjava.awt.*;publicclassBullet{staticGraphicsg;

int

x,y,dir=0,radius=5;

int

oldX,oldY;//保存移动前的坐标

boolean

canMove=true;publicBullet(int

x,int

y,intdir){this.x=x;this.y=y;this.dir=dir;}publicvoidmove(int

moveDir){oldX=x;oldY=y;

switch(moveDir){case0:x=x-5;break;//0表示左

case1:y=y-5;break;//1表示上

case2:x=x+5;break;//2表示右

case3:y=y+5;break;//3表示下

}draw();}

publicvoiddraw(){//擦除移动前的图形

g.setColor(Color.white);g.fillRect(oldX-5,oldY-5,10,10);

if(canMove){g.setColor(Color.red);g.fillOval(x-5,y-5,10,10);}}publicvoidgo(){}}Bullet类的说明Bullet类与Tank类的不同之处在于Bullet没有shoot()方法子弹的半径要比坦克的半径小,颜色是红色的Bullet多了一个布尔变量canMove,该对象的作用是判断子弹是否已经消失,因为子弹击中目标或者移出边界以后,就可以宣告子弹结束了生命周期了,当canMove是true时,子弹还在移动中否则,子弹已经“死亡”Bullet类的说明子弹的产生是由坦克决定的,当我们按下键盘的某个键时候,就会调用坦克的shoot()方法,控制坦克发炮,然后产生一个子弹,子弹自动向前移动。我们设定按下“K”键的时候发射一颗子弹,需要对GameCanva做相应改动。坦克类的shoot()方法按照简单的设想,shoot()方法的流程应该如下:第一步:产生一个Bullet对象;第二步:调用Bullet对象的go()方法,让子弹自动移动。根据这个设想来实现Tank类的shoot()方法。shoot()方法的代码publicvoidshoot(){ Bulletb=null;

switch(dir) { case0:b=newBullet(x-25,y,dir);break;//左

case1:b=newBullet(x,y-25,dir);break;//上

case2:b=newBullet(x+25,y,dir);break;//右

case3:b=newBullet(x,y+25,dir);break;//下

}

//让自己go出去,自生自灭吧

b.go();}子弹移动go()方法关键的逻辑就在于go()方法了,go()方法是子弹自动移动的方法,涉及到线程机制,应该创建子弹移动线程,在这个线程中调用move()方法定时移动,这个线程类的名字是BulletMovement子弹移动类publicclassBull

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论