VUE+WebPack遊戲設計:實現子彈發射擊打外星人效果

本節將要實現的遊戲效果是,當用戶在頁面上拖拽了一個炮臺後,炮臺會自動發射出子彈,當飛躍的子彈打中外星人時,外星人就會從頁面上消失,本節代碼完成後效果如下:


VUE+WebPack遊戲設計:實現子彈發射擊打外星人效果

我們看看代入如何實現。第一步是構建子彈對象,代碼如下:

// change 1 bullet (damageDeal) { var obj = new this.cjs.Container() obj.addChild(new this.assetsLib.Bullet()) obj.cache(-25, -25, 50, 50) obj.damageDeal = damageDeal | 1 return obj }, // change 2 bulletTick (bullet) { if (this.cjs.Ticker.getPaused()) { return } bullet.y -= 1.5 }

bullet函數構造一個cjs容器對象,然後從資源庫中加載子彈圖片資源,並調用cache緩存在頁面裡,damgeDeal用於設置子彈的攻擊力。bulletTick在時鐘循環函數中被調用,它會不斷的修改子彈對象在頁面上的y座標,從而實現子彈在頁面上的飛昇效果。

圖片中發射子彈的炮臺是我們以前實現的castle對象,我們要把所有的castle對象加入到一個列表中,這樣我們才能知道有多少炮臺要發射子彈,所以代碼修改如下:

castle () { var b = this.building() b.addChild(new this.assetsLib.Castle()) b.hp = 300 b.shield = 5 b.damageDeal = 2 b.attackSpeed = 120 // change 3 b.tick = 0 // change 10 this.castleList.push(b) return b },

代碼用castleList數組來記錄所有炮臺,其中的tick變量用來設置炮臺發射子彈的時間間隔。接著我們要增加一個castleTick函數,在主時鐘函數中調用,代碼如下:

// change 4 castleTick () { if (this.cjs.Ticker.getPaused()) { return } for (var i = 0; i < this.castleList.length; i++) { var castle = this.castleList[i] castle.tick += 1 if (castle.tick % castle.attackSpeed === 0) { this.summonBullet(castle) } } for (i = 0; i < this.bulletList.length; i++) { this.bulletTick(this.bulletList[i]) } },

主時鐘循環函數里,它會反覆調用castleTick函數,該函數輪詢castleList數組,從中取出炮臺對象,增加炮臺對象的tick計數器,一旦計數器達到指定值時,它會調用summonBullet函數創建子彈對象,然後該函數又會輪詢子彈對象數組,然後調用blletTick函數設置頁面上子彈對象的y座標,從而使得子彈產生往上飛的效果。我們再看summonBullet函數的實現:

// change 5 summonBullet (castle) { var bullet = this.bullet(castle.damageDeal) bullet.x = castle.x + Math.random() * 20 - 10 bullet.y = castle.y this.addBullet(bullet) },// change 7addBullet (bullet) { this.effectLayer.addChild(bullet) this.bulletList.push(bullet)},

該函數就是調用原先實現的bullet函數創建子彈對象,並把子彈在頁面上的座標設置成與對應的炮臺一致,然後調用addBullet函數把子彈對象加入特效圖層和bulletList數組。這裡用到的幾個變量要在data()函數中增加:

data () { return { .... // change 6 bulletList: [], // change 9 castleList: [] } }

接著我們要在主輪詢函數中添加代碼,驅動上面代碼的調用,在boardTick函數中增加如下代碼:

boardTick () { .... // change 11 this.castleTick() // change 8 輪詢敵人隊列和子彈隊列,看看兩者是否相撞 for (i = this.enemyList.length - 1; i >= 0; i--) { for (var j = this.bulletList.length - 1; j >= 0; j--) { var bullet = this.bulletList[j] var pos = bullet.localToLocal(0, 0, this.effectLayer) rowCol = this.screenToRowCol(pos.x, pos.y) if (this.enemyMap[rowCol.col][rowCol.row] !== undefined) { var enemyHit = this.enemyMap[rowCol.col][rowCol.row] this.enemyDamage(enemyHit, bullet.damageDeal) if (enemyHit.hp <= 0) { this.enemyMap[rowCol.col][rowCol.row] = undefined this.removeItem(this.enemyList, enemyHit) this.boardLayer.removeChild(enemyHit) } this.removeItem(this.bulletList, bullet) this.effectLayer.removeChild(bullet) } } }},....enemyDamage (enemy, damage) { enemy.hp -= damage },

boardTick函數會被主循環函數調用,它會調用castleTick函數,於是炮臺對象會不斷的創建子彈對象。然後代碼通過兩個循環輪詢外星人數組和子彈數組,它從子彈數組中取出子彈對象,將子彈所在的座標轉換成頁面上的行和列,接著根據行和列到外星人分佈圖,也就是enemyMap中查詢,如果對應的位置有外星人對象,那表明子彈擊中了外星人。此時代碼調用enemyDamage函數計算外星人被擊中後會掉多少血,如果外星人的能力耗盡,那麼if(enemyHit.hp <=0)部分的代碼會被執行,於是外星人對象就會從頁面上被刪除。同時不管外星人是否被摧毀,最後的兩句代碼:

this.removeItem(this.enemyList, bullet)this.effectLayer.removeChild(bullet) 

都會把子彈從頁面上去除。完成以上代碼後,圖片所示的效果就可以完成了。

更多詳細內容,請參看視頻:

http://study.163.com/provider-search?keyword=Coding%E8%BF%AA%E6%96%AF%E5%B0%BC


分享到:


相關文章: