05.04 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 7
addBullet (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


分享到:


相關文章: