Java基础 - 坦克大战(第六章,增加射出子弹与被击中后效果)

193 篇文章 1 订阅
8 篇文章 1 订阅

坦克大战0.4

增加功能

  1. 我方坦克在发射的子弹消亡后,才能发射新的子弹。 => 扩展(发多发子弹怎么办)

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

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

我方坦克在发射的子弹消亡后,才能发射新的子弹

  1. 在按下J键时,我们判断当前hero对象的子弹是否已经销毁
  2. 如果没有销毁,就不去触发 showEnemyTank
  3. 如果已经销毁,才去触发shotEnemyTank
        if (e.getKeyCode() == KeyEvent.VK_J) {  //发射子弹

            if(hero.shot == null || hero.shot.isLive == false)
            hero.shotEnemyTank();
        }
  1. 如果要发射多颗子弹,就是用Vector保存

hero类

    Vector<Shot> shots = new Vector<>();
            //把新创建的shot放入到shots
        shots.add(shot);
  1. 在绘制我方子弹时,需要遍历该Vector 集合
  • 为了优化我们的坦克每次射出多发子弹机制:我们需要把子弹放在一个集合中,我们同样要用Vector集合,我们在hero类创建集合,每次启动一个线程集合时,我们就让子弹集合add(shot),我们在MyPanel类的paint方法中做些修改,将hero的子弹集合shots,遍历取出并绘制,并加入判断语句,如果此子弹为null,并且此子弹isLive属性为true,我们就再画一个子弹,else,此子弹集合元素执行remove()

MyPanel类

        //画出敌人的坦克,遍历Vector
        for (int i = 0; i < enemyTanks.size(); i++) {
            //取出坦克
            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.draw3DRect(shot.x, shot.y, 2, 2, false);
                    } else {
                        //从Vector 移除
                        enemyTank.shots.remove(shot);
                    }
                }
            }
        if (e.getKeyCode() == KeyEvent.VK_J) {  //发射子弹
            if (hero.shot.isLive == false || hero.shot.isLive == true)
          hero.shotEnemyTank();
        }

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

  • 为了使敌方坦克可以不断射出子弹:我们需要为敌方子弹新建一个vector集合,当敌方坦克子弹集合长度为空时,我们就新建子弹线程集合启动一个线程、并且添加一个敌方坦克集合元素,需要考虑子弹方向,我们依然用switch来控制,因为我们每个敌方坦克都是一个单独的线程与单独的集合,我们得到敌方坦克的坐标位置,通过direct属性,给子弹方向赋值

EnemyTank类

public void run() {
        //然后随机的改变坦克方向
        while (true) {
            //这里我们判断如果shots size() = 0,创建一颗子弹,放入到shots集合中,并启动
            if(isLive && shots.size() == 0 ){

                Shot s = null;
                //判断坦克的方向,创建对应的子弹
                switch(getDirect()){
                    case 0:
                        s = new Shot(getX() + 20,getY(),0);
                        break;
                    case 1:
                        s = new Shot(getX() + 60,getY(),1);
                        break;
                    case 2:
                        s = new Shot(getX() + 20,getY() + 60,2);
                        break;
                    case 3:
                        s = new Shot(getX() + 20,getY(),3);
                        break;
                }
                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) {
                                e.printStackTrace();
                            }
                        }
                    }

                    break;
                case 1://for (int i = 0; i < 30; i++) {
//                        if (getX() + 60 < 1000){
                        if (getX() < 902) {

                            moveRight();
                            //休眠50毫秒
                            try {
                                Thread.sleep(50);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    break;
                case 2://for (int i = 0; i < 30; i++) {
                        if (getY() < 620) {
//                        if(getY() + 60 < 750){
                            moveDown();
                            //休眠50毫秒
                            try {
                                Thread.sleep(50);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    break;
                case 3://for (int i = 0; i < 30; i++) {
                        if (getX() > 0) {
                            moveLeft();
                            //休眠50毫秒
                            try {
                                Thread.sleep(50);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    break;
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //随机改变坦克方向0 - 3
            setDirect((int) (Math.random() * 4));
            //如果坦克被击中线程终止
            if (!isLive) {
                break;
            }
        }


    }
}

发射多颗子弹后,保证每颗子弹都能实际命中敌方坦克

因为我们的子弹与敌方坦克都是一个单独的集合与线程,通过我们的子弹线程不断地遍历子弹集合元素,而每颗子弹线程又不断地遍历敌方坦克,用遍历集合的方法,依然调用hitTank()方法,实现多颗子弹命中功能

MyPanel类新建方法

    public void hitEnemyTank() {
        //遍历我们的子弹
        for (int j = 0; j < hero.shots.size(); j++) {
            Shot shot = hero.shots.get(j);

            //判断是否击中了敌人坦克
            if (shot != null && shot.isLive) {   //当前我的子弹存活
                //遍历所有的坦克
                for (int i = 0; i < enemyTanks.size(); i++) {
                    EnemyTank enemyTank = enemyTanks.get(i);
                    hitTank(shot, enemyTank);
                }
            }
        }
    }

run方法中调用

    @Override
    public void run() {  //每隔10毫秒,重绘区域,刷新绘图区域,子弹就移动
        while (true) {

            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            hitEnemyTank();
            this.repaint();
        }

实现敌方坦克子弹命中我方坦克爆炸功能

因为我们之前已经实现过“我方坦克击中敌方坦克爆炸功能”,所以,我们直接利用参数多态,用hitTank方法传入父类参数Tank类,编写一个hitHero方法,遍历敌人的坦克与每个敌人坦克的每个子弹,判断是否击中我放坦克,并调用我们之前写的hitTank方法,实现击中后爆炸

新建hitHero()方法

    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);
                }
            }
        }

我们虽然实现了子弹击中坦克后爆炸功能,但是,hero坦克依然存在,我们思路依然很清晰,当我们的坦克被击中时,我们给hero坦克isLive属性为false,并给paint方法一个判断语句,如果isLive == false,则不执行draw.hero

 if(hero.isLive)
        drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1);        //type坦克类型

未解决bug

1.我们的hero坦克被击中后,依然可以射出子弹

思路:加入isLive判断语句,好像不行

我的的坦克被击中消失后后,可以移动,可以射出子弹,射出的子弹没有颜色,有弹道,并且是“实弹”

评论 4 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

鬼鬼骑士

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值