XNA-2D碰撞-使用矩形偵測
大部分的遊戲都會有碰撞的發生,在2D遊戲裡要偵測碰撞其實不難!最簡單的方式,就是使用Rectangle的Intersects方法。
我們修改上一個範例XNA-二維空間物體的移動,將分出如下的階層圖
GameObject是此遊戲的基礎物件,VisualObject表示可以在畫面上顯示的物體,MoveObject是可以在畫面上移動的物體,
ICollideable是擁有碰撞功能的介面,IRectangleCollideable是使用矩形偵測的碰撞方式,IMoveable是移動物體功能的介面。
我們要使用矩形偵測的話,必須有一個物體的碰撞矩形,設定在IRectangleCollideable的成員內,此矩形必須不斷跟著圖案移動,
所以在Ball的Update裡必須在position有所變動時也相對應的改變它,如下程式碼:
if (!enabled) return;
base.Update(gameTime);
collideRectangle.X = (int)position.X;
collideRectangle.Y = (int)position.Y;
}
然後是偵測碰撞的程式碼:
if (collodeable) {
IRectangleCollideable o = obj as IRectangleCollideable;
return collideRectangle.Intersects(o.CollideRectangle);
} else return false;
}
此函式當傳入的矩形和自身的矩形發生重疊時就回傳true,我設計成ICollideable的成員,此介面的另外兩個成員如下:
Ball b = obj as Ball;
if (b != null) {
Vector2 tempV = this.velocity;
this.velocity = b.velocity;
b.velocity = tempV;
}
}
public bool Collodeable {
get { return collodeable; }
set { collodeable = value; }
}
Collided函式是用來處理當碰撞發生時要做什麼事,這裡暫時就設定成兩個物件彼此交換速度。
Collodeable就是用來決定要不要偵測碰撞了!
接著在我們的主程式裡增加了兩個List,一個存放要畫的物件,另一個存要偵測碰撞的物件。
主程式裡的Update如下:
collided = false;
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
foreach (GameObject o in drawList) {
o.Update(gameTime);
}
for (int i = 0; i < collideList.Count; i++) {
for (int j = i + 1; j < collideList.Count; j++) {
if (collideList[i].CollideCheck(collideList[j])) {
collided = true;
collideList[i].Collided(collideList[j]);
}
}
}
base.Update(gameTime);
}
我們總共有五顆球,每顆都已經存到drawList裡,且因為這五顆球也要有碰撞的行為,所以也都有存在collideList裡,
存在List裡的好處是呼叫很方便,以後的遊戲物件會越來越多,只要把每個物件的Update和Draw(如果需要畫出來的話)寫好,每次只要呼叫物件自己的函式,
讓物件自己做好自己該做的事,主程式只要做整個遊戲的協調即可。
第10到17行是呼叫偵測碰撞函式的地方,要注意的是我們在每一次的Update中,collideList[0]和collideList[1]測過的話,collideList[1]就不用再和collideList[0]測了,
當然,自己也不用和自己測,所以j由i+1開始。而第16行只是為了發生碰撞時改變背景顏色所做的設定,在Draw函式中依據collided來改變背景的顏色。
矩形碰撞是最簡單的偵測方式,但是對於不規則的圖形就比較沒輒了!
此篇的範例:WindowsGame1.rar