在以前電腦還不普及的年代,在地上打彈珠是孩子的遊戲,一種跟碰撞有關的遊戲。另一個會想到的是撞球運動,母球要用什麼角度撞進子球,母球撞擊後,會以什麼角度離開,這也都是屬於碰撞的問題。
(圖片來源:wikipedia)
真正要了解碰撞,當然要從物理原理來了解。(別走,別走,就是「物理」嘛!),雖然感覺過程會很辛苦,但是為了理解原理與自己實作,是必經之路。在蒐集資料的過程中發現,物理學中的彈性碰撞與我想做的碰撞似乎非常有關。
彈性碰撞是理想中的碰撞,在撞擊前後,不會有能量的損失。雖然在生活中的碰撞會有一些耗損,但是這個一個好的起點。
(圖片來源:wikipedia)
接下來是跟彈性碰撞有關的公式,了解公式才能在Scratch中帶入相關的模擬計算。先從一維的碰撞開始。下圖的第1個公式是兩物體撞擊前後的動量守恆。第2個公式是撞擊前後的動能守恆。經由前兩個公式可以推導出表示撞擊後兩物體速度的第3個公式。
當然在看了這3個公式後,有些人可能像我一樣,心中浮現的第一個想法就是…放棄算了。但是當我們做出一些假設後,是可以簡化的。假設兩個物體的質量一樣(例如彈珠每顆都一樣),會得到彈性碰撞後,兩物體速度會交換的結論。可以從以下的圖片中看出各種撞擊後速度交換的情形。
(圖片來源:wikipedia)
再來要如何表示速度呢?速度除了有大小以外,還有方向。所以要用數學工具中的向量來表示。還記得在Scratch中的方向是怎麼表達的嗎?每個角色有它的方向,如果再加上速度大小的變數,就可以來代表速度。不過要利用角度來計算時,需要用到三角函數。
其實向量還有另一種表達方式,是以x座標分量,y座標分量來表示。我後來的選擇是用這種方式來表達速度。這樣可以不使用到三角。
另外要在Scratch中計算碰撞,還會遇到問題。像是角色有個屬性無法得知:角色的大小。 原本為了使用上的簡化,Scratch中能知道的就是角色大小的百分比,這個是相對的值。但是在做碰撞計算,是需要精細到每一個點的。
關於角色精確大小的問題,有找到一個解法。下圖是Scratch遊戲設計的另一種類型(所有程式與圖形都在同一個角色中)。其中的物件,使用畫筆功能來畫出,由於畫筆的大小可以由程式指定,這樣就可以解決精確大小的問題。(如用畫筆功能畫出直徑為5的圓球),當然這個做法比較麻煩,流程也要熟悉一下,不過實作後發現這種做法比較接近傳統做遊戲方法,不特別使用多工,比較好掌握程式的流程。
在掌握了所以的相關知識與可行做法後,接下來就是實作了。一開始先從兩顆相同球體(粒子)的一維彈性碰撞開始。
實做出來的Scratch程式結果如下
有一維的左右方向碰撞與上下方向碰撞(介面左方是按鈕),由Scratch即時算出,由於大小與速度的隨機,所以每次都不同。
細心的人應該會發現上面的程式也包含了2維的彈性碰撞。2維與1維有什麼不同呢?
之前提到的公式是1維的,那到了2維會變成怎樣呢?在下圖中的動畫可以看出,原本的撞擊速度向量,可以分成兩個方向,法線方向與切線方向。法線方向是撞擊瞬間,兩個球體的圓心連線方向。2維彈性碰撞中的法線方向會像1維的公式一樣(同質量的話,速度互換),切線方向的速度維持相同,不受撞擊影響。球撞擊後的速度向量就是最後法線與切線向量的總和。
(圖片來源:wikipedia)
接下來的問題是,原來的速度向量,要如何切成法線向量與切線向量嗎?這時要使用到向量的運算。向量的內積(dot product)可以計算出某一向量在另一向量的投影量,利用這個就可以算出法線向量與切線向量。(也可用三角函數來算)
(圖片來源:wikipedia)
只要正確的計算速度向量在撞擊前後的變化,Scratch的球就會進行該有的彈性碰撞。(計算的步驟,很考驗耐性。)
在實作完2個球體的彈性碰撞,要如何做出多個球體的呢?這是屬於運算思維的問題,這時要用到Scratch中提供的資料結構工具,清單。利用多個清單,把每個球體的資訊都記在裡面。以我的程式為例,只要將原有2個球體中的程式,做好相關清單存取的轉換即可。
最後做出來的多個物體的彈性碰撞的Scratch程式如下:
程式中也有實作可調整的各種參數(球的大小、數量、速度)
所以算是一個小小的彈性碰撞模擬程式
在寫了以上兩個程式後,沒有太多時間來寫應用的遊戲。那如何應用呢?
以下是由外國網友eRKSToCK所寫的撞球遊戲,應用了彈性碰撞的原理,非常棒也非常好玩。
(這個遊戲當然也是我一開始學習參考的對象)
了解彈性碰撞雖然不能增加我打彈珠、打撞球的技巧。卻讓我了解生活中的一些物理原理。再加上能用Scratch,自己動手模擬出來,就更有趣了。只要有心、有動機想學習,物理、數學、程式都會是你的好朋友。(雖然過程中真的很辛苦啊!)。
物理模擬程式會帶來真實感,每次結果不同,如好像運動比賽一樣,球迷百看不厭,這也是吸引我很想要動手做出來相關物理程式模擬的最大原因了。
作者已經移除這則留言。
回覆刪除