XNA中簡單的矩形碰撞的方法
矩形碰撞是設計2D遊戲一開始需要知道的最基礎的碰撞偵測的方法,利用bounding box的方法將圖片的大小包住,甚至可以更仔細的指出圖片中圖案的4面大小,但是通常會以圖片的大小為主,因為使用上較方便,將兩個要碰撞的圖片去檢查他們是否發生交集,是的話就表示碰到,不是的話則表示沒有碰到,當然這樣的碰撞相對於像點偵測的發方會較不準確,之前有提到過像點偵測的做法,往後也會在用程式來解說實際地設計方法。
此範例是參考了XNA開發者俱樂部裡的Collision Series 1: 2D Rectangle Collision這個範例,將裡面的程式碼再加以簡化,只是比較單純的移動人物去碰障礙物看會不會發生碰撞而已,碰到的話畫面會變成紅色,沒有的話則是淡藍色。
02 using System.Collections.Generic;
03 using System.Linq;
04 using Microsoft.Xna.Framework;
05 using Microsoft.Xna.Framework.Audio;
06 using Microsoft.Xna.Framework.Content;
07 using Microsoft.Xna.Framework.GamerServices;
08 using Microsoft.Xna.Framework.Graphics;
09 using Microsoft.Xna.Framework.Input;
10 using Microsoft.Xna.Framework.Media;
11 using Microsoft.Xna.Framework.Net;
12 using Microsoft.Xna.Framework.Storage;
13
14 namespace boundbox
15 {
16 public class Game1 : Microsoft.Xna.Framework.Game
17 {
18 GraphicsDeviceManager graphics;
19 SpriteBatch spriteBatch;
20 Texture2D block;
21 Texture2D person;
22 Vector2 blockpos;
23 Vector2 personpos;
24 int movespeed=3;
25 bool personHit = false;
26
27 public Game1()
28 {
29 graphics = new GraphicsDeviceManager(this);
30 Content.RootDirectory = "Content";
31 }
32
33 protected override void Initialize()
34 {
35 base.Initialize();
36 blockpos = new Vector2(0, 0);
37 personpos = new Vector2(50,0);
38 }
39
40 protected override void LoadContent()
41 {
42 spriteBatch = new SpriteBatch(GraphicsDevice);
43 block = Content.Load<Texture2D>("Block");
44 person = Content.Load<Texture2D>("Person");
45
46 }
47
48 protected override void UnloadContent()
49 {
50
51 }
52
53 protected override void Update(GameTime gameTime)
54 {
55 KeyboardState keyboard = Keyboard.GetState();
56 if (keyboard.IsKeyDown(Keys.Up))
57 {
58 personpos = new Vector2(personpos.X, personpos.Y - movespeed);
59 }
60 if (keyboard.IsKeyDown(Keys.Down))
61 {
62 personpos = new Vector2(personpos.X, personpos.Y + movespeed);
63 }
64 if (keyboard.IsKeyDown(Keys.Left))
65 {
66 personpos = new Vector2(personpos.X - movespeed,personpos.Y);
67 }
68 if (keyboard.IsKeyDown(Keys.Right))
69 {
70 personpos = new Vector2(personpos.X + movespeed,personpos.Y);
71 }
72 Rectangle personRectangle = new Rectangle((int)personpos.X,(int)personpos.Y,person.Width,person.Height);
73 Rectangle blockRectangle =new Rectangle((int)blockpos.X, (int)blockpos.Y,block.Width, block.Height);
74 if (personRectangle.Intersects(blockRectangle))
75 personHit = true;
76 else
77 personHit = false;
78
79 base.Update(gameTime);
80 }
81
82 protected override void Draw(GameTime gameTime)
83 {
84 if (personHit == true)
85 GraphicsDevice.Clear(Color.Red);
86 else
87 GraphicsDevice.Clear(Color.CornflowerBlue);
88 spriteBatch.Begin();
89 spriteBatch.Draw(block,blockpos,Color.White);
90 spriteBatch.Draw(person,personpos,Color.White);
91 spriteBatch.End();
92 base.Draw(gameTime);
93 }
94 }
95 }
程式一開始的20和21行宣告存放圖片的物件,而Texture2D此種型態裡面有Width和Height的成員變數可以方便我們知道該圖片的寬和高各是多少。
22~23行主要是宣告存放兩張圖片的位置,Vector2此種型態裡面有提供X和Y的成員變數,分別代表X和Y的位置,以方便我們使用。
24行宣告移動圖片的速度為3。
25行是宣告一個布林型態的變數去判斷是否有碰撞到。
36~37指定兩圖片一開始的位置為(0,0)與(50,0)的位置。
43~44將圖片載入進來,用變數block和person存起來。
55~71則是運用鍵盤操控person這張圖片,鍵盤的上下左右代表著person圖片上下左右的移動,而每移動的單位為3,就是一開始所宣告movespeed的變數。
72~73則是宣告兩張圖片的框框大小,運用來看是否有碰撞到,使用到Rectangle這種型態,裡面需要輸入X位置、Y位置、有多寬、有多高四個參數。
74~77則是判斷兩圖片的框框是否有碰撞到,Rectangle型態提供了Intersects這個成員函數,裡面只需要輸入你要跟哪個Rectangle型態的變數看是否有交集的發生即可做判斷。
84~87利用一開始宣告的布林型態的變數去判斷是否有碰撞到,有的話畫面則變成紅色,沒有的話則是藍色。
因為是使用圖片矩形來看是否有交集,故這樣算碰撞到,雖然人並未碰到障礙物
必須要在障礙物矩形外才會不算碰撞到
88~91將兩張圖片實際的畫上去螢幕上面,Draw函數必須在Begin和End成員函數之間。
最後附上此範例的專案檔:boundbox.rar