一開始到現在,雖然我們沒有特別提到,物體就那麼自然的向下掉,就像蘋果掉到牛頓頭上的自然,這背後的理所當然,就是重力在作用。今天我們要來介紹 engine 上的 gravity 參數,我們來看看,怎麼操縱 matter.js 世界中的重力。
如上段開頭引言說的,gravity 是掛在 matter.js 裡面的一個參數,所以我們可以很容易地來調整它。
它是一個物件,形式如下:
engine.gravity = {
x: 0,
y: 1,
scale: 0.001
};
基本上這三個數值就能夠操控重力的表現了。
如我們的Canvas的座標軸一樣,Y上到下是小到大,X左到右是小到大。
預設的值是如上面展示物件結構的一樣,沒有橫向重力,y 軸重力為 1 表示向下(Canvas Y往下為正向),只有如地球一樣向下的重力,scale 是一個常數,用來同時對 x y 施加倍數增量。
我們可以稍微看一下套用重力的原始碼:
/**
* Applys a mass dependant force to all given bodies.
* @method _bodiesApplyGravity
* @private
* @param {body[]} bodies
* @param {vector} gravity
*/
Engine._bodiesApplyGravity = function(bodies, gravity) {
var gravityScale = typeof gravity.scale !== 'undefined' ? gravity.scale : 0.001;
if ((gravity.x === 0 && gravity.y === 0) || gravityScale === 0) {
return;
}
for (var i = 0; i < bodies.length; i++) {
var body = bodies[i];
if (body.isStatic || body.isSleeping)
continue;
// apply gravity
body.force.y += body.mass * gravity.y * gravityScale;
body.force.x += body.mass * gravity.x * gravityScale;
}
};
這邊可以看到有 matter.js 中有預寫一個函式,會是針對傳入的所有物體作重力施加判斷,但忽略 isStatic和 isSleeping 的物體。其他一般物體會被視作分別對 x y 軸施力,x y 軸施力的公式為物體本身的重量乘上 scale 增量與對應方向 x y 的重力。
使用情境也不難想像,我們可以在 engine.update 中找到呼叫的痕跡。
Engine._bodiesApplyGravity(allBodies, engine.gravity);
也就是定期透過每次呼叫來對物體施加穩定、定向的力。
matter.js 實作的 engine.gravity 有一個限制,就是整個 engine 就是所有物體遵照同一個 gravity 數值,雖然一般來說重力在區塊內是單一量級很正常,但是有時候還是會有特殊需求,比如依距離或一些其他變因持續施不同方向的力。
理解後其實如果有需要,我們大可直接仿造上面的方式,自己撰寫,對物體類重力的處理方式(說到底重力其實就是力的一種、對物體施力即可表現力的存在),就如同上面的倚賴質量與軸向力。
如果要做到無重力,就是把兩個軸向的力調成 0 就可以了。
但依據上面的實作可以了解,兩軸向為0表示不對物體施力,物體本身也是不會浮起來的,只會維持在原位。
讀者可以用今天的 Demo 頁面嘗試對三個參數做調整,看一下在兩個軸向的施力上做變化物體會如何移動。
今天關於重力的介紹就到這裡,也帶讀者走過了實作原始碼,增加了一些情境下的客製想像。
可以預告一下重力會在我們最後一個專案裡扮演一個重要的角色,大家敬請期待。