iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
Modern Web

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

Day7. 依點成形,創造物件 - RigidBody(中)

  • 分享至 

  • xImage
  •  

暨昨天介紹了物體的基本建立,我們今天來到中篇,沒錯,中篇後面還會有一個下篇,因為筆者寫著寫著發現篇幅會過長,決定再拆成兩篇,長度會比較剛好,今天會專注在 Body 模組中泛用的物體操控方法,下篇會講一些偏細節的屬性設置。

好的,讓我們開始吧!

今天的Demo

今天的Demo原始碼

https://ithelp.ithome.com.tw/upload/images/20210922/20142057Q1O8SQ1yjn.png

講到操控物體的物理行為,離不開物理上幾個屬性:位置 / 角度 / 物體本身的狀態。

我們依這個順序依依講起,首先來到位置。

今天模組引入的縮寫我會用 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 了一點,明天,再讓我們來針對物體本身的各種屬性一一了解。


上一篇
Day6. 依點成形,創造物件 - RigidBody(上)
下一篇
Day8. 依點成形,創造物件 - RigidBody(下)
系列文
在JS的世界碰碰撞撞乒乒乓乓!30天一起玩Matter.js!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言