iT邦幫忙

2021 iThome 鐵人賽

DAY 19
1
Modern Web

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

Day19. 手牽手,我的朋友,物體永遠在你左右 - Constraint

今天是彈珠台完成後的第一篇,我們依然會帶大家看一些還沒提到的模組,最後再來做一個小實作,實作題目先賣個小關子。
記得 Day17 我們提到的 mouseConstraint 嗎,那時候簡單帶過的 constraint,今天我們先來把他補起來,讓我們不再對他一知半解,能夠更認識這個模組。

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

今天會帶大家看一下 Constraint 模組的 Create 方法原始碼,也就是創建,裡面會有各個屬性與 default 值。

讀者可以把 Constraint 想成像類似 Rigidbody 的一個物體,但他沒有面積,他由一條線構成,也就是兩個點或是用於制約兩個物體的距離。

所以我們可以看到兩對屬性 : Body AB / Point AB,以及衍生的 length屬性。

if (constraint.bodyA && !constraint.pointA)
    constraint.pointA = { x: 0, y: 0 };
if (constraint.bodyB && !constraint.pointB)
    constraint.pointB = { x: 0, y: 0 };

var initialPointA = constraint.bodyA ? Vector.add(constraint.bodyA.position, constraint.pointA) : constraint.pointA,
initialPointB = constraint.bodyB ? Vector.add(constraint.bodyB.position, constraint.pointB) : constraint.pointB,
length = Vector.magnitude(Vector.sub(initialPointA, initialPointB));

constraint.length = typeof constraint.length !== 'undefined' ? constraint.length : length;

當有物體且沒有指定點的時候,會讓點為 0,0。

另外當有 AB 兩物體時,點會基於 AB 兩物體的位置上再加上去。

當只給物體不給點的時候,會以物體的中心為點座標。

當沒有輸入長度的時候,而預設長度會由AB兩點距離算出。

這個長度是可以設定的,這個長度會在最後力歸零的時候確保指定的點與點間的距離為 0。

var render = {
    visible: true,
    lineWidth: 2,
    strokeStyle: '#ffffff',
    type: 'line',
    anchors: true
};

Render 的屬性一樣是拿來設定外觀相關參數,可以注意到屬性多跟線有關,如我們一開始說的一樣,Constraint 就是指一條線,Render屬性可以設定這條線的外觀,如可不可見、粗度、填充方式。

anchors 是指線兩端繫上的兩點要不要被渲染出來,渲染出來的話會是用一個點來呈現。

render這裡的 type 會自動依賴其他的屬性來決定,一般建議不要針對這個屬性作設置,下面我們再來看 type 的屬性。

這裡有兩個比較跟物理學相關的值。

damping : 1,
stiffness : 0.1,

stiffness 用於表示這條線的僵硬度,僵硬度影響具體一點是用來表示線的行為會更像彈簧還是更像一條直線。越靠近 0 表示越像彈簧,1的話表示完全僵硬的直線,預設為 1。

damping 是物理學上的一個數值,中文稱作阻尼,簡單的解釋可以理解為使振動衰減的各種力,阻尼大,振動小,越大會讓連接越貼近剛性連接,阻尼力也稱為減震力,太高會起不到緩衝效果。

看了這兩個參數,我們可以來看一下上面說的渲染時 type 的種類:

if (constraint.length === 0 && constraint.stiffness > 0.1) {
    render.type = 'pin';
    render.anchors = false;
} else if (constraint.stiffness < 0.9) {
    render.type = 'spring';
}

當線的長度 0,且剛性較大的時候,行為會貼近成一個釘子,所以將 Type 設為 pin,且把釘住的點的顯示取消。

當僵硬度小於 0.9 的時候,因具有彈性表現,所以顯示為彈簧的樣式。

所以說 type 不建議手動設定,可以讓他自動判斷就好。

最後就是基本屬性:

plugin : {},
label : "constraintA",

label 就是拿來存一些特定辨識用的標籤,跟 body 一樣。

plugin 是如果有透過一些 plugin 模組匯入插件,可以拿來存一些 plugin 用的屬性。

上面介紹的就是 API 文件上此版本有提到關於 Constraint 的屬性了,Constraint 可用於製作釘子固定物體,或是一條懸吊物體的線,也能成為彈起物體的彈簧,善用這些設置,可以讓我們的世界更豐富,像以前物理課上過的牛頓擺也能做出來。

本來打算拆成上下兩篇來講屬性跟方法,但筆者在準備的時候突然發現 ─ Constraint 只有一個方法!這邊緊急加開一點篇幅補上,

Matter.Constraint.pointAWorld(constraint);
Matter.Constraint.pointBWorld(constraint);

這兩個方法筆者是當作一個方法啦,他其實就是顯示 constraint 中的點在世界座標的位置,如果你直接拿 constraint上的 pointA,拿到的會是相對座標,可以按按看最右邊的按鈕來了解當下直接點 property 跟用方法拿到的世界座標的差異。
https://ithelp.ithome.com.tw/upload/images/20211004/20142057Iw9ARK98IG.png

那更新完後,Constraint 模組在此告一個段落!我們明天見!


上一篇
Day18. 一起動手做彈珠台!(4)
下一篇
Day20. 麻痺手錶,小五郎叔叔的噩夢 - Sleeping
系列文
在JS的世界碰碰撞撞乒乒乓乓!30天一起玩Matter.js!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言