iT邦幫忙

2022 iThome 鐵人賽

DAY 18
0
Modern Web

PixiJS青銅玩家系列 第 18

【LV. 18】PixiJS青銅玩家:play( )(2)

  • 分享至 

  • xImage
  •  

▉ 前言

這裡將利用教程所提供的"Treasure Hunter Game"來直接學習PixiJS中的語法。"Treasure Hunter Game"的程式碼 ---> Click Here !

系統提示:「Success grows out of struggles to overcome difficulties.」,PixiJS青銅玩家仍卡關在play()階段僅獲得經驗提昇等級。

▉ 主線任務:play( ):怪物移動

▍任務說明

泡泡怪們的移動並不是由玩家操控,因此我們需要製作一個循環機制,使泡泡怪們可以自行的上下移動,讓玩家去閃躲。

▍作法

blobs.forEach(function(blob) {

blob.y += blob.vy;

let blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480});

if (blobHitsWall === "top" || blobHitsWall === "bottom") {
  blob.vy *= -1;
}

if(hitTestRectangle(explorer, blob)) {
  explorerHit = true;
}
});

▍分析

這裡的blobs為一個陣列,在【LV. 12】中曾經提過,我們在setup()函式中,將創建好的泡泡怪的Sprite一一推進blobs陣列中。

而此處就是當初推進blobs陣列的用意,因為每個泡泡怪的運動行為模式是一樣的,所以我們只須利用陣列的特性,對陣列的內容依序去執行動作,也因此只須一次程式即可完成,而非對各個泡泡怪都各執行一次。

blobs.forEach(function(blob) {
    ...
}
  • for loop VS. forEach
    這裡稍微試著去理解兩者的差異,一般來說forEach的功能跟for loop很像,都是對一個陣列的內容一一去取值的動作。

    以上方例子來說,若利用for loop寫法則變成:

    for(let i = 0; i < blobs.length; i++){
        blobs[i].y += blob[i].vy;
        ...
        ...
    }
    

    相較之下,for loop寫法稍嫌麻煩了,不過for loop可以搭配break,在迴圈當中把程式給中斷,且forEach並非所有陣列皆可以使用,例如說類陣列就沒有辦法使用forEach去運行。

    PS 類陣列利用forEach還是有辦法的,可以利用「展開」語法,將類陣列轉換成純陣列去使用即可(如下)。

    let array = [...arrayLike];
    array.forEach(i=>console.log(i));
    

    ***

接著看到forEach()裡頭的內容,首先就是處理泡泡怪移動的速度。

blob.y += blob.vy;

而其中的blob.vy一樣在【LV. 12】時就提到,泡泡怪們的移動速度是利用speed為2去乘上direction方向,也就是說泡泡怪他們是以每幀2px向下或向上去移動的(至於向下或向上,取決於direction為+1或是-1),程式碼如下(回顧一下):

blob.vy = speed * direction;
direction *= -1;

再來是在昨天【LV. 17】提到的自定義函式contain(),昨天是運用在不要讓explorer跑出地牢之外,而今天利用了contain()幫助我們達到兩件事情:

  1. 把泡泡怪限制在地牢之中,至於參數的設置即使用方法,可以到【LV. 17】的任務中回顧。
let blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480});
  1. 再來是【LV. 17】沒有提到的部份,contain()這個函式回return一個叫做collision的值,而他的值會依第一個參數碰撞到第二個參數的上邊、下邊、左邊或右邊給予回傳值,分別為top、bottom、left、right,而如果碰撞並未發生,則collision則return undefined。

    藉此來判斷當泡泡怪碰到下邊或上邊時,就得使他的移動方向反方向,而這裡只需要透過正負號即可轉換往上或往下的動作。

if (blobHitsWall === "top" || blobHitsWall === "bottom") {
  blob.vy *= -1;
}

來到最後,便是偵測explorer是否與blob相撞,因為explorer與blob相撞的話會扣血,因此我們必須有個程式去判斷,而這裡便又是利用到了一個自定義函式,稱作hitTestRectangle()

一樣先不談程式碼(若有需要,這裡附上官方教程碰撞偵測函數的電梯

但可以先知道的是hitTestRectangle()具有兩個參數,而參數便是兩個不同的Sprite,當這兩個不同的Sprite相碰相撞時,這個函式會回傳true,以便使我們做判斷他們兩者是否有接觸。

因此底下程式碼的意思,就是當explorer與blob相撞了,這個時候我們必須使explorerHit這變數賦值為true

if(hitTestRectangle(explorer, blob)) {
  explorerHit = true;
}
});

▉ 結語

今天先將泡泡怪們的移動以及碰撞偵測寫完!明天或許能把play()以及end()給結束。


參考資料


上一篇
【LV. 17】PixiJS青銅玩家:play( )(1)
下一篇
【LV. 19】PixiJS青銅玩家:play( )(3)& end( )
系列文
PixiJS青銅玩家30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言