1.课程设计的目的
随着手机的日益普及,java功能在移动设备上的实现及java应用程序产生的影响力,对丰富人们的生活内容,提供便捷的咨询起着不可忽视的作用。本项目介绍了坦克大战的基本构建方法、java的相关技术及本程序的结构分析和具体功能的实现。游戏是在Eclipse3.2环境下编程。本项目重点运用了图形化用户界面GUI,Thread多线程的有关知识,其中涉及了绘图工具的运用,事件处理操作以及图形的碰撞检测等知识点。通过此课程设计,使学生巩固所学知识、培养学生动手能力,了解Java的面向对象的体系结构。学生用Java语言设计一个完整的应用程序,综合应用所学知识完成软件的分析、设计、调试和总结,提高学生对Java语言的综合应用能力和解决问题的能力。 2.设计方案论证 2.1设计思路
本项目介绍了坦克大战的基本构建方法、java的相关技术及本程序的结构分析和具体功能的实现。游戏是在Eclipse3.2环境下编程。
一、游戏基本元素: 二、它的主要功能:
(1)能够朝四个方向移动:上、下、左、右键。
(2) 按下鼠标左键发射普通子弹;按下鼠标右键发射散弹;子
弹爆炸的效果,普通子弹和炮弹的效果 (3)敌人能够移动
坦克,炮管,子弹, 墙壁,地雷
(4)能够模拟爆炸 (5)能够产生障碍 (6)能够增长生命
玩家控制主坦克(上方有血条的)的移动以及炮弹的发射。若玩家将敌方坦克全部打掉则玩家胜;若期间由玩家控制的主坦克被打掉则视为玩家失败。游戏中只有普通墙作为障碍物,玩家无法穿越它们并且普通子弹不能将墙打穿
;但是玩家可以用炮弹将普通墙打掉。桃心可以将坦克的血加满。
2.2简要的设计流程:
游戏开始刷屏(间接调用paint)延迟25ms初始化游戏元素键盘判断按下的是那个键paint()根据游戏元素的属性,对其经行操作和绘出其图形改变相应游戏元素的属性战斗是否结束
2.2设计方法
2.2.1构建游戏主类
在主类中构造一个主Frame框架,设置它的大小和位置,并将其显示。在主类中编写一段代码,构造一个窗口。并添加窗口关闭的处理事件,将窗口设置成打小不可变。 主要代码如下:
this.addWindowListener(new WindowAdapter() {
2.2.2构建坦克类Tank
构造主窗口中所需要的Tank类,并将坦克加到窗口中,实现坦克的四个方向的移动
创建一个坦克类,用画图工具构造出简单的图形代表坦克,并将坦克加入到主窗口当中。 主要代码如下:
abstract class Tank { boolean init=false; //第一次画时将图片载入内存 static final Toolkit TLK=Toolkit.getDefaultToolkit(); //用来将图片读入Image数组 public static Image[] turretImg={ TLK.getImage(Tank.class.getClassLoader().getResource(\"Image/Tank/turret1.png\")), TLK.getImage(Tank.class.getClassLoader().getResource(\"Image/Tank/turret2.png\"))}; BufferedImage bTurretImg=null;
}
public void windowClosing(WindowEvent e) { System.exit(0);
});
this.setResizable(false);
数
Graphics2D g2=null;
AffineTransform trans=new AffineTransform();
public static final int SHOTSCOUNT=5; //同时可发射的子弹int shotsCount=0; //已经发射的子弹数
public static final int TANKSPEED=5; //Tank移动速度 public static final int TANKWIDTH=36; //Tank的尺寸 public static final int TANKHEIGHT=38;
public static enum TANK_DIR {U,D,L,R,STOP}; TANK_DIR tankDir; //Tank主体的方向 TANK_DIR moveDir; //Tank的运动方向 boolean camp; //Tank的阵营
boolean isNPC; //是否是有电脑控制的机器人Tank boolean isLive=true; //Tank是否存活
int x,y; //Tank主体的中心点坐标 int oldx,oldy; //存储Tank前一步的坐标
int turretDirx, turretDiry; //大炮端点的坐标
public static final int TURRETLENGTH=30; //炮筒的长度
double oldAngel=0; double nowAngel; double turnAngel;
TankClient tc=null; //主界面类的引用 Bomb tankBomb=null;
HitPoint tankHitPoint; //Tank的生命值
static Random rn=new Random(); //随机数发生器
让坦克朝四个方向运动起来,在主类TankClient中启用多线程机制,让系统不断的进行重画。
class RepaintThread implements Runnable //画面重画线程 { public void run() { while(repaintFlag) { try
{ repaint(); ut.move(); //Tank定时移动 Shot tcShots=null; for(int i=0;i { if(0==count) //电脑Tank全灭后重新加几辆 { //RobotTank.add(1,false,RobotTank.RTANKTYPE.BOSS,tc); RobotTank.add(2,false,RobotTank.RTANKTYPE.SPE,tc); } try { count=0; for(int i=0;i 调用Tank类中的方法: class TankMoveLis extends KeyAdapter //玩家Tank按键监听者 { public void keyPressed(KeyEvent e) { if(ut.isLive) { ut.keyDispose(e.getKeyCode(),true); } } public void keyReleased(KeyEvent e) { if(ut.isLive) { ut.keyDispose(e.getKeyCode(),false); } else { if(e.getKeyCode()==KeyEvent.VK_F2) { ut.rebirth(); //复活 } } } } class MouseMoveLis extends MouseMotionAdapter 移动监听者 { public void mouseMoved(MouseEvent e) { //鼠标 if(ut.isLive) { mousePoint=e.getPoint(); ut.setTurretDir(mousePoint); //根据鼠标位置更新炮筒方向 } } } 在Tank类当中添加的按键方法,代码如下 public void keyDispose(int Key,boolean b) //对用户按键的处理 { if(b) //有键按下 { switch(Key) { case KeyEvent.VK_UP: case KeyEvent.VK_W: { keyList.remove(TANK_DIR.U); keyList.add(TANK_DIR.U); }break; case KeyEvent.VK_DOWN: case KeyEvent.VK_S: { keyList.remove(TANK_DIR.D); keyList.add(TANK_DIR.D); }break; case KeyEvent.VK_LEFT: case KeyEvent.VK_A: { keyList.remove(TANK_DIR.L); keyList.add(TANK_DIR.L); }break; case KeyEvent.VK_RIGHT: case KeyEvent.VK_D: { keyList.remove(TANK_DIR.R); keyList.add(TANK_DIR.R); }break; case KeyEvent.VK_SPACE: { this.superFire(); }break; default:break; } } else //有键抬起 { switch(Key) { case KeyEvent.VK_UP: case KeyEvent.VK_W:{ keyList.remove(TANK_DIR.U); }break; case KeyEvent.VK_DOWN: case KeyEvent.VK_S:{ keyList.remove(TANK_DIR.D); }break; case KeyEvent.VK_LEFT: case KeyEvent.VK_A:{ keyList.remove(TANK_DIR.L); }break; case KeyEvent.VK_RIGHT: case KeyEvent.VK_D:{ keyList.remove(TANK_DIR.R); }break; default:break; } } if(keyList.size()==0) { keyList.add(TANK_DIR.STOP); } super.setMoveDir(keyList.get(keyList.size()-1)); } 2.2.3添加炮弹Shot类 在Shot类当中添加x,y,dir等属性以及常量。在Shot类当中添加构造方法,draw方法等必要方法。根据不同的方向, 子弹要进行不同的运动。在TankClient当中new一颗子弹出来。 public void draw(Graphics g) { if(isLive) { g.drawImage(HYDRASHOT,sx-shotRadius,sy-shotRadius,null); } else { if(isBomb&&shotBomb!=null) { shotBomb.draw(g); } } } void draw(Graphics g) { if(isLive) { g.drawImage(SUPERSHOT,sx-shotRadius,sy-shotRadius,null); } else { if(isBomb&&shotBomb!=null) { shotBomb.draw(g); } } } 2.2.4实现坦克的互相攻击 (1)让主战坦克打出炮弹在Tank类当中增加对空格键的处理,使每按下空格键的时候,坦克打出一发炮弹。 2)根据“坦克打出炮弹”这句话,确定Tank当中的fire方法。 publicShot fire() { „„ Shot m = new Shot(x, y, ptDir); 3)为了解决坦克停下来也能开火的问题——给坦克加一炮筒,根据炮筒方向和 位置设定子弹的方向和位置并new出来,然后返回。每次move之后根据Tank 的新方向确定炮筒的方向。 if(this.dir != Direction.STOP) { } 4)为了能够打出多发炮弹,使用容器填装多发炮弹,每当抬起空格键的时候就往 容器中加入新的炮弹 List 5)解决炮弹不消亡的问题,加入控制炮弹生死的量live(Shot),当炮弹已经死去就不需要对其重画,当炮弹飞出边界就死亡,当炮弹死亡就从容器中移去。 public void dead() { if(isLive) { this.isLive=false; this.ptDir = this.dir; } return m; if(isBomb) { shotBomb=new ShotBomb(sx-32,sy-32,this); } //当撞到墙或Tank时子弹才爆炸 else { this.tc.shotsList.remove(this); //将子弹从List中移除 } } } void move() { if(isLive) { sx+=lengthX; sy+=lengthY; if(isOutOfWindow()||isHitTank()) { this.dead(); } } } (2)实现坦克的互相开火 1)在TankClient中new出敌人并画出 public static void main(String[] args) { TankClient tc=new TankClient(); tc.lunchFrame(); } 2)在Shot中加入isHitTank()方法,返回布尔类型 public boolean isHitTank() //检查炮弹是否击中Tank { Tank tempTk=null; for(int i=0;i public void hitDispose() { Tank tempTank; for(int i=0;i } { case U: case D:{y=oldy;}break; case L: case R:{x=oldx;}break; default:break; } this.setMoveDir(TANK_DIR.STOP); if(camp!=tempTank.camp) //碰到不同阵营的{ } tempTank.tankHitPoint.cutsHitPoint(1); this.tankHitPoint.cutsHitPoint(1); 4)增加控制坦克生死的Boolean量live,如果live为false就不画了。当炮弹击中敌人坦克时,坦克,子弹也死去。 public boolean hitTank(Tank t) { if(this.getRect().intersects(t.getRect()) && t.isLive()) { } return false; t.setLive(false); this.live = false; return true; } 2.2.5创建Item类 (1)创建HitPointerItem子类,作为为tank加血的道具,构造函数eat(Tank tk)加血 void eat(Tank tk) { tk.tankHitPoint.raisesHitPoint(raisesNum); //Tank涨血 tc.itemList.remove(this); } 2)创建ShotsItem子类,作为涨炮弹的道具。涨炮弹的构造函数为: void draw(Graphics g) { Color c=g.getColor(); g.setColor(Color.orange); g.fillOval(x,y,width,height); g.setColor(c); } } } 2.2.8添加障碍物 1)添加普通墙 private void creat() { for(int i=0;i 2)普通子弹可以穿墙 public boolean isHits(Shot s) //普通子弹可以破坏墙 { WallNode wn=null; for(int i=0;i 4.设计体会 通过这次课程设计,通过此课程设计,初步了解了java面向对象的特点,掌握了Java的许多基本知识,提升了自己的动手能力。使我对JAVA这门课又做了一次系统的复习,对各个知识点也都有了更深刻的理解,让我掌握的更扎实,掌握JAVA的应用、编写、上机调试的基本方法,同时也增强了实际操作能力,了解了学生信息管理系统的工作流程以及工作模式,程序开发过程中涉及到了数据库的相关知识,使我对数据库的使用也更加的熟练,另一方面也对编程语言有了新的认识,为以后的学习打下了基础。 本项目要学会图形化用户界面的构建,并且本项目用到了多线程Thread的知识。通过启用多线程机制,不断调用java.awt.*中的paint(Graphics g)方法,将画面构造出来。其中要使用双缓冲消 除闪烁现象。程序中还使用了键盘类KeyMonitor实现坦克的控制操作。碰撞检测的辅助类Rectangle可以完成坦克之间,以及坦克与障碍物之间的碰撞检测。初步了解反射,知道对于classloader, 每一个.class实际就是一个Class对象。学会使用Toolkit类,并使用该类加载得到图片。学会使用Random类,并使用其中的nextInt()方法得到随机数。利用了容器类往里添加对象。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 7swz.com 版权所有 赣ICP备2024042798号-8
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务