XNA-2D 打磚塊遊戲(一)
大家小時候都有完過打磚塊遊戲嗎?接著就讓我們試著寫寫看吧!
因為是第一次試做,我們就先做出核心玩法,就像是上面連結遊戲的第一關就好,
首先決定一下大致上的規則:
- 遊戲畫面為800X600。
- 物件有磚塊、球、板子、能力膠囊。
- 磚塊大小都固定,但是可以設定被打幾下才會消失。
- 使用像素碰撞偵測
主要的功能大概如此,我們就先解決磚塊與球碰撞的問題,之前的範例在發生碰撞時是直接將兩個物體的速度互換,
這在遊戲中會顯得非常不自然,我們運用一點國中教的物理來做簡單的處理。
首先的想法是球發生碰撞後,重疊的像素取出一個矩型,此矩型的中點當做碰撞點,如圖:
當然,這只是權宜之計,當物體是不規則形狀,或是移動過快就會出問題,不過我們就先將就一點吧!
知道碰撞點之後,再和球心座標相減即可得到碰撞力量的法向量,此時國中物理就來了!
假設碰撞沒有損失能量,且球的質量都相同,則兩物體法線上的速度分量會互換,
因此a物體撞b物體時,a物體的速度先扣掉a物體的法線速度分量,再加上b物體的法線速度分量,即為a物體碰撞後的速度。
反之毅然,且因為我們碰撞不會重複偵測,所以在計算a物體的時候也要將b物體的速度也算出來。
另外我們的的球還會撞到磚塊,撞到磚塊只有球會反彈,磚塊不會動,所以我們直接將a物體的速度扣掉兩倍的法線速度分量即可,程式碼片段如下:
01 public override void Collided(ICollidable obj, Vector2 collidePoint) {
02 if (obj is Ball) {
03 Ball b = obj as Ball;
04 float d1 = Vector2.DistanceSquared(position, b.position);
05 float d2 = Vector2.DistanceSquared(position + velocity, b.position + b.velocity);
06 if (d1 > d2) {
07 //指向我的法線
08 Vector2 normal = new Vector2(collideRectangle.Center.X - collidePoint.X, collideRectangle.Center.Y - collidePoint.Y);
09 normal.Normalize();
10 Vector2 momentum = normal * (Vector2.Dot(b.Velocity, normal) + Vector2.Dot(Velocity, -normal));
11
12 velocity += momentum;
13 b.velocity -= momentum;
14 }
15 } else if (obj is Brick) {
16 Brick b = obj as Brick;
17 Vector2 center = new Vector2(collideRectangle.Center.X, collideRectangle.Center.Y);
18 float d1 = Vector2.DistanceSquared(center, collidePoint);
19 float d2 = Vector2.DistanceSquared(center + velocity, collidePoint);
20 if (d1 > d2) {
21 Vector2 normal = center - collidePoint;
22 normal.Normalize();
23 Vector2 momentum = normal * (Vector2.Dot(Velocity, -normal) * 2);
24
25 velocity += momentum;
26 }
27 }
28 }
02 if (obj is Ball) {
03 Ball b = obj as Ball;
04 float d1 = Vector2.DistanceSquared(position, b.position);
05 float d2 = Vector2.DistanceSquared(position + velocity, b.position + b.velocity);
06 if (d1 > d2) {
07 //指向我的法線
08 Vector2 normal = new Vector2(collideRectangle.Center.X - collidePoint.X, collideRectangle.Center.Y - collidePoint.Y);
09 normal.Normalize();
10 Vector2 momentum = normal * (Vector2.Dot(b.Velocity, normal) + Vector2.Dot(Velocity, -normal));
11
12 velocity += momentum;
13 b.velocity -= momentum;
14 }
15 } else if (obj is Brick) {
16 Brick b = obj as Brick;
17 Vector2 center = new Vector2(collideRectangle.Center.X, collideRectangle.Center.Y);
18 float d1 = Vector2.DistanceSquared(center, collidePoint);
19 float d2 = Vector2.DistanceSquared(center + velocity, collidePoint);
20 if (d1 > d2) {
21 Vector2 normal = center - collidePoint;
22 normal.Normalize();
23 Vector2 momentum = normal * (Vector2.Dot(Velocity, -normal) * 2);
24
25 velocity += momentum;
26 }
27 }
28 }
另外要說的是,當兩個物體的距離是互相靠近時才要做碰撞處理。
範例程式的畫面如下:
藍色的是磚塊,原諒我畫的很醜!