牛頓運動定律


要在虛擬世界中進行物理模擬,就是要模擬實體世界中物體的運動,實體世界中物體運動的基礎是牛頓運動定律(Newton's laws of motion)

  • 第一定律:慣性,若施加於物體的外力為零,物體的運動速度不變。靜者恆靜,動者恆動。
  • 第二定律:加速度,施加於物體的外力為質量與加速度的乘積。若 F 為力,m 為質量,a 為加速度,那麼 F = ma
  • 第三定律:作用力與反作用力,兩物體互相施力於對方時,力的大小相等、方向相反。

為了模擬物體,需要有物體的位置,而模擬慣性定律時,因為沒有外力,只需要簡單地定義速度就可以了,p5.js 提供了 p5.Vector,利用向量來定義位置與速度,在計算上就蠻方便的:

這邊要思考一個問題,實體世界中的速度是有單位的,那麼這邊的範例 velocity 單位是什麼?這要看你的虛擬世界是怎麼定義的。

就這邊來說,移動的單位是像素,update 設計為每次 draw 執行時呼叫,也就是頁框間的時隔為一個時間單位,位移量為時間乘上速度,也就是每次新座標可以單純地加上速度作為位移量。

運動定律不涉及形狀,Body 定義時也就不涉及形狀,形狀會涉及物體與物體之間的碰撞、受力的面積、角度等,是個複雜的議題,這邊在繪製形狀時,單純地使用圓,因為這是最簡單的形狀。

範例給定的速度是 (1, 1),執行結果就是圓從左上持續移動至右下,這是因為沒有任何外力改變或停止該物體,也就是動者恆動,如果範例給定的速度是 (0, 0),就是靜者恆靜了。

若要為物體套上力,就涉及第二定律 F = ma,因而 Body 需要定義質量:

class Body {
    constructor(coordinate, velocity, mass = 1) {
        this.coordinate = coordinate;
        this.velocity = velocity;
        this.mass = mass;
    }
  
    applyForce(force) {
        const acceleration = p5.Vector.div(force, this.mass);
        this.velocity.add(acceleration);
    }
  
    update() {
        this.coordinate.add(this.velocity);
    }
}

那麼在這邊質量的單位是?同樣地,這要看你的虛擬世界是怎麼定義的,就這邊而言,會將一個像素就當為質量 1,也就是形狀佔的面積就會是質量,如果物體的形狀是圓,半徑為 r,那麼就要在建構 Body 時給定 massPI * r * r

每次套用力後,速度就會改變,根據 F = maa = F / m,也就是速度的變化量,applyForce 中就是將之加至速度。

在這邊簡單地模擬一下球碰到邊界反彈,碰到邊界會反彈是因為第三定律,球被施予了反作用力,簡單地作法是直接改變速度的方向,不過這邊要透過 applyForce,那麼反彈的力要怎麼算呢?

若物體速度為 (x, 0) 往右運動,碰到邊界的瞬間,速度會是 (-x, 0),也就是速度變化為 (-2 * x, 0),結合物體的質量 mass,碰到邊界的瞬間,可看成受到 mass * (-2 * x, 0) 的反作用力。

來看看半徑為 10,初始速度 (2, 3) 的圓,在畫布中來回運動:

目前除了邊界反彈之外,還可以做些什麼呢?來試著在球上點一下,改變球的運動方向如何?這邊定義若點在球內,就施予一個點選處往球心的加速度,力道可以藉由 strength 來變化,範例中球一開始是沒有速度的,點選球來讓它運動吧!