Anúncio
Anúncio

Mais conteúdo relacionado

Último(20)

Destaque(20)

Anúncio

學習歷程-使用javascript製作二維物理引擎.pdf

  1. 使用 Javascript 製作 二維物理引擎 1547 06 張博崴
  2. 動機 之前在使用Three.js製做3D遊戲時,曾經使 用過別人做的物理引擎Cannon.js,但是有 許多的功能或是函式我都不太了解要怎麼用, 又或者是沒有辦法達到我的需求,因此我就 想著或許可以做出自己的物理引擎。 但是由於三維的物理碰撞對我來說可能過於 複雜,因此決定先試著製作二維的物理引擎, 完成後可以搭配HTML5的canvas畫布使用。
  3. 製作 二維向量模組 • 製作原因 由於是要做二維的物理模擬,速度、加速度、位移等各種物理量都 是二維向量,因此若是有二維向量的模組可以使用,程式碼的可讀 性將會變高許多,因此首先要做的就是二維向量的模組。 • 內容 我做了一個名為vec2的物件(如左圖),有兩個屬性x和y,還 帶有十幾個函式用來計算。 • 新增方法 使用 new vec2(x分量,y分量) 新增新的向量 例:let a=new vec2(0,0) 則a為0向量 • 計算方法 使用vec2裡面的函示來計算,若結果為一向量,則函式名稱 結尾為 _in 的會將結果覆蓋到自己,否則回傳一個新的向 量,若結果不是一個向量,則直接回傳結果。 例:(v1,v2為兩向量) v1.add(v2) => 回傳v1+v2 v1.add_in(v2) => v1=v1+v2 v1.deg() => 回傳v1的角度 • 完整程式碼 我已經將每個函式加上註解並放上github,網址如下: https://github.com/weichang0307/vec2_module/blob/main/vect or_md.js
  4. 物理引擎製 作方法 我決定參考之前使用過的物 理引擎,使用多個物件來製 作(class方法),主要分為 world以及不同幾何物件。 *由於目的是要模擬幾何物件的碰撞,因此 幾何物件我只製作比較簡單的圓形(ball) 和矩形(rect)。 • 幾何物件 包含多個屬性,用來記 錄一個物體的速度、位 置等數據。除此之外, 還包含一些函式以方便 使用。 • world 物件 使用陣列紀錄所有加入到 這個world的幾何物件, 並由附帶的函式計算所有 這個world裡的幾何物件 的活動及互動,並改變他 們的屬性數據。
  5. 幾何物件 矩形 球(圓形) 包含多個屬性以及一個繪圖用函式 * constructor()為物件的建構函式
  6. world物件 屬性 • 迭代(iteration) 由於碰撞的偵測是圖形重 疊時發生,因此為了要盡 量讓物體一接觸時就發生, 可藉由提高迭代次數,使 update函式將時間切成更 多段來計算,由此提高精 確度。 較低iteration 較高iteration 碰撞 碰撞 屬性
  7. 函式 update 使用這個雙重迴圈可將objs陣列中的每兩 個物件進行碰撞檢測 (不會重複檢測也不會跟自己檢測) * 每次迴圈的 i 跟 y 都是不同 的組合且 i 不會等於 y 每次迭代將時間推進time_(time/iteration)毫秒
  8. 碰撞 使用迴圈將每兩個幾何物件 放入collision函式之後,要 分成不同狀況交給不同的函 示去做運算,並判斷是否需 要再次進行碰撞檢測(遞迴) 一次update 分成 iteration次 雙重迴圈 一組 collision 重力及阻力 改變速度 碰撞 改變速度 速度 改變位置 一次迭代 分類碰撞種類 判斷是否 call back 矩形-矩形 圓形-圓形 圓形-矩形
  9. 將四種可能的狀況 放入對應的三種碰 撞函式中進行碰撞 的檢測與計算 若是速度發生改變 (有碰撞發生),則 再次檢測與其他物 件是否有碰撞 紀錄初始速度,後 面用來檢測是否有 碰撞發生 • 為何要遞迴(call back) 由於在碰撞之後物體的速度發生改 變,因此原本不成立碰撞的兩個物 體可能發生碰撞,又或者是碰撞的 初速度發生了變化,因此要再次進 行碰撞檢測,不斷遞迴直到所有物 體都不再發生碰撞。 Ex:(以下例子以右為正) 以下為物體A、B、C,速度分別為5、0、0 一開始B與C沒有碰撞。 5 0 0 經過第一輪的碰撞,各自的速度可能會變 成這樣,而此時B與C 應該要發生碰撞。 0 5 0 由於在第一輪A與B發生了碰撞,因此A與B 會與其他物體再次進 行碰撞檢測,於是B與 C發生碰撞。 0 0 5 此時已沒有物體會再發生碰撞,遞迴結束
  10. 碰撞函 式
  11. 這裡就放上最簡潔的 球-球碰撞 其他的碰撞除了要先分類以外 概念大致相同,都是先將二維 碰撞簡化為某一方向上的一維 碰撞來做計算。 含註解的程式碼都放在github
  12. 應用 程式碼的部分到此結束,以下是我對這次成果的一些應用
  13. 省思 以上就是完整的成果展示了,其實以上的程式碼已經是我精簡了好多次的最終成果, 畢竟一開始的程式碼有700多行,可讀性也很差。 但就算這已經是改良後的版本,我仍然發現了許多問題: 1.向量使用閉包導致效能不佳 2.只能模擬完全彈性碰撞 3.無法模擬物體的轉動 4.無法模擬摩擦力 因此我打算繼續努力改良,同時提升我的物理能力,希望能夠造就功能更完善,效 能更好的物理引擎,甚至是將來有能力了我也想挑戰看看三維的物理世界。
  14. 總結 以上就是這次計畫的完整成果報告,在過程中也遇到了許多困 難,一開始連彈性碰撞都不知道(當時才高一),要找資料都不 知道要打什麼關鍵字,到現在做出了這樣一個可用度頗高的一 個模組,我想我在技術跟心理層面都成長了許多。 向量模組完整程式碼: https://github.com/weichang0307/vec2_module/blob/main/vector_md.js 物理引擎完整程式碼: https://github.com/weichang0307/physic_module/blob/main/physic_md.js
Anúncio