Day7. 依点成形,创造物件 - RigidBody(中)

暨昨天介绍了物体的基本建立,我们今天来到中篇,没错,中篇後面还会有一个下篇,因为笔者写着写着发现篇幅会过长,决定再拆成两篇,长度会比较刚好,今天会专注在 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 了一点,明天,再让我们来针对物体本身的各种属性一一了解。


<<:  Leetcode 挑战 Day 19 [ 633. Sum of Square Numbers ]

>>:  JavaScript Day07 - 阵列

[ Day 37 ] - 在 Github Release 上发布我们的安装档

之前本鲁都将打包出来的安装档 , 放到 git 中上传到 github 中 来产生一个公开连结让邦友...

30天打造品牌特色电商网站 Day.28 网站分析工具

一转眼30天的文章就快到尾声啦,在结束之前这两天会跟大家分享关於网站分析以及SEO优化的部分,网站分...

[Day 26] 实作-节庆详情页面

今天来实作节庆详情页面! 昨天有讲到我是用router-link query的方式把参数带到URL中...

CMoney工程师战斗营weekly1

上紧发条开始转动的一周 久违的早睡早起彷佛是回到学生时期的脚步,紧张的心情刺激肾上腺素分泌,就连作梦...

python入门学习day 2

#初学程序语言的你为什麽需要有GitHub? #Git & Github区别在哪里?? Gi...