day05-线程的应用04

铁佛  金牌会员 | 2022-9-17 08:37:27 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 911|帖子 911|积分 2733

7.线程的应用03

7.4坦克大战5.0版

增加功能:

  • 我方坦克在发射的子弹消亡之后,才能发射新的子弹==>拓展:发射多颗子弹怎么办,控制一次最多只能发射5颗子弹
  • 让敌人坦克发射的子弹消亡之后,可以再发射子弹
  • 当地人的坦克击中我方坦克之后,我方坦克小时,并出现爆炸效果
7.4.1功能1plus:我方坦克连发子弹

思路:

  • 要发射多颗子弹,就使用Vector保存子弹对象
  • 在绘制我方子弹的时候需要遍历Vector集合
  • 同时要修改击中判定方法hitTank
修改处1:Hero类:
  1. package li.TankGame.version05;
  2. import java.util.Vector;
  3. /**
  4. * @author 李
  5. * @version 5.0
  6. */
  7. public class Hero extends Tank {
  8.     //定义一个shot对象,表示一个射击(线程)
  9.     Shot shot = null;
  10.     //定义一个集合用来装hero发射的子弹对象,使其可以发射多颗子弹
  11.     Vector<Shot> shots = new Vector<>();
  12.     public Hero(int x, int y) {
  13.         super(x, y);
  14.     }
  15.     //射击
  16.     public void shotEnemyTank() {
  17.         if (shots.size() == 5) {//如果当前的子弹已经有 5颗,就不继续创建新的shot对象,直到当前子弹集合中的子弹对象被移除
  18.             return ;
  19.         }
  20.         //创建Shot对象,根据当前Hero对象的坐标位置和方向来设置子弹的位置和方向
  21.         switch (getDirect()) {//获取Hero对象的方向
  22.             case 0://向上
  23.                 shot = new Shot(getX() + 20, getY(), 0);
  24.                 break;
  25.             case 1://向右
  26.                 shot = new Shot(getX() + 60, getY() + 20, 1);
  27.                 break;
  28.             case 2://向下
  29.                 shot = new Shot(getX() + 20, getY() + 60, 2);
  30.                 break;
  31.             case 3://向左
  32.                 shot = new Shot(getX(), getY() + 20, 3);
  33.                 break;
  34.         }
  35.         //把新创建的shot放入到shots集合中
  36.         shots.add(shot);
  37.         //启动Shot线程
  38.         new Thread(shot).start();
  39.     }
  40. }
复制代码
2:MyPanel的paint方法(部分):
  1. //画出hero发射的子弹
  2. for (int i = 0; i < hero.shots.size(); i++) {
  3.     Shot shot = hero.shots.get(i);
  4.     if (shot != null && shot.isLive) { //如果子弹对象不为空,并且处于存活状态(isLive=true)
  5.         System.out.println("hero的子弹被绘制");
  6.         g.draw3DRect(hero.shots.get(i).x, hero.shots.get(i).y, 2, 2, false);
  7.     } else {//如果该shot对象已经无效,就从shot集合中删除
  8.         hero.shots.remove(shot);
  9.     }
  10. }
复制代码
3:在MyPanel的hitTank方法之前再封装一个hitEnemyTank方法:
  1. public void hitEnemyTank(){
  2.     //判断是否击中敌人坦克
  3.     for (int i = 0; i <hero.shots.size() ; i++) {
  4.         Shot shot=hero.shots.get(i);//shot为当前的子弹对象
  5.         if (shot != null && shot.isLive) {//如果当前我的子弹不为空并且子弹还存活
  6.             //就遍历敌人所有的坦克
  7.             for (int j = 0; j < enemyTanks.size(); j++) {
  8.                 EnemyTank enemyTank = enemyTanks.get(j);
  9.                 hitTank(shot, enemyTank);
  10.             }
  11.         }
  12.     }
  13. }
复制代码
7.4.3功能3:我方坦克被击中时销毁并出现爆炸效果

思路:编写方法,判断敌人的坦克是否击中我们的坦克
修改1:在Tank类中增加isLive属性
  1. package li.TankGame.version05;
  2. import java.util.Vector;
  3. public class EnemyTank extends Tank implements Runnable {
  4.     //在敌人坦克类使用Vector保存多个shot
  5.     Vector<Shot> shots = new Vector<>();
  6.     boolean isLive = true;
  7.     public EnemyTank(int x, int y) {
  8.         super(x, y);
  9.     }
  10.     @Override
  11.     public void run() {
  12.         while (true) {
  13.             //这我们先判断当前的坦克是否存活
  14.             // 在判断shots.size<3是否真,为真,说明当前的3颗子弹已经消亡了,
  15.             // 就创建一颗子弹,放到shots集合中,并启动线程
  16.             if (isLive && (shots.size() < 3)) {//可以通过控制数字来修改敌人坦克一次发射几颗子弹
  17.                 Shot s = null;
  18.                 //判断坦克的方创建对应的子弹
  19.                 switch (getDirect()) {
  20.                     case 0://向上
  21.                         s = new Shot(getX() + 20, getY(), 0);
  22.                         break;
  23.                     case 1://向右
  24.                         s = new Shot(getX() + 60, getY() + 20, 1);
  25.                         break;
  26.                     case 2://向下
  27.                         s = new Shot(getX() + 20, getY() + 60, 2);
  28.                         break;
  29.                     case 3://向左
  30.                         s = new Shot(getX(), getY() + 20, 3);
  31.                         break;
  32.                 }
  33.                 shots.add(s);
  34.                 new Thread(s).start();
  35.             }
  36.             //根据坦克的方法来继续移动
  37.             switch (getDirect()) {
  38.                 case 0://上
  39.                     //让坦克保持一个方向走50步
  40.                     for (int i = 0; i < 50; i++) {
  41.                         if (getY() > 0) {
  42.                             moveUp();
  43.                         }
  44.                         try {
  45.                             Thread.sleep(50);
  46.                         } catch (InterruptedException e) {
  47.                             e.printStackTrace();
  48.                         }
  49.                     }
  50.                     break;
  51.                 case 1://右
  52.                     //让坦克保持一个方向走50步
  53.                     for (int i = 0; i < 50; i++) {
  54.                         if (getX() + 60 < 700) {//700为面板宽度
  55.                             moveRight();//走一步
  56.                         }
  57.                         try {
  58.                             Thread.sleep(50);//每走一步就休眠50毫秒
  59.                         } catch (InterruptedException e) {
  60.                             e.printStackTrace();
  61.                         }
  62.                     }
  63.                     break;
  64.                 case 2://下
  65.                     for (int i = 0; i < 50; i++) {
  66.                         if (getY() + 60 < 550) {//550为面板宽度
  67.                             moveDown();
  68.                         }
  69.                         try {
  70.                             Thread.sleep(50);
  71.                         } catch (InterruptedException e) {
  72.                             e.printStackTrace();
  73.                         }
  74.                     }
  75.                     break;
  76.                 case 3://左
  77.                     for (int i = 0; i < 50; i++) {
  78.                         if (getX() > 0) {
  79.                             moveLeft();
  80.                         }
  81.                         try {
  82.                             Thread.sleep(50);
  83.                         } catch (InterruptedException e) {
  84.                             e.printStackTrace();
  85.                         }
  86.                     }
  87.                     break;
  88.             }
  89.             //随机地改变坦克的方向 0-3
  90.             setDirect((int) (Math.random() * 4));//[0,4)的取整
  91.             //如果被击中了,就退出线程
  92.             if (!isLive) {
  93.                 break;//退出线程
  94.             }
  95.         }
  96.     }
  97. }
复制代码
2:修改MyPanel类的hitTank方法的参数改为(Shot s, Tank enemyTank):即将获得的坦克类型改为父类Tank
3 :在hitTank方法前面增加hitHero方法:
  1. boolean isLive = true ;
复制代码
4:在MyPanel类的paint方法里面增加绘出hero坦克的条件:
原来:

现在:
  1. public void hitHeroTank() {
  2.         //遍历敌人所有的坦克
  3.         for (int i = 0; i < enemyTanks.size(); i++) {
  4.             //取出当前的敌人坦克
  5.             EnemyTank enemyTank = enemyTanks.get(i);
  6.             //取出当enemyTank所有子弹
  7.             for (int j = 0; j < enemyTank.shots.size(); j++) {
  8.                 //取出一颗子弹
  9.                 Shot shot = enemyTank.shots.get(j);
  10.                 //判断该子弹是否击中我们的坦克
  11.                 if (hero.isLive && shot.isLive) {
  12.                     hitTank(shot, hero);
  13.                 }
  14.             }
  15.         }
  16.     }
复制代码
ps:关于我方坦克被打爆后还是可以再继续移动操作的问题,是因为并没有处理hero对象,可以在Hero类中先判断hero对象的isLive为true,之后再进行移动发射等操作。该问题之后再解决。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

铁佛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表