关于碰撞检测,喜欢深入探究的同学可以去书店买书看,网上当然也有很多资源可以参考,这里只贴出代码,供C#开发的同学参照。
以下代码中,AABBvsAABB()是给不倾斜的矩形判断碰撞时调用的,OBBvsOBB则是给任意角度矩形判断碰撞时使用。
首先是旋转矩阵或者说分离轴的单位向量计算:
/// <summary>
/// 设置旋转角度和旋转矩阵
/// </summary>
/// <param name="rotation"></param>
/// <returns></returns>
public void SetAxisByAngle(float rotation)
{
this.axis[0] = (float)(Math.Cos(rotation * Math.PI / 180));
this.axis[1] = (float)(Math.Sin(rotation * Math.PI / 180));
this.axis[2] = -(float)(Math.Sin(rotation * Math.PI / 180));
this.axis[3] = (float)(Math.Cos(rotation * Math.PI / 180));
this.Slope = Define.AngleToSlope(rotation);
return;
}
然后分别投射到A和B各自的分离轴上进行判断:
public class OBBCollisionDetect
{
/// <summary>
/// AABB 碰撞检测
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static Boolean AABBvsAABB(OBB a, OBB b)
{
if (a.CenterPoint.X + a.HalfWidth < b.CenterPoint.X - b.HalfWidth ||
a.CenterPoint.Y + a.HalfHeight < b.CenterPoint.Y - b.HalfHeight ||
b.CenterPoint.X + b.HalfWidth < a.CenterPoint.X - a.HalfWidth ||
b.CenterPoint.Y + b.HalfHeight < a.CenterPoint.Y - a.HalfHeight)
return false;
else
return true;
}
/// <summary>
/// OBB碰撞检测
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static Boolean OBBvsOBB(OBB a, OBB b)
{
// two OBB center distance vector
float centerDistanceX = a.CenterPoint.X - b.CenterPoint.X;
float centerDistanceY = a.CenterPoint.Y - b.CenterPoint.Y;
// 投影到A的两根轴上
for (int i = 0; i < a.axis.Count() / 2; i++)
{
if (a.HalfHeight * Math.Abs(a.axis[2 * i] * a.axis[0] + a.axis[1 + 2 * i] * a.axis[1]) +
a.HalfWidth * Math.Abs(a.axis[2 * i] * a.axis[2] + a.axis[1 + 2 * i] * a.axis[3]) +
b.HalfHeight * Math.Abs(a.axis[2 * i] * b.axis[0] + a.axis[1 + 2 * i] * b.axis[1]) +
b.HalfWidth * Math.Abs(a.axis[2 * i] * b.axis[2] + a.axis[1 + 2 * i] * b.axis[3])
<= Math.Abs(centerDistanceX * a.axis[2 * i] + centerDistanceY * a.axis[1 + 2 * i]))
{
return false;
}
}
// 投影到B的两根轴上
for (int i = 0; i < b.axis.Count() / 2; i++)
{
if (a.HalfHeight * Math.Abs(b.axis[2 * i] * a.axis[0] + b.axis[1 + 2 * i] * a.axis[1]) +
a.HalfWidth * Math.Abs(b.axis[2 * i] * a.axis[2] + b.axis[1 + 2 * i] * a.axis[3]) +
b.HalfHeight * Math.Abs(b.axis[2 * i] * b.axis[0] + b.axis[1 + 2 * i] * b.axis[1]) +
b.HalfWidth * Math.Abs(b.axis[2 * i] * b.axis[2] + b.axis[1 + 2 * i] * b.axis[3])
<= Math.Abs(centerDistanceX * b.axis[2 * i] + centerDistanceY * b.axis[1 + 2 * i]))
{
return false;
}
}
return true;
}