此範例也是運用鍵盤的上、下、左、右鍵來移動人物圖片,最主要就是看它與磚塊圖片碰撞的地方,會比矩形偵測來的準確。
程式範例:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Audio;
- using Microsoft.Xna.Framework.Content;
- using Microsoft.Xna.Framework.GamerServices;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework.Input;
- using Microsoft.Xna.Framework.Media;
- using Microsoft.Xna.Framework.Net;
- using Microsoft.Xna.Framework.Storage;
- namespace Per_Pixel_Collision
- {
- public class Game1 : Microsoft.Xna.Framework.Game
- {
- GraphicsDeviceManager graphics;
- SpriteBatch spriteBatch;
- Texture2D block;
- Texture2D person;
- Vector2 blockpos;
- Vector2 personpos;
- Color[] blockTextureData;
- Color[] personTextureData;
- int movespeed = 3;
- bool personHit = false;
- public Game1()
- {
- graphics = new GraphicsDeviceManager(this);
- Content.RootDirectory = "Content";
- }
- protected override void Initialize()
- {
- blockpos = new Vector2(0, 0);
- personpos = new Vector2(50, 0);
- base.Initialize();
- }
- protected override void LoadContent()
- {
- spriteBatch = new SpriteBatch(GraphicsDevice);
- spriteBatch = new SpriteBatch(GraphicsDevice);
- block = Content.Load<Texture2D>("Block");
- blockTextureData = new Color[block.Width * block.Height];
- block.GetData(blockTextureData);
- person = Content.Load<Texture2D>("Person");
- personTextureData = new Color[person.Width * person.Height];
- person.GetData(personTextureData);
- }
- protected override void UnloadContent()
- {
- }
- protected override void Update(GameTime gameTime)
- {
- KeyboardState keyboard = Keyboard.GetState();
- if (keyboard.IsKeyDown(Keys.Up))
- {
- personpos = new Vector2(personpos.X, personpos.Y - movespeed);
- }
- if (keyboard.IsKeyDown(Keys.Down))
- {
- personpos = new Vector2(personpos.X, personpos.Y + movespeed);
- }
- if (keyboard.IsKeyDown(Keys.Left))
- {
- personpos = new Vector2(personpos.X - movespeed, personpos.Y);
- }
- if (keyboard.IsKeyDown(Keys.Right))
- {
- personpos = new Vector2(personpos.X + movespeed, personpos.Y);
- }
- Rectangle personRectangle = new Rectangle((int)personpos.X, (int)personpos.Y, person.Width, person.Height);
- Rectangle blockRectangle = new Rectangle((int)blockpos.X, (int)blockpos.Y, block.Width, block.Height);
- if (IntersectPixels(personRectangle,personTextureData,blockRectangle, blockTextureData ))
- {
- personHit = true;
- }
- else
- {
- personHit = false;
- }
- base.Update(gameTime);
- }
- protected override void Draw(GameTime gameTime)
- {
- if (personHit == true)
- GraphicsDevice.Clear(Color.Red);
- else
- GraphicsDevice.Clear(Color.CornflowerBlue);
- spriteBatch.Begin();
- spriteBatch.Draw(block, blockpos, Color.White);
- spriteBatch.Draw(person, personpos, Color.White);
- spriteBatch.End();
- base.Draw(gameTime);
- }
- public bool IntersectPixels(Rectangle rectangleA, Color[] dataA, Rectangle rectangleB, Color[] dataB)
- {
- int top = Math.Max(rectangleA.Top, rectangleB.Top);
- int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
- int left = Math.Max(rectangleA.Left, rectangleB.Left);
- int right = Math.Min(rectangleA.Right, rectangleB.Right);
- for (int y = top; y < bottom; y++)
- {
- for (int x = left; x < right; x++)
- {
- Color colorA = dataA[(x - rectangleA.Left) + (y - rectangleA.Top) * rectangleA.Width];
- Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width];
- if ((colorA.A != 0 ) && (colorB.A != 0))
- {
- return true;
- }
- }
- }
- return false;
- }
- }
- }
24~25行宣告的變數是用來存放兩圖片RGBA的資訊。
47~48行和50~51行運用讀取圖片完的寬和高來決定存放該圖所需要的陣列大小,並且取出兩圖片RGBA的資訊。
79行判斷是否碰撞到的函數IntersectPixels需要傳入的參數為兩圖片的Rectange型態和兩圖片Color型態的資訊。
105~108行則是找出兩圖片交集的矩形範圍是多少乘多少。
110行迴圈最主要檢查交集圖片中每個點是否有碰撞到。
114~115行得到交集圖片各點的RGBA的資料。
116行運用圖片的alpha值來判斷是否有碰撞到,如果交集圖片的某點alpha值都不是0那就代表碰到了。
這樣表示沒有碰撞到
這樣才表示有碰撞到
122行交集圖片沒有碰撞在一起的點,所以回傳false。
最後附上專案檔Per-Pixel Collision.rar
<script></script> <script src="http://s1.dotblogs.com.tw/admentorserve.aspx?type=js&z=18&target=_top&a=11"></script>