XNA中关于2D图形像素碰撞
2009-11-23 22:53
423 查看
下面所介绍的例子是微软官方的一个例子,这里给出下载XNA官方2D像素碰撞例子的链接。
在这个例子中没有涉及到什么新鲜的技术,主要是利用提取图像的像素,然后根据两张图像画布相交的范围构造一个小范围的矩形框,之后遍历此矩形框中的每一个像素点,判断当前遍历到的像素点的alpha值是否为零,若两张图片同一个像素点的alpha值同时不为零,则两张图片碰撞,反之则没有进行碰撞。好了,不罗嗦了,下面就展开介绍一下这个例子吧。
这个例子比较简单,没有自己封装类,所有功能都是在PerPixelCollisionGame类中实现的,该类继承Game类。
首先是定义一些常用的变量,这里找了几个主要的变量列了出来:
// 将要渲染的图片,一张是小人,一张是三角块
Texture2D personTexture;
Texture2D blockTexture;
// 这两个数组像素是用来存储小人的图片像素和三角块的图片像素
Color[] personTextureData;
Color[] blockTextureData;
//小人的坐标
Vector2 personPosition;
//小人的移动速度
const int PersonMoveSpeed = 5;
//创建一个坐标链表记录每一个三角块儿的坐标
List<Vector2> blockPositions = new List<Vector2>();
// 检测是否碰撞
bool personHit = false;
下面就是PerPixelCollisionGame类的构造函数,在这个构造函数中主要是定义了小人的初始位置,并且为了不让小人跑出我们的视线,特意定义了一个所谓的安全边框即safeBounds
protected override void Initialize()
{
base.Initialize();
Viewport viewport = graphics.GraphicsDevice.Viewport;
safeBounds = new Rectangle(
(int)(viewport.Width * SafeAreaPortion),
(int)(viewport.Height * SafeAreaPortion),
(int)(viewport.Width * (1 - 2 * SafeAreaPortion)),
(int)(viewport.Height * (1 - 2 * SafeAreaPortion)));
personPosition.X = (safeBounds.Width - personTexture.Width) / 2;
personPosition.Y = safeBounds.Height - personTexture.Height;
}
接下来是加载所用到的图像,这里没有什么好说的
/// <summary>
/// 加载图像资源
/// </summary>
protected override void LoadContent()
{
// 加载图片,包括小人和三角块
blockTexture = Content.Load<Texture2D>("Block");
personTexture = Content.Load<Texture2D>("Person");
//初始化三角块儿的像素数组大小
blockTextureData =
new Color[blockTexture.Width * blockTexture.Height];
// 提取三角块图片像素
blockTexture.GetData(blockTextureData);
///初始化小人的像素数组大小
personTextureData =
new Color[personTexture.Width * personTexture.Height];
//提取小人图片像素
personTexture.GetData(personTextureData);
// 增加一个精灵画刷来渲染图片
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
}
接下来是PerPixelCollisionGame类的Update方法,在这个方法中前半部分是对键盘输入的检测,以此来控制小人儿的左移和右移。接下来是随机生成一个三角块的初始位置,并把此位置添加到名为blockPositions的坐标链表中。其中personRectangle是定义了包含小人的一个矩形框,这个矩形框的宽度和高度是这个小人图片宽度和高度(其本质是图片画布的宽度和高度)。再接下来的这个for语句是这个例子的关键,不停的遍历整个三角块儿链表,判断是否有三角块与小人有像素碰撞,若有personHit返回true,否则返回false,这个for语句中的IntersectPixels方法实现了两个图片的像素碰撞功能,下面重点讨论一下这个方法:
上图是两张图片相交构成的一个小矩形框(中间红色部分)
static 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);
// 在这个小矩形框范围内从上倒下,从左到右检查每一个像素点的值,
//并判断每一个像素点上两张图片的alpha的值是否同时等于零,以此来判
//断两张图片是否产生像素碰撞
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];
// 判断两张图片在同一像素点上alpha值是否同时为零
if (colorA.A != 0 && colorB.A != 0)
{
//相碰撞,返回真
return true;
}
}
}
//没有碰撞,返回假
return false;
}
最后剩下渲染部分了:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice device = graphics.GraphicsDevice;
// 若personHit为真值,则屏幕背景颜色改为红色,否则为矢车菊蓝色
if (personHit)
{
device.Clear(Color.Red);
}
else
{
device.Clear(Color.CornflowerBlue);
}
spriteBatch.Begin();
// 渲染小人 spriteBatch.Draw(personTexture, personPosition, Color.White);
// 渲染三角块的坐标链表渲染链表中的每一个三角块
foreach (Vector2 blockPosition in blockPositions)
spriteBatch.Draw(blockTexture, blockPosition, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
至此这个例子也就完成了,其中最重要的部分就是IntersectPixels方法了,这个方法完成了两张图片的像素碰撞的功能,这个例子的本质也就是判断两个图片相交的画布部分的alpha值,如果同时不为零就代表碰撞,反之则没有碰撞。
在这个例子中没有涉及到什么新鲜的技术,主要是利用提取图像的像素,然后根据两张图像画布相交的范围构造一个小范围的矩形框,之后遍历此矩形框中的每一个像素点,判断当前遍历到的像素点的alpha值是否为零,若两张图片同一个像素点的alpha值同时不为零,则两张图片碰撞,反之则没有进行碰撞。好了,不罗嗦了,下面就展开介绍一下这个例子吧。
这个例子比较简单,没有自己封装类,所有功能都是在PerPixelCollisionGame类中实现的,该类继承Game类。
首先是定义一些常用的变量,这里找了几个主要的变量列了出来:
// 将要渲染的图片,一张是小人,一张是三角块
Texture2D personTexture;
Texture2D blockTexture;
// 这两个数组像素是用来存储小人的图片像素和三角块的图片像素
Color[] personTextureData;
Color[] blockTextureData;
//小人的坐标
Vector2 personPosition;
//小人的移动速度
const int PersonMoveSpeed = 5;
//创建一个坐标链表记录每一个三角块儿的坐标
List<Vector2> blockPositions = new List<Vector2>();
// 检测是否碰撞
bool personHit = false;
下面就是PerPixelCollisionGame类的构造函数,在这个构造函数中主要是定义了小人的初始位置,并且为了不让小人跑出我们的视线,特意定义了一个所谓的安全边框即safeBounds
protected override void Initialize()
{
base.Initialize();
Viewport viewport = graphics.GraphicsDevice.Viewport;
safeBounds = new Rectangle(
(int)(viewport.Width * SafeAreaPortion),
(int)(viewport.Height * SafeAreaPortion),
(int)(viewport.Width * (1 - 2 * SafeAreaPortion)),
(int)(viewport.Height * (1 - 2 * SafeAreaPortion)));
personPosition.X = (safeBounds.Width - personTexture.Width) / 2;
personPosition.Y = safeBounds.Height - personTexture.Height;
}
接下来是加载所用到的图像,这里没有什么好说的
/// <summary>
/// 加载图像资源
/// </summary>
protected override void LoadContent()
{
// 加载图片,包括小人和三角块
blockTexture = Content.Load<Texture2D>("Block");
personTexture = Content.Load<Texture2D>("Person");
//初始化三角块儿的像素数组大小
blockTextureData =
new Color[blockTexture.Width * blockTexture.Height];
// 提取三角块图片像素
blockTexture.GetData(blockTextureData);
///初始化小人的像素数组大小
personTextureData =
new Color[personTexture.Width * personTexture.Height];
//提取小人图片像素
personTexture.GetData(personTextureData);
// 增加一个精灵画刷来渲染图片
spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
}
接下来是PerPixelCollisionGame类的Update方法,在这个方法中前半部分是对键盘输入的检测,以此来控制小人儿的左移和右移。接下来是随机生成一个三角块的初始位置,并把此位置添加到名为blockPositions的坐标链表中。其中personRectangle是定义了包含小人的一个矩形框,这个矩形框的宽度和高度是这个小人图片宽度和高度(其本质是图片画布的宽度和高度)。再接下来的这个for语句是这个例子的关键,不停的遍历整个三角块儿链表,判断是否有三角块与小人有像素碰撞,若有personHit返回true,否则返回false,这个for语句中的IntersectPixels方法实现了两个图片的像素碰撞功能,下面重点讨论一下这个方法:
上图是两张图片相交构成的一个小矩形框(中间红色部分)
static 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);
// 在这个小矩形框范围内从上倒下,从左到右检查每一个像素点的值,
//并判断每一个像素点上两张图片的alpha的值是否同时等于零,以此来判
//断两张图片是否产生像素碰撞
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];
// 判断两张图片在同一像素点上alpha值是否同时为零
if (colorA.A != 0 && colorB.A != 0)
{
//相碰撞,返回真
return true;
}
}
}
//没有碰撞,返回假
return false;
}
最后剩下渲染部分了:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice device = graphics.GraphicsDevice;
// 若personHit为真值,则屏幕背景颜色改为红色,否则为矢车菊蓝色
if (personHit)
{
device.Clear(Color.Red);
}
else
{
device.Clear(Color.CornflowerBlue);
}
spriteBatch.Begin();
// 渲染小人 spriteBatch.Draw(personTexture, personPosition, Color.White);
// 渲染三角块的坐标链表渲染链表中的每一个三角块
foreach (Vector2 blockPosition in blockPositions)
spriteBatch.Draw(blockTexture, blockPosition, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
至此这个例子也就完成了,其中最重要的部分就是IntersectPixels方法了,这个方法完成了两张图片的像素碰撞的功能,这个例子的本质也就是判断两个图片相交的画布部分的alpha值,如果同时不为零就代表碰撞,反之则没有碰撞。
相关文章推荐
- XNA-2D碰撞-使用像素偵測
- XNA系列教程 2D碰撞教程2:像素检测
- [翻译]XNA系列教程 2D碰撞教程2:像素检测
- 2D平面中关于矩阵(Matrix)跟图形变换的讲解
- 2D平面中关于矩阵(Matrix)跟图形变换的讲解
- 关于Qt4的图形视图框架的理解(一)——碰撞的小鼠
- 关于两个不规则图形的碰撞检测
- Unity3D NGUI 给2D不规则图形加碰撞盒
- 2D平面中关于矩阵(Matrix)跟图形变换的讲解
- 2D平面中关于矩阵(Matrix)跟图形变换的讲解
- [翻译]XNA系列教程 2D 碰撞教程 1: 矩形检测
- 关于2D的触发器OnTriggerEnter2D和碰撞器OnCollisionEnter2D,注意参数变量区别
- Windows Phone 7 XNA开发之关于图形的配置 推荐
- xna像素的碰撞检测
- 关于swt 2D图形的一些知识介绍
- XNA系列教程 2D碰撞教程3:转换物体的碰撞检测
- Xna 2D图形概述
- (转)cocos2d-x 不规则图形碰撞检测(像素级碰撞检测)
- [翻译]XNA系列教程2D碰撞教程3:转换物体的碰撞检测
- 向量碰撞类---2D图形