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; } /** * 设置图片 * @param image -所显示的图片 */ public void setImage(String url) { try { this.image = ImageIO.read(new File(url)); }catch (IOException e) { // TODO: handle exception e.printStackTrace(); } } /** * 判断是否发生碰撞 * @param v - 目标图片对象 * @return 如果两者相交,返回true,否则返回false */ public boolean hit(VisibleImage v) { return hit(v.getBounds());//执行重载方法 } /** * 判断是否发生碰撞 * @param r - 目标边界 * @return 如果两者相交,返回true,否则返回false */ public boolean hit(Rectangle r){ if(r == null) { return false; //不发生碰撞 } return getBounds().intersects(r); //判断边界对象是否相交 } /** * 获取边界对象 */ public Rectangle getBounds() { //创建一个坐标在(x,y)位置,宽高为(width,height)的矩形边界对象并返回 return new Rectangle(x, y, width, height); } /** * setter,getter方法获取并设置长宽高 */ public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } @Override public String toString() { return "VisibleImage [x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + "]"; } }
碰撞:子弹的碰撞有销毁他人,自我销毁,而坦克没有该功能。
刷新帧:(关键技术)
public GamePanel(MainFrame frame,int level,GameType gameType) { this.frame =frame ; this.level=level; this.gameType=gameType; setBackground(Color.GRAY); init(); Thread t=new FreshThead(); t.start(); addListener(); } private void init() { bullets=new ArrayList<Bullet>(); allTanks=new ArrayList<>(); walls=new ArrayList<>(); boomImage=new ArrayList<>(); image=new BufferedImage(794,572,BufferedImage.TYPE_INT_BGR); g2 =image.createGraphics(); playerTanks=new ArrayList<>(); play1=new Tank(278,537,ImageUtil.PLAYER1_UP_IMAGE_URL,this,TankType.player1); if(gameType==GameType.TWO_PLAYER) { play2=new Tank(500,537,ImageUtil.PLAYER2_UP_IMAGE_URL,this,TankType.player2); playerTanks.add(play2); } playerTanks.add(play1); botTanks=new Vector<>(); botTanks.add(new Bot(botX[0],1,this,TankType.bot)); botTanks.add(new Bot(botX[1],1,this,TankType.bot)); botTanks.add(new Bot(botX[2],1,this,TankType.bot)); botReadyCount-=3; allTanks.addAll(playerTanks); allTanks.addAll(botTanks); base=new Base(367,532); initWalls(); } private void addListener() { frame.addKeyListener(this); } private void initWalls() { Map map=Map.getMap(level); walls.addAll(map.getWalls()); walls.add(base); } public void paint(Graphics g) { paintTankActoin(); CreateBot(); paintImage(); g.drawImage(image, 0, 0, this); } private void paintImage() { g2.setColor(Color.BLACK); g2.fillRect(0, 0, image.getWidth(),image.getHeight() ); panitBoom(); paintBotTanks(); paintBotCount(); panitPlayerTanks(); allTanks.addAll(playerTanks); allTanks.addAll(botTanks); paintWalls(); paintBullets(); if(botSurplusCount==0) { stopThread(); paintBotCount(); g2.setFont(new Font("楷体",Font.BOLD,50)); g2.setColor(Color.GREEN); g2.drawString("胜利", 250, 400); gotoNextLevel(); } if(gameType ==GameType.ONE_PLAYER) { if(!play1.isAlive()) { stopThread(); boomImage.add(new Boom(play1.x,play1.y)); panitBoom(); paintGameOver(); gotoPrevisousLevel(); } } else {//双人模式 if(play1.isAlive()&&!play2.isAlive()) { survivor=play1; } else if(!play1.isAlive()&&play2.isAlive()) { survivor=play2; } else if(!(play1.isAlive()||play2.isAlive())) { stopThread(); boomImage.add(new Boom(survivor.x,survivor.y)); panitBoom(); paintGameOver(); gotoPrevisousLevel();//重新进入本关 } } if(!base.isAlive()) { stopThread(); paintGameOver(); base.setImage(ImageUtil.BREAK_BASE_IMAGE_URL); gotoPrevisousLevel(); } g2.drawImage(base.getImage(),base.x,base.y,this); } private void paintBotCount() { g2.setFont(new Font("楷体",Font.BOLD,25)); g2.setColor(Color.BLUE); g2.drawString("敌方坦克剩余:"+ botSurplusCount, 10,30); } private void paintGameOver() { g2.setFont(new Font("楷体",Font.BOLD,50)); g2.setColor(Color.RED); g2.drawString("Game Over !",250,400); } private void panitBoom() { for(int i=0;i<boomImage.size();i++) { Boom boom=boomImage.get(i); if(boom.isAlive()) { boom.show(g2); } else { boomImage.remove(i); i--; } } } private void paintWalls() { for(int i=0;i<walls.size();i++) { Wall w=walls.get(i); if(w.isAlive()) { g2.drawImage(w.getImage(),w.x,w.y,this); } else { walls.remove(i); i--; } } } private void paintBullets() { for(int i=0;i<bullets.size();i++) { Bullet b=bullets.get(i); if(b.isAlive()) { b.move(); b.hitBase(); b.hitWall(); b.hitTank(); g2.drawImage(b.getImage(), b.x,b.y,this); }else { bullets.remove(i); i--; } } } private void paintBotTanks() { for(int i=0;i<botTanks.size();i++) { Bot t=(Bot)botTanks.get(i); if(t.isAlive()) { t.go(); g2.drawImage(t.getImage(), t.x,t.y,this); }else { botTanks.remove(i); i--; boomImage.add(new Boom(t.x,t.y)); decreaseBot(); } } } private void panitPlayerTanks() { for(int i=0;i<playerTanks.size();i++) { Tank t=playerTanks.get(i); if(t.isAlive()) { g2.drawImage(t.getImage(), t.x,t.y,this); }else { playerTanks.remove(i); i--; boomImage.add(new Boom(t.x,t.y)); } } } private synchronized void stopThread() { frame.removeKeyListener(this); finish=true; } private class FreshThead extends Thread { public void run() { while(!finish) { repaint(); try { Thread.sleep(FRESH); } catch(InterruptedException e) { e.printStackTrace(); } } } } private void CreateBot() { createBotTimer +=FRESH; if(botTanks.size()<botMaxInMap&&botReadyCount>0&&createBotTimer>=4000) { int index=r.nextInt(3); Rectangle bornRect=new Rectangle(botX[index],1,35,35); for(int i=0,lengh=allTanks.size();i<lengh;i++) { Tank t=allTanks.get(i); if(t.isAlive()&&t.hit(bornRect)) { return; } } botTanks.add(new Bot(botX[index],1,GamePanel.this,TankType.bot)); botReadyCount--; createBotTimer=0; } } private void gotoNextLevel() { Thread jump=new JumpPageThead(Level.nextLevel()); jump.start(); } private void gotoPrevisousLevel() { Thread jump=new JumpPageThead(Level.previsousLevel()); jump.start(); } public void decreaseBot() { botSurplusCount--; } @Override public void keyPressed(KeyEvent e) { // TODO 自动生成的方法存根 switch(e.getKeyCode()) { case KeyEvent.VK_Y: y_key=true; break; case KeyEvent.VK_W: w_key=true; a_key=false; s_key=false; d_key=false; break; case KeyEvent.VK_A: w_key=false; a_key=true; s_key=false; d_key=false; break; case KeyEvent.VK_S: w_key=false; a_key=false; s_key=true; d_key=false; break; case KeyEvent.VK_D: w_key=false; a_key=false; s_key=false; d_key=true; break; case KeyEvent.VK_HOME: case KeyEvent.VK_NUMPAD1: num1_key=true; break; case KeyEvent.VK_UP: up_key=true; down_key=false; right_key=false; left_key=false; break; case KeyEvent.VK_DOWN: up_key=false; down_key=true; right_key=false; left_key=false; break; case KeyEvent.VK_LEFT: up_key=false; down_key=false; right_key=false; left_key=true; break; case KeyEvent.VK_RIGHT: up_key=false; down_key=false; right_key=true; left_key=false; break; } } private void paintTankActoin() { if(y_key) { play1.attack(); } if(w_key) { play1.upward(); } if(d_key) { play1.rightward(); } if(a_key) { play1.leftward(); } if(s_key) { play1.downward(); } if(gameType==GameType.TWO_PLAYER) { if(num1_key) { play2.attack(); } if(up_key) { play2.upward(); } if(right_key) { play2.rightward(); } if(left_key) { play2.leftward(); } if(down_key) { play2.downward(); } } } @Override public void keyReleased(KeyEvent e) { // TODO 自动生成的方法存根 switch(e.getKeyCode()) { case KeyEvent.VK_Y: y_key=false; break; case KeyEvent.VK_W: w_key=false; break; case KeyEvent.VK_A: a_key=false; break; case KeyEvent.VK_S: s_key=false; break; case KeyEvent.VK_D: d_key=false; break; case KeyEvent.VK_HOME: case KeyEvent.VK_NUMPAD1: num1_key=false; break; case KeyEvent.VK_UP: up_key=false; break; case KeyEvent.VK_DOWN: down_key=false; break; case KeyEvent.VK_LEFT: left_key=false; break; case KeyEvent.VK_RIGHT: right_key=false; break; } } public void addBullet(Bullet b) { bullets.add(b); } public List<Wall>getWalls(){ return walls; } public Base getBase() { return base; } public List<Tank>getTanks() { return allTanks; } private class JumpPageThead extends Thread{ int level; public JumpPageThead (int level) { this.level=level; } public void run() { try { Thread.sleep(1000); frame.setPanel(new LevelPanel(level,frame,gameType)); }catch(InterruptedException e) { e.printStackTrace(); } } } @Override public void keyTyped(KeyEvent e) { // TODO 自动生成的方法存根 } }
帧是一个量词,一个静态的画面就是一帧,帧的刷新频率决定了动画是否流畅。
repaint();每隔一段时间画一张图片,这样实现了刷新的效果。在游戏面板的构造方法里创建游戏帧线程,结束通过一个finsh来判断。
六·项目代码扫描结果及改正
提交检查前请先将IDE中提示的所有警告(warning)解决。然后使用,阿里巴巴静态代码扫描工具(https://www.cnblogs.com/bb1119/p/7672939.html)对自己的项目进行扫描,并根据提示改正。
1.代码扫描结果
2.改正
l 对if-else语句进行大括号补充
l 对命名包文件进行修改,让它符合javac的命名规范
l Switch-case语句必须以default结尾,对此进行补充
七·尚待改进
本次的坦克大战课设实现的是一些最基本坦克大战游戏功能,比较简单易懂,对于该游戏我们还存在很多的不足,比如可以尝试着做能够联网的多人游戏,一个游戏排行榜(好友,非好友)。
原文地址:https://www.cnblogs.com/chenhuilin/p/10275664.html