今天要來運用昨天我們前兩天學到的滑鼠互動方式來為我們的彈珠台加上互動操作。
在彈珠台裡,球碰到釘子就會彈開,有時候就因為多了那一個普通釘子,跟顏色釘失之交臂,我們今天預計做的操作是,點擊任一個釘子後,把釘子消掉。
所以比起昨天的 mouseConstraint 類似 constraint 的行為,我們更著重的會是前天的 mouse 物件的屬性監測。
首先我們要先創立我們的 mouse 物件,另外 mouse 物件是不需要加入 engine.world 就可以作用了。我們清楚定義 mouse 依附的對象會是 render 出來的 canvas。
mouse = Mouse.create(render.canvas);
接著我們在本來的 frame 檢測裡面加上一個函式
function frameUpdated()
{
var cameraSpeedByFrame = 1.5 * isZoomIn? 0.3 : 1;
Bounds.translate(render.bounds, {x:0,y:1.5});
checkClosedToAnyColorBlock(blockList, mainBall);
mouseEventCheck();
}
今天的主要功能都會在 mouseHandle 裡面完成。
var mouseKeepPressed = false;
function mouseEventCheck()
{
var isMousePressed = mouse.button == 0;
if(isMousePressed && !mouseKeepPressed)
{
mouseKeepPressed = true;
var collissionedList =getClickedBoxesList();
for(var i in collissionedList) { removeBlocks(collissionedList[i]); }
}
else if(!isMousePressed)
{
mouseKeepPressed = false;
}
}
每個 frame 都會呼叫 mouseEventCheck,函式內第一件我們要判斷的行為:滑鼠是否被按下。
是否被按下我們透過 mouse.button 來判斷,0表示按下,-1表示沒按下(如果不熟這部分,請參考Day16的內容),沒有其他的值。
同時如果持續按壓,我們不會讀做另一次點擊,這個透過 mouseKeepPressed 來達成,初始為 false,一旦按下就會被更新為 true,直到放開為止都會是 true,放開則更新為 false。
所以我們判斷點擊的邏輯會是:滑鼠目前是被按下的狀態且上一次檢測時非被按下狀態,換句話說就是獨立一次的點擊最開始那次會被抓到,且同一次點擊不會重複跑進上半部點擊邏輯裡。
抓到點擊事件後,我們透過 getClickedBoxesList 來拿到碰撞清單:
function getClickedBoxesList()
{
return Query.point(blockList, {x: mouse.mousedownPosition.x, y: mouse.mousedownPosition.y + render.bounds.min.y});
}
這邊我們用了一個先前在碰撞單元提到的模組(雖然沒有詳提),Query.point的作用是給一組 body list,以及一個單點,會判斷 body list 中有哪些 body 是有涵蓋到該點的,並回傳一個陣列。
所以透過這個方法,我們就能拿到點到的釘子。
拿到點到的釘子後,我們會跑 removeBlocks 來移除該釘子,這是先前寫過的方法,因為這邊也要呼叫,所以抽出成一個函式,寫在 triggeredHandle.js 裡面。
function removeBlocks(targetBody)
{
Composite.remove(engine.world, targetBody);
blockList = blockList.filter(x=>x.id != targetBody.id);
}
到這裡,透過滑鼠物件與畫面互動的內容就完成了!
嘗試跑跑看,點下你的滑鼠,就會看到釘子消失了!
讓礙事的釘子通通消失吧!
我們歷時了 18 天,把彈珠台中需要做的物理判斷都做完了!恭喜一起走到這裡的你!
剩下的 12 天,我們會繼續介紹其他模組,最後我們會有一個額外實作,也會是一個小遊戲 ,請大家敬請期待。