动态爆炸效果

本文档详细介绍了如何在坦克大战游戏中实现炸弹爆炸的动态效果,包括定义炸弹实体类,设置其生命周期,并通过Java的线程机制来实时更新画面,展示不同阶段的爆炸图像。同时,讨论了如何在子弹击中坦克时触发爆炸,并通过一个自定义的画板线程持续监控和更新游戏状态,确保爆炸效果的流畅呈现。此外,还展示了如何在框架中添加和启动画板线程,以保持游戏的运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定义💣实体类

  • 🚡炸弹的位置

  • 🚡炸弹的生命周期[可以理解为震慑的强度,爆炸强度由强到弱]

public class Boom {
   int x;
   int y;
   //炸弹的生命周期
   int life=9;
   boolean isLive=true;

   public Boom(int x, int y) {
       this.x = x;
       this.y = y;
   }
   public void lifeTime(){
       if(life>0){
           life--;
       }else {
           isLive=false;
       }
   }
}

画动态💣

  • 👀何时爆炸?
    • 当子弹击中坦克的时候爆炸
  • 👀如何展示爆炸效果
    • 这个要用到开始演示的画图片的方法,可以找到一些静态炸弹爆炸的过程图,然后当炸弹的生命值低于6显示一种效果,当高于6.显示另一种爆炸效果
  • 👀如何用代码实现?
    • 在开始的时候我们可以初始化一个集合用来存放💣,当子弹击中坦克,我们就放一颗炸弹到集合中,然后在展示爆炸效果
    //定义炸弹集合 当子弹击中坦克存放炸弹
    Vector<Boom> booms=new Vector<>();
    //定义爆炸的图片
    Image image1=null;
    Image image2=null;
    Image image3=null;

   //初始化图片
        image1=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/b1.jpg"));
        image2=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/b2.jpg"));
        image3=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/b3.jpg"));
    
  
  ![在这里插入图片描述](https://img-blog.csdnimg.cn/b0a3c43c69ca487db6e27732db90b4c4.png#pic_center)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

根据自己的喜好可以自行添加自己想要的爆炸效果
🧛‍♀️🧛‍♀️🧛‍♀️注意!!!
图片的格式必须是JPG格式,否则无法显示

🚄画板线程

  • 💦为了保证能够随时监听到子弹碰到坦克的时候实现爆炸效果
  • 💦应该将画板也作为一个线程,一直运行,终止的条件就是当我们点击窗口的取消❌按钮时,线程终止
  • 💦所以完成版的画板代码如下:
public class Mypanel extends JPanel implements KeyListener,Runnable {
    //定义我的坦克
    Hero hero=null;
    //定义敌人坦克
    Vector<EnemyTank> enemyTanks=new Vector<>();
    //初始化敌人的坦克个数
    int enemySize=3;
    //定义炸弹集合 当子弹击中坦克存放炸弹
    Vector<Boom> booms=new Vector<>();
    //定义爆炸的图片
    Image image1=null;
    Image image2=null;
    Image image3=null;

    public Mypanel(){
        hero = new Hero(100,100);//初始化自己的坦克
        hero.setSpeed(10);//设置速度
        //初始化敌人坦克  并放入子弹  并开启线程
        for (int i = 0; i < enemySize; i++) {
            //定义一个坦克
            EnemyTank enemyTank=new EnemyTank(100*(i+1),0);
            //设置坦克方向
            enemyTank.setDirect(2);
            //设置敌人坦克速度
            enemyTank.setSpeed(1);
            //定义一个子弹
            Shot shot = new Shot(enemyTank.getX()+20,enemyTank.getY()+60,2);
            //开启坦克线程
            new Thread(enemyTank).start();
            //添加子弹到敌人坦克集合中
            enemyTank.shots.add(shot);
            //开启子弹线程
            new Thread(shot).start();
            //添加坦克到敌人坦克集合中
            enemyTanks.add(enemyTank);
        }
        //初始化图片
        image1=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/b1.jpg"));
        image2=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/b2.jpg"));
        image3=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/b3.jpg"));
    }
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        //画游戏界面大小
        g.fillRect(0,0,1000,750);
        //画自己坦克
        drawTank(hero.getX(),hero.getY(),g,hero.getDirect(),0);

        //画出爆炸效果
        for (int i = 0; i < booms.size(); i++) {
            Boom boom=booms.get(i);
            if(boom.life>6){
                g.drawImage(image2,boom.x,boom.y,80,80,this);
            }
            else if (boom.life>3){
                g.drawImage(image1,boom.x,boom.y,80,80,this);
            }
            else {
                g.drawImage(image3,boom.x,boom.y,80,80,this);
            }
            //让炸弹生命值减少  配合动态爆炸效果
            boom.lifeTime();
            //如果某个炸弹生命值为0  从booms删除
            if(boom.life<=0){
                booms.remove(boom);
            }
        }


        //画敌人坦克
        for (int i = 0; i < enemyTanks.size(); i++) {
            EnemyTank enemyTank = enemyTanks.get(i);
            if(enemyTank.leap){
                //画敌人坦克
                drawTank(enemyTank.getX(),enemyTank.getY(),g,enemyTank.getDirect(),1);
                //画敌人子弹
                for (int j = 0; j < enemyTank.shots.size(); j++) {
                    //先取子弹
                    Shot shot=enemyTank.shots.get(j);
                    //绘制子弹 先判断坐标是否越界 若越界则从shots集合里面去除 否则绘制
                    if(!shot.isLive){
                        enemyTank.shots.remove(j);
                    } else{
                        g.draw3DRect(shot.x,shot.y,3,3,false);
                    }
                }
            }
        }
        //画己方子弹
        if(hero.shot!=null&&hero.shot.isLive==true){
            g.draw3DRect(hero.shot.x,hero.shot.y,3,3,false);
        }
    }

    /**
     *
     * @param x 坦克左上角x坐标
     * @param y 坦克左上角y坐标
     * @param g 画笔
     * @param direct  方向
     * @param type   坦克类型(自己/敌人)
     */
    public void drawTank(int x,int y,Graphics g,int direct,int type){

        //0我的坦克  1敌人坦克
        switch (type){
            case 0:
                g.setColor(Color.cyan);
                break;
            case 1:
                g.setColor(Color.green);
                break;
        }

        //方向 (w 0上 1d 2右 s 3下 a左)
        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,x+20,y+20);//炮筒
                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+60,y+20,x+20,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+20,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,y+20,x+20,y+20);//炮筒
                break;
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyCode()==KeyEvent.VK_W){
           if(hero.getY()>0){
               hero.moveUp();
           }
            hero.setDirect(0);
        } else if (e.getKeyCode()==KeyEvent.VK_D) {
            if(hero.getX()+60<1000){
                hero.moveRight();
            }
            hero.setDirect(1);
        }
        else if (e.getKeyCode()==KeyEvent.VK_S) {
            if (hero.getY()+60<750){
                hero.moveDown();
            }
            hero.setDirect(2);
        }else if (e.getKeyCode()==KeyEvent.VK_A) {
            if (hero.getX()>0){
                hero.moveLeft();
            }
            hero.setDirect(3);
        }

        if (e.getKeyCode()==KeyEvent.VK_J){
            hero.shotEnemyTank();
        }

        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    //判断子弹是否击中坦克
    public void hitEnemyTank(Shot shot,EnemyTank enemyTank){
        switch (enemyTank.getDirect()){
            case 0:
            case 2:
                if(shot.x>enemyTank.getX()&&shot.x<enemyTank.getX()+40
                &&shot.y>enemyTank.getY()&&shot.y<enemyTank.getY()+60){
                    shot.isLive=false;
                    enemyTank.leap=false;
                    enemyTanks.remove(enemyTank);
                    Boom boom=new Boom(enemyTank.getX(),enemyTank.getY());
                    booms.add(boom);
                }
                break;
            case 1:
            case 3:
                if(shot.x>enemyTank.getX()&&shot.x<enemyTank.getX()+60
                        &&shot.y>enemyTank.getY()&&shot.y<enemyTank.getY()+40){
                    shot.isLive=false;
                    enemyTank.leap=false;
                    enemyTanks.remove(enemyTank);
                    Boom boom=new Boom(enemyTank.getX(),enemyTank.getY());
                    booms.add(boom);
                }
                break;
        }
    }
    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
                if(hero.shot!=null && hero.shot.isLive){
                    for (int i = 0; i < enemyTanks.size(); i++) {
                        EnemyTank enemyTank=enemyTanks.get(i);
                        hitEnemyTank(hero.shot,enemyTank);
                    }
                }
            this.repaint();
        }
    }
}

👼框架添加画板线程

  • 💞画板的根基是在我们开始的时候定义的框架里面运行的,所以我们应该在框架的构造器里面开启画板线程

    public class TankGame03 extends JFrame {
        private Mypanel mp=null;
        public static void main(String[] args) {
            TankGame03 tankGame01 = new TankGame03();
        }
    
        public TankGame03() {
            mp=new Mypanel();
            
            🚜🚜🚜🚜
            Thread thread = new Thread(mp);
            thread.start();
            🚜🚜🚜🚜
                
            this.add(mp);
            this.addKeyListener(mp);
            this.setSize(1030,810);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setVisible(true);
        }
    }
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C_x_330

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值