JAVA坦克大战课程设计.docx
《JAVA坦克大战课程设计.docx》由会员分享,可在线阅读,更多相关《JAVA坦克大战课程设计.docx(30页珍藏版)》请在冰豆网上搜索。
JAVA坦克大战课程设计
JAVA坦克大战课程设计实验报告
专业班级:
计算机
学号:
201110000
姓名:
指导老师:
JAVA坦克大战课程设计
一、课程设计目的
Java坦克大战程序设计的课程程序设计是我们学习完Java语言程序设计课程后,进行的一次全面的综合设计,其目的是加深对理论教学内容的理解和掌握,使学生综合运用.学知识,利用软件工程为基础进行软件开发、并在实践应用方面打下基础。
二、课程设计的预备知识和实验环境
熟悉Java语言以及eclipse开发工具,实验环境为JDK1.6。
三、课程设计的主要内容
坦克大战游戏是在eclipse环境下编程的游戏,其中包括对主坦克的编写、坦克的初始位置的编写、坦克移动方向的编写、坦克的速度的编写、坦克子弹速度的编写、敌对坦克子弹速度的编写、敌对坦克的编写等等。
游戏主要实现的功能有:
1.能够四处移动
2.能够打击敌人
3.敌人能够移动
4.能够模拟爆炸
5.能够产生障碍
6.能够增长生命
四、程序具体设计
1.版本0.1~0.2
实现的主要功能:
产生一个不能修改大小的窗体,并实现关闭窗体的事件处理。
源代码如下:
2.版本0.3~0.5
实现的主要功能:
画出代表坦克的同心圆;让坦克运动起来;使用双缓冲来消除坦克移动时的闪烁现象;利用代码重构将以后可能需要多处修改的量定义为常量,例如窗体的宽度和高度(常量名一般为大写)主要代码如下:
publicclassTankClientextendsFrame{
intx=50,y=50;
publicvoidpaint(Graphicsg){
Colorc=g.getColor();
g.setColor(Color.RED);
g.fillOval(x,y,30,30);
g.setColor(c);
y+=5;
}
使用paint方法来画出坦克,并将坦克的位置设置成变量来实现坦克的移动。
publicvoidlauchFrame(){
this.setLocation(400,300);
this.setSize(800,600);
this.setTitle("TankWar");
this.addWindowListener(newWindowAdapter(){
publicvoidwindowClosing(WindowEvente){
System.exit(0);
}
this.setResizable(false);
this.setBackground(Color.GREEN);
setVisible(true);
newThread(newPaintThread()).start();
}
publicstaticvoidmain(String[]args){
TankClienttc=newTankClient();
tc.lauchFrame();
}
privateclassPaintThreadimplementsRunnable{
publicvoidrun(){
while(true){
repaint();
try{
Thread.sleep(100);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
使用update来实现双缓冲结局移动时的闪烁问题
publicvoidupdate(Graphicsg){
if(offScreenImage==null){
offScreenImage=this.createImage(GAME_WIDTH,GAME_HEIGHT);
}
GraphicsgOffScreen=offScreenImage.getGraphics();
Colorc=gOffScreen.getColor();
gOffScreen.setColor(Color.GREEN);
gOffScreen.fillRect(0,0,GAME_WIDTH,GAME_HEIGHT);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage,0,0,null);
}
在lauchFrame方法中启动线程,来实现坦克的移动,并加入sleep方法使移动出现延时。
publicvoidlauchFrame(){
this.setLocation(400,300);
this.setSize(GAME_WIDTH,GAME_HEIGHT);
this.setTitle("TankWar");
this.addWindowListener(newWindowAdapter(){
publicvoidwindowClosing(WindowEvente){
System.exit(0);
}
});
this.setResizable(false);
this.setBackground(Color.GREEN);
this.addKeyListener(newKeyMonitor());
setVisible(true);
newThread(newPaintThread()).start();
}
publicstaticvoidmain(String[]args){
TankClienttc=newTankClient();
tc.lauchFrame();
}
classPaintThreadimplementsRunnable{
publicvoidrun(){
while(true){
repaint();
try{
Thread.sleep(50);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
使用publicstaticfinal定义窗体的大小使窗体的长度和宽度变为常量。
3.版本0.6
实现的主要功能:
添加键盘监听器类KeyMonitor,让坦克听从我们指挥,针对不同的键改变坦克的位置,与重画线程结合产生不同方向运动。
主要代码如下:
privateclassKeyMonitorextendsKeyAdapter{
publicvoidkeyPressed(KeyEvente){
intkey=e.getKeyCode();
switch(key){
caseKeyEvent.VK_LEFT:
x-=5;
break;
caseKeyEvent.VK_UP:
y-=5;
break;
caseKeyEvent.VK_RIGHT:
x+=5;
break;
caseKeyEvent.VK_DOWN:
y+=5;
break;
}
4.版本0.7
实现的主要功能:
将坦克单独包装成类。
建立Tank类;为Tank类添加成员变量xy;添加draw方法,使Tank类独立控制自己的画法;添加Tank类处理按键的方法;根据Tank类修改TankClient类。
主要代码如下:
建立tank类:
publicclassTank{
intx,y;
publicTank(intx,inty){
this.x=x;
this.y=y;
}
publicvoiddraw(Graphicsg){
Colorc=g.getColor();
g.setColor(Color.RED);
g.fillOval(x,y,30,30);
g.setColor(c);
}
cvoidkeyPressed(KeyEvente){
intkey=e.getKeyCode();
switch(key){
caseKeyEvent.VK_LEFT:
x-=5;
break;
caseKeyEvent.VK_UP:
y-=5;
break;
caseKeyEvent.VK_RIGHT:
x+=5;
break;
caseKeyEvent.VK_DOWN:
y+=5;
break;
}
5.版本0.8~0.9
实现的主要功能:
让坦克能够在八个方向移动。
使用枚举添加代表方向的量;添加纪录按键状态的布尔量;处理按键抬起的消息。
主要代码如下:
publicclassTank{
publicstaticfinalintXSPEED=5;
publicstaticfinalintYSPEED=5;
privateintx,y;
privatebooleanbL=false,bU=false,bR=false,bD=false;
enumDirection{L,LU,U,RU,R,RD,D,LD,STOP};
eDirectiondir=Direction.STOP;
publicTank(intx,inty){
this.x=x;
this.y=y;
}
publicvoiddraw(Graphicsg){
Colorc=g.getColor();
g.setColor(Color.RED);
g.fillOval(x,y,30,30);
g.setColor(c);
move();
}
利用move()方法实现坦克的坐标变化
voidmove(){
switch(dir){
caseL:
x-=XSPEED;
break;
caseLU:
x-=XSPEED;
y-=YSPEED;
break;
caseU:
y-=YSPEED;
break;
caseRU:
x+=XSPEED;
y-=YSPEED;
break;
caseR:
x+=XSPEED;
break;
caseRD:
x+=XSPEED;
y+=YSPEED;
break;
caseD:
y+=YSPEED;
break;
caseLD:
x-=XSPEED;
y+=YSPEED;
break;
caseSTOP:
break;
}
}
使用KeyPressed方法,监听键盘按下去的动作:
publicvoidkeyPressed(KeyEvente){
intkey=e.getKeyCode();
switch(key){
caseKeyEvent.VK_LEFT:
bL=true;
break;
caseKeyEvent.VK_UP:
bU=true;
break;
caseKeyEvent.VK_RIGHT:
bR=true;
break;
caseKeyEvent.VK_DOWN:
bD=true;
break;
}
locateDirection();
}
使用KeyReleased方法实现按键抬起时的动作:
publicvoidkeyPressed(KeyEvente){
intkey=e.getKeyCode();
switch(key){
caseKeyEvent.VK_LEFT:
bL=true;
break;
caseKeyEvent.VK_UP:
bU=true;
break;
caseKeyEvent.VK_RIGHT:
bR=true;
break;
caseKeyEvent.VK_DOWN:
bD=true;
break;
}
locateDirection();
}
判断坦克所朝的方向:
voidlocateDirection(){
if(bL&&!
bU&&!
bR&&!
bD)dir=Direction.L;
elseif(bL&&bU&&!
bR&&!
bD)dir=Direction.LU;
elseif(!
bL&&bU&&!
bR&&!
bD)dir=Direction.U;
elseif(!
bL&&bU&&bR&&!
bD)dir=Direction.RU;
elseif(!
bL&&!
bU&&bR&&!
bD)dir=Direction.R;
elseif(!
bL&&!
bU&&bR&&bD)dir=Direction.RD;
elseif(!
bL&&!
bU&&!
bR&&bD)dir=Direction.D;
elseif(bL&&!
bU&&!
bR&&bD)dir=Direction.LD;
elseif(!
bL&&!
bU&&!
bR&&!
bD)dir=Direction.STOP;
}
}
6.版本1.0~1.4
实现的主要功能:
添加子弹类;根据主坦克的方向和位置打出子弹;解决坦克停下也能打出炮弹的问题,画出炮筒;打出多发炮弹;解决炮弹不消亡的问题;解决坦克出界的问题。
主要代码有:
模仿tank类新建Missile类(子弹类):
mportjava.awt.*;
publicclassMissile{
publicstaticfinalintXSPEED=10;
publicstaticfinalintYSPEED=10;
publicstaticfinalintWIDTH=10;
publicstaticfinalintHEIGHT=10;
intx,y;
Tank.Directiondir;
publicMissile(intx,inty,Tank.Directiondir){
this.x=x;
this.y=y;
this.dir=dir;
}
publicvoiddraw(Graphicsg){
Colorc=g.getColor();
g.setColor(Color.BLACK);
g.fillOval(x,y,WIDTH,HEIGHT);
g.setColor(c);
move();
子弹的移动move()方法与tank类类似:
privatevoidmove(){
switch(dir){
caseL:
x-=XSPEED;
break;
caseLU:
x-=XSPEED;
y-=YSPEED;
break;
caseU:
y-=YSPEED;
break;
caseRU:
x+=XSPEED;
y-=YSPEED;
break;
caseR:
x+=XSPEED;
break;
caseRD:
x+=XSPEED;
y+=YSPEED;
break;
caseD:
y+=YSPEED;
break;
caseLD:
x-=XSPEED;
y+=YSPEED;
break;
}
利用ctrl键实现坦克发出子弹的动作:
publicvoidkeyReleased(KeyEvente){
intkey=e.getKeyCode();
switch(key){
caseKeyEvent.VK_LEFT:
bL=false;
break;
caseKeyEvent.VK_UP:
bU=false;
break;
caseKeyEvent.VK_RIGHT:
bR=false;
break;
caseKeyEvent.VK_DOWN:
bD=false;
break;
}
locateDirection();
}
Tank类中发出子弹的fire()方法:
publicMissilefire(){
intx=this.x+Tank.WIDTH/2-Missile.WIDTH/2;
inty=this.y+Tank.HEIGHT/2-Missile.HEIGHT/2;
Missilem=newMissile(x,y,dir);
returnm;
}
新增的方法,用于画出作为炮筒的直线:
publicvoiddraw(Graphicsg){
Colorc=g.getColor();
g.setColor(Color.RED);
g.fillOval(x,y,WIDTH,HEIGHT);
g.setColor(c);
switch(ptDir){
caseL:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x,y+Tank.HEIGHT/2);
break;
caseLU:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x,y);
break;
caseU:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x+Tank.WIDTH/2,y);
break;
caseRU:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x+Tank.WIDTH,y);
break;
caseR:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x+Tank.WIDTH,y+Tank.HEIGHT/2);
break;
caseRD:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x+Tank.WIDTH,y+Tank.HEIGHT);
break;
caseD:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x+Tank.WIDTH/2,y+Tank.HEIGHT);
break;
caseLD:
g.drawLine(x+Tank.WIDTH/2,y+Tank.HEIGHT/2,x,y+Tank.HEIGHT);
break;
}
move();
}
在move()方法中加入下段代码,为了协调炮筒与坦克的位置保持一致:
if(this.dir!
=Direction.STOP){
this.ptDir=this.dir;
}
在fire()方法中加入m对象,修改炮筒方向:
publicMissilefire(){
intx=this.x+Tank.WIDTH/2-Missile.WIDTH/2;
inty=this.y+Tank.HEIGHT/2-Missile.HEIGHT/2;
Missilem=newMissile(x,y,ptDir);
tc.missiles.add(m);
returnm;
在窗体指定位置显示子弹数量,以及通过循环发射一组子弹:
publicclassTankClientextendsFrame{
publicstaticfinalintGAME_WIDTH=800;
publicstaticfinalintGAME_HEIGHT=600;
TankmyTank=newTank(50,50,this);
Listmissiles=newArrayList();
ImageoffScreenImage=null;
publicvoidpaint(Graphicsg){
g.drawString("missilescount:
"+missiles.size(),10,50);
for(inti=0;iMissilem=missiles.get(i);
m.draw(g);
}
myTank.draw(g);
}
解决子弹的越界问题:
privatevoidmove(){
switch(dir){
caseL:
x-=XSPEED;
break;
caseLU:
x-=XSPEED;
y-=YSPEED;
break;
caseU:
y-=YSPEED;
break;
caseRU:
x+=XSPEED;
y-=YSPEED;
break;
caseR:
x+=XSPEED;
break;
ca