【重點】:
主要就是分兩種情況:
第一種:就是圓形與矩形邊框的碰撞檢測
檢測Y軸圓心到矩中心的距離是否小於半徑+矩形X軸1/2寬
檢測X軸圓心到矩中心的距離是否小於半徑+矩形Y軸1/2高
第二種:就是特殊的矩形四個角檢測
四個矩形頂角到圓心的距離是否小於半徑
相信後面的大家就很容易理解:
這篇文章講解一下基本的矩形和圓形之間的碰撞檢測演算法。上次我已經介紹過了矩形和矩形之間的碰撞檢測,這次比上次麻煩那麼一點。看圖:
圖上中間的紅色矩形是碰撞的矩形,四個黑色圓形是代表要碰撞的圓形的四種不同位置。
二者碰撞最主要還是位於矩形的四個角。為了簡潔,我還是運用上次的函數架構,雖然不是很方便,下面直接上代碼:
Code
ViewCopyPrint
bool OverLap(RECT round, RECT rect)
{
int cr = (round.right - round.left)/2;
int cx = round.left + cr;
int cy = round.top + cr;
int distanceX = abs(cx - rect.left - (rect.right-rect.left)/2);
int distanceY = abs(cy - rect.top - (rect.bottom-rect.top)/2);
if(distanceX > ((rect.right-rect.left)/2 + cr))
return
false;
if(distanceY > ((rect.bottom-rect.top)/2 + cr))
return
false;
if(distanceX <= (rect.right-rect.left)/2)
return
true;
if(distanceY <= (rect.bottom-rect.top)/2)
return
true;
int sq = (distanceX-(rect.right-rect.left)/2)*(distanceX-(rect.right-rect.left)/2)
+
(distanceY-(rect.bottom-rect.top)/2)*(distanceY-(rect.bottom-rect.top)/2);
return (sq <= cr*cr);
}
應該很容易看懂,函數輸入的是兩個矩形,前者是畫圓用的外接矩形,後者是碰撞的矩形。
代碼簡單的分析一下:
Code
ViewCopyPrint
int cr = (round.right - round.left)/2;
int cx = round.left + cr;
int cy = round.top + cr;
上面的幾行代碼是為了求出圓的半徑和圓心。
Code
ViewCopyPrint
int distanceX = abs(cx - rect.left - (rect.right-rect.left)/2);
int distanceY = abs(cy - rect.top - (rect.bottom-rect.top)/2);
接下來的兩行代碼其實就是求圓心和矩形中心的距離。第一行是橫座標的距離,第二行是縱座標的距離。
Code
ViewCopyPrint
if(distanceX > ((rect.right-rect.left)/2 + cr))
return
false;
if(distanceY > ((rect.bottom-rect.top)/2 + cr))
return
false;
這兩行是排除顯而易見的情況,其實就是圖上中間大的矩形外部的所有範圍。第一句是表示圓形到矩形X座標的距離大於二者半徑的累加,排除圖上的灰色線條兩邊的範圍。第二句話排出的是兩條藍色線之外的範圍,結合兩者,正好剩餘中間大的矩形範圍。
Code
ViewCopyPrint
if(distanceX <= (rect.right-rect.left)/2+r)
return
true;
if(distanceY <= (rect.bottom-rect.top)/2+r)
return
true;
接下來是顯而易見的碰撞情況。這是為了檢測矩形上下左右的碰撞。構成的圖形是圖上的粉色線條圍成的十字形。這兩條語句放在這裡,是必須的。結合上邊的兩句話構成的是一個小的十字形,正好能檢測矩形上下左右的碰撞情況。碰撞檢測的形狀就是這個樣子:
最後兩句代碼:
Code
ViewCopyPrint
int sq = (distanceX-(rect.right-rect.left)/2)*(distanceX-(rect.right-rect.left)/2)
+ (distanceY-(rect.bottom-rect.top)/2)*(distanceY-(rect.bottom-rect.top)/2);
return (sq <= cr*cr);
就是非常單純的檢測矩形的四個角落碰撞。方法就是檢驗矩形和圓形的距離的平方和與圓的半徑的平方的大小關係。
如果上邊的你不太懂,沒有關係,我用這個演算法寫了一個DEMO,你可以下載測試,然後注釋掉演算法的每一條語句來檢測,看看語句的作用,到時候就懂了。
DEMO: