iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
Modern Web

在JS的世界碰碰撞撞乒乒乓乓!30天一起玩Matter.js!系列 第 11

Day11. 人與人之間偶有摩擦,物體與物體之間叫做碰撞 - Collision(下)

  • 分享至 

  • twitterImage
  •  

昨天聊到碰撞是什麼,又如何在 Matter.js 中發生,相關函式扮演的角色等等。不知道大家還記不記得一個廣告:

https://www.youtube.com/watch?v=o6Yn6HzP2bM

我們之前的碰撞,都是讓引擎自然發生處理的,我們也沒有對物體做事情,就好像腳踏車壓到阿嬤的腳,阿嬤你怎麼沒感覺?我們今天要讓阿嬤,喔不是,物體知道他被撞到了,或是他撞到人了,不再沒感覺!

今天的Demo
今天的Demo原始碼
https://ithelp.ithome.com.tw/upload/images/20210926/20142057TaI3YQ8mIs.png

今天要來聊的是實作面一點的 ─ 如何知道兩物體發生碰撞,收到碰撞資訊後我們怎麼從訊號中得到我們需要的內容。
大家看到熟悉的場景,應該會發覺,沒錯,這裡又是我們的範例程式碼。
今天的Demo有針對 render 的 options 做一些設置,讓大家可以看到一些細節。

目前碰撞我預設行為是任何碰撞事件都會讓 Runner 暫停,暫停後請持續按 Run the Runner 的按鈕來讓 Runner 繼續運行。
那我們可以先跑一次現在狀態,總共有兩個方形一個地面。

https://ithelp.ithome.com.tw/upload/images/20210926/201420577WaB2smikS.png
第一個是注意左上角的 Pair 數量的變動,也就是我們上篇提到的碰撞對, Pair 的變化如下:

  • 一開始物體間沒接觸時,Pair = 0
  • 第一個方形接觸到地面,Pair = 1
  • 第二個方形和第一個方形碰撞,Pair = 2
  • 第二個方形和地面接觸且和第一個方形的Pair尚未消除,Pair = 3
  • 最後物體靜止,第一與第二個方形保持與地面接觸,Pair = 2

透過這個觀察,相信大家有更了解Pair。

我們會用 Matter.js 中的 Event 模組來讓 Mater.js 在指定事件發生時執行指定的 Callback 函式。

Events 模組就三個方法,on 來掛上指定的 Event, off 來移除指定的 Event,trigger 針對物件觸發指定的事件。

Events 模組相對簡單,會在下面的例子直接讓大家看實際應用,想再確認 API 文件的讀者可以點上面的連結。

那我們來看一下我們是如何偵測碰撞的。

function AttachEvents()
{
    Events.on(engine, "collisionStart", CollisionTriggered);
    Events.on(engine, "collisionActive", CollisionTriggered);
    Events.on(engine, "collisionEnd", CollisionTriggered);
}

在API文件 Engine 模組中的事件,我們可以看到範例代碼的這三個事件。

分別是 collisionStart, collisionActive, collisionEnd。

發生順序也是 collisionStart, collisionActive, collisionEnd。

https://ithelp.ithome.com.tw/upload/images/20210926/20142057OboiMxSsMH.png

除了碰撞到會暫停 Runner 以外,我們的 Callback 函式還會把當下丟進來的 event 印在 console.log,可以打開網頁中的開發者工具來應證這件事。

https://ithelp.ithome.com.tw/upload/images/20210926/20142057kqheGZgd85.png

我們稍微看一下 Event 丟進來內容我們可以怎麼讀。

首先會看到第一層有三個物件:name, pairs, source。

name就是碰撞事件本身是哪個事件被觸發,這應該不用多說,型別會是字串。

source會是一些和 engine 或物體本身相關的參數內容,我們也不會特別讀取裡面的資料。

最重要的會是 pairs 這個陣列,裡面的 collision 就是我們的目標,可以透過 bodyA, bodyB 了解是哪兩個物體參與到這次的碰撞裡。

可以看看這段加在碰撞後 callback 函式中的範例代碼:

if(e.name == 'collisionStart' && e.pairs.length > 0 && e.pairs[0].bodyA.id == 1 && e.pairs[0].bodyB.id == 2)
{
    e.pairs[0].bodyB.render.fillStyle = "green"
}
if(e.name == 'collisionStart' && e.pairs.length > 0 && e.pairs[0].bodyA.id == 2 && e.pairs[0].bodyB.id == 3)
{
    e.pairs[0].bodyA.render.fillStyle = "#7DB4A2"
}

做的事情就是偵測碰撞事件、碰撞對象,當方塊 2 碰到 方塊1,則將方塊2 變色,而方塊2 再碰到地板時再進行二次變色。

參考這段代碼以及上面的解說,讀者應該能夠理解碰撞事件中的事件資訊回傳與對物體本身的操作。

碰撞的單元到此告一個段落,希望大家對碰撞都有所了解了,明天會來實作彈珠台中的球體碰撞後變色的部分。


上一篇
Day10. 人與人之間偶有摩擦,物體與物體之間叫做碰撞 - Collision(上)
下一篇
Day12. 一起動手做彈珠台!(2)
系列文
在JS的世界碰碰撞撞乒乒乓乓!30天一起玩Matter.js!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言