遊戲的根本—碰撞檢測
碰撞檢測為何重要?
一個好的遊戲中,有什麼是不可或缺的條件呢?除非你是開發桌遊或卡牌遊戲,否則你一定會需要 「碰撞檢測」 。
碰撞檢測為何重要?想一想,今天你玩Minecraft,如果你碰不到東西,整個人像幽靈一樣開旁觀者飄來飄去,會好玩嗎?嘿嘿,其實挺好玩的,亂七八糟!如果Minecraft不會碰到東西,絕對不會有人想玩!
那你隨便想以前的2D遊戲,例如超級馬力歐,馬力歐總要踩在地面吧?馬力歐也必須要碰到怪物會死掉,還得要用腳可以踩死怪物。那達成這些需要什麼?就是碰撞檢測,我們要能夠偵測「兩個物件相撞」這件事,而這個動作就稱為「碰撞檢測」。
碰撞檢測在scratch的實踐是非常簡單的,你只要拉出「碰到XXX?」來偵測一個狀態,就可以處理碰撞檢測。
完了… Python沒有碰撞檢測
可是問題來了,Python並沒有內建碰撞檢測。咦?!!你不是說用程式語言功能比較強大?怎麼連這個基礎的功能都沒有。
我們必須要釐清一件事,「碰撞檢測」這類事情是遊戲設計比較會遇到的,Python的主要使用是做資料運算,像是現在很夯的AI、深度學習等等。大部分會有碰撞檢測的工具是「遊戲框架」,框架這種東西就如字面上的意思,它已經幫你把整個專案架構給設計好了,你只要按照需求把剩餘的東西給填入就好。
至於Python上有的遊戲框架…實在不多,而且學習如何使用一個框架也是非常耗費心力的過程,於是最後我就決定自己寫碰撞檢測啦!
在接下來的介紹中,我會按照各個形狀之間的碰撞檢測來做說明,之所以用形狀區分,由於我是用簡單的幾何圖形,例如:圓形、矩形,來進行碰撞檢測。是的,碰撞檢測在每種圖形的「算法」都不一樣,因為我的遊戲就只有圓形和矩形兩種形狀,因此僅實做圓形矩形之間的碰撞檢測。
當殭屍碰到了你 —圓形對圓形
要如何去偵測一個圓形是否碰到了另一個圓形呢?
在我的遊戲中,例如怪物碰到了玩家,子彈射中了怪物,玩家被子彈射中等等,都是圓形與圓形的碰撞檢測。如果我們無法檢測這些,嗯…那這個遊戲大概會很無聊,因此我們要來實做圓形對圓形的碰撞檢測。
首先,我們列出我們所知道的資訊:
- x, y座標
- 半徑
就這樣?是的,就只要這樣。
我們利用圓的性質,由於邊長上的任何一點到圓心都等長,不管從那個角度相撞,撞擊點到圓心的距離都會是圓的半徑。
所以如果一個點距離圓心小於半徑,就代表跟它重疊了。
那由於有兩個圓,所以只要「兩個圓心的距離」小於「兩個圓的半徑之合」,就代表兩個圓重疊,也就是「碰到」了。
至於如何取得兩點之間的距離,就是使用「畢氏定理」囉!在場的一年級應該還沒上到,礙於時間有限,我就只說重點。畢氏定理可以讓我們取得一個直角三角形的斜邊長,那我們兩個相異點之間的距離,其實就是以這兩點為頂點,畫出的直角三角形的斜邊。
畢氏定理數學公式:
由此可得出:
以下為Python的實做:
1 | ''' |
小結
圓形對圓形的碰撞檢測是碰撞檢測中的基礎,很實用也非常好理解。那接下來會繼續介紹矩形對矩形的碰撞檢測。