用数学方法解决工程问题系列(二) 两个矩形(多边形)的碰撞检测

关于碰撞检测,喜欢深入探究的同学可以去书店买书看,网上当然也有很多资源可以参考,这里只贴出代码,供C#开发的同学参照。

以下代码中,AABBvsAABB()是给不倾斜的矩形判断碰撞时调用的,OBBvsOBB则是给任意角度矩形判断碰撞时使用。

首先是旋转矩阵或者说分离轴的单位向量计算:

/// 
        /// 设置旋转角度和旋转矩阵
        /// 
        /// 
        /// 
        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
    {
        /// 
        /// AABB 碰撞检测
        /// 
        /// "a">
        /// "b">
        /// 
        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;
        }

        /// 
        ///  OBB碰撞检测
        /// 
        /// "a">
        /// "b">
        /// 
        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;
        }
  • * 用数学方法解决工程问题系列(一) 在Winform里画旋转矩形 *
  • * 用数学方法解决工程问题系列(二) 两个矩形(多边形)的碰撞检测 *
  • * 用数学方法解决工程问题系列(三) 判断任意给定一点是否在多边形内 *
  • * 用数学方法解决工程问题系列(四) 计算包围一组多边形的几何形状 *

你可能感兴趣的:(数学与算法应用,.NET开发)