JAVA课程设计(坦克大战)
Posted Lemon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA课程设计(坦克大战)相关的知识,希望对你有一定的参考价值。
2019-01-16
坦克大战游戏背景:
1. 需求分析
1.1环境要求
操作系统:Windows 7(SP1)以上
JAVA虚拟机:JDK1.8以上
开发环境:Eclipse(4.5以上)
1.2角色设定
用户在系统中扮演的角色,以及可以执行的职责。
玩 家 操纵玩家坦克,与敌方坦克作战,同时保护本基地。敌方坦克随机移动,发射子弹。
1.3设定玩家(玩家一,玩家二,即一个人玩还是两个人玩),我方坦克的方向和子弹由用户控制,所有墙块都可以打碎,但是铁墙是打不碎的,草地不能阻止坦克和子弹的前进,河流能阻止坦克前进,但是不能阻止子弹前进。我方基地被毁则游戏结束,自己的坦克被毁游戏也结束,唯一赢得方式是消灭所有的敌方坦克,则可以进入下一关。一关比一关的难度大,通过地图来实现。
一·团队介绍
团队名称:阳光四人组
学号 | 班级 | 姓名 | 简介 |
201721123094 | 网络1714 | 何昕桐(组长) | 学习能力强,漂亮又可爱 |
201721123068 | 网络1713 | 梁琦珧 | 有思想,有能力,有担当 |
201721123093 | 网络1714 | 李志婷 | 有专研精神,刻苦,积极向上 |
201721123069 | 网络1713 | 陈慧琳 | 低调~ |
团员任务分配:
成员 | 任务 | 博客链接 |
何昕桐 | 坦克类 (电脑坦克类,玩家坦克类),代码整合 | https://www.cnblogs.com/hexintong99/p/10279072.html |
梁琦珧 | 枚举,子弹类,工具类 | https://www.cnblogs.com/liangqiyao/p/10275786.html |
李志婷 | GUI界面(游戏面板,登录面板,主窗体) | https://www.cnblogs.com/lizhiting/p/10275909.html |
陈慧琳 | 基地类,墙块类,爆炸效果类,地图类 | https://www.cnblogs.com/chenhuilin/p/10275855.html |
这个坦克游戏几位同志可是很辛苦啦!经过重重考虑,联网功能和游戏排行榜还是未成功实现:
时间太短,能力有限啊!
二·项目git
1.项目git地址
https://gitee.com/mayun126/TankWar.git
2.项目git提交记录截图
三·项目功能架构图与主要功能流程图
1.项目功能架构图
2.功能流程图
3.面向对象类设计图
Wall:
Visible:
乖乖献上了类图:
四·项目运行截图和屏幕录制
演示:
双人游戏和界面地图的设计是我们这个课设的特点:
1.游戏面板:绘制游戏界面,将所有游戏元素展现出来
2.显示关卡面板(第几关开始提示):登录面板和游戏面板的过渡界面,只有一个闪烁的动画效果
3.主窗体:整个面板最外层载体,一个800*600的窗体
4.登录面板:选择游戏模式是单人还是双人
五·项目关键代码
代码太多,主要列出了主要的类以及特色的功能代码,耐心看看,O(∩_∩)O哈哈~
玩家坦克类:
public class Tank extends VisibleImage{ GamePanel gamePanel; //游戏界面,提供当前面板的内容进行判断 Direction direction; //移动方向 protectedbooleanalive=true; //是否存活 protectedintspeed=3; //移动速度 privatebooleanattackCoolDown =true;//攻击冷却状态 privateintattackCoolDownTime =500;//攻击冷却时间毫秒间隔500ms发射子弹 TankType type;//坦克类型 private String upImage; //向上移动时的图片 private String downImage;//向下移动时的图片 private String rightImage;//向右移动时的图片 private String leftImage;//向左移动时的图片 //坦克构造方法初始化横纵坐标xy //url默认为向上的图片 public Tank(int x,int y,String url,GamePanel gamePanel,TankType type){ super(x,y,url); this.gamePanel=gamePanle; this.type=type; direction= Directon.UP; switch(type){ case player1://玩家1 upImage=ImageUtil.PLAYER1_UP_IMAGE_URL; downImage=ImageUtil.PLAYER1_DOWN_IMAGE_URL; rightImage=ImageUtil.PLAYER1_LEFT_IMAGE_URL; leftImage=ImageUtil.PLAYER1_RIGHT_IMAGE_URL; break; case player2://玩家2 upImage=ImageUtil.PLAYER2_UP_IMAGE_URL; downImage=ImageUtil.PLAYER2_DOWN_IMAGE_URL; rightImage=ImageUtil.PLAYE2_LEFT_IMAGE_URL; leftImage=ImageUtil.PLAYER2_RIGHT_IMAGE_URL; break; case bot: upImage=ImageUtil.BOT_UP_IMAGE_URL; downImage=ImageUtil.BOT_DOWN_IMAGE_URL; rightImage=ImageUtil.BOT_LEFT_IMAGE_URL; leftImage=ImageUtil.BOT_RIGHT_IMAGE_URL; break; } } //向左 public void leftward(){ if(direxction!=Directon.LEFT) setImage(leftImage);//若之前的移动方向不是左移,跟换左移图片 direxction=Directon.LEFT; if(!hitWall(x-speed,y)&&hitTank(x-speed,y)){ x-=speed;//横坐标递减 moveToborder();//判断是否移动到游戏面板的边界 } } //向右 public void rightward(){ if(direxction!=Directon.RIGHT) setImage(rightImage); direxction=Directon.RIGHT; if(!hitWall(x+speed,y)&&hitTank(x+speed,y)){ x+=speed; moveToborder();//判断是否移动到游戏面板的边界 } } //向上 public void upward(){ if(direxction!=Directon.UP) setImage(upImage); direxction=Directon.UP; if(!hitWall(x,y-speed)&&hitTank(x,y-speed)){ y-=speed; moveToborder();//判断是否移动到游戏面板的边界 } } //向下 public void downward(){ if(direxction!=Directon.DOWN) setImage(downImage); direxction=Directon.DOWN; if(!hitWall(x,y+speed)&&hitTank(x,y+speed)){ y+=speed; moveToborder();//判断是否移动到游戏面板的边界 } } //是否撞到墙块 public boolean hitWall(int x,int y){ Rectangle next=new Rectangle(x,y,width,height);//创建坦克移动后的目标区域 List<Wall> walls=gamePanel.getWalls();//获取面板上所有的墙体对象 for(int i=0,length=walls.size();i<length;i++){ Wall w=walls.get(i);//获取墙块对象 if(w instanceof GrassWall){//碰到草坪 continue; }elseif(w.hit(next)){ //撞到墙 return true; } } return false;//没撞到墙 } //是否撞到坦克 public boolean hitTank(int x,int y){ Rectangle next=new Rectangle(x,y,width,height);//创建坦克移动后的目标区域 List<Tank> tanks=gamePanel.getTanks();//获取面板上所有的坦克对象 for(int i=0,length=tanks.size();i<length;i++){ Tank t=tanks.get(i);//获取坦克对象 if(!this.equals(t)){//此坦克与自身不是一个对象 if(t.isAlive()&&t.hit(next)){//此坦克存活并且与自身相撞 return true; } } } return false;//没撞到坦克 } //移动到面板的边界 protected void moveToBorder(){ if(x<0){ x=0; }else if(x>gamePanel.getWidth()-width){ x=gamePanel.getWidth-width; } if(y<0){ y=0; }else if(y>gamePanel.getHeight()-height){ y=gamePanel.getHeight-height } } //获取坦克头 private Point getHeadPoint(){ Point p=new Point();//创建头对象,作为头点 switch(direxction){//判断移动方向 case UP: p.x=x+width/2; p.y=y; break; case DOWN: p.x=x+width/2; p.y=y+height; break; case RIGHT: p.x=x+width; p.y=y+height/2; break; case LEFT: p.x=x; p.y=y+height/2; break; default: p=null; } return p;//返回头点 } //攻击 public void attack(){ if(attackCoolDown){//如果攻击功能完成冷却 Point p=getHeadPoint();//获取坦克头对象 Bullet b=new Bullet(p.x-Bullet.LENGTH/2,p.y-Bullet.LENGTH/2,direction,gamePanel,type); gamePanel.addBullet(b);//游戏面板添加子弹 new AttackCD().start();//开始冷却倒计时 } } //坦克是否存活 public boolean isAlive(){ return alive; } public void setAlive(boolean alive){ this.alive=alive; } //坦克的速度 public void setSpeed(int speed){ this.speed=speed; } //攻击冷却时间线程 private class AttackCD extends Thread{ public void run(){ attackCoolDown=false;//将攻击功能设置为冷却状态 try{ Tread.sleep(attackCoolDown);//休眠0.5秒 }catch(InterruptedException e){ e.printStackTrace(); } attackCoolDown=true;//将攻击功能解除冷却状态 } } //获取攻击功能是否处于冷却 public boolean isAttackCoolDown(){ return attackCoolDown; } public void setAttackCoolDownTime(int attackCoolDownTime){ this.attackCoolDownTime=attackCoolDownTime; } }
敌方坦克类:
public class Bot extends Tank{ private Random random=new Random();// private Direction dir; private int fresh=GamePanel.FRESH; private int MoveTimer=0; public Bot(int x,int y,GamePanel gamePanel,TankType type) { super(x,y,ImageUtil.BOT_DOWN_IMAGE_URL,gamePanel,type); dir=Direction.DOWN; setAttackCoolDownTime(1000); //setSpeed(2); } public void go() { if(isAttackCoolDown()) { attack(); } if(MoveTimer>=3000) { dir=randomDirection(); MoveTimer=0; }else { MoveTimer+=fresh; } switch(dir) { case UP: upward(); break; case DOWN: downward(); break; case RIGHT: rightward(); break; case LEFT: leftward(); break; } } protected void moveToBorder() { if(x<0) { x=0; dir=randomDirection(); }else if(x>gamePanel.getWidth()-width) { x=gamePanel.getWidth()-width; dir=randomDirection(); } if(y<0) { y=0; dir=randomDirection(); }else if(y>gamePanel.getHeight()-height) { y=gamePanel.getHeight()-height; dir=randomDirection(); } } //重写碰到坦克的方法 boolean hitTank(int x,int y) { Rectangle next=new Rectangle(x,y,width,height);//创建坦克移动后的目标区域 List<Tank> tanks=gamePanel.getTanks();//获取面板上所有的坦克对象 for(int i=0,length=tanks.size();i<length;i++){ Tank t=tanks.get(i);//获取坦克对象 if(!this.equals(t)){//此坦克与自身不是一个对象 if(t.isAlive()&&t.hit(next)){//此坦克存活并且与自身相撞 if(t instanceof Bot) { dir=randomDirection(); } return true; } } } return false;//没撞到坦克 } public Direction randomDirection() { int rnum =random.nextInt(4); switch(rnum) { case 0: return Direction.UP; case 1: return Direction.RIGHT; case 2: return Direction.LEFT; default: return Direction.DOWN; } } public void attack() { int rnum =random.nextInt(100); if(rnum<4) { super.attack(); } } }
子弹类:
public class Bullet extends VisibleImage{ Direction direction; static final int LENGTH = 8; //子弹的(正方体)边长 private GamePanel gamePanel;//游戏面板 private int speed = 7;//移动速度 private boolean alive = true;//子弹是否有效 Color color = Color.ORANGE;//子弹颜色 TankType owner;//发出子弹的坦克类型 /** * 子弹构造方法 * * @param x - 子弹的初始横坐标 * @param y - 子弹的初始纵坐标 * @param direction - 子弹的发射方向 * @param gamePanel - 游戏面板对象 * @param Owner - 发出子弹的坦克类型 */ public Bullet(int x, int y, Direction direction, GamePanel gamePanel, TankType owner) { super(x, y, LENGTH, LENGTH); //调用父类构造方法 // TODO 自动生成的构造函数存根 this.direction = direction; this.gamePanel = gamePanel; this.owner = owner; init();//初始化组件 } /** * 初始化组件 */ private void init() { // TODO 自动生成的方法存根 Graphics g = image.getGraphics();//获取图片的绘图方法 g.setColor(Color.WHITE);//使用白色绘图 g.fillRect(0, 0, LENGTH, LENGTH);// 绘制一个铺满整个图片的白色实心矩形 g.setColor(color);//使用子弹颜色 g.fillOval(0, 0, LENGTH, LENGTH);// 铺满整个图片的实心圆形 g.setColor(Color.BLACK); //使用黑色 g.drawOval(0, 0, LENGTH-1, LENGTH-1); //绘制黑色边框,防止出界 } /** * 子弹移动 */ public void move() { switch(direction) { //判断移动方向 case UP: upward(); break; case DOWN: downword(); break; case LEFT: leftword(); break; case RIGHT: rightword(); break; } } /** * 移动函数 */ private void rightword() { // TODO 自动生成的方法存根 x += speed; moveToBorder(); } private void leftword() { // TODO 自动生成的方法存根 x -= speed; moveToBorder(); //移动出面板后销毁子弹 } private void downword() { // TODO 自动生成的方法存根 y += speed; moveToBorder(); } private void upward() { // TODO 自动生成的方法存根 y -= speed; moveToBorder(); } /** * 击中坦克 */ public void hitTank() { List<Tank> tanks = gamePanel.getTanks(); //获取坦克的集合 for(int i = 0,length = tanks.size();i<length;i++) {//遍历坦克集合 Tank t = tanks.get(i); if (t.isAlive()&&this.hit(t)) {//坦克活着并且子弹击中坦克 switch (owner) { case player1://玩家的子弹 case player2: if (t instanceof Bot) {//击中电脑 alive = false;//子弹销毁 t.setAlive(false);//电脑坦克死亡 }else if(t instanceof Tank){//击中玩家 alive = false; } break; case bot://电脑的子弹 if (t instanceof Bot) { alive = false; }else if (t instanceof Tank) { alive = false; t.setAlive(false); } break; default: alive = false; t.setAlive(false); break; } } } } //击中基地 public void hitBase() { Base b=gamePanel.getBase(); if(this.hit(b)) { alive =false; b.setAlive(false); } } public void hitWall(){ List<Wall> walls=gamePanel.getWalls(); for(int i=0,length=walls.size();i<length;i++) { Wall w=walls.get(i); if(this.hit(w)) { if(w instanceof BrickWall) { alive=false; w.setAlive(false); } if(w instanceof IronWall) { alive=false; } } } } //移除面板边界时销毁子弹 private void moveToBorder() { if(x < 0|| x > gamePanel.getWidth() - getWidth()|| y < 0 || y > gamePanel.getHeight() - getHeight()) { dispose(); } } // private synchronized void dispose() { alive=false; } // public boolean isAlive() { return alive; } }
主窗体:
1.调整屏幕尺寸及位置
2.建立窗口事件监听,使得在关闭窗口时会提示我们是否就此退出游戏。
3.添加登录面板。
public class MainFrame extends JFrame{ public MainFrame() { setTitle("坦克大战"); setSize(800,610); setResizable(false); Toolkit tool=Toolkit.getDefaultToolkit(); Dimension d=tool.getScreenSize(); setLocation((d.width-getWidth())/2, (d.height-getHeight())/2); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); addListener(); setPanel(new LoginPanel(this)); } private void addListener(){ addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { int closeCode=JOptionPane.showConfirmDialog(MainFrame.this, "是否退出游戏","提示!", JOptionPane.YES_NO_OPTION); if(closeCode==JOptionPane.YES_OPTION) { System.exit(0); } } }); } public void setPanel(JPanel panel) { Container c=getContentPane(); c.removeAll(); c.add(panel); c.validate(); } }
碰撞检测:
public class VisibleImage { /** * 横、纵坐标 */ public int x; public int y; /** * 长、宽 */ int width; int height; /** * 图像对象 */ BufferedImage image; /** * 构造方法 * @param x -横坐标 * @param y -纵坐标 * @param width -宽 * @param height -高 */ public VisibleImage(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);//实例化图片 } /** * 构造方法 * @param x -横坐标 * @param y -纵坐标 * @param url -图片路径 */ public VisibleImage(int x, int y, String url) { this.x = x; this.y = y; try { image = ImageIO.read(new File(url));//获取此路径的图片对象 this.width = image.getWidth(); this.height = image.getHeight(); }catch (IOException e) { // TODO: handle exception e.printStackTrace(); } } /** * 获取图片 * @return 所显示的图片 */ public BufferedImage getImage() { return image; } /** * 设置图片 * @param image -所显示的图片 */ public void setImage(BufferedImage image) { this.image = image以上是关于JAVA课程设计(坦克大战)的主要内容,如果未能解决你的问题,请参考以下文章