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

关于碰撞检测,喜欢深入探究的同学可以去书店买书看,网上当然也有很多资源可以参考,这里只贴出代码,供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;
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值