定义💣实体类
🚡炸弹的位置
🚡炸弹的生命周期[可以理解为震慑的强度,爆炸强度由强到弱]
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")); 
根据自己的喜好可以自行添加自己想要的爆炸效果
🧛♀️🧛♀️🧛♀️注意!!!
图片的格式必须是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); } }