撞球遊戲的核心演算法和AI 1

2021-09-08 22:40:32 字數 3597 閱讀 6218

前言:基礎物理知識:

摩擦阻力

其滿足牛頓第二定律:

f = m * a

速度與加速度關係公式:

vt = v0 + a * t

地面摩擦力與運動物體的方向相反, 阻礙物體的向前運動.

動量守恆

假設物體a質量為m1, 速度為v1, 物體b質量為m2, 速度為v2, 碰撞後速度分別為v1', v2'.

則滿足動量守恆定律:

碰撞型別和能量守恆定律

1).完全彈性碰撞

動能沒有損失, 則滿足如下公式:

1/2 * m1 * v1^2 + 1/2 * m2 * v2^2 = 1/2 * m1 * v1'^2 + 1/2 * m2 * v2'^2

注: 前後物體的動能保持均衡, 沒有其他能量的轉化. 

結合之前的動量守恆定律, 我們可以進一步得到:

v1' = [(m1-m2) * v1 + 2 * m2 * v2] / (m1 + m2)

v2' = [(m2-m1) * v2 + 2 * m1 * v1] / (m1 + m2)

2).完全非彈性碰撞

則存在其他能量的轉化, 動能不守恆. 

且此時兩物體粘連, 速度一致, 即v1'=v2', 此時動能損失最大.

3).彈性碰撞

介於完全彈性碰撞和完全非彈性碰撞兩者之間. 動能有損失的.

物理模型:

撞球遊戲中, 最核心的就是其物理模型的抽象及其碰撞演算法的執行過程了.

鑑於是2d版的撞球遊戲, 因此我們對物理模型做下簡化, 球運動的方向必然穿越球的中心.

把每個撞球抽象為圓(x, y, radius), 而撞球桌邊框抽象為線段((x1, y1), (x2, y2)).

碰撞檢測

1).檢測球與球碰撞

我們假定球a(x1, y1, r), 球b(x2, y2, r). 則滿足條件:

(x1 - x2) ^ 2 + (y1 - y2) ^ 2 <= (2*r) ^ 2

則發生碰撞, 否則沒有發生碰撞

2).檢測球與球檯邊框碰撞

相對比較簡單. 求球心到邊框的垂直距離即可, 若小於等於則發生碰撞, 若大於則沒有.

碰撞反應

1).球與球的碰撞反應

動量是向量, 其在正交的兩個方向上, 互相守恆. 我們選取兩球圓心的直線為x軸,垂直於圓心直線的為y軸. 如上圖所述.

x軸上滿足動量守恆:

m1 * vx + m2 * ux = m1 * vx' + m2 * ux';

並假定兩球碰撞是完全彈性碰撞, 兩球質量相等m1=m2, 依據基礎物理知識篇的結論.

vx' = [(m1-m2) * vx + 2 * m2 * ux] / (m1 + m2) = ux;

ux' = [(m2-m1) * ux + 2 * m1 * vx] / (m1 + m2) = vx;

在x軸方向, 兩球交換速度, 而在y軸方向, 兩球分速度不變.

vy' = vy;

uy' = uy;

最終碰撞後的速度公式為:

v' = vx' + vy' = ux + vy;

u' = ux' + uy' = vx + uy;

2).球與邊框的碰撞反應

把撞球邊框視為質量無窮大, 則簡單把運動的球, 其在垂直邊框的分方向反向即可.

假定碰撞碰撞平面為x軸

vx' = vx;

vy' = -vy;

最終速度公式為:

v' = vx' + vy' = vx - vy;

碰撞執行演算法:

遊戲的主迴圈往往遵循如下**結構:

while ( true

)

這個時間間隔(time_interval), 由遊戲的fps來確定. 以24幀為例, 每40毫秒重新整理一次.

對於撞球本身而言, 若以該time_interval為更新週期, 使得運動的球體滿足:

vt = v0 + a * t

執行距離為:

s = v0 * t + 1/2 * a * t^2.

然後來檢測球體是否發生了碰撞, 然後進行碰撞反應處理. 看似沒有問題.

但是當球體初速度很快時, 在time_interval中有可能, 發生穿越現象.

如下圖所展示的現象:

紫色球在t2時刻, 和藍球檢測到碰撞, 但實際上, 在紫球在t1~t2之間的某時刻和藍球發生了碰撞.

為了解決該問題, 在具體的演算法中, 需要引入更細的時間分片slice, 該過程在具體的update中進行模擬.

整個撞球場景的更新函式:

void

update(time_interval)

注: 碰撞反應, 按物理模型篇講述的來.

而具體的碰撞檢測演算法為:

/*

@brief

在time_interval 時間內, 返回最先碰撞的球或撞球邊, 以及時間點

*/bool detectioncollide(time_interval, least_time, ball_pairs)

注:對於一元二次方程, 也可以借助分1000個細粒度時間片, 然後計算逼近求解.

撞球模擬碰撞演算法過程, 大致就是如上所述. 

計算最複雜的時刻, 其實就是開球, 打散一堆球的時候.

總結:

本文參考了"nehe的opengl中文教程 第30課 碰撞檢測與模型運動". 當然實現撞球遊戲, 未必真的需要該演算法, 很多開發者直接使用box2d就能完美並輕鬆的實現. 參考"使用 cocos2d-x box2d 的實現". 後續的文章, 想講述**球遊戲的ai如何設計和實現. 望一同努力.

2048 遊戲核心演算法

2048 遊戲核心演算法 架構顯示 介面 與控制 演算法 分離 控制台pyqt pygame 演算法1.高內聚 上下移動 矩陣轉置 左右移動 向左移動 合併資料 零元素後移 向右移動 翻轉 合併資料 零元素後移 2.降維思想 將二維列表的操作,改為對一維列表的操作.list merge none z...

打地鼠遊戲核心演算法

1.新增背景 2.新增敵方小怪地板 for var i 0 i0.4?that.visible true that.visible false that.type parseint math.random 4 that.initwithspriteframe cc.spriteframecache....

rsync 的核心演算法

rsync是unix linux下同步檔案的乙個高效演算法,它能同步更新兩處計算機的檔案與目錄,並適當利用查詢檔案中的不同塊以減少資料傳輸。rsync中一項與其他大部分類似程式或協定中所未見的重要特性是映象是只對有變更的部分進行傳送。rsync可拷貝 顯示目錄屬性,以及拷貝檔案,並可選擇性的壓縮以及...