为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

java坦克大战游戏详细设计说明

2017-09-01 29页 doc 76KB 56阅读

用户头像

is_212655

暂无简介

举报
java坦克大战游戏详细设计说明java坦克大战游戏详细设计说明 单机版坦克大战游戏系统 —详细设计 目录 1.引言„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 1.1 编写目的„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 1.2 项目背景„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 1.3 定义„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 1.4 参考资料„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 2.总体设计„„„„„„„„„„„„„„„„„„„„„„„...
java坦克大战游戏详细设计说明
java坦克大战游戏详细设计说明 单机版坦克大战游戏系统 —详细设计 目录 1.引言„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 1.1 编写目的„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 1.2 项目背景„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 1.3 定义„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 1.4 参考资料„„„„„„„„„„„„„„„„„„„„„„„„„„„„2 2.总体设计„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„3 2.1需求概述„„„„„„„„„„„„„„„„„„„„„„„„„„„„3 3.程序描述„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„4 3.1 程序逻辑„„„„„„„„„„„„„„„„„„„„„„„„„„„„4 3.1.1 主类模块„„„„„„„„„„„„„„„„„„„„„„„„„4 3.1.2 坦克类模块„„„„„„„„„„„„„„„„„„„„„„„„4 3.1.3 子弹类模块„„„„„„„„„„„„„„„„„„„„„„„„12 3.1.4 爆炸类模块„„„„„„„„„„„„„„„„„„„„„„„„14 3.1.5 墙类模块„„„„„„„„„„„„„„„„„„„„„„„„„16 3.1.6 血块类模块„„„„„„„„„„„„„„„„„„„„„„„„16 3.3 存储分配„„„„„„„„„„„„„„„„„„„„„„„„„„„17 3.4 限制条件„„„„„„„„„„„„„„„„„„„„„„„„„„„18 3.5 测试要点„„„„„„„„„„„„„„„„„„„„„„„„„„„18 - 1 - 1(引言 随着社会的进步,现在人们工作的压力越来越大,休息的时候很少,为了让疲惫的心灵得以休息,开发了坦克大战的小游戏来让玩家轻松一会,该游戏操作十分简单,只要操作键盘上的方向键按住攻击键就可以玩该游戏,轻松享受玩游戏的喜悦,可操作性好,而且不会使玩家沉溺于该游戏,对玩家的学习和工作都起积极的作用。 1.1编写目的 为明确软件需求、安排项目规划与进度、组织软件开发与测试,撰写本文档。 本文档供项目经理、设计人员、开发人员参考。 1.2项目背景 a. 项目名称:坦克大战游戏开发 b. 产品用户:对该游戏感兴趣的玩家 c. 项目和系统的关系:本项目旨在编写出一个操作简单但可玩性良好的小游戏来让玩家放松一下心情,对系统硬件配置低。实现简单。 1.3定义 持有对方的引用:在一个类里面有一个成员变量是另一个类的对象,这个对象相对于这个类来说就是持有了另一个类的引用,通过这个对象作成员变量可以引用对象这个类的成员变量和成员方法。 内部类:写在一个类内部的类是内部类,内部类封装在类的内部,不能被其他的外部类直接访问,起到保护作用,但要写的简短。 1.4参考资料 《Java基础知识详解》 《Java游戏开发》等。 - 2 - 2.总体设计 2.1需求概述 游戏包括的范围:本游戏包括主类、坦克类、子弹类、爆炸类、墙类、血块类。 要求游戏能有效、快速、安全、可靠和无误的完成上述操作。并要求客户端 的界面要简单明了、易于操作,服务器程序利于维护。 需求 模块 产生游戏的屏幕 主类模块 将坦克大战的过程呈现在屏幕上 画出坦克 控制坦克的移动并让坦克可以攻 击 坦克类模块 让坦克不可以穿越墙或别的坦克 添加坦克的图片 画出子弹 控制子弹的移动 详细查看员工信息 子弹类模块 让子弹不可以穿墙 添加子弹的图片 添加培训信息 画出爆炸的过程 爆炸类模块 控制坦克的爆炸 添加爆炸的图片 画出墙 墙类模块 实现墙的功能 画出血块 让血块围绕着固定的轨迹移动 血块类模块 实现血块的功能 - 3 - 3.程序描述 3.1程序逻辑 3.1.1 主类模块 主类是要画出屏幕,并且要将坦克之间打斗的全过程都呈现出来的,所以要先产生一个窗口,窗口产生之后应该要不停的刷新,否则屏幕会定格成画面,用多线程来控制刷新的频率,如果此时屏幕出现闪屏现象,应该用双缓冲机制来画出屏幕。双缓冲机制是通过虚拟出一张图片,将屏幕画在这张虚拟的图片上,再将这张虚拟的图片呈现在屏幕上。 调用的方法如下: public void update(Graphics g){ if(offScreenImage==null){ offScreenImage=this.createImage(GAME_WIDTH,GAME_HEIGHT); } Graphics gOffScreen=offScreenImage.getGraphics(); Color c=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); } 用多线程来控制屏幕刷新的频率的方法如下: private class PaintThread implements Runnable{ public void run(){ while(true){ try { repaint(); Thread.sleep((int)Math.random()*200); } catch (InterruptedException e) { e.printStackTrace(); } } } } 控制其他模块的操作都是在主类中调用其他类的方法即可。 3.1.2 坦克类模块 该类实现在屏幕上画出坦克,并控制坦克的移动,让坦克可以发射炮弹打对方等功能。 - 4 - 画出坦克的方法如下: public void draw(Graphics g){ Color c=g.getColor(); if(good)g.setColor(Color.RED); else g.setColor(Color.BLUE); g.fillOval(x, y, WIDTH, HEIGHT); g.setColor(c); move(); switch(ptDir){ case L: g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x, y+Tank.HEIGHT/2); break; case LU: g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x, y); break; case LD: g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x, y+Tank.HEIGHT); break; case R: g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH, y+Tank.HEIGHT/2); break; case RU: g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH, y); break; case RD: g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH, y+Tank.HEIGHT); break; case U: g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH/2, y); break; case D: g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH/2, y+Tank.HEIGHT); break; } } - 5 - 该方法里实现了一个move方法,可以将坦克的移动都画出来,坦克的move方法如下: public void move(){ switch(dir){ case L: x-=XSPEED; break; case LU: x-=XSPEED; y-=YSPEED; break; case LD: x-=XSPEED; y+=XSPEED; break; case R: x+=XSPEED; break; case RU: x+=XSPEED; y-=YSPEED; break; case RD: x+=XSPEED; y+=YSPEED; break; case U: y-=YSPEED; break; case D: y+=YSPEED; break; case STOP: break; } if(dir!=Direction.STOP){ this.ptDir=dir; } if(x<0) x=0; if(y<30) y=30; if(x+Tank.WIDTH>tc.GAME_WIDTH) x = tc.GAME_WIDTH-Tank.WIDTH; if(y+Tank.HEIGHT>tc.GAME_HEIGHT) y = tc.GAME_HEIGHT-Tank.HEIGHT; - 6 - if(!good){ Direction[] dirs = Direction.values(); if(step==0){ step = r.nextInt(12)+3; int rn = r.nextInt(dirs.length); dir = dirs[rn]; } if(r.nextInt(40)>38) fire(); step--; } } 这里就涉及了随机数的概念了,用随机数来控制敌军坦克在屏幕上移动的频率,让敌军坦克显得 更加的智能一些,让我军坦克无法预料敌军运动的轨迹,从而增添可玩性。 对按键的处理也是很讲究的,应该是按下某个键或抬起某个键的时候激发事件,而不应该是按下 某个键就一直激发事件,让坦克不停的移动或者开火。实现激发按键事件的代码如下: public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); switch(key){ case KeyEvent.VK_CONTROL: fire(); break; case KeyEvent.VK_LEFT: BL=true; break; case KeyEvent.VK_RIGHT: BR=true; break; case KeyEvent.VK_UP: BU=true; break; case KeyEvent.VK_DOWN: BD=true; break; } locateDirection(); } public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); switch(key){ - 7 - case KeyEvent.VK_LEFT: BL=false; break; case KeyEvent.VK_RIGHT: BR=false; break; case KeyEvent.VK_UP: BU=false; break; case KeyEvent.VK_DOWN: BD=false; break; } locateDirection(); } public void locateDirection(){ if(BL&&!BU&&!BR&&!BD) dir = Direction.L; else if(BL&&!BU&&!BR&&BD) dir = Direction.LD; else if(BL&&BU&&!BR&&!BD) dir = Direction.LU; else if(!BL&&!BU&&BR&&!BD) dir = Direction.R; else if(!BL&&BU&&BR&&!BD) dir = Direction.RU; else if(!BL&&!BU&&BR&&BD) dir = Direction.RD; else if(!BL&&BU&&!BR&&!BD) dir = Direction.U; else if(!BL&&!BU&&!BR&&BD) dir = Direction.D; else if(!BL&&!BU&&!BR&&!BD) dir = Direction.STOP; } 以上代码实现了按下键的时候激发事件,抬起键的时候不激发事件,这样就可以控制坦克的移动 方向和发射炮弹要不停的按键才能转换了。 坦克发射炮弹应该在坦克的中心位置开始发射的,不应该是在坦克的左边或是右边还是在后边,这些地方都不合适,实现坦克的发射的代码如下: public Missile fire() { if (!live) return null; int x = this.x + Tank.WIDTH / 2 - Missile.WIDTH / 2; int y = this.y + Tank.HEIGHT / 2 - Missile.HEIGHT / 2; Missile m = new Missile(x, y, good, ptDir, this.tc); tc.missiles.add(m); return m; } 当然为了增添游戏的好玩性也可以让我军坦克实现向八个方向同时开火,这个方法的代码如 下: public Missile fire(Direction dir) { if (!live) - 8 - return null; int x = this.x + Tank.WIDTH / 2 - Missile.WIDTH / 2; int y = this.y + Tank.HEIGHT / 2 - Missile.HEIGHT / 2; Missile m = new Missile(x, y, good, dir, this.tc); tc.missiles.add(m); return m; } 这个方法实现的很简单,只是重载了以上的单方向开火方法,这个方法传递了一个方向,通过这个方向实现向八个方向同时开火。代码如下: private void superFire() { Direction[] dirs = Direction.values(); for (int i = 0; i < 8; i++) { fire(dirs[i]); } } 坦克不可以从墙上穿过去,也不可以从别的坦克身上轧过去,所以就涉及到了碰撞检测的问题,那怎样可以进行碰撞检测呢,可以用一个矩形框将两个要相撞的物体包住,如果两个矩形相撞则判定为相撞了。实现方法如下: public Rectangle getRect() { return new Rectangle(x, y, WIDTH, HEIGHT); } 两个物体都被矩形包住之后,如何相撞呢,下面是坦克与墙相撞的代码: public boolean collidesWithWall(Wall w) { if (this.live && this.getRect().intersects(w.getRect())) { this.stay(); return true; } return false; } Stay方法是让坦克一旦与墙壁发生碰撞的时候,让坦克返回碰撞前的地方,重新移动一次,方法如下: private void stay() { x = oldX; y = oldY; } 当坦克与坦克之间发生碰撞时,分为我军坦克与敌军坦克相撞和敌军坦克之间的相撞。代码如下: public boolean collidesWithTank(Tank t) { if (this != t) { if (this.live && t.isLive() && this.getRect().intersects(t.getRect())) { this.stay(); t.stay(); return true; - 9 - } } return false; } public boolean collidesWithTanks(List tanks) { for (int i = 0; i < tanks.size(); i++) { if (collidesWithTank(tanks.get(i))) { return true; } } return false; } 坦克类换上了图片的代码是要通过工具包来加载图片,将图片加载到内存上。代码如下: private static Toolkit tk=Toolkit.getDefaultToolkit(); private static Image[]tankImages=null; private static Map imgs =new HashMap(); static{ tankImages=new Image[]{ tk.getImage(Tank.class.getClassLoader().getResource("images/tankL.gif")), tk.getImage(Tank.class.getClassLoader().getResource("images/tankLU.gif")), tk.getImage(Tank.class.getClassLoader().getResource("images/tankLD.gif")), tk.getImage(Tank.class.getClassLoader().getResource("images/tankR.gif")), tk.getImage(Tank.class.getClassLoader().getResource("images/tankRU.gif")), tk.getImage(Tank.class.getClassLoader().getResource("images/tankRD.gif")), tk.getImage(Tank.class.getClassLoader().getResource("images/tankU.gif")), tk.getImage(Tank.class.getClassLoader().getResource("images/tankD.gif")) - 10 - }; imgs.put("L", tankImages[0]); imgs.put("LU", tankImages[1]); imgs.put("LD", tankImages[2]); imgs.put("R", tankImages[3]); imgs.put("RU", tankImages[4]); imgs.put("RD", tankImages[5]); imgs.put("U", tankImages[6]); imgs.put("D", tankImages[7]); } 之后draw方法也需要重写,代码如下: public void draw(Graphics g) { if(!live){ if(!good){ tc.tanks.remove(this); } return; } if(good) bb.draw(g); switch(ptDir){ case L: g.drawImage(imgs.get("L"),x,y,null); break; case LU: g.drawImage(imgs.get("LU"),x,y,null); break; case LD: g.drawImage(imgs.get("LD"),x,y,null); break; case R: g.drawImage(imgs.get("R"),x,y,null); break; case RU: g.drawImage(imgs.get("RU"),x,y,null); break; case RD: g.drawImage(imgs.get("RD"),x,y,null); break; case U: g.drawImage(imgs.get("U"),x,y,null); break; case D: - 11 - g.drawImage(imgs.get("D"),x,y,null); break; } move(); } 3.1.3 子弹类模块 该类实现在屏幕上画出子弹和子弹的移动轨迹以及实现了坦克攻击墙壁与攻击敌方坦 克的功能。 在屏幕上画出坦克的代码如下: public void draw(Graphics g) { if(!live) { tc.missiles.remove(this); return; } Color c = g.getColor(); g.setColor(Color.BLACK); g.fillOval(x, y, WIDTH, HEIGHT); g.setColor(c); move(); } 里面有一个move方法,与前面的坦克类相似,都是画出物体移动的轨迹,这里是画出子弹在屏 幕上移动的轨迹。代码如下: private void move() { switch(dir) { case L: x -= XSPEED; break; case LU: x -= XSPEED; y -= YSPEED; break; case U: y -= YSPEED; break; case RU: x += XSPEED; - 12 - y -= YSPEED; break; case R: x += XSPEED; break; case RD: x += XSPEED; y += YSPEED; break; case D: y += YSPEED; break; case LD: x -= XSPEED; y += YSPEED; break; case STOP: break; } if(x < 0 || y < 0 || x > TankClient.GAME_WIDTH || y > TankClient.GAME_HEIGHT) { live = false;//如果子弹超出边界,则定义子弹已经死掉了。 } } 子弹击中了墙壁之后的代码如下: public boolean hitWall(Wall w) { if(this.live && this.getRect().intersects(w.getRect())) { this.live = false; return true; } return false; } 以上代码当子弹击中了墙壁之后即让子弹消失掉,然而当子弹击中了敌军坦克或是敌军坦克击中 了我军坦克之后会怎样了呢,代码如下: public boolean hitTank(Tank t) { if(this.live && this.getRect().intersects(t.getRect()) && t.isLive() && this.good != t.isGood()) { if(t.isGood()) { t.setLife(t.getLife()-20); if(t.getLife() <= 0) t.setLive(false); } else { t.setLive(false); } - 13 - this.live = false; Explode e = new Explode(x, y, tc); tc.explodes.add(e); return true; } return false; } public boolean hitTanks(List tanks) { for(int i=0; i知识点
还是很多的。 - 17 - 上图就是加载了图片之后的坦克大战游戏的演示图,这样显得比原先的图片要美观一些。 3.4限制条件 暂无 3.5测试要点 在设计的好的软件系统中,每个模块完成一个清晰定义的子功能,而且这个子功能和同级其他模块的功能之间没有相互依赖关系,因此,有可能把每个模块作为一个独立的实体来测试,而且通常比较容易设计检验模块正确性的测试。 1、 所有测试都应该能追溯到用户需求。 2、 应该远在测试开始之前就制定出测试。 3、 应该从“小规模”测试开始。 4、 穷举测试是不可能的 5、 为了达到最佳的测试效果,应该由独立的第三方从事测试工作。 6、 各模块的页面显示是否正常。 7、 界面的图片显示是否正常。 - 18 -
/
本文档为【java坦克大战游戏详细设计说明】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索