XNA-像素碰撞Per-Pixel Collision(程式范例)

来源:互联网 发布:matlab是什么编程语言 编辑:程序博客网 时间:2024/06/05 16:46

此範例也是運用鍵盤的上、下、左、右鍵來移動人物圖片,最主要就是看它與磚塊圖片碰撞的地方,會比矩形偵測來的準確。

程式範例:

view plaincopy to clipboardprint?
  1. using System;   
  2. using System.Collections.Generic;   
  3. using System.Linq;   
  4. using Microsoft.Xna.Framework;   
  5. using Microsoft.Xna.Framework.Audio;   
  6. using Microsoft.Xna.Framework.Content;   
  7. using Microsoft.Xna.Framework.GamerServices;   
  8. using Microsoft.Xna.Framework.Graphics;   
  9. 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 Per_Pixel_Collision   
  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.         Color[] blockTextureData;   
  25.         Color[] personTextureData;   
  26.         int movespeed = 3;   
  27.         bool personHit = false;   
  28.   
  29.         public Game1()   
  30.         {   
  31.             graphics = new GraphicsDeviceManager(this);   
  32.             Content.RootDirectory = "Content";   
  33.         }   
  34.   
  35.         protected override void Initialize()   
  36.         {   
  37.             blockpos = new Vector2(0, 0);   
  38.             personpos = new Vector2(50, 0);   
  39.             base.Initialize();   
  40.         }   
  41.   
  42.         protected override void LoadContent()   
  43.         {   
  44.             spriteBatch = new SpriteBatch(GraphicsDevice);   
  45.             spriteBatch = new SpriteBatch(GraphicsDevice);   
  46.             block = Content.Load<Texture2D>("Block");   
  47.             blockTextureData = new Color[block.Width * block.Height];   
  48.             block.GetData(blockTextureData);   
  49.             person = Content.Load<Texture2D>("Person");   
  50.             personTextureData = new Color[person.Width * person.Height];   
  51.             person.GetData(personTextureData);   
  52.         }   
  53.   
  54.         protected override void UnloadContent()   
  55.         {   
  56.         }   
  57.   
  58.         protected override void Update(GameTime gameTime)   
  59.         {   
  60.             KeyboardState keyboard = Keyboard.GetState();   
  61.             if (keyboard.IsKeyDown(Keys.Up))   
  62.             {   
  63.                 personpos = new Vector2(personpos.X, personpos.Y - movespeed);   
  64.             }   
  65.             if (keyboard.IsKeyDown(Keys.Down))   
  66.             {   
  67.                 personpos = new Vector2(personpos.X, personpos.Y + movespeed);   
  68.             }   
  69.             if (keyboard.IsKeyDown(Keys.Left))   
  70.             {   
  71.                 personpos = new Vector2(personpos.X - movespeed, personpos.Y);   
  72.             }   
  73.             if (keyboard.IsKeyDown(Keys.Right))   
  74.             {   
  75.                 personpos = new Vector2(personpos.X + movespeed, personpos.Y);   
  76.             }   
  77.             Rectangle personRectangle = new Rectangle((int)personpos.X, (int)personpos.Y, person.Width, person.Height);   
  78.             Rectangle blockRectangle = new Rectangle((int)blockpos.X, (int)blockpos.Y, block.Width, block.Height);   
  79.             if (IntersectPixels(personRectangle,personTextureData,blockRectangle, blockTextureData ))   
  80.             {   
  81.                 personHit = true;   
  82.             }   
  83.             else  
  84.             {   
  85.                 personHit = false;   
  86.             }   
  87.             base.Update(gameTime);   
  88.         }   
  89.   
  90.         protected override void Draw(GameTime gameTime)   
  91.         {   
  92.             if (personHit == true)   
  93.                 GraphicsDevice.Clear(Color.Red);   
  94.             else  
  95.                 GraphicsDevice.Clear(Color.CornflowerBlue);   
  96.             spriteBatch.Begin();   
  97.             spriteBatch.Draw(block, blockpos, Color.White);   
  98.             spriteBatch.Draw(person, personpos, Color.White);   
  99.             spriteBatch.End();   
  100.             base.Draw(gameTime);   
  101.         }   
  102.   
  103.         public bool IntersectPixels(Rectangle rectangleA, Color[] dataA, Rectangle rectangleB, Color[] dataB)   
  104.         {   
  105.             int top = Math.Max(rectangleA.Top, rectangleB.Top);   
  106.             int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);   
  107.             int left = Math.Max(rectangleA.Left, rectangleB.Left);   
  108.             int right = Math.Min(rectangleA.Right, rectangleB.Right);   
  109.   
  110.             for (int y = top; y < bottom; y++)   
  111.             {   
  112.                 for (int x = left; x < right; x++)   
  113.                 {   
  114.                     Color colorA = dataA[(x - rectangleA.Left) + (y - rectangleA.Top) * rectangleA.Width];   
  115.                     Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width];   
  116.                     if ((colorA.A != 0 ) && (colorB.A != 0))   
  117.                     {   
  118.                         return true;   
  119.                     }   
  120.                 }   
  121.             }   
  122.             return false;   
  123.         }   
  124.     }   
  125. }  

    24~25行宣告的變數是用來存放兩圖片RGBA的資訊。

    47~48行和50~51行運用讀取圖片完的寬和高來決定存放該圖所需要的陣列大小,並且取出兩圖片RGBA的資訊。

    79行判斷是否碰撞到的函數IntersectPixels需要傳入的參數為兩圖片的Rectange型態和兩圖片Color型態的資訊。

    105~108行則是找出兩圖片交集的矩形範圍是多少乘多少。

    110行迴圈最主要檢查交集圖片中每個點是否有碰撞到。

    114~115行得到交集圖片各點的RGBA的資料。

    116行運用圖片的alpha值來判斷是否有碰撞到,如果交集圖片的某點alpha值都不是0那就代表碰到了。

1

這樣表示沒有碰撞到

這樣才表示有碰撞到

    122行交集圖片沒有碰撞在一起的點,所以回傳false。

最後附上專案檔Per-Pixel Collision.rar