XNA-2D碰撞-使用矩形偵測

XNA-2D碰撞-使用矩形偵測

大部分的遊戲都會有碰撞的發生,在2D遊戲裡要偵測碰撞其實不難!最簡單的方式,就是使用Rectangle的Intersects方法。

我們修改上一個範例XNA-二維空間物體的移動,將分出如下的階層圖

image

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