Html飞机大战(十六): 完成"清除"敌机奖励类

好家伙,

 

我们先来尝试完成一个最简单的功能

正面buff:

1.消灭全图敌机

 

我们要先找一个好看一点的素材

 

 

把背景弄成透明的(搞了好久),感谢度娘的技术支持Photoshop中如何把图片的背景变成透明的-百度经验 (baidu.com)

你问我为什么是篮球?

只因你太美

 

为了方便测试,我们先弄个测试版本出来

// 全局函数 隔一段时间就来初始化一架敌机/奖励
    function createComponent() {
      const currentTime = new Date().getTime();
      if (currentTime - ENEMY_LASTTIME >= ENEMY_CREATE_INTERVAL) {
        let ran = Math.floor(Math.random() * 100);
        // if (ran < 55) {
        //   enemies.push(new Enemy(E1));
        // } else if (ran < 85 && ran > 55) {
        //   enemies.push(new Enemy(E2));
        // } else if (ran < 95 && ran > 85) {
        //   enemies.push(new Enemy(E3));
        // } else if (ran > 95) {
        //   awards.push(new award(C1));

        // }
        if (ran < 30) {
          enemies.push(new Enemy(E1));
        } else {
          awards.push(new award(C1));
        }
        ENEMY_LASTTIME = currentTime;
      }
    }

(将原本的敌机生产流程,变成只生产小敌机和奖励类)

这么做是为了方便测试

 

来吧,

1.奖励类图片素材路径

c1: "img/lanqiu.jpg"
const c1 = createImage(IMAGES.c1);

 

 

2.奖励类配置项

const C1 = {
      type: 4,
      width: 75,
      height: 75,
      life: 1,
      score: 1,
      img: c1,
      minSpeed: 5,
      maxSpeed: 10
    };

 

 

3.奖励类

这个奖励类的实现逻辑其实和敌机一样(没有动画渲染,甚至比敌机类更简单一点)

//初始化奖励类
    class award {
      constructor(config) {
        this.type = config.type;
        this.width = config.width;
        this.height = config.height;
        this.x = Math.floor(Math.random() * (480 - config.width));
        this.y = -config.height;
        this.life = config.life;
        this.score = config.score;
        this.img = config.img;
        this.live = true;
        this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;
        this.lastTime = new Date().getTime();
        this.deathIndex = 0;
        this.destory = false;
      }
      move() {
        const currentTime = new Date().getTime();
        if (currentTime - this.lastTime >= this.speed) {
          if (this.live) {
            this.y = this.y + 6;
            this.lastTime = currentTime;
          } else {
            this.destory = true;

          }
        }
      }
      paint(context) {
        context.drawImage(this.img, this.x, this.y, this.width, this.height);
      }
      outOfBounds() {
        if (this.y > 650) {
          return true;
        }
      }
      hit(o) {
        let ol = o.x;
        let or = o.x + o.width;
        let ot = o.y;
        let ob = o.y + o.height;
        let el = this.x;
        let er = this.x + this.width;
        let et = this.y;
        let eb = this.y + this.height;
        if (ol > er || or < el || ot > eb || ob < et) {
          return false;
        } else {
          return true;
        }
      }
      // collide() {
      //   this.life--;
      //   if (this.life === 0) {
      //     this.live = false;
      //     score += this.score;
      //   }
      // }
    }

 

 

4.全局渲染

// 全局函数 来绘制所有的子弹/敌人组件 绘制score&life面板
    function paintComponent() {
      for (let i = 0; i < hero.bulletList.length; i++) {
        hero.bulletList[i].paint(context);
      }
      for (let i = 0; i < enemies.length; i++) {
        enemies[i].paint(context);
      }
      for (let i = 0; i < awards.length; i++) {
        awards[i].paint(context);
      }
      context.font = "20px 微软雅黑";
      context.fillStyle = "red";
      context.textAlign = "left";
      context.fillText("score: " + score, 10, 20);
      context.textAlign = "right";
      context.fillText("life: " + life, 480 - 10, 20);
      //重置样式
      context.fillStyle = "black";
      context.textAlign = "left";
    }

 

 

5.全局移动

// 全局函数 来判断所有的子弹/敌人组件 "负责移动"
    function judgeComponent() {
      for (let i = 0; i < hero.bulletList.length; i++) {
        hero.bulletList[i].move();
      }
      for (let i = 0; i < enemies.length; i++) {
        enemies[i].move();
      }
      for (let i = 0; i < awards.length; i++) {
        awards[i].move();
      }
    }

 

 

6.全局碰撞判断

// 碰撞检测函数
    //此处的碰撞检测包括 
    //1.子弹与敌机的碰撞
    //2.英雄与敌机的碰撞
    //3.英雄与随机奖励的碰撞
    function checkHit() {
      // 遍历所有的敌机
      for (let i = 0; i < awards.length; i++) {
        //检测英雄是否碰到奖励类
        if (awards[i].hit(hero)) {
          //当然了,这个随机奖励的样式也要删了
          awards.splice(i,1);
          //清除所有的敌机
          // for (let i = 0; i < enemies.length; i++) {
          //   enemies.splice(i, 1);
          // }
          enemies.length =0;
          
        }
      }
      for (let i = 0; i < enemies.length; i++) {
        //检测英雄是否撞到敌机
        if (enemies[i].hit(hero)) {
          //将敌机和英雄的destory属性改为true
          enemies[i].collide();
          hero.collide();
        }
        for (let j = 0; j < hero.bulletList.length; j++) {
          enemies[i].hit(hero.bulletList[j]);
          //检测子弹是否撞到敌机
          if (enemies[i].hit(hero.bulletList[j])) {
            //将敌机和子弹的destory属性改为true
            enemies[i].collide();
            hero.bulletList[j].collide();
          }
        }
      }
    }

 

看这里就好

for (let i = 0; i < awards.length; i++) {
        //检测英雄是否碰到奖励类
        if (awards[i].hit(hero)) {
          //当然了,这个随机奖励的样式也要删了
          awards.splice(i,1);
          //清除所有的敌机
          // for (let i = 0; i < enemies.length; i++) {
          //   enemies.splice(i, 1);
          // }
          enemies.length =0;
          
        }
      }

(全删了不就好了,刚开始是想着一个个删的)

 

来看看效果:

 

 (非常nice)

 

现在我们调回上线版本

function createComponent() {
      const currentTime = new Date().getTime();
      if (currentTime - ENEMY_LASTTIME >= ENEMY_CREATE_INTERVAL) {
        let ran = Math.floor(Math.random() * 100);
        if (ran < 55) {
          enemies.push(new Enemy(E1));
        } else if (ran < 85 && ran > 55) {
          enemies.push(new Enemy(E2));
        } else if (ran < 95 && ran > 85) {
          enemies.push(new Enemy(E3));
        } else if (ran > 95) {
          awards.push(new award(C1));

        }
        
        ENEMY_LASTTIME = currentTime;
      }
    }

(随机奖励给个百分之五吧,不然太bug了)

 

来看看效果:

 

 

posted @ 2022-09-18 22:28  养肥胖虎  阅读(85)  评论(0编辑  收藏  举报