VUE游戏设计:实现外星人的攻击冲击波

游戏的趣味性在与各种关卡和难度,游戏的难度如上台阶,具有层层递进的性质。本节我们为太空防御游戏增加关卡功能,让游戏的难度由低到高,每一关我们称作一个冲击波,前面的冲击波,外星人的数量比较少,下落速度也相对较慢,等到后面的冲击波时,外星人的数量会越来越多,速度和攻击力越来越大,于是游戏的难度也逐渐变大。

当完成本节代码后,我们会得到如下效果,在每一轮冲击波开始时,界面会出现如下信号:


这里写图片描述

当游戏进行到后几轮冲击波时,外星人数量和种类越来越多,战况越来越激烈:

这里写图片描述

我们看看代码的实现,在gamescenecomponent.vue中添加新的数据结构:

export default {
    data () {
      return {
      ....
      // change 1
        waves: {}
      }
    },
    methods: {
      init () {
      ....
      // change 2
      this.initWaves()
      this.startWave()
      ...
      },
      // change 3
      initWaves () {
        console.log('begin init wave')
        this.waves.nextWave = 0
        this.waves.isActive = false
        // 定义一轮冲击波中外星人从天而降的次序
        this.waves.enemySummonOrder = ['EnemyDummy', 'Enemy1', 'Enemy2', 'Enemy3', 'Boss', 'Boss2']
        console.log('init wave data')
        this.waves.data = [
        // 第一轮冲击波
        {'EnemyDummy': 1, frequency: 10},
        // 第二轮冲击波
        {'EnemyDummy': 8, 'Enemy1': 5, 'Enemy2': 5, 'Boss': 2, frequency: 150},
        // 第三轮冲击波
        {'EnemyDummy': 1, 'Enemy1': 1, 'Enemy2': 1, 'Enemy3': 1, 'Boss': 1, 'Boss2': 30, frequency: 50}
        ]
        console.log('init wave sprite')
        this.nextWaveSprite = new this.assetsLib.WaveCleared()
        this.stage.addChild(this.nextWaveSprite)
        this.nextWaveSprite.x = 999
      },

      // change4 启动一轮外星人攻击的冲击波
      startWave () {
        this.energies = 120
        this.waves.currentWave = this.waves.data[this.waves.nextWave]
        this.waves.isActive = true
        this.waves.enemiesSummoned = 0
      },

      // change 5
      wavesCleared () {
        this.waves.nextWave += 1
        if (this.waves.nextWave >= this.waves.data.length) {
          this.waves.nextWave = this.waves.data.length - 1
        }
      },
}

上面代码定义了外星人攻击冲击波的数据结构,其中定义了每一轮攻击过程中,外星人的种类和数量,在每一轮冲击波启动前,页面会出现“wave cleared"的字体显示特效,startWave启动新一轮冲击波流程,wavesCleared在冲击波结束后,负责清理页面和各种数据结构。接下来我们实现冲击波流程的动态效果:

// change 6
      waveTick () {
        if (!this.waves.isActive) {
          return
        }

        if (this.cjs.Ticker.getTicks() % this.waves.currentWave.frequency === 0) {
          // 依次把不同种类的外星人召唤出来
          var accumunateTargetCount = 0
          for (var i = 0, len = this.waves.enemySummonOrder.length; i < len; i++) {
            var enemyType = this.waves.enemySummonOrder[i]
            // 获得外星人个数
            var targetCount = this.waves.currentWave[enemyType] || 0
            accumunateTargetCount += targetCount
            if (this.waves.enemiesSummoned < accumunateTargetCount) {
              break
            }
          }

          if (this.waves.enemiesSummoned >= accumunateTargetCount) {
            this.waves.isActive = false
          } else {
            this.addEnemy(enemyType)
            this.waves.enemiesSummoned += 1
          }
        }
      },
      tick () {
      ....
       // change 9
        this.wavesSpan.textContent = this.waves.nextWave + 1

        this.boardTick()

        // change 7
        this.waveTick()
        if (!this.waves.isActive && this.areEnemiesCleared()) {
          this.boardLayer.isAddingBuilding = false
          this.removeAllBuildings()
          this.removeAllBullets()
          this.wavesCleared()

          // 显示字体动画
          this.cjs.Tween.get(this.nextWaveSprite).to({x: this.canvas.width / 2, y: this.canvas.height / 2, alpha: 0}).to({alpha: 1.0}, 300).wait(1000).to({alpha: 0}, 300).to({x: 999})

          this.startWave()
        }
      },
      // change 8
      removeAllBuildings () {
        for (var i = 0; i < this.boardLayer.cols; i++) {
          for (var j = 0; j < this.boardLayer.rows; j++) {
            this.removeBuilding(this.boardLayer.buildingMap[i][j])
          }
        }

        this.satelliteList = []
        this.castleList = []
      },
      areEnemiesCleared () {
        return this.enemyList.length === 0
      },
      removeAllBullets () {
        this.bulletList.length = 0
        this.effectLayer.removeAllChildren()
      },

waveTick函数用于在冲击波进行的过程中不断的更新页面。每一轮冲击波有哪些种类的外星人已经外星人数量是多少,都是由wave.data中定义的数据决定的。waveTick的作用是把wave.data中定义的外星人种类和数量加载到页面上,然后刷新页面,实现页面动态效果。waveTick是在时钟函数tick中被调用的,在tick函数中,一旦判断到一轮冲击波结束时,他们把"wave cleared"的字体特效显示到页面上,就如开头图片展示的那样。removeAllBuildings和removeAllBullets负责在一轮冲击波结束时,将页面上的建筑物和飞翔的子弹清除掉。最后我们从资源库中将不停种类的外星人资源加载到浏览器里,并在合适的时候将他们描绘在页面上:

// change 9
      enemy1 () {
        console.log('enemy1')
        var enemy1 = this.enemy()
        enemy1.addChild(new this.assetsLib.Enemy1())
        enemy1.attackSpeed = 50
        enemy1.speed = enemy1.originalSpeed
        enemy1.name = 'enemy1'

        return enemy1
      },
      enemy2 () {
        console.log('enemy2')
        var enemy2 = this.enemy()
        enemy2.addChild(new this.assetsLib.Enemy2())
        enemy2.originalSpeed = 1.0
        enemy2.attackSpeed = 40
        enemy2.hp = 8
        enemy2.deceleration = 0.008
        enemy2.speed = enemy2.originalSpeed
        enemy2.name = 'enemy2'

        return enemy2
      },
      boss2 () {
        var bossEnemy = this.enemy()
        bossEnemy.addChild(new this.assetsLib.Boss2())
        bossEnemy.originalSpeed = 0.2
        bossEnemy.deceleration = 0.002
        bossEnemy.hp = 300
        bossEnemy.attackSpeed = 50

        bossEnemy.name = 'boss'
        return bossEnemy
      },
      enemy3 () {
        console.log('enemy3')
        var enemy3 = this.enemy()
        enemy3.addChild(new this.assetsLib.Enemy3())
        enemy3.originalSpeed = 3.0
        enemy3.attackSpeed = 10
        enemy3.hp = 8
        enemy3.deceleration = 0.002
        enemy3.speed = enemy3.originalSpeed
        enemy3.name = 'enemy3'

        return enemy3
      },

完成上面代码后,我们就可以看到如开头第二幅图那样的,五花八门的外星人从天而降,我们在底部架起各种炮台和建筑打击外星人,整幅画面具有星球大战般的绚丽感。

更详细的讲解和代码调试演示过程,请点击链接

更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:


这里写图片描述
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容