前言
通过Java程序编写实现经典游戏坦克大战的运行
一、团队成员及任务
组长:韦子豪 计科(智能)22-1 202203200011
负责任务:游戏规则程序代码编写,地图设计,游戏Panel和主界面设计
组员:孙梓容 计科(智能)22-1 202203200019
负责任务:坦克类代码编写,所有砖块类代码编写,子弹类,基地类和爆炸特效代码编写
二、流程图运行结果截图
三、设计思路
-
创建游戏的主窗口界面,加载菜单及游戏面板。
-
在游戏面板中初始化各种参数,并建立各种功能组件。
-
利用多线程与线程池的技术创建敌方坦克和所有子弹类。
-
利用线程固定刷新游戏界面,利用双缓冲机制防止画面闪烁。
-
确定运行逻辑和体积参数,处理各种碰撞问题,优化子弹判定机制
-
设置多张游戏地图
-
设置游戏通关目标和失败条件,完成目标或失败后游戏结束。
四、具体代码
1.TankWar.java 游戏入口类
代码如下:
package TankWarrrrrrr;
public class TankWar{
public static void main(String[] args){
new GameFrame();//坦克大战,启动!
}
}
2.GameFrame.Java游戏窗口
代码如下:
package TankWarrrrrrr; import java.awt.*; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class GameFrame extends JFrame implements ActionListener{ private GamePanel gamePanel; //游戏面板 public GameFrame(){ try{ // 定制菜单 JMenuBar main = new JMenuBar(); // 菜单栏 JMenu game = new JMenu("游戏"); // 游戏菜单 game.setFont(new Font("微软雅黑",Font.PLAIN,12)); JMenuItem newgame = new JMenuItem("新游戏"); // 子菜单 newgame.setFont(new Font("微软雅黑",Font.PLAIN,12)); newgame.addActionListener(this); // 为窗口增加新游戏菜单的事件监听 newgame.setActionCommand("new"); //新游戏菜单的监听标识 game.add(newgame); // 将新游戏子菜单附加到游戏菜单上 JMenuItem select = new JMenuItem("选关卡"); select.setFont(new Font("微软雅黑",Font.PLAIN,12)); select.addActionListener(this); select.setActionCommand("grade"); game.add(select); game.addSeparator(); // 菜单分隔符 JMenuItem exit = new JMenuItem("退出"); exit.setFont(new Font("微软雅黑",Font.PLAIN,12)); exit.addActionListener(this); exit.setActionCommand("exit"); game.add(exit); main.add(game); this.setJMenuBar(main);//以上的this都是调用私有变量gamePanel // 定制面板 this.gamePanel = new GamePanel(); this.add(this.gamePanel); // 定制窗口 this.setTitle("坦克大战"); // 标题 this.setLayout(null); // 清空布局管理器 this.setSize(this.gamePanel.getWidth() + 10,this.gamePanel.getHeight() + 60); // 根据游戏面板大小设置游戏窗口大小 this.setResizable(false); // 程序运行时禁止改变窗口大小尺寸 this.setLocationRelativeTo(null); // 窗口居中 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 点击窗口X按钮时默认关闭程序 this.setVisible(true); // 显示窗口 } catch (Exception e){ e.printStackTrace(); JOptionPane.showMessageDialog(this,"程序出现异常错误,即将退出\r\n"+e.toString(),"提示",JOptionPane.ERROR_MESSAGE); System.exit(0); } } @Override public void actionPerformed(ActionEvent e) { //事件监听 // 监听事件的标识 String command = e.getActionCommand(); switch (command) { case "new": // 如果点了new,开始新游戏 this.gamePanel.newGame(); break; case "grade": //选关,一共两关 int gradeCount = GameMap.getGradeCount(); String[] options = new String[gradeCount]; for (int i = 0; i < gradeCount; i++) options[i] = i + 1 + ""; String grade = (String)JOptionPane.showInputDialog(this, "请选择你要进行的关卡:","选关", JOptionPane.INFORMATION_MESSAGE, null, options, options[0]); gamePanel.setGrade(Integer.parseInt(grade)); gamePanel.newGame(); break; case "exit": //退出 System.exit(0); break; } } }
3.GamePanel.Java游戏面板
代码如下(示例):
package TankWarrrrrrr; import java.awt.*; import javax.swing.*; import java.util.List; import java.util.ArrayList; import java.util.Vector; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.image.BufferedImage; public class GamePanel extends JPanel implements KeyListener{ //初始化各种变量 private final static int GAME_STATE_READY = 0; // 游戏未开始 private final static int GAME_STATE_RUNNING = 1; // 游戏运行中 private final static int GAME_STATE_OVER = 9; // 游戏已结束 public final static int GAME_ACTION_WIDTH = Block.BLOCK_WIDTH * 26; // 游戏运行场景宽度 public final static int GAME_ACTION_HEIGHT = Block.BLOCK_HEIGHT * 26; // 游戏运行场景宽度 public final static int GAME_PANEL_WIDTH = GAME_ACTION_WIDTH + 150; // 游戏面板宽度 public final static int GAME_PANEL_HEIGHT = GAME_ACTION_HEIGHT; // 游戏面板高度 private BufferedImage bufferedImage = new BufferedImage(GAME_ACTION_WIDTH,GAME_ACTION_HEIGHT,BufferedImage.TYPE_4BYTE_ABGR); //利用双缓冲机制防止画面闪烁,创建一张与面板画面一样大小的图片,所有的元素先绘制到该图片上,再将该图片一次性绘制到面板画面上 private int repaintInterval = 20; // 游戏每秒刷新(1000/repaintInterval)次 private int gameState = GAME_STATE_READY; //游戏状态 private Hero hero;//我方坦克 private Hero heroModel = new Hero(GAME_ACTION_WIDTH + 30,200,Tank.TANK_DIRECTION_RIGHT); //我方坦克模型,显示在计分榜上 private Vector<Enemy> enemyPool = new Vector<>(); //敌方坦克池,为了线程安全用Vector,不用ArrayList private int enemyPoolMaxNum = 0; //限制敌方坦克池最大数量 private int enemyDeadNum = 0; //敌方坦克死亡数量 private Enemy enemyModel = new Enemy(GAME_ACTION_WIDTH + 30,20,Tank.TANK_DIRECTION_RIGHT); //敌方坦克模型,显示在计分榜上 private boolean createEnemyTankThreadRunning = false; //标识地方坦克线程是否运行 private long lastCreateEnemyTankTime = System.currentTimeMillis(); //记下上次投放时间,用来设置投放坦克最小时间间隔 private List<Block> blockList = new ArrayList<>(); //块列表 private List<Bomb> bombList = new ArrayList<>(); //爆炸列表 private int grade = 1; //游戏关卡 private byte[][] gameGradeMap; //游戏某关地图 private Camp camp = new Camp(12 * Block.BLOCK_WIDTH,24 * Block.BLOCK_HEIGHT); //我方基地 public GamePanel(){ this.setSize(GAME_PANEL_WIDTH,GAME_PANEL_HEIGHT); //设置面板大小 //监听键盘事件 this.setFocusable(true); //让面板得到焦点 this.addKeyListener(this); //将监听键盘事件附加到面板上 GameLogic.setInstance(new GameLogic(this)); //创建游戏逻辑实例 } public void newGame(){ //开始新游戏方法 gameReset(); //先调用游戏重置方法 this.gameState = GAME_STATE_RUNNING; //设置游戏状态为运行中 loadGameMap(); //加载游戏地图方法 camp.setState(Camp.CAMP_STATE_RUNNING); //设置我方基地 //创建我方坦克 int heroX = 8 * Block.BLOCK_WIDTH; int heroY = (this.gameGradeMap.length - 2) * Block.BLOCK_HEIGHT; hero = new Hero(heroX,heroY,Tank.TANK_DIRECTION_UP); hero.work(); //创建敌方坦克方法 createEnemyTank(); //启动线程来定时刷新画面 refresh(); } private void loadGameMap(){ //加载游戏地图方法 this.gameGradeMap = GameMap.getGameMap(this.grade); // 得到本关地图 int row = this.gameGradeMap.length; // 得到地图位置(几行几列) int column = this.gameGradeMap[0].length; // 开始循环 for (int i = 0; i < row; i++) { for (int j = 0; j < column; j++) { int mapValue = this.gameGradeMap[i][j]; switch (mapValue) { case Block.BLOCK_KIND_BRICK: Brick brick = new Brick(Block.BLOCK_WIDTH * j,Block.BLOCK_HEIGHT * i); this.blockList.add(brick); break; case Block.BLOCK_KIND_IRON: Iron iron = new Iron(Block.BLOCK_WIDTH * j,Block.BLOCK_HEIGHT * i); this.blockList.add(iron); break; } } } this.enemyPoolMaxNum = GameMap.getEnemyTankNum(this.grade); // 本关敌方坦克数量 } private void gameReset(){ //游戏重置方法 // 停止上局正在运行的线程 if(this.gameState == GAME_STATE_RUNNING){this.gameState = GAME_STATE_READY;} while (true){ if(this.createEnemyTankThreadRunning){ try{ Thread.sleep(10); } catch (InterruptedException e){ throw new RuntimeException(e); } } else{ break; } } // 清空敌方坦克池中的所有坦克及其子弹 for (int i = 0; i < enemyPool.size(); i++) { Enemy enemy = enemyPool.get(i); enemy.reset(); for (int j = 0; j < enemy.getBulletPool().size(); j++){ Bullet bullet = enemy.getBulletPool().get(j); bullet.reset(); } enemy.getBulletPool().clear(); } enemyPool.clear(); enemyDeadNum = 0; // 清空我方坦克及其子弹 if(hero != null) { hero.reset(); for (int i = 0; i < hero.getBulletPool().size(); i++) { Bullet bullet = hero.getBulletPool().get(i); bullet.reset(); } hero.getBulletPool().clear(); } // 清空块池中的所有块 blockList.clear(); } //创建地方坦克 private void createEnemyTank(){ this.createEnemyTankThreadRunning = true; // 线程运行中 new Thread(()->{ // 记录已投放的坦克数量 int createEnemyTankNum = 0; try{ while (this.gameState == GAME_STATE_RUNNING){ // 休眠一会 try{ Thread.sleep(repaintInterval); // 休眠时间短主要是考虑可以迅速退出本线程 } catch (InterruptedException e){ e.printStackTrace(); } // 控制连续投放间隔 long curCreateEnemyTankTime = System.currentTimeMillis(); if((curCreateEnemyTankTime - this.lastCreateEnemyTankTime) >= 3000) { // 3秒投放 this.lastCreateEnemyTankTime = curCreateEnemyTankTime; } else{ continue; } // 投放敌方坦克到达最大值后退出本线程 if(createEnemyTankNum >= enemyPoolMaxNum){break;} // 在敌方坦克池中寻找空闲的坦克随机显示在左上角或右上角 Enemy enemy = null; for (int i = 0; i < enemyPool.size(); i++) { Enemy tmpEnemy = enemyPool.get(i); if(tmpEnemy.getState() == Tank.TANK_STATE_FREE) { enemy = tmpEnemy; break; } } // 没有就增加一个 if(enemy == null) { enemy = new Enemy(-100,-100,Tank.TANK_DIRECTION_DOWN); enemyPool.add(enemy); } // 开始投放(随机投放到左上角与右上角,坦克不能重叠) int enemyX; // 坦克X坐标 int enemyDirection = Tank.TANK_DIRECTION_DOWN; // 坦克方向默认向下 int randomPos = GameLogic.getRandomInt(0,1); // 随机生成位置(0-左上角,1-右上角) if(randomPos == 0){ // 左上角 enemyX = 0; if(GameLogic.getRandomInt(0,1) == 1){enemyDirection = Tank.TANK_DIRECTION_RIGHT;} } else { // 右上角 enemyX = GAME_ACTION_WIDTH - Tank.TANK_WIDTH; if(GameLogic.getRandomInt(0,1) == 1){enemyDirection = Tank.TANK_DIRECTION_LEFT;} } enemy.setX(enemyX); enemy.setY(0); enemy.setDirection(enemyDirection); // 判断该范围内是否可以投放运行 boolean workFlag = true; for (int i = 0; i < enemyPool.size(); i++){ Enemy tmpEnemy = enemyPool.get(i); if(tmpEnemy.getState() == Tank.TANK_STATE_RUNNING && enemy != tmpEnemy) { if(GameLogic.getInstance().tankCollideTank(enemy,tmpEnemy)) { // 敌方坦克占位,不能投放 workFlag = false; continue; } } } if(GameLogic.getInstance().tankCollideTank(enemy,hero)) { // 我方坦克占位,不能投放 workFlag = false; } // 不能投放准备下一次 if(!workFlag){continue;} // 可以投放了 enemy.work(); // 线程,启动! createEnemyTankNum++; } } catch (Exception e){ e.printStackTrace(); } finally{ this.createEnemyTankThreadRunning = false; // 线程结束 } }).start(); } //游戏结束方法 private void gameOver(){ // 设置游戏状态 this.gameState = GAME_STATE_OVER; // 清空重置 gameReset(); } //y游戏胜利方法 private void gameWin() { if(enemyPoolMaxNum - enemyDeadNum <= 0){ this.grade++; newGame(); } } //碰撞处理 private void collide(){ // 判断我方子弹碰撞 for (int i = 0; i < hero.getBulletPool().size(); i++){ Bullet bullet = hero.getBulletPool().get(i); if(bullet.getState() == Bullet.BULLET_STATE_RUNNING) { // 判断是否与敌方坦克碰撞 for (int j = 0; j < enemyPool.size(); j++){ //子弹 Enemy enemy = enemyPool.get(j); if(enemy.getState() == Tank.TANK_STATE_RUNNING) { // 敌方坦克 if(GameLogic.getInstance().bulletCollideTank(bullet,enemy)) { // 如果碰上了 // 记录坦克坐标,因为坦克销毁时会改变其坐标 int bombX = enemy.getX(); int bombY = enemy.getY(); // 子弹销毁,坦克受到伤害,判断坦克是否死亡 bullet.reset(); enemy.hurt(bullet); if(enemy.isDead()){ // 坦克销毁,爆炸,每消灭一个敌人判断一次是否胜利 enemy.reset(); enemyDeadNum++; addBomb(bombX,bombY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT); gameWin(); } } } } // 判断是否与块碰撞 for (int m = blockList.size() - 1; m >= 0; m--) { Block block = blockList.get(m); if(GameLogic.getInstance().bulletCollideBlock(bullet,block)) { //如果碰上了 // 记录块坐标 int bombX = block.getX(); int bombY = block.getY(); // 子弹销毁 bullet.reset(); if(block.getBlockKind() == Block.BLOCK_KIND_BRICK){ // 砖块销毁,爆炸 blockList.remove(m); addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT); } else{ addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT); } } } // 判断是否与基地碰撞 if(camp.getState() == Camp.CAMP_STATE_RUNNING){ if(GameLogic.getInstance().bulletCollideCamp(bullet,camp)) { //基地GG //子弹销毁,基地销毁,基地爆炸,游戏结束 bullet.reset(); camp.setState(Camp.CAMP_STATE_FREE); addBomb(camp.getX(),camp.getY(),camp.getWidth(),camp.getHeight()); gameOver(); //这样就可以自毁基地了 } } } } // 判断敌方子弹是否与我方坦克或块或大本营碰撞(不需要判断敌方坦克状态,因为即使坦克销毁子弹可能仍然在飞) for (int i = 0; i < enemyPool.size(); i++) { // 判断是否与我方坦克碰撞 Enemy enemy = enemyPool.get(i); for (int j = 0; j < enemy.getBulletPool().size(); j++){ Bullet bullet = enemy.getBulletPool().get(j); if(bullet.getState() == Bullet.BULLET_STATE_RUNNING) { // 判断子弹是否与坦克碰撞 if(GameLogic.getInstance().bulletCollideTank(bullet,hero)) { // 坦克GG // 记录坦克坐标,因为坦克销毁时会改变其坐标 int bombX = hero.getX(); int bombY = hero.getY(); //子弹销毁、坦克受伤、判断是否死亡 bullet.reset(); hero.hurt(bullet); if(hero.isDead()){ // 坦克销毁并爆炸,游戏结束 hero.reset(); addBomb(bombX,bombY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT); gameOver(); } } // 判断子弹是否与块碰撞 for (int m = blockList.size() - 1; m >= 0; m--) { Block block = blockList.get(m); // 开始判断 if(GameLogic.getInstance().bulletCollideBlock(bullet,block)) { // 如果碰上了 // 记录块坐标 int bombX = block.getX(); int bombY = block.getY(); bullet.reset(); if(block.getBlockKind() == Block.BLOCK_KIND_BRICK){ // 砖块销毁并爆炸 blockList.remove(m); addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT); } else{ addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT); } } } // 判断子弹是否与基地碰撞 if(camp.getState() == Camp.CAMP_STATE_RUNNING){ if(GameLogic.getInstance().bulletCollideCamp(bullet,camp)) { // 如果碰上 // 子弹销毁,基地销毁,基地爆炸,游戏结束 bullet.reset(); camp.setState(Camp.CAMP_STATE_FREE); addBomb(camp.getX(),camp.getY(),camp.getWidth(),camp.getHeight()); gameOver(); } } } } } } //添加爆炸效果 private void addBomb(int x,int y,int w,int h){ // 查找空闲的爆炸 Bomb bomb = null; for (int i = 0; i < bombList.size(); i++) { Bomb tmpBomb = bombList.get(i); if(tmpBomb.getState() == Bomb.BOMB_STATE_FREE) { bomb = tmpBomb; break; } } // 没有就增加一个 if(bomb == null){ bomb = new Bomb(-100,-100); bombList.add(bomb); } bomb.setX(x); bomb.setY(y); bomb.setWidth(w); bomb.setHeight(h); bomb.work(); } //字符被输入 @Override public void keyTyped(KeyEvent e){} //某键被按下 @Override public void keyPressed(KeyEvent e){ // 游戏未开始或结束后禁止按键 if(this.gameState != GAME_STATE_RUNNING){return;} int keyCode = e.getKeyCode(); switch (keyCode){ case KeyEvent.VK_W: case KeyEvent.VK_UP: //两个case一个break hero.move(Tank.TANK_DIRECTION_UP); break; case KeyEvent.VK_D: case KeyEvent.VK_RIGHT: hero.move(Tank.TANK_DIRECTION_RIGHT); break; case KeyEvent.VK_S: case KeyEvent.VK_DOWN: hero.move(Tank.TANK_DIRECTION_DOWN); break; case KeyEvent.VK_A: case KeyEvent.VK_LEFT: hero.move(Tank.TANK_DIRECTION_LEFT); break; case KeyEvent.VK_SPACE: hero.shoot(); break; } } //某键被释放 @Override public void keyReleased(KeyEvent e){} //利用线程来定时刷新重绘游戏画面 private void refresh(){ new Thread(() ->{ while (this.gameState == GAME_STATE_RUNNING) { collide(); // 碰撞处理 repaint(); // 开始刷新 try { // 延时睡眠 Thread.sleep(repaintInterval); } catch (InterruptedException e){ e.printStackTrace(); } } }).start(); } //绘制游戏画面,利用双缓冲机制防止画面闪烁 @Override public void paint(Graphics g){ // 完成初始化工作,该语句千万不要动 super.paint(g); // 开始游戏时 if(this.gameState == GAME_STATE_READY){ // 清背景 g.setColor(Color.GRAY); g.fillRect(0,0,this.getWidth(),this.getHeight()); // 显示 g.setColor(Color.ORANGE); g.setFont(new Font("微软雅黑",Font.BOLD,60)); g.drawString("坦 克 大 战", 180,160); g.setColor(Color.BLUE); g.setFont(new Font("微软雅黑",Font.BOLD,40)); g.drawString("2023.6.15", 220,250); g.setColor(Color.WHITE); g.setFont(new Font("宋体",Font.PLAIN,20)); g.drawString("面向对象程序设计答辩", 220,420); return; } // 游戏结束时 if(this.gameState == GAME_STATE_OVER){ g.setColor(Color.BLACK); g.fillRect(0,0,this.getWidth(),this.getHeight()); g.setColor(Color.RED); g.setFont(new Font("宋体",Font.BOLD,60)); g.drawString("游戏结束\n", 180,170); g.setColor(Color.GREEN); g.drawString("感谢游玩", 180,280); g.setColor(Color.WHITE); g.setFont(new Font("宋体",Font.PLAIN,20)); g.drawString("面向对象程序设计答辩", 200,420); } // 游戏进行中 if(this.gameState == GAME_STATE_RUNNING){ // 设置游戏面板区域 g.setColor(Color.LIGHT_GRAY); g.fillRect(0,0,this.getWidth(),this.getWidth()); g.setColor(Color.WHITE); g.fill3DRect(GAME_ACTION_WIDTH,0,2,GAME_ACTION_HEIGHT,true); // 绘制分数 // 敌方坦克信息 enemyModel.draw(g); g.setColor(Tank.TANK_COLOR_ENEMY); g.setFont(new Font("微软雅黑",Font.BOLD,20)); g.drawString("总数:" + enemyPoolMaxNum,enemyModel.getX() ,enemyModel.getY() + 70); g.drawString("死亡:" + enemyDeadNum,enemyModel.getX() ,enemyModel.getY() + 100); g.drawString("剩余:" + (enemyPoolMaxNum - enemyDeadNum),enemyModel.getX() ,enemyModel.getY() + 130); // 我方坦克信息 heroModel.draw(g); g.setColor(Tank.TANK_COLOR_HERO); g.setFont(new Font("微软雅黑",Font.BOLD,20)); g.drawString("歼敌:"+enemyDeadNum ,heroModel.getX() - 1 ,heroModel.getY() + 70); g.drawString("生命:" + hero.getHp() ,heroModel.getX() ,heroModel.getY() + 100); // 关口信息 g.setColor(Color.BLACK); int gradeModelX = heroModel.getX(); int gradeModelY = heroModel.getY() + 150; g.fillRect(gradeModelX,gradeModelY,3,40); Polygon triangle = new Polygon(); triangle.addPoint(gradeModelX + 3, gradeModelY); triangle.addPoint(gradeModelX + 3, gradeModelY + 20); triangle.addPoint(gradeModelX + 40, gradeModelY + 20); g.setColor(Color.RED); g.fillPolygon(triangle); g.setColor(Color.WHITE); g.setFont(new Font("微软雅黑",Font.BOLD,20)); g.drawString("关数:" + this.grade ,gradeModelX ,gradeModelY + 70); //双缓冲机制来重绘画面,先把所有的元素绘制到缓冲图片上,再将该图片一次性绘制到画面上 Graphics ig = bufferedImage.getGraphics(); //得到缓冲图片的画笔 // 设置游戏面板区域 ig.setColor(Color.BLACK); ig.fillRect(0,0,GAME_ACTION_WIDTH,GAME_ACTION_HEIGHT); // 绘制地图 for (Block block : this.blockList){block.draw(ig);} // 绘制基地 if(camp.getState() == Camp.CAMP_STATE_RUNNING){camp.draw(ig);} // 绘制我方坦克 hero.draw(ig); // 绘制我方子弹 for (Bullet bullet : hero.getBulletPool()){if(bullet.getState() == Bullet.BULLET_STATE_RUNNING){bullet.draw(ig);}} // 绘制敌方坦克、子弹 for (int i = 0; i < enemyPool.size(); i++) { Enemy enemy = enemyPool.get(i); // 绘制坦克 if(enemy.getState() == Tank.TANK_STATE_RUNNING){enemy.draw(ig);} // 绘制子弹 for (Bullet bullet : enemy.getBulletPool()){if(bullet.getState() == Bullet.BULLET_STATE_RUNNING){bullet.draw(ig);}} } // 绘制爆炸 for (Bomb bomb : bombList){if(bomb.getState() == Bomb.BOMB_STATE_RUNNING){bomb.draw(ig);}} // 将缓冲图片一次性显示到画面上 g.drawImage(bufferedImage,0,0,null); } } public Hero getHero(){return hero;} public Vector<Enemy> getEnemyPool(){return enemyPool;} public List<Block> getBlockList(){return blockList;} public Camp getCamp(){return camp;} public void setGrade(int grade){this.grade = grade;} }
4.GameLogic.java游戏逻辑
代码如下(示例):
package TankWarrrrrrr; import java.awt.*; import javax.swing.*; import java.util.List; import java.util.ArrayList; import java.util.Vector; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.image.BufferedImage; public class GamePanel extends JPanel implements KeyListener{ //初始化各种变量 private final static int GAME_STATE_READY = 0; // 游戏未开始 private final static int GAME_STATE_RUNNING = 1; // 游戏运行中 private final static int GAME_STATE_OVER = 9; // 游戏已结束 public final static int GAME_ACTION_WIDTH = Block.BLOCK_WIDTH * 26; // 游戏运行场景宽度 public final static int GAME_ACTION_HEIGHT = Block.BLOCK_HEIGHT * 26; // 游戏运行场景宽度 public final static int GAME_PANEL_WIDTH = GAME_ACTION_WIDTH + 150; // 游戏面板宽度 public final static int GAME_PANEL_HEIGHT = GAME_ACTION_HEIGHT; // 游戏面板高度 private BufferedImage bufferedImage = new BufferedImage(GAME_ACTION_WIDTH,GAME_ACTION_HEIGHT,BufferedImage.TYPE_4BYTE_ABGR); //利用双缓冲机制防止画面闪烁,创建一张与面板画面一样大小的图片,所有的元素先绘制到该图片上,再将该图片一次性绘制到面板画面上 private int repaintInterval = 20; // 游戏每秒刷新(1000/repaintInterval)次 private int gameState = GAME_STATE_READY; //游戏状态 private Hero hero;//我方坦克 private Hero heroModel = new Hero(GAME_ACTION_WIDTH + 30,200,Tank.TANK_DIRECTION_RIGHT); //我方坦克模型,显示在计分榜上 private Vector<Enemy> enemyPool = new Vector<>(); //敌方坦克池,为了线程安全用Vector,不用ArrayList private int enemyPoolMaxNum = 0; //限制敌方坦克池最大数量 private int enemyDeadNum = 0; //敌方坦克死亡数量 private Enemy enemyModel = new Enemy(GAME_ACTION_WIDTH + 30,20,Tank.TANK_DIRECTION_RIGHT); //敌方坦克模型,显示在计分榜上 private boolean createEnemyTankThreadRunning = false; //标识地方坦克线程是否运行 private long lastCreateEnemyTankTime = System.currentTimeMillis(); //记下上次投放时间,用来设置投放坦克最小时间间隔 private List<Block> blockList = new ArrayList<>(); //块列表 private List<Bomb> bombList = new ArrayList<>(); //爆炸列表 private int grade = 1; //游戏关卡 private byte[][] gameGradeMap; //游戏某关地图 private Camp camp = new Camp(12 * Block.BLOCK_WIDTH,24 * Block.BLOCK_HEIGHT); //我方基地 public GamePanel(){ this.setSize(GAME_PANEL_WIDTH,GAME_PANEL_HEIGHT); //设置面板大小 //监听键盘事件 this.setFocusable(true); //让面板得到焦点 this.addKeyListener(this); //将监听键盘事件附加到面板上 GameLogic.setInstance(new GameLogic(this)); //创建游戏逻辑实例 } public void newGame(){ //开始新游戏方法 gameReset(); //先调用游戏重置方法 this.gameState = GAME_STATE_RUNNING; //设置游戏状态为运行中 loadGameMap(); //加载游戏地图方法 camp.setState(Camp.CAMP_STATE_RUNNING); //设置我方基地 //创建我方坦克 int heroX = 8 * Block.BLOCK_WIDTH; int heroY = (this.gameGradeMap.length - 2) * Block.BLOCK_HEIGHT; hero = new Hero(heroX,heroY,Tank.TANK_DIRECTION_UP); hero.work(); //创建敌方坦克方法 createEnemyTank(); //启动线程来定时刷新画面 refresh(); } private void loadGameMap(){ //加载游戏地图方法 this.gameGradeMap = GameMap.getGameMap(this.grade); // 得到本关地图 int row = this.gameGradeMap.length; // 得到地图位置(几行几列) int column = this.gameGradeMap[0].length; // 开始循环 for (int i = 0; i < row; i++){ for (int j = 0; j < column; j++){ int mapValue = this.gameGradeMap[i][j]; switch (mapValue){ case Block.BLOCK_KIND_BRICK: Brick brick = new Brick(Block.BLOCK_WIDTH * j,Block.BLOCK_HEIGHT * i); this.blockList.add(brick); break; case Block.BLOCK_KIND_IRON: Iron iron = new Iron(Block.BLOCK_WIDTH * j,Block.BLOCK_HEIGHT * i); this.blockList.add(iron); break; } } } this.enemyPoolMaxNum = GameMap.getEnemyTankNum(this.grade); // 本关敌方坦克数量 } private void gameReset(){ //游戏重置方法 // 停止上局正在运行的线程 if(this.gameState == GAME_STATE_RUNNING){this.gameState = GAME_STATE_READY;} while (true){ if(this.createEnemyTankThreadRunning){ try{ Thread.sleep(10); } catch (InterruptedException e){ throw new RuntimeException(e); } } else{ break; } } // 清空敌方坦克池中的所有坦克及其子弹 for (int i = 0; i < enemyPool.size(); i++) { Enemy enemy = enemyPool.get(i); enemy.reset(); for (int j = 0; j < enemy.getBulletPool().size(); j++){ Bullet bullet = enemy.getBulletPool().get(j); bullet.reset(); } enemy.getBulletPool().clear(); } enemyPool.clear(); enemyDeadNum = 0; // 清空我方坦克及其子弹 if(hero != null) { hero.reset(); for (int i = 0; i < hero.getBulletPool().size(); i++) { Bullet bullet = hero.getBulletPool().get(i); bullet.reset(); } hero.getBulletPool().clear(); } // 清空块池中的所有块 blockList.clear(); } //创建地方坦克 private void createEnemyTank(){ this.createEnemyTankThreadRunning = true; // 线程运行中 new Thread(()->{ // 记录已投放的坦克数量 int createEnemyTankNum = 0; try{ while (this.gameState == GAME_STATE_RUNNING){ // 休眠一会 try{ Thread.sleep(repaintInterval); // 休眠时间短主要是考虑可以迅速退出本线程 } catch (InterruptedException e){ e.printStackTrace(); } // 控制连续投放间隔 long curCreateEnemyTankTime = System.currentTimeMillis(); if((curCreateEnemyTankTime - this.lastCreateEnemyTankTime) >= 3000) { // 3秒投放 this.lastCreateEnemyTankTime = curCreateEnemyTankTime; } else{ continue; } // 投放敌方坦克到达最大值后退出本线程 if(createEnemyTankNum >= enemyPoolMaxNum){break;} // 在敌方坦克池中寻找空闲的坦克随机显示在左上角或右上角 Enemy enemy = null; for (int i = 0; i < enemyPool.size(); i++) { Enemy tmpEnemy = enemyPool.get(i); if(tmpEnemy.getState() == Tank.TANK_STATE_FREE) { enemy = tmpEnemy; break; } } // 没有就增加一个 if(enemy == null) { enemy = new Enemy(-100,-100,Tank.TANK_DIRECTION_DOWN); enemyPool.add(enemy); } // 开始投放(随机投放到左上角与右上角,坦克不能重叠) int enemyX; // 坦克X坐标 int enemyDirection = Tank.TANK_DIRECTION_DOWN; // 坦克方向默认向下 int randomPos = GameLogic.getRandomInt(0,1); // 随机生成位置(0-左上角,1-右上角) if(randomPos == 0){ // 左上角 enemyX = 0; if(GameLogic.getRandomInt(0,1) == 1){enemyDirection = Tank.TANK_DIRECTION_RIGHT;} } else { // 右上角 enemyX = GAME_ACTION_WIDTH - Tank.TANK_WIDTH; if(GameLogic.getRandomInt(0,1) == 1){enemyDirection = Tank.TANK_DIRECTION_LEFT;} } enemy.setX(enemyX); enemy.setY(0); enemy.setDirection(enemyDirection); // 判断该范围内是否可以投放运行 boolean workFlag = true; for (int i = 0; i < enemyPool.size(); i++){ Enemy tmpEnemy = enemyPool.get(i); if(tmpEnemy.getState() == Tank.TANK_STATE_RUNNING && enemy != tmpEnemy) { if(GameLogic.getInstance().tankCollideTank(enemy,tmpEnemy)) { // 敌方坦克占位,不能投放 workFlag = false; continue; } } } if(GameLogic.getInstance().tankCollideTank(enemy,hero)) { // 我方坦克占位,不能投放 workFlag = false; } // 不能投放准备下一次 if(!workFlag){continue;} // 可以投放了 enemy.work(); // 线程,启动! createEnemyTankNum++; } } catch (Exception e){ e.printStackTrace(); } finally{ this.createEnemyTankThreadRunning = false; // 线程结束 } }).start(); } //游戏结束方法 private void gameOver(){ // 设置游戏状态 this.gameState = GAME_STATE_OVER; // 清空重置 gameReset(); } //y游戏胜利方法 private void gameWin() { if(enemyPoolMaxNum - enemyDeadNum <= 0){ this.grade++; newGame(); } } //碰撞处理 private void collide(){ // 判断我方子弹碰撞 for (int i = 0; i < hero.getBulletPool().size(); i++){ Bullet bullet = hero.getBulletPool().get(i); if(bullet.getState() == Bullet.BULLET_STATE_RUNNING) { // 判断是否与敌方坦克碰撞 for (int j = 0; j < enemyPool.size(); j++){ //子弹 Enemy enemy = enemyPool.get(j); //在这里判断子弹是否与敌方子弹碰撞 for (int k = 0; k < enemy.getBulletPool().size();k++) { Bullet bullet2 = enemy.getBulletPool().get(k); if(GameLogic.getInstance().bulletCollideBullet(bullet, bullet2)) { //如果碰上了 //记录子弹位置 int bulletX = bullet.getX(); int bulletY = bullet.getY(); //子弹销毁 bullet.reset(); bullet2.reset(); addBomb(bulletX,bulletY,bullet.getWidth(),bullet.getHeight()); } } if(enemy.getState() == Tank.TANK_STATE_RUNNING) { // 敌方坦克 if(GameLogic.getInstance().bulletCollideTank(bullet,enemy)) { // 如果碰上了 // 记录坦克坐标,因为坦克销毁时会改变其坐标 int bombX = enemy.getX(); int bombY = enemy.getY(); // 子弹销毁,坦克受到伤害,判断坦克是否死亡 bullet.reset(); enemy.hurt(bullet); if(enemy.isDead()){ // 坦克销毁,爆炸,每消灭一个敌人判断一次是否胜利 enemy.reset(); enemyDeadNum++; addBomb(bombX,bombY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT); gameWin(); } } } } // 判断是否与块碰撞 for (int m = blockList.size() - 1; m >= 0; m--) { Block block = blockList.get(m); if(GameLogic.getInstance().bulletCollideBlock(bullet,block)) { //如果碰上了 // 记录块坐标 int bombX = block.getX(); int bombY = block.getY(); // 子弹销毁 bullet.reset(); if(block.getBlockKind() == Block.BLOCK_KIND_BRICK){ // 砖块销毁,爆炸 blockList.remove(m); addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT); } else{ addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT); } } } // 判断是否与基地碰撞 if(camp.getState() == Camp.CAMP_STATE_RUNNING){ if(GameLogic.getInstance().bulletCollideCamp(bullet,camp)) { //基地GG //子弹销毁,基地销毁,基地爆炸,游戏结束 bullet.reset(); camp.setState(Camp.CAMP_STATE_FREE); addBomb(camp.getX(),camp.getY(),camp.getWidth(),camp.getHeight()); gameOver(); //这样就可以自毁基地了 } } } } // 判断敌方子弹是否与我方坦克或块或大本营碰撞(不需要判断敌方坦克状态,因为即使坦克销毁子弹可能仍然在飞) for (int i = 0; i < enemyPool.size(); i++) { // 判断是否与我方坦克碰撞 Enemy enemy = enemyPool.get(i); for (int j = 0; j < enemy.getBulletPool().size(); j++){ Bullet bullet = enemy.getBulletPool().get(j); if(bullet.getState() == Bullet.BULLET_STATE_RUNNING) { // 判断子弹是否与坦克碰撞 if(GameLogic.getInstance().bulletCollideTank(bullet,hero)) { //如果碰上了 // 记录坦克坐标,因为坦克销毁时会改变其坐标 int bombX = hero.getX(); int bombY = hero.getY(); //子弹销毁、坦克受伤、判断是否死亡 bullet.reset(); hero.hurt(bullet); if(hero.isDead()){ // 坦克销毁并爆炸,游戏结束 hero.reset(); addBomb(bombX,bombY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT); gameOver(); } } //判断子弹是否与块碰撞 for (int m = blockList.size() - 1; m >= 0; m--) { Block block = blockList.get(m); // 开始判断 if(GameLogic.getInstance().bulletCollideBlock(bullet,block)) { // 如果碰上了 // 记录块坐标 int bombX = block.getX(); int bombY = block.getY(); bullet.reset(); if(block.getBlockKind() == Block.BLOCK_KIND_BRICK){ // 砖块销毁并爆炸 blockList.remove(m); addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT); } else{ addBomb(bombX,bombY,Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT); } } } // 判断子弹是否与基地碰撞 if(camp.getState() == Camp.CAMP_STATE_RUNNING){ if(GameLogic.getInstance().bulletCollideCamp(bullet,camp)) { // 如果碰上 // 子弹销毁,基地销毁,基地爆炸,游戏结束 bullet.reset(); camp.setState(Camp.CAMP_STATE_FREE); addBomb(camp.getX(),camp.getY(),camp.getWidth(),camp.getHeight()); gameOver(); } } } } } } //添加爆炸效果 private void addBomb(int x,int y,int w,int h){ // 查找空闲的爆炸 Bomb bomb = null; for (int i = 0; i < bombList.size(); i++) { Bomb tmpBomb = bombList.get(i); if(tmpBomb.getState() == Bomb.BOMB_STATE_FREE) { bomb = tmpBomb; break; } } // 没有就增加一个 if(bomb == null){ bomb = new Bomb(-100,-100); bombList.add(bomb); } bomb.setX(x); bomb.setY(y); bomb.setWidth(w); bomb.setHeight(h); bomb.work(); } //字符被输入 @Override public void keyTyped(KeyEvent e){} //某键被按下 @Override public void keyPressed(KeyEvent e){ // 游戏未开始或结束后禁止按键 if(this.gameState != GAME_STATE_RUNNING){return;} int keyCode = e.getKeyCode(); switch (keyCode){ case KeyEvent.VK_W: case KeyEvent.VK_UP: //两个case一个break hero.move(Tank.TANK_DIRECTION_UP); break; case KeyEvent.VK_D: case KeyEvent.VK_RIGHT: hero.move(Tank.TANK_DIRECTION_RIGHT); break; case KeyEvent.VK_S: case KeyEvent.VK_DOWN: hero.move(Tank.TANK_DIRECTION_DOWN); break; case KeyEvent.VK_A: case KeyEvent.VK_LEFT: hero.move(Tank.TANK_DIRECTION_LEFT); break; case KeyEvent.VK_SPACE: hero.shoot(); break; } } //某键被释放 @Override public void keyReleased(KeyEvent e){} //利用线程来定时刷新重绘游戏画面 private void refresh(){ new Thread(() ->{ while (this.gameState == GAME_STATE_RUNNING) { collide(); // 碰撞处理 repaint(); // 开始刷新 try { // 延时睡眠 Thread.sleep(repaintInterval); } catch (InterruptedException e){ e.printStackTrace(); } } }).start(); } //绘制游戏画面,利用双缓冲机制防止画面闪烁 @Override public void paint(Graphics g){ // 完成初始化工作 super.paint(g); // 开始游戏时 if(this.gameState == GAME_STATE_READY){ // 清背景 g.setColor(Color.GRAY); g.fillRect(0,0,this.getWidth(),this.getHeight()); // 显示 g.setColor(Color.ORANGE); g.setFont(new Font("微软雅黑",Font.BOLD,60)); g.drawString("坦 克 大 战", 180,160); g.setColor(Color.BLUE); g.setFont(new Font("微软雅黑",Font.BOLD,40)); g.drawString("2023.6.15", 220,250); g.setColor(Color.WHITE); g.setFont(new Font("宋体",Font.PLAIN,20)); g.drawString("面向对象程序设计答辩", 220,420); return; } // 游戏结束时 if(this.gameState == GAME_STATE_OVER){ g.setColor(Color.BLACK); g.fillRect(0,0,this.getWidth(),this.getHeight()); g.setColor(Color.RED); g.setFont(new Font("宋体",Font.BOLD,60)); g.drawString("游戏结束\n", 180,170); g.setColor(Color.GREEN); g.drawString("感谢游玩", 180,280); g.setColor(Color.WHITE); g.setFont(new Font("宋体",Font.PLAIN,20)); g.drawString("面向对象程序设计答辩", 200,420); } // 游戏进行中 if(this.gameState == GAME_STATE_RUNNING){ // 设置游戏面板区域 g.setColor(Color.LIGHT_GRAY); g.fillRect(0,0,this.getWidth(),this.getWidth()); g.setColor(Color.WHITE); g.fill3DRect(GAME_ACTION_WIDTH,0,2,GAME_ACTION_HEIGHT,true); // 绘制分数 // 敌方坦克信息 enemyModel.draw(g); g.setColor(Tank.TANK_COLOR_ENEMY); g.setFont(new Font("微软雅黑",Font.BOLD,20)); g.drawString("总数:" + enemyPoolMaxNum,enemyModel.getX() ,enemyModel.getY() + 70); g.drawString("死亡:" + enemyDeadNum,enemyModel.getX() ,enemyModel.getY() + 100); g.drawString("剩余:" + (enemyPoolMaxNum - enemyDeadNum),enemyModel.getX() ,enemyModel.getY() + 130); // 我方坦克信息 heroModel.draw(g); g.setColor(Tank.TANK_COLOR_HERO); g.setFont(new Font("微软雅黑",Font.BOLD,20)); g.drawString("歼敌:"+enemyDeadNum ,heroModel.getX() - 1 ,heroModel.getY() + 70); g.drawString("生命:" + hero.getHp() ,heroModel.getX() ,heroModel.getY() + 100); // 关口信息 g.setColor(Color.BLACK); int gradeModelX = heroModel.getX(); int gradeModelY = heroModel.getY() + 150; g.fillRect(gradeModelX,gradeModelY,3,40); Polygon triangle = new Polygon(); triangle.addPoint(gradeModelX + 3, gradeModelY); triangle.addPoint(gradeModelX + 3, gradeModelY + 20); triangle.addPoint(gradeModelX + 40, gradeModelY + 20); g.setColor(Color.RED); g.fillPolygon(triangle); g.setColor(Color.WHITE); g.setFont(new Font("微软雅黑",Font.BOLD,20)); g.drawString("关数:" + this.grade ,gradeModelX ,gradeModelY + 70); //双缓冲机制来重绘画面,先把所有的元素绘制到缓冲图片上,再将该图片一次性绘制到画面上 Graphics ig = bufferedImage.getGraphics(); //得到缓冲图片的画笔 // 设置游戏面板区域 ig.setColor(Color.BLACK); ig.fillRect(0,0,GAME_ACTION_WIDTH,GAME_ACTION_HEIGHT); // 绘制地图 for (Block block : this.blockList){block.draw(ig);} // 绘制基地 if(camp.getState() == Camp.CAMP_STATE_RUNNING){camp.draw(ig);} // 绘制我方坦克 hero.draw(ig); // 绘制我方子弹 for (Bullet bullet : hero.getBulletPool()){if(bullet.getState() == Bullet.BULLET_STATE_RUNNING){bullet.draw(ig);}} // 绘制敌方坦克、子弹 for (int i = 0; i < enemyPool.size(); i++) { Enemy enemy = enemyPool.get(i); // 绘制坦克 if(enemy.getState() == Tank.TANK_STATE_RUNNING){enemy.draw(ig);} // 绘制子弹 for (Bullet bullet : enemy.getBulletPool()){if(bullet.getState() == Bullet.BULLET_STATE_RUNNING){bullet.draw(ig);}} } // 绘制爆炸 for (Bomb bomb : bombList){if(bomb.getState() == Bomb.BOMB_STATE_RUNNING){bomb.draw(ig);}} // 将缓冲图片一次性显示到画面上 g.drawImage(bufferedImage,0,0,null); } } public Hero getHero(){return hero;} public Vector<Enemy> getEnemyPool(){return enemyPool;} public List<Block> getBlockList(){return blockList;} public Camp getCamp(){return camp;} public void setGrade(int grade){this.grade = grade;} } ———————————————————————————— package TankWarrrrrrr; public class GameLogic{ private static GameLogic instance; //创建唯一实例 private GamePanel gamePanel; //创建游戏面板 public GameLogic(GamePanel gamePanel){ this.gamePanel = gamePanel; } //得到唯一实例 public static GameLogic getInstance(){ return instance; } //设置唯一实例 public static void setInstance(GameLogic gameLogic){ instance = gameLogic; } //判断矩形1是否碰撞到矩形2 public boolean rectCollideRect(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){ // 判断原理(1、矩形1的四个顶点是否落在矩形2里;2、矩形2的四个顶点是否落在矩形1里。若高度或宽阔相等时特殊判断) //挨着不算碰撞 // 判断矩形1的四个顶点是否落在矩形2里 if((x1 > x2 && x1 < x2 + w2 && y1 > y2 && y1 < y2 + h2) || (x1 + w1 > x2 && x1 + w1 < x2 + w2 && y1 > y2 && y1 < y2 + h2) || (x1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 + h1 < y2 + h2) || (x1 + w1 > x2 && x1 + w1 < x2 + w2 && y1 + h1 > y2 && y1 + h1 < y2 + h2)) {return true;} // 判断矩形2的四个顶点是否落在矩形1里 if((x2 > x1 && x2 < x1 + w1 && y2 > y1 && y2 < y1 + h1) || (x2 + w2 > x1 && x2 + w2 < x1 + w1 && y2 > y1 && y2 < y1 + h1) || (x2 > x1 && x2 < x1 + w1 && y2 + h2 > y1 && y2 + h2 < y1 + h1) || (x2 + w2 > x1 && x2 + w2 < x1 + w1 && y2 + h2 > y1 && y2 + h2 < y1 + h1)) {return true;} // 特殊情况处理 // 若2个矩形的宽度相等时 if(w1 == w2){if(x1 == x2 && x1 + w1 == x2 + w2 && ((y1 > y2 && y1 < y2 + h2) || (y1 + h1 > y2 && y1 + h1 < y2 + h2))){return true;}} // 若2个矩形的高度相等时 if(h1 == h2){if(y1 == y2 && y1 + h1 == y2 + h2 && ((x1 > x2 && x1 < x2 + w2) || (x1 + w1 > x2 && x1 + w1 < x2 + w2))){return true;}} // 2个矩形完全重合 if(x1 == x2 && y1 == y2 && w1 == w2 && h1 == h2){return true;} return false; } //判断坦克移动时的下一个位置是否碰撞到任何对象 public boolean tankMoveCollide(Tank tank){ int newX = tank.getX(); int newY = tank.getY(); // 得到移动后的新坐标 switch (tank.getDirection()){ case Tank.TANK_DIRECTION_UP: newY = tank.getY() - tank.getSpeed(); break; case Tank.TANK_DIRECTION_RIGHT: newX = tank.getX() + tank.getSpeed(); break; case Tank.TANK_DIRECTION_DOWN: newY = tank.getY() + tank.getSpeed(); break; case Tank.TANK_DIRECTION_LEFT: newX = tank.getX() - tank.getSpeed(); break; } // 判断是否碰撞到边界 switch (tank.getDirection()) { case Tank.TANK_DIRECTION_UP: if(newY < 0){return true;} break; case Tank.TANK_DIRECTION_RIGHT: if(newX + Tank.TANK_WIDTH > GamePanel.GAME_ACTION_WIDTH){return true;} break; case Tank.TANK_DIRECTION_DOWN: if(newY + Tank.TANK_HEIGHT > GamePanel.GAME_ACTION_HEIGHT){return true;} break; case Tank.TANK_DIRECTION_LEFT: if(newX < 0){return true;} break; } // 判断是否碰撞到敌方坦克 for (int i = 0; i < gamePanel.getEnemyPool().size(); i++){ Enemy enemy = gamePanel.getEnemyPool().get(i); if(enemy.getState() == Tank.TANK_STATE_RUNNING && tank != enemy) { if(rectCollideRect(newX,newY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT,enemy.getX(),enemy.getY(),Tank.TANK_WIDTH,Tank.TANK_HEIGHT)){return true;} } } // 判断是否碰撞到我方坦克 if(tank.getTankKind() == Tank.TANK_KIND_ENEMY) { if(rectCollideRect(newX,newY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT,gamePanel.getHero().getX(),gamePanel.getHero().getY(),Tank.TANK_WIDTH,Tank.TANK_HEIGHT)){return true;} } // 判断是否碰撞到块 for (Block block : gamePanel.getBlockList()){ if(rectCollideRect(newX,newY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT,block.getX(),block.getY(),Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT)){return true;} } // 判断是否碰撞基地 if(gamePanel.getCamp().getState() == Camp.CAMP_STATE_RUNNING){ if(rectCollideRect(newX,newY,Tank.TANK_WIDTH,Tank.TANK_HEIGHT,gamePanel.getCamp().getX(),gamePanel.getCamp().getY(),gamePanel.getCamp().getWidth(),gamePanel.getCamp().getHeight())){return true;} } return false; } //判断坦克是否碰撞到坦克 public boolean tankCollideTank(Tank tank1,Tank tank2){ return rectCollideRect(tank1.getX(),tank1.getY(),Tank.TANK_WIDTH,Tank.TANK_HEIGHT,tank2.getX(),tank2.getY(),Tank.TANK_WIDTH,Tank.TANK_HEIGHT); } //判断子弹是否碰撞到坦克 public boolean bulletCollideTank(Bullet bullet,Tank tank){ return rectCollideRect(bullet.getX(),bullet.getY(),bullet.getWidth(),bullet.getHeight(),tank.getX(),tank.getY(),Tank.TANK_WIDTH,Tank.TANK_HEIGHT); } //判断子弹是否碰撞到块 public boolean bulletCollideBlock(Bullet bullet,Block block){ return rectCollideRect(bullet.getX(),bullet.getY(),bullet.getWidth(),bullet.getHeight(),block.getX(),block.getY(),Block.BLOCK_WIDTH,Block.BLOCK_HEIGHT); } //判断子弹是否碰撞到基地 public boolean bulletCollideCamp(Bullet bullet,Camp camp){ return rectCollideRect(bullet.getX(),bullet.getY(),bullet.getWidth(),bullet.getHeight(),camp.getX(),camp.getY(),camp.getWidth(),camp.getHeight()); } //判断子弹是否碰撞到子弹 public boolean bulletCollideBullet(Bullet bullet1,Bullet bullet2) { return rectCollideRect(bullet1.getX(),bullet1.getY(),bullet1.getWidth(),bullet1.getHeight(),bullet2.getX(),bullet2.getY(),bullet2.getWidth(),bullet2.getHeight()); } //得到某范围内的随机整数 public static int getRandomInt(int min,int max) { return (int)(min + Math.random() * (max - min + 1)); } }
5.GameMap.java游戏地图
代码如下(示例)
package TankWarrrrrrr; public class GameMap{ //各关地图[26行26列](0-空地,1-砖块,2-铁块) private static byte[][][] gradeMap ={ { //第一关地图 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,1,1,0,0,2,2,2,0,2,0,0,2,0,0,2,0,2,0,2,0,1,1,0,0}, {0,0,1,1,0,0,0,2,0,2,0,2,0,2,2,0,2,0,2,2,0,0,1,1,0,0}, {0,0,1,1,0,0,0,2,0,2,2,2,0,2,0,2,2,0,2,2,0,0,1,1,0,0}, {0,0,1,1,0,0,0,2,0,2,0,2,0,2,0,0,2,0,2,0,2,0,1,1,0,0}, {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0}, {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0}, {0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0} }, //第二关地图 { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,1,1,1,1,1,1,1,0,0,2,2,2,0,0,1,1,1,1,1,1,1,1,0,0}, {0,0,1,1,1,1,1,1,1,0,0,2,2,2,0,0,1,1,1,1,1,1,1,1,0,0}, {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0}, {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0}, {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0}, {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0}, {0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,0,0}, {0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}, {2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0}, {0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0}, {0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0}, {0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0}, {0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0}, {0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0}, {2,2,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,2,2}, {2,2,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,2,2} }, //第三关地图 { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0}, {0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0}, {0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0}, {0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0}, {0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0}, {0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0}, {0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0}, {0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}, {2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,2,2,0,0}, {0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,2,2,0,0}, {0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,2,2,0,0}, {0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,2,2,0,0}, {0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,2,2,0,0}, {0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,0,2,2,0,0,2,2,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0}, {2,2,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,2,2}, {2,2,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,2,2} }, //第四关地图 { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,0,0}, {0,0,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2,2,2,2,2,2,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,1,1,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,2,2,2,1,1,0,0}, {0,0,1,1,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,2,2,2,1,1,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1}, {2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,2,2}, {0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,2,2,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,2,2,0,0}, {0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0}, {0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0}, {0,0,0,2,2,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,2,2,0,0}, {0,0,0,2,2,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,0,0,2,2,0,0}, {0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {2,2,2,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,2,2,2}, {1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1}, {1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1} }, //第五关地图 { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0}, {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2}, {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,2}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}, {0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }, // 第六关地图 { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,2,2,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,2,2,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0}, {0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1}, {2,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,2,2}, {0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,0,0,2,2,0,0,0,0,1,1,0,0,1,1,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }, // 第七关地图 { {0,0,0,0,0,0,2,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,2,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0}, {0,0,1,1,0,0,2,2,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,2,2,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1,2,2,1,1,0,0}, {0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1,2,2,1,1,0,0}, {0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0}, {0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,1,1,0,0,1,1,2,2}, {0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,1,1,0,0,1,1,2,2}, {0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,2,2,0,0,0,0,0,0,0,0}, {0,0,1,1,1,1,1,1,0,0,0,0,0,0,2,2,0,0,0,0,0,0,1,1,0,0}, {0,0,1,1,1,1,1,1,0,0,0,0,0,0,2,2,0,0,0,0,0,0,1,1,0,0}, {0,0,0,0,0,0,2,2,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {0,0,0,0,0,0,2,2,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0}, {2,2,1,1,0,0,2,2,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0}, {2,2,1,1,0,0,2,2,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,2,2,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,2,2,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}, {0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0}, {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,0,0,0,0,0,0,2,2,0,0,0,0,1,1,0,0,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0}, {0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0} } }; private static int gradeCount = gradeMap.length; //总关卡数 private static int[] enemyTankNum = {5,10,15,20,25,25,25}; //各关敌方坦克数量 //返回某关地图 public static byte[][] getGameMap(int grade){ // 由于数组是个对象,而原始地图是不允许被修改的,所以不能直接赋值(引用地址),得复制一个新的地图让游戏随便修改。 byte[][] tempMap = null; if(grade > 0 && grade <= gradeCount){ tempMap = gradeMap[grade - 1]; } else{ tempMap = gradeMap[0]; } //开始复制 int row = tempMap.length; int column = tempMap[0].length; byte[][] returnMap = new byte[row][column]; for (int i = 0; i < row; i++){ for (int j = 0; j < column; j++){ returnMap[i][j] = tempMap[i][j]; } } return returnMap; } //功能:返回总关卡数 public static int getGradeCount(){return gradeCount;} //返回某关敌方坦克数量 public static int getEnemyTankNum(int grade){ if(grade < 1 || grade > gradeCount){grade = gradeCount;} return enemyTankNum[grade - 1]; } }
6.Tank.java坦克父类
设置坦克父类,创建各种常量,作为参数由我方坦克和敌方坦克继承,从而生成游戏内的坦克单位
代码如下
package TankWarrrrrrr;
import java.awt.*;
import java.util.Vector;
public class Tank{
//坦克类别常量
public final static int TANK_KIND_HERO = 0; // 我方坦克
public final static int TANK_KIND_ENEMY = 1; // 敌方坦克
//坦克颜色常量
public final static Color TANK_COLOR_HERO = Color.YELLOW; // 我方坦克颜色
public final static Color TANK_COLOR_ENEMY = Color.CYAN; // 敌方坦克颜色
//坦克方向常量
public final static int TANK_DIRECTION_UP = 0; // 向上
public final static int TANK_DIRECTION_RIGHT = 1; // 向右
public final static int TANK_DIRECTION_DOWN = 2; // 向下
public final static int TANK_DIRECTION_LEFT = 3; // 向左
//坦克状态常量
public final static int TANK_STATE_FREE = 0; // 空闲中
public final static int TANK_STATE_RUNNING = 1; // 运行中
//坦克最大血量值
public final static int TANK_MAX_BLOOD = 100;
//坦克尺寸常量
public final static int TANK_WIDTH = 40;
public final static int TANK_HEIGHT = 40;
private int x; //坦克左上角X坐标
private int y; //坦克左上角Y坐标
private int speed = 8; //坦克速度
private int hp = TANK_MAX_BLOOD; //坦克血量
private int direction = TANK_DIRECTION_UP; //坦克方向
private int tankKind = TANK_KIND_HERO; //坦克类别
private int state = TANK_STATE_FREE; //坦克状态
//子弹池(考虑线程安全用Vector,没用ArrayList)
private Vector<Bullet> bulletPool = new Vector<>();
//上次射击时间(用来设置2次射击最小时间间隔,禁止连续射击)
private long lastShootTime = System.currentTimeMillis();
public Tank(int tankKind, int x, int y, int direction){
this.tankKind = tankKind;
this.x = x;
this.y = y;
this.direction = direction;
}
public void draw(Graphics g){
// 绘制血条
g.setColor(Color.YELLOW);
g.fill3DRect(this.x,this.y,TANK_WIDTH,3,false); // 底色
g.setColor(Color.RED);
g.fill3DRect(this.x,this.y,(hp * TANK_WIDTH)/TANK_MAX_BLOOD,3,false); // 血量(计算宽度时由于都是int类型,因此除法是放到最后计算的,防止出现结果为0的问题【int取整了】)
g.setColor(Color.WHITE);
int tankToBloodHeight = 5; // 坦克到血条的高度
// 设置坦克颜色
if(this.tankKind == TANK_KIND_HERO) { // 我方坦克颜色
g.setColor(TANK_COLOR_HERO);
}
else { // 敌方坦克颜色
g.setColor(TANK_COLOR_ENEMY);
}
// 根据方向开始绘制坦克
switch (direction){
case TANK_DIRECTION_UP:
g.fill3DRect(this.x + tankToBloodHeight,this.y + tankToBloodHeight,7,30,false); // 左边轮子
g.fill3DRect(this.x + 23 + tankToBloodHeight,this.y + tankToBloodHeight,7,30,false); // 右边轮子
g.fill3DRect(this.x + 7 + tankToBloodHeight,this.y + 5 + tankToBloodHeight,16,20,false); // 驾驶室
g.fillOval(this.x + 9 + tankToBloodHeight,this.y + 9 + tankToBloodHeight,12,12); // 炮台
g.fill3DRect(x + 14 + tankToBloodHeight,y + tankToBloodHeight,3,15,false); // 炮管
break;
case TANK_DIRECTION_RIGHT:
g.fill3DRect(this.x + tankToBloodHeight,this.y + tankToBloodHeight,30,7,false); // 上边轮子
g.fill3DRect(this.x + tankToBloodHeight,this.y + 23 + tankToBloodHeight,30,7,false); // 下边轮子
g.fill3DRect(this.x + 5 + tankToBloodHeight,this.y + 7 + tankToBloodHeight,20,16,false); // 驾驶室
g.fillOval(this.x + 9 + tankToBloodHeight,this.y + 9 + tankToBloodHeight,12,12); // 炮台
g.fill3DRect(x + 15 + tankToBloodHeight,y + 14 + tankToBloodHeight,15,3,false); // 炮管
break;
case TANK_DIRECTION_DOWN:
g.fill3DRect(this.x + tankToBloodHeight,this.y + tankToBloodHeight,7,30,false); // 左边轮子
g.fill3DRect(this.x + 23 + tankToBloodHeight,this.y + tankToBloodHeight,7,30,false); // 右边轮子
g.fill3DRect(this.x + 7 + tankToBloodHeight,this.y + 5 + tankToBloodHeight,16,20,false); // 驾驶室
g.fillOval(this.x + 9 + tankToBloodHeight,this.y + 9 + tankToBloodHeight,12,12); // 炮台
g.fill3DRect(x + 14 + tankToBloodHeight,y + 15 + tankToBloodHeight,3,15,false); // 炮管
break;
case TANK_DIRECTION_LEFT:
g.fill3DRect(this.x + tankToBloodHeight,this.y + tankToBloodHeight,30,7,false); // 上边轮子
g.fill3DRect(this.x + tankToBloodHeight,this.y + 23 + tankToBloodHeight,30,7,false); // 下边轮子
g.fill3DRect(this.x + 5 + tankToBloodHeight,this.y + 7 + tankToBloodHeight,20,16,false); // 驾驶室
g.fillOval(this.x + 9 + tankToBloodHeight,this.y + 9 + tankToBloodHeight,12,12); // 炮台
g.fill3DRect(x + tankToBloodHeight,y + 14 + tankToBloodHeight,15,3,false); // 炮管
break;
}
}
//坦克移动,direction为方向
public void move(int direction){
if(this.direction == direction) { // 方向相同,加速前进(要判断边界及是否碰撞到别的对象)
if(!GameLogic.getInstance().tankMoveCollide(this)) { // 没有碰撞,可以移动
switch (direction){
case TANK_DIRECTION_UP:
this.y -= this.speed;
break;
case TANK_DIRECTION_RIGHT:
this.x += this.speed;
break;
case TANK_DIRECTION_DOWN:
this.y += this.speed;
break;
case TANK_DIRECTION_LEFT:
this.x -= this.speed;
break;
}
}
}
else { // 方向不同,仅调整方向不前进
this.direction = direction;
}
}
//坦克射击
public void shoot(){
// 禁止连续射击
long curShootTime = System.currentTimeMillis();
if((curShootTime - this.lastShootTime) >= 500) { // 2发/秒
this.lastShootTime = curShootTime;
}
else{
return;
}
// 在子弹池中寻找空闲的子弹
Bullet bullet = null;
for (int i = 0; i < bulletPool.size(); i++){
Bullet tmpBullet = bulletPool.get(i);
if(tmpBullet.getState() == Bullet.BULLET_STATE_FREE) {
bullet = tmpBullet;
break;
}
}
// 没有就增加一个
if(bullet == null){
bullet = new Bullet(this);
bulletPool.add(bullet);
}
// 设置子弹位置
switch (this.direction){
case TANK_DIRECTION_UP:
bullet.setPosition(this.x + TANK_WIDTH/2 - bullet.getWidth()/2,this.y - bullet.getHeight(),this.direction);
break;
case TANK_DIRECTION_RIGHT:
bullet.setPosition(this.x + TANK_WIDTH,this.y + TANK_HEIGHT/2 - bullet.getHeight()/2,this.direction);
break;
case TANK_DIRECTION_DOWN:
bullet.setPosition(this.x + TANK_WIDTH/2 - bullet.getWidth()/2,this.y + TANK_HEIGHT,this.direction);
break;
case TANK_DIRECTION_LEFT:
bullet.setPosition(this.x - bullet.getWidth(),this.y + TANK_HEIGHT/2 - bullet.getHeight()/2,this.direction);
break;
}
// 让子弹飞一会
bullet.fly();
}
//坦克受到伤害
public void hurt(Bullet bullet){
this.hp -= bullet.getAtk();
if(this.hp < 0){this.hp = 0;}
}
//坦克是否死亡
public boolean isDead(){
return this.hp <= 0;
}
//坦克开始工作
public void work() {
this.state = TANK_STATE_RUNNING;
}
//坦克重置
public void reset(){
this.setX(-100);
this.setY(-100);
this.setHp(Tank.TANK_MAX_BLOOD);
this.setState(TANK_STATE_FREE);
}
public int getX(){return x;}
public void setX(int x){this.x = x;}
public int getY(){return y;}
public void setY(int y){this.y = y;}
public int getSpeed(){return speed;}
public void setSpeed(int speed){this.speed = speed;}
public int getHp(){return hp;}
public void setHp(int hp){this.hp = hp;}
public int getDirection(){return direction;}
public void setDirection(int direction){this.direction = direction;}
public int getState(){return state;}
public void setState(int state){this.state = state;}
public int getTankKind(){return tankKind;}
public Vector<Bullet> getBulletPool(){return bulletPool;}
}
7.我方的坦克代码
代码如下
package TankWarrrrrrr;
public class Hero extends Tank{
public Hero(int x, int y, int direction){
super(TANK_KIND_HERO, x, y, direction);
}
}
8.敌方的坦克代码
在继承父类坦克常量参数的基础上,通过线程和判定语句实现敌方坦克的运行,移动,攻击的行为,与我方坦克博弈
代码如下
package TankWarrrrrrr;
public class Enemy extends Tank{
public Enemy(int x, int y, int direction){
super(TANK_KIND_ENEMY, x, y, direction);
}
@Override
public void work(){
super.work();
// 启动线程让坦克跑
new Thread(()->{
//System.out.println("坦克线程启动...");
while (this.getState() == TANK_STATE_RUNNING){
try{
Thread.sleep(200);
}
catch (InterruptedException e){
e.printStackTrace();
}
// 随机确认是原地不动还是移动(0-不动,其它-移动)
if(GameLogic.getRandomInt(0,8) != 0) { // 移动(概率设大点)
// 随机确认是改变方向还是向前移动(0-改变方向,其它-向前移动)
if(GameLogic.getRandomInt(0,12) == 0) { // 改变方向(概率设小点)
int newDirection = GameLogic.getRandomInt(TANK_DIRECTION_UP, TANK_DIRECTION_LEFT + 3);
if(newDirection > TANK_DIRECTION_LEFT){newDirection = TANK_DIRECTION_DOWN;} // 向下概率设大点
this.setDirection(newDirection);
}
else { // 向前移动
// 如果到边界了就换方向
boolean toBorder = false; // 默认未到边界
switch (this.getDirection()){
case TANK_DIRECTION_UP:
if((this.getY() - this.getSpeed() < 0)){
toBorder = true;
}
break;
case TANK_DIRECTION_RIGHT:
if((this.getX() + TANK_WIDTH + this.getSpeed() > GamePanel.GAME_ACTION_WIDTH)){
toBorder = true;
}
break;
case TANK_DIRECTION_DOWN:
if((this.getY() + TANK_HEIGHT + this.getSpeed() > GamePanel.GAME_ACTION_HEIGHT)){
toBorder = true;
}
break;
case TANK_DIRECTION_LEFT:
if((this.getX() - this.getSpeed() < 0)){
toBorder = true;
}
break;
}
if(toBorder) { // 到边界了换方向
int newDirection = GameLogic.getRandomInt(TANK_DIRECTION_UP, TANK_DIRECTION_LEFT);
this.setDirection(newDirection);
}
else { // 继续前进
this.move(this.getDirection());
}
}
}
// 随机确认是发射子弹还是省子弹(1-发射,其它-不发射)
if(GameLogic.getRandomInt(0,8) == 1){
this.shoot();
}
}
}).start();
}
}
9.Bullet.java子弹类
设置子弹常量和属性,确定子弹的基础参数,状态和攻击力上下限,通过线程完成子弹启动的运行,随机设定子弹的伤害,根据攻击力高低进行判定,从而确定子弹颜色
代码如下(示例)
package TankWarrrrrrr;
import java.awt.*;
public class Bullet{
//子弹状态常量
public final static int BULLET_STATE_FREE = 0; // 空闲中
public final static int BULLET_STATE_RUNNING = 1; // 运行中
//子弹攻击力常量
public final static int BULLET_MAX_ATTACK = 100; // 最大攻击力
public final static int BULLET_MIN_ATTACK = 20; // 最小攻击力
private int x; //子弹左上角X坐标
private int y; //子弹左上角Y坐标
private int width = 10; //子弹宽度
private int height = 10; //子弹高度
private int direction; //子弹方向
private int speed = 16; //子弹速度
private int state = BULLET_STATE_FREE; //子弹状态
private Tank tank; //所属坦克
private int atk; //子弹攻击力
public Bullet(Tank tank){
this.tank = tank;
this.atk = GameLogic.getRandomInt(BULLET_MIN_ATTACK,BULLET_MAX_ATTACK);
}
//设置子弹位置
public void setPosition(int x,int y,int direction){
this.x = x;
this.y = y;
this.direction = direction;
}
//功能:子弹重置
public void reset() {
this.x = -100;
this.y = -100;
this.atk = GameLogic.getRandomInt(BULLET_MIN_ATTACK,BULLET_MAX_ATTACK); // 重新随机生成攻击力
this.state = BULLET_STATE_FREE;
}
//子弹飞行
public void fly(){
// 设置子弹状态为运行中
this.state = BULLET_STATE_RUNNING;
//启动子弹线程
new Thread(()->{
while (this.state == BULLET_STATE_RUNNING) { //tank.getState() == Tank.TANK_STATE_RUNNING &&
try{
Thread.sleep(50);
}
catch (InterruptedException e){
e.printStackTrace();
}
switch (direction){
case Tank.TANK_DIRECTION_UP:
if(this.y - this.speed >= 0){
this.y -= this.speed;
}
else{
this.reset();
}
break;
case Tank.TANK_DIRECTION_RIGHT:
if(this.x + this.width + this.speed <= GamePanel.GAME_ACTION_WIDTH){
this.x += this.speed;
}
else{
this.reset();
}
break;
case Tank.TANK_DIRECTION_DOWN:
if(this.y + this.height + this.speed <= GamePanel.GAME_ACTION_HEIGHT){
this.y += this.speed;
}
else{
this.reset();
}
break;
case Tank.TANK_DIRECTION_LEFT:
if(this.x >= this.speed) {
this.x -= this.speed;
}
else{
this.reset();
}
break;
}
}
}).start();
}
// 画子弹
public void draw(Graphics g){
if(tank.getTankKind() == Tank.TANK_KIND_HERO) { // 我方子弹
g.setColor(Tank.TANK_COLOR_HERO);
}
else { // 敌方子弹
g.setColor(Tank.TANK_COLOR_ENEMY);
}
g.fillOval(this.x,this.y,this.width,this.height);
// 根据攻击力画加强子弹
g.setColor(Color.RED);
if(this.atk == 100){
g.fillOval(this.x,this.y,this.width,this.height);
}
else if(this.atk >= 90) {
g.fillOval(this.x + 1,this.y + 1,this.width - 2,this.height - 2);
}
else if(this.atk >= 70){
g.fillOval(this.x + 2,this.y + 2,this.width - 4,this.height - 4);
}
else if(this.atk >= 50){
g.fillOval(this.x + 3,this.y + 3,this.width - 6,this.height - 6);
}
}
public int getX(){return x;}
public int getY(){return y;}
public int getWidth(){return width;}
public int getHeight(){return height;}
public int getDirection(){return direction;}
public int getSpeed(){return speed;}
public int getState(){return state;}
public int getAtk(){return atk;}
}
10. Bomb.java爆炸效果
设置爆炸参数,根据进度呈现爆炸效果,增添坦克消灭时的特效
代码如下(示例)
package TankWarrrrrrr;
import java.awt.*;
public class Bomb{
//爆炸状态常量
public final static int BOMB_STATE_FREE = 0; // 空闲中
public final static int BOMB_STATE_RUNNING = 1; // 运行中
private int x; //爆炸左上角X坐标
private int y; //爆炸左上角Y坐标
private int width = 20; //爆炸宽度
private int height = 20; //爆炸高度
private int state = BOMB_STATE_FREE; //状态
//爆炸进度,根据它来决定显示哪种爆炸形状,-1-不显示爆炸,0-准备显示,1-显示第一种爆炸形状,2-显示第二种爆炸形状,3-显示第三种爆炸形状
public int bombProgress = -1;
public Bomb(int x, int y){
this.x = x;
this.y = y;
}
public void work(){
this.state = BOMB_STATE_RUNNING; // 设置爆炸状态为运行中
bombProgress = 0; // 爆炸进度,准备显示
}
//重置爆炸
public void reset(){
this.setX(-100);
this.setY(-100);
this.state = BOMB_STATE_FREE;
this.bombProgress = -1;
}
// 画爆炸,每帧显示一种形状,共三种,即3帧结束爆炸
public void draw(Graphics g) {
// 进度走起
this.bombProgress++;
// 根据进度显示某种爆炸形状
switch (this.bombProgress){
case 1: // 第一种形状
g.setColor(Color.WHITE);
g.fillRoundRect(this.x + 5,this.y + 5,20,20,10,10);
g.fillOval(this.x + 10,this.y,10,30);
g.setColor(Color.YELLOW);
g.drawOval(this.x + 10,this.y,10,30);
g.setColor(Color.WHITE);
g.fillOval(this.x,this.y + 10,30,10);
g.setColor(Color.YELLOW);
g.drawOval(this.x,this.y + 10,30,10);
break;
case 2: // 第二种形状
g.setColor(Color.WHITE);
g.fillOval(this.x + 12,this.y + 5,6,20);
g.setColor(Color.YELLOW);
g.drawOval(this.x + 12,this.y + 5,6,20);
g.setColor(Color.WHITE);
g.fillOval(this.x + 5,this.y + 12,20,6);
g.setColor(Color.YELLOW);
g.drawOval(this.x + 5,this.y + 12,20,6);
break;
case 3: // 第三种形状
g.setColor(Color.WHITE);
g.fillOval(this.x + 10,this.y + 10,10,10);
g.setColor(Color.YELLOW);
g.drawOval(this.x + 10,this.y + 10,10,10);
break;
default:
this.reset();
break;
}
}
public int getX(){return x;}
public void setX(int x){this.x = x;}
public int getY(){return y;}
public void setY(int y){this.y = y;}
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;}
public int getState(){return state;}
}
----------------------
package TankWarrrrrrr;
public class Brick extends Block{
public Brick(int x, int y){
super(BLOCK_KIND_BRICK, x, y);
}
}
11.Block.java砖块与铁块的父类
设置砖块和铁块的父类,设定不同的参数,确定砖块和铁块的外观和属性,使砖块可以通过攻击击破,铁块不可被击破
代码如下(示例)
package TankWarrrrrrr;
import java.awt.*;
//块和铁块父类
public class Block{
public final static int BLOCK_KIND_BRICK = 1; // 砖块 //块类别常量
public final static int BLOCK_KIND_IRON = 2; // 铁块
public final static int BLOCK_WIDTH = Tank.TANK_WIDTH/2; //块尺寸常量,和坦克等大
public final static int BLOCK_HEIGHT = Tank.TANK_HEIGHT/2 ;
private int x; //块左上角X坐标
private int y; //块左上角Y坐标
private int blockKind = BLOCK_KIND_BRICK; //块类别
public Block(int blockKind,int x, int y){
this.blockKind = blockKind;
this.x = x;
this.y = y;
}
public void draw(Graphics g){ //画块
if(this.blockKind == BLOCK_KIND_BRICK) { // 画砖块
g.setColor(new Color(210, 105, 30));
g.fillRect(this.x,this.y,BLOCK_WIDTH,BLOCK_HEIGHT);
g.setColor(new Color(244, 164, 96));
g.drawLine(this.x,this.y,this.x + BLOCK_WIDTH - 1,this.y);
g.drawLine(this.x,this.y + BLOCK_HEIGHT / 2,this.x + BLOCK_WIDTH - 1,this.y + BLOCK_HEIGHT / 2);
g.drawLine(this.x,this.y,this.x,this.y + BLOCK_HEIGHT / 2);
g.drawLine(this.x + BLOCK_WIDTH / 2,this.y + BLOCK_HEIGHT / 2, this.x + BLOCK_WIDTH / 2, this.y + BLOCK_HEIGHT - 1);
}
else if(this.blockKind == BLOCK_KIND_IRON) { // 画铁块
g.setColor(new Color(190, 190, 190));
g.fillRect(this.x,this.y,BLOCK_WIDTH,BLOCK_HEIGHT);
g.setColor(Color.WHITE);
g.fillRect(this.x + 3,this.y + 3,BLOCK_WIDTH - 6,BLOCK_HEIGHT - 6);
g.draw3DRect(this.x + 3,this.y + 3,BLOCK_WIDTH - 6,BLOCK_HEIGHT - 6,true);
g.drawLine(this.x + 1,this.y + 1,this.x + 3,this.y + 3);
g.drawLine(this.x + BLOCK_WIDTH - 1,this.y + 1,this.x + BLOCK_WIDTH - 3,this.y + 3);
g.drawLine(this.x + 1,this.y + BLOCK_HEIGHT - 1,this.x + 3,this.y + BLOCK_HEIGHT - 3);
g.drawLine(this.x + BLOCK_WIDTH - 1,this.y + BLOCK_HEIGHT - 1,this.x + BLOCK_WIDTH - 3,this.y + BLOCK_HEIGHT - 3);
}
}
public int getX(){return x;}
public void setX(int x){this.x = x;}
public int getY(){return y;}
public void setY(int y){this.y = y;}
public int getBlockKind(){return blockKind;}
}
12.Brick.java砖块
代码如下(示例)
package TankWarrrrrrr;
public class Brick extends Block{
public Brick(int x, int y){
super(BLOCK_KIND_BRIKCK, x, y);
}
}
13.Iron.java铁块
代码如下(示例)
package TankWarrrrrrr;
public class Iron extends Block{
public Iron(int x, int y){
super(BLOCK_KIND_IRON, x, y);
}
}
14.Camp.java营地
代码如下(示例)
package TankWarrrrrrr;
import java.awt.*;
public class Camp{
//基地状态常量
public final static int CAMP_STATE_FREE = 0; // 空闲中
public final static int CAMP_STATE_RUNNING = 1; // 运行中
private int x; // 基地左上角X坐标
private int y; //营地左上角Y坐标
private int width = Tank.TANK_WIDTH; //基地宽度
private int height = Tank.TANK_HEIGHT; //基地高度
private int state = CAMP_STATE_FREE; //基地状态
private int elementWidth = 2; //元素宽度
private int elementHeight = 2; //元素高度
private static byte[][] campMap = //基地地图
{
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0},
{1,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1},
{0,2,1,1,1,0,0,0,1,0,0,1,1,0,0,1,1,1,2,0},
{1,1,2,0,1,0,0,0,1,1,1,1,0,0,0,1,0,2,1,1},
{0,0,1,2,1,1,0,0,1,1,1,1,0,0,1,1,2,1,0,0},
{0,1,1,1,2,1,0,0,1,1,1,1,0,0,1,2,1,1,1,0},
{0,0,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,0,0},
{0,0,0,1,1,1,2,1,1,1,1,1,1,2,1,1,1,0,0,0},
{0,0,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,0,0},
{0,0,0,1,1,1,1,1,1,2,1,2,1,1,1,1,1,0,0,0},
{0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0},
{0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0},
{0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0},
{0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,1,0,1,0,1,1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
public Camp(int x, int y){
this.x = x;
this.y = y;
}
//画基地
public void draw(Graphics g){
int row = campMap.length;
int column = campMap[0].length;
for (int i = 0; i < row; i++){
for (int j = 0; j < column; j++){
int mapValue = campMap[i][j];
if(mapValue == 1){
g.setColor(Color.WHITE);
drawElement(g,this.x + elementWidth * j,this.y + elementHeight * i);
}
else if(mapValue == 2){
g.setColor(Color.LIGHT_GRAY);
drawElement(g,this.x + elementWidth * j,this.y + elementHeight * i);
}
}
}
}
//画元素
private void drawElement(Graphics g,int x,int y){
g.fillRect(x,y,elementWidth,elementHeight);
g.setColor(Color.WHITE);
g.draw3DRect(x,y,elementWidth,elementHeight,true);
}
public int getX(){return x;}
public void setX(int x){this.x = x;}
public int getY(){return y;}
public void setY(int y){this.y = y;}
public int getWidth(){return width;}
public int getHeight(){return height;}
public int getState(){return state;}
public void setState(int state){this.state = state;}
}
总结:
通过这次课程设计,感觉收获颇多,团队内两个人通过不断地学习查找,修改,更新,完成了最终的确定的代码。也切实感受到了自己不会的东西还有太多,思路的设计上反映出学习需要自己长期积累。由于能力有限,所以在整个课程设计的底层逻辑上对他人有所借鉴,最后才让整个程序完全运行起来。