项目-坦克大战

项目-坦克大战

码农世界 2024-05-16 前端 63 次浏览 0个评论

增加功能

我方坦克在发射的子弹消亡后,才能发射新的子弹。同时实现发多颗子弹

  • 1,在按下J键,我们判断当前hero对象的子弹,是否已经销毁
  • 2,如果没有销毁,就不去触发shotEnemyTank
  • 3,如果已经销毁,才去触发shotEnemyTank
  • 4,如果要发射多颗子弹,就使用Vector保存(hero类)
  • 5,在绘制我方子弹时,需要遍历Vector,在按键J时,再次调用shotEnemyTank
  • 6,如果需要控制在我们的面板上最多只有5颗子弹:用if语句进行判断即可(hero类),

    Hero类

    import java.util.Vector;
    //自己的坦克,继承坦克父类
    public class Hero extends Tank {
        //定义一个Shot对象,表示一个射击(线程)
        Shot shot = null;
        //可以发射多颗子弹
        Vector shots = new Vector<>();
        public Hero(int x, int y) {
            super(x, y);
        }
        public void  shotEnemyTank(){
            //发多颗子弹怎么办? 控制在我们的面板上,最多只有5颗子弹
            if (shots.size()==5){
                return;
            }
            //创建Shot对象,根据当前Hero对象的位置和方向来创建Shot
            switch (getDirect()){//得到Hero对象方向
                case 0://上
                    shot = new Shot(getX()+20,getY(),0);
                    break;
                case 1://右
                    shot = new Shot(getX()+60,getY()+20,1);
                    break;
                case 2://下
                    shot = new Shot(getX()+20,getY()+60,2);
                    break;
                case 3://左
                    shot = new Shot(getX(),getY()+20,3);
                    break;
            }
            //把新创建的shot放入到shots中
            shots.add(shot);
            //启动我们的shot线程
            new Thread(shot).start();
        }
    }
    

    画板类

    改变keyPressed方法

     //当某个键按下,该方法会触发
        @Override
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_W) {//上
                //改变坦克方向
                hero.setDirect(0);
                //让坦克动起来
                if (hero.getY()>0){
                    hero.moveUp();
                }
            } else if (e.getKeyCode() == KeyEvent.VK_S) {//下
                hero.setDirect(2);
                if (hero.getY()+60<750){
                    hero.moveDown();
                }
            } else if (e.getKeyCode() == KeyEvent.VK_A) {//左
                hero.setDirect(3);
                if (hero.getX()>0){
                    hero.moveLeft();
                }
            } else if (e.getKeyCode() == KeyEvent.VK_D) {//右
                hero.setDirect(1);
                if (hero.getX()+60<1000)
                hero.moveRight();
            }
            //如果用户按下的是J,就发射
            if (e.getKeyCode() == KeyEvent.VK_J) {
                //判断hero的子弹是否销毁---发射一颗子弹
                if (hero.shot==null|| !hero.shot.isLive) {
                    //线程销毁后,不代表shot对象为空,所以还需要判断shot的声明周期,才可以继续发子弹
                    hero.shotEnemyTank();
                }
                //发射多颗子弹
                hero.shotEnemyTank();
            }
            //重绘
            repaint();
        }
    

    在paint方法中遍历Vector集合

      @Override
        public void paint(Graphics g) {
            super.paint(g);
            //3,通过画笔填充一个矩形区域   g.fillRect();
            g.fillRect(0, 0, 1000, 750);//填充矩形,默认为黑色
            //画出自己的坦克
            drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1);
    //        drawTank(hero.getX() +100,hero.getY(),g,hero.getDirect(),0);
    //        drawTank(hero.getX() +200,hero.getY(),g,hero.getDirect(),0);
    //        drawTank(hero.getX() +300,hero.getY(),g,hero.getDirect(),1);
            //判断何时画子弹
    //        if (hero.shot != null && hero.shot.isLive == true) {
    //            g.setColor(Color.white);
    //            g.draw3DRect(hero.shot.x, hero.shot.y, 1, 1, false);
    //
    //        }
            //将hero的子弹集合shots,遍历取出绘制
            for (int i = 0; i < hero.shots.size(); i++) {
                Shot shot = hero.shots.get(i);
                if (shot != null && shot.isLive == true) {
                g.setColor(Color.white);
                g.draw3DRect(shot.x, shot.y, 1, 1, false);
            }else {//如果该shot对象已经无效,就从shots集合中拿掉
                    hero.shots.remove(shot);
                }
            }
            //如果bombs 集合中有对象,就画出
            for (int i = 0; i < bombs.size(); i++) {
                //取出来炸弹
                Bomb bomb = bombs.get(i);
                //根据当前这个bomb对象的life值去画出对应的图片
                if (bomb.life > 6) {
                    g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);
                } else if (bomb.life > 3) {
                    g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);
                } else {
                    g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);
                }
                //让这个炸弹的生命值减少
                bomb.lifeDown();
                //如果 bomb life 为0 ,就从bombs的集合中删除
                if (bomb.life == 0) {
                    bombs.remove(bomb);
                }
            }
            //画出敌人的坦克
            for (int i = 0; i < enemyTanks.size(); i++) {
                //从Vector取出坦克
                EnemyTank enemyTank = enemyTanks.get(i);
                //判断当前坦克是否还存活
                if (enemyTank.isLive) {//当敌人坦克时存活的,才画出该坦克
                    drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 0);
                    //画出 enemyTank 所有子弹
                    for (int j = 0; j < enemyTank.shots.size(); j++) {
                        //取出子弹
                        Shot shot = enemyTank.shots.get(j);
                        //绘制
                        if (shot.isLive) {//isLive=true
                            g.setColor(Color.white);
                            g.draw3DRect(shot.x, shot.y, 1, 1, false);
                        } else {
                            //从Vector 移除
                            enemyTank.shots.remove(shot);
                        }
                    }
                }
            }
        }
    

    让敌人坦克发射的子弹消亡后,可以再发射子弹

    • 1,在敌人坦克类中的run方法中判断 Vector集合的数量
    • 2,如果仍然存活且数量小于1,则执行相关业务代码
      //敌人坦克
      public class EnemyTank extends Tank implements Runnable {
          //给敌人坦克类,使用Vector 保存多个Shot
          Vector shots = new Vector<>();
          //定义敌人坦克的存货属性
          boolean isLive = true;
          public EnemyTank(int x, int y) {
              super(x, y);
          }
          @Override
          public void run() {
              while (true) {
                  //这里我们判断如果shots size() = 0; 创建一颗子弹,放入到shots集合,并启动
                  if (isLive&&shots.size()<1){
                      Shot s = null;
                      //判断坦克的方向,创建对应的子弹
                      switch (getDirect()){
                          case 0:
                              s=new Shot(getX()+20,getY(),0);
                          case 1:
                              s=new Shot(getX()+60,getY()+20,0);
                          case 2:
                              s=new Shot(getX()+20,getY()+60,0);
                          case 3:
                              s=new Shot(getX(),getY()+20,0);
                      }
                       shots.add(s);
                      new Thread(s).start();
                  }
                  switch (getDirect()) {
                      //根据坦克的方向来进行移动
                      case 0://向上
                          //让坦克保持一个方向,走30步
                          for (int i = 0; i < 30; i++) {
                              if (getY()>0){
                                  moveUp();
                              }
                              //休眠50好眠
                              try {
                                  Thread.sleep(50);
                              } catch (InterruptedException e) {
                                  throw new RuntimeException(e);
                              }
                          }
                          break;
                      case 1://向右
                          //让坦克保持一个方向,走30步
                          for (int i = 0; i < 30; i++) {
                              if (getX()+60<1000){
                                  moveRight();
                              }
                              //休眠50好眠
                              try {
                                  Thread.sleep(50);
                              } catch (InterruptedException e) {
                                  throw new RuntimeException(e);
                              }
                          }
                          break;
                      case 2://向下
                          //让坦克保持一个方向,走30步
                          for (int i = 0; i < 30; i++) {
                              if (getY()+60<750){
                                  moveDown();
                              }
                              //休眠50好眠
                              try {
                                  Thread.sleep(50);
                              } catch (InterruptedException e) {
                                  throw new RuntimeException(e);
                              }
                          }
                          break;
                      case 3://向左
                          //让坦克保持一个方向,走30步
                          for (int i = 0; i < 10; i++) {
                              if (getX()>0){
                                  moveLeft();
                              }
                              //休眠50好眠
                              try {
                                  Thread.sleep(50);
                              } catch (InterruptedException e) {
                                  throw new RuntimeException(e);
                              }
                          }
                          break;
                  }
                  //休眠50好眠
                  try {
                      Thread.sleep(50);
                  } catch (InterruptedException e) {
                      throw new RuntimeException(e);
                  }
                  // 然后随机的改变坦克方向0-3
                  setDirect((int) (Math.random() * 4));  //0-3
                  //一旦写并发程序,一定要考虑清楚,该线程什么时候结束
                  if (!isLive) {
                      break;
                  }
              }
          }
      }
      

      当敌人的坦克击中我方坦克时,我方坦克消失,并出现爆炸效果

      • 1,编写方法,判断敌人坦克是否击中我方坦克
      • 2,在run方法中调用该方法
        //画板类
        public class MyPanel extends JPanel implements KeyListener, Runnable {
            //定义我的坦克
            Hero hero = null;
            //定义敌人坦克,放入到Vector(线程安全,可以有多个)
            Vector enemyTanks = new Vector<>();
            int enemyTankSize = 3;
            //定义一个Vector,用于存放炸弹(炸弹既不属于我方坦克也不属于地方坦克 ,所以坦克放在画板类)
            //当我们的子弹击中坦克时,就加入一个Bomb对象到bombs
            Vector bombs = new Vector<>();
            //定义三张炸弹图片,用于显示爆炸效果
            Image image1 = null;
            Image image2 = null;
            Image image3 = null;
            public MyPanel() {//初始化自己的坦克
                hero = new Hero(100, 100);
                hero.setSpeed(5);
                //初始化敌人的坦克
                for (int i = 0; i < enemyTankSize; i++) {
                    //创建一个敌人的坦克
                    EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 0);
                    //启动敌人坦克线程,让他动起来
                    new Thread(enemyTank).start();
                    //设置方向
                    enemyTank.setDirect(2);
                    //给该enemyTank 加入一颗子弹
                    Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());
                    enemyTank.shots.add(shot);
                    //启动shot对象
                    new Thread(shot).start();
                    //把敌人的坦克加入的总的坦克对象中
                    enemyTanks.add(enemyTank);
                }
        //        image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/1.gif"));
        //        image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/2.gif"));
        //        image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/3.gif"));
                //初始化照片对象
                image1 = new ImageIcon("image/1.gif").getImage();
                image2 = new ImageIcon("image/2.gif").getImage();
                image3 = new ImageIcon("image/3.gif").getImage();
            }
            @Override
            public void paint(Graphics g) {
                super.paint(g);
                //3,通过画笔填充一个矩形区域   g.fillRect();
                g.fillRect(0, 0, 1000, 750);//填充矩形,默认为黑色
                if (hero != null && hero.isLive){
                //画出自己的坦克
                drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1);}
        //        drawTank(hero.getX() +100,hero.getY(),g,hero.getDirect(),0);
        //        drawTank(hero.getX() +200,hero.getY(),g,hero.getDirect(),0);
        //        drawTank(hero.getX() +300,hero.getY(),g,hero.getDirect(),1);
                //判断何时画子弹
        //        if (hero.shot != null && hero.shot.isLive == true) {
        //            g.setColor(Color.white);
        //            g.draw3DRect(hero.shot.x, hero.shot.y, 1, 1, false);
        //
        //        }
                //将hero的子弹集合shots,遍历取出绘制
                for (int i = 0; i < hero.shots.size(); i++) {
                    Shot shot = hero.shots.get(i);
                    if (shot != null && shot.isLive == true) {
                    g.setColor(Color.white);
                    g.draw3DRect(shot.x, shot.y, 1, 1, false);
                }else {//如果该shot对象已经无效,就从shots集合中拿掉
                        hero.shots.remove(shot);
                    }
                }
                //如果bombs 集合中有对象,就画出
                for (int i = 0; i < bombs.size(); i++) {
                    //取出来炸弹
                    Bomb bomb = bombs.get(i);
                    //根据当前这个bomb对象的life值去画出对应的图片
                    if (bomb.life > 6) {
                        g.drawImage(image1, bomb.x, bomb.y, 60, 60, this);
                    } else if (bomb.life > 3) {
                        g.drawImage(image2, bomb.x, bomb.y, 60, 60, this);
                    } else {
                        g.drawImage(image3, bomb.x, bomb.y, 60, 60, this);
                    }
                    //让这个炸弹的生命值减少
                    bomb.lifeDown();
                    //如果 bomb life 为0 ,就从bombs的集合中删除
                    if (bomb.life == 0) {
                        bombs.remove(bomb);
                    }
                }
                //画出敌人的坦克
                for (int i = 0; i < enemyTanks.size(); i++) {
                    //从Vector取出坦克
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //判断当前坦克是否还存活
                    if (enemyTank.isLive) {//当敌人坦克时存活的,才画出该坦克
                        drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 0);
                        //画出 enemyTank 所有子弹
                        for (int j = 0; j < enemyTank.shots.size(); j++) {
                            //取出子弹
                            Shot shot = enemyTank.shots.get(j);
                            //绘制
                            if (shot.isLive) {//isLive=true
                                g.setColor(Color.white);
                                 g.draw3DRect(shot.x, shot.y, 1, 1, false);
                            } else {
                                //从Vector 移除
                                enemyTank.shots.remove(shot);
                            }
                        }
                    }
                }
            }
            /*
            int x 坦克的横坐标
            int y 坦克的纵坐标
            Graphics g  画笔
            int direct  坦克的方向
            int type  坦克的类型
             */
            public void drawTank(int x, int y, Graphics g, int direct, int type) {
                switch (type) {
                    case 0://敌人的坦克
                        g.setColor(Color.cyan);
                        break;
                    case 1://我的坦克
                        g.setColor(Color.yellow);
                        break;
                }
                //根据坦克的方向,来绘制坦克
                //direct表示方法:  0:向上   1:向右    2:向下    3:向左
                switch (direct) {
                    case 0://表示向上
                        g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                        g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                        g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
                        g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                        g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒
                        break;
                    case 1://表示向右
                        g.fill3DRect(x, y, 60, 10, false);//画出坦克上边轮子
                        g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克下边轮子
                        g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克盖子
                        g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子
                        g.drawLine(x + 30, y + 20, x + 60, y + 20);//画出炮筒
                        break;
                    case 2://表示向下
                        g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                        g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                        g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
                        g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
                        g.drawLine(x + 20, y + 30, x + 20, y + 60);//画出炮筒
                        break;
                    case 3://表示向左
                        g.fill3DRect(x, y, 60, 10, false);//画出坦克上边轮子
                        g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克下边轮子
                        g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克盖子
                        g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子
                        g.drawLine(x + 30, y + 20, x, y + 20);//画出炮筒
                        break;
                    default:
                        System.out.println("暂时没有处理");
                }
            }
            //编写方法,判断敌人坦克是否击中我方坦克
            public void hitHero(){
                //遍历所有的敌人坦克
                for (int i = 0; i < enemyTanks.size(); i++) {
                    //取出敌人坦克
                    EnemyTank enemyTank = enemyTanks.get(i);
                    //遍历enemyTank 对象的所有子弹
                    for (int j = 0; j < enemyTank.shots.size(); j++) {
                        //取出子弹
                        Shot shot = enemyTank.shots.get(j);
                        //判断shot 是否击中我的坦克
                        if (hero.isLive&&shot.isLive){
                            hitTank( shot,hero);
                        }
                    }
                }
            }
            public void hitEnemy(){
                //判断我们的子弹是否击中了敌人坦克
                if (hero.shot != null && hero.shot.isLive) {//当我方的子弹还存活
                    //遍历敌人所有的坦克
                    for (int i = 0; i < enemyTanks.size(); i++) {
                        EnemyTank enemyTank = enemyTanks.get(i);
                        hitTank(hero.shot, enemyTank);
                    }
                }
            }
            //编写方法:判断我方子弹是否击敌人坦克
            //什么时候判断,我方坦克是否击中敌人坦克?  run方法
            public void hitTank(Shot s, Tank tank) {
                //判断s 击中坦克
                switch (tank.getDirect()) {
                    case 0://敌人坦克向上
                    case 2://敌人坦克向下
                        if (s.x > tank.getX() && s.y < tank.getY() + 40 &&
                                s.y > tank.getY() && s.y < tank.getY() + 60) {
                            s.isLive = false;
                            tank.isLive = false;
                            //当我的子弹击中敌人坦克后,将enenmyTank 从Vector 拿掉
                            enemyTanks.remove(tank);
                            //这里敌人坦克被击中
                            //创建Bomb对象,加入到bombs集合
                            Bomb bomb = new Bomb(tank.getX(), tank.getY());
                            bombs.add(bomb);
                        }
                        break;
                    case 1://敌人坦克向右
                    case 3://敌人坦克向下
                        if (s.x > tank.getX() && s.y < tank.getY() + 60 &&
                                s.y > tank.getY() && s.y < tank.getY() + 40) {
                            s.isLive = false;
                            tank.isLive = false;
                            Bomb bomb = new Bomb(tank.getX(), tank.getY());
                            bombs.add(bomb);
                        }
                        break;
                }
            }
            //有字符输出时,该方法就会触发
            @Override
            public void keyTyped(KeyEvent e) {
            }
            //当某个键按下,该方法会触发
            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_W) {//上
                    //改变坦克方向
                    hero.setDirect(0);
                    //让坦克动起来
                    if (hero.getY()>0){
                        hero.moveUp();
                    }
                } else if (e.getKeyCode() == KeyEvent.VK_S) {//下
                    hero.setDirect(2);
                    if (hero.getY()+60<750){
                        hero.moveDown();
                    }
                } else if (e.getKeyCode() == KeyEvent.VK_A) {//左
                    hero.setDirect(3);
                    if (hero.getX()>0){
                        hero.moveLeft();
                    }
                } else if (e.getKeyCode() == KeyEvent.VK_D) {//右
                    hero.setDirect(1);
                    if (hero.getX()+60<1000)
                    hero.moveRight();
                }
                //如果用户按下的是J,就发射
                if (e.getKeyCode() == KeyEvent.VK_J) {
                    //判断hero的子弹是否销毁---发射一颗子弹
                    if (hero.shot==null|| !hero.shot.isLive) {
                        //线程销毁后,不代表shot对象为空,所以还需要判断shot的声明周期,才可以继续发子弹
                        hero.shotEnemyTank();
                    }
                    //发射多颗子弹
                    hero.shotEnemyTank();
                }
                //重绘
                repaint();
            }
            //当某个键释放(松开),该方法会触发
            @Override
            public void keyReleased(KeyEvent e) {
            }
            //添加线程的方法,确保子弹可以重绘
            @Override
            public void run() {//每隔 100毫秒,重绘区域,刷新绘图区域,子弹就移动
                while (true) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    //判断我们坦克是否击中别人
                    hitEnemy();
                    //判断敌人坦克是否击中我们
                    hitHero();
                    this.repaint();
                }
            }
        }
        

转载请注明来自码农世界,本文标题:《项目-坦克大战》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,63人围观)参与讨论

还没有评论,来说两句吧...

Top