暨昨天介紹了物體的基本建立,我們今天來到中篇,沒錯,中篇後面還會有一個下篇,因為筆者寫著寫著發現篇幅會過長,決定再拆成兩篇,長度會比較剛好,今天會專注在 Body 模組中泛用的物體操控方法,下篇會講一些偏細節的屬性設置。
好的,讓我們開始吧!
講到操控物體的物理行為,離不開物理上幾個屬性:位置 / 角度 / 物體本身的狀態。
我們依這個順序依依講起,首先來到位置。
今天模組引入的縮寫我會用 BodyM,不像之前直接命名成和模組名稱相同是因為避開 Body 這個字,所以宣告才會用 var BodyM = Matter.Body,下面我都會寫 BodyM,同義於 Matter.Body,可以看我的原始碼初始化的地方來對照,基本上除了這種特例我都會直接和模組用同樣名稱。
位置的話可以分成相對位置與絕對位置:
絕對位置的話,就是直接給予要操作的物體,以及指定移動座標,執行後物體不管在哪裡,都會直接被定位到該座標。
//setPosition(body, position)
BodyM.setPosition(circleA,{x:300,y:350});
相對位置則是依據物體現在的位置對他做指定向量的移動。
//translate(body, translation)
BodyM.translate(circleA,{x:0,y:-300});
以上兩種位置的調整,都不會對物體本身施加任何力量與角度,就像是魔法一樣,piu的就移動了物體,在現實世界做得到的話就真的是魔法了。
同時在執行這些指令的當下都會無視與其他物體的任何互動,也就是即使移動的路徑中間有其他物體,他也會直接移動到指定地點,且不會與該物體產生互動,可以想像在移動的過程中他不存在,是直接被放到新的位置。
另外,我們也可以對物體施力:
//applyForce(body, position, force)
BodyM.applyForce(circleA,{x:100,y:500},{x:1,y:0});
指定物體,指定施力點,最後指定施力點出發的施力方向。以這個為例,等於是向右水平水平施力。關於施力位置,其實主要影響的是最後施在物體上的力矩,可以參考下面這段 Lib 的原始碼(來自這裡)
Body.applyForce = function(body, position, force) {
body.force.x += force.x;
body.force.y += force.y;
var offset = { x: position.x - body.position.x, y: position.y - body.position.y };
body.torque += offset.x * force.y - offset.y * force.x;
};
因為我們這個例子是圓型,可能看不太出來,讀者可以嘗試在矩形上針對不同方向對矩形施加力量,就能看出不同。
談完位置與施力,我們來談談角度,角度一樣可以分為絕對與相對,絕對就是直接設定:
//setAngle(body, angle)
var degree = 120;
var radius = Math.PI / 180 * degree;
BodyM.setAngle(rectA, radius);
相對的話會是指定物體旋轉角度,但是不會對物體有任何施力,也是魔法的一種 。
//rotate(body, rotation, [point])
var degree = 90;
var radius = Math.PI / 180 * degree;
BodyM.rotate(rectA, radius);
另外注意的是在這邊所有 Matter.js 中吃的角度輸入都是吃弧度,弧度換算公式可以參考我的算式或是點進去 Wiki 的頁面了解更多。
旋轉的時候除了自體旋轉以外,可以發現他其實還可以多帶一個依循某點作旋轉,就像是地球繞太陽那種感覺,我們可以透過以下程式碼來體驗看看:
var degree = 90;
var radius = Math.PI / 180 * degree;
BodyM.rotate(rectA, radius, {x:300,y:350});
以這個例子我們就是讓方形繞著中心做90度旋轉,可以試試在 Stop The Runner 的情況下跑跑看,可以清楚地看到不受外力時他的位置角度變化。
在角度的世界裡也有速度,也就是角速度,可以透過以下方式對物體施加角速度:
//setAngularVelocity(body, velocity)
BodyM.setAngularVelocity(rectA, 1);
執行上面這段程式碼,會發現方形發生了旋轉,就是因為我們對他施加了角速度。
相關一些物理層面的名詞如果讀者發現不太了解的,可以用關鍵字去搜尋,或是看看筆者附上的 Wiki / 文章,30天的文章內不會對這些物理名詞做太多描述或講解。
不知道大家有沒有嘗試跟著我們一起執行上面這些程式嗎?或是玩玩看筆者附上的 Demo 網頁,應該可以發現我們施加力量的時候其實力量數值都給的不太大,但是物體卻都像是被車撞到一樣飛起來。
那是因為施力的時候要考量物體本身的質量與密度:
//setMass(body, mass)
//setDensity(body, density)
BodyM.setMass(rectA,1000);
透過上面的方式可以改變物體質量與密度,更新其一的時候另一個也會被同時更新,畢竟兩者是直接緊密相依的屬性。要看看這帶來的改變,可以先跑這段改動物體的質量,再跑施力於圓形,會發現本來圓形能直接碰飛方形,現在方形卻不太動了。
另外我們也可以改變物體的形狀,透過施加不同軸向的變形:
//scale(body, scaleX, scaleY, [point])
var scaleX = Math.random()*2;
var scaleY = Math.random()*2;
BodyM.scale(circleA, scaleX < 0.3 ? 0.3 : scaleX, scaleY < 0.3 ? 0.3 : scaleY);
記得昨天我們聊到 Bodies 模組中圓形只能宣告正圓形嗎?變形可以幫助你做出一個橢圓形!先創建一個圓形,對該圓形的 X 軸與 Y 軸施加不等量的變形,一個橢圓形,就變出來了!
最後一個參數跟旋轉一樣是來設置變形中心,如果不給值的話會默認為剛體中心,也就是我們一般認知的縮放。
以上大概是我們今天主要提到幾個對物體操作的方法,其他API文件提到的方法有些我們會到下一篇才提到,有一些我們可能不會深入去了解,有興趣的人可以自行前往閱讀或提出反饋,我們可以再針對反饋的地方做討論。
感謝今天大家的一同努力,我們又更了解 Matter.js 了一點,明天,再讓我們來針對物體本身的各種屬性一一了解。