增加功能
我方坦克在发射的子弹消亡后,才能发射新的子弹。同时实现发多颗子弹
- 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(); } } }
还没有评论,来说两句吧...