圆形与矩形的碰撞检测

作者:追风剑情 发布于:2016-12-4 12:13 分类:Algorithms

将矩形向外扩张圆半径r来进行碰撞检测

111111.png

主要可以分为以下两个阶段进行碰撞:

1. 将需要检测的长方形,在上下左右4个方向均向外扩张,扩张的长度为圆半径r,如果扩张后得到新的长方形内包含了圆心坐标,则认为两物体具备碰撞的可能(反之则无碰撞的可能)。

2. 在满足条件1的情况下,如果圆心坐标在原长方形以外、扩张后的长方形的左上、左下、右上、右下四个角处,且圆内没有包含长方形最近的顶点,则认为两物体没有碰撞。

示例代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HitTest
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.Read();
        }
    }

    /// <summary>
    /// 矩形碰撞器
    /// </summary>
    public class RectCollider
    {
        //定义左下角为(minX, minY)
        public int minX;
        public int minY;
        //定义右上角为(maxX, maxY)
        public int maxX;
        public int maxY;

        //判断某点是否在矩形内
        public bool CheckHit(int x, int y)
        {
            return x >= minX && x <= maxX && y >= minY && y <= maxY;
        }

        public bool CheckHit(RectCollider rect)
        {
            //水平方向存在重叠
            if (rect.maxX >= minX && rect.minX <= maxX)
            {
                //垂直方向存在重叠
                if (rect.maxY >= minY && rect.minY <= maxY)
                    return true;
            }
            return false;
        }

        //判断矩形与圆形是否发生碰撞
        public bool CheckHit(CircleCollider circle)
        {
            //判断圆心是否在原矩形内
            if (this.CheckHit(circle.x, circle.y))
                return true;

            //扩展矩形区
            RectCollider rect_b = new RectCollider();
            rect_b.minX = minX - circle.r;
            rect_b.minY = minY - circle.r;
            rect_b.maxX = maxX + circle.r;
            rect_b.maxY = maxY + circle.r;

            //判断圆心是否在扩展矩形内
            if (!rect_b.CheckHit(circle.x, circle.y))
                return false;//无碰撞可能

            //判断矩形左下角是否在圆内
            if (AtLeftBottom(circle.x, circle.y))
                return circle.CheckHit(minX, minY);
            //判断矩形左上角是否在圆内
            else if (AtLeftTop(circle.x, circle.y))
                return circle.CheckHit(minX, maxY);
            //判断矩形的右下角是否在圆内
            else if (AtRightBottom(circle.x, circle.y))
                return circle.CheckHit(maxX, minY);
            //判断矩形右上角是否在圆内
            else if (AtRightTop(circle.x, circle.y))
                return circle.CheckHit(maxX, maxY);

            return true;
        }

        //判断某个点是否在矩形的左下方
        public bool AtLeftBottom(int x, int y)
        {
            return x < minX && y < minY;
        }

        //判断某个点是否在矩形的左上方
        public bool AtLeftTop(int x, int y)
        {
            return x < minX && y > maxY;
        }

        //判断某个点是否在矩形的右下方
        public bool AtRightBottom(int x, int y)
        {
            return x > maxX && y < minY;
        }

        //判断某个点是否在矩形的右上方
        public bool AtRightTop(int x, int y)
        {
            return x > maxX && y > maxY;
        }
    }

    /// <summary>
    /// 圆形碰撞器
    /// </summary>
    public class CircleCollider
    {
        public int x;
        public int y;
        public int r;

        //判断某点是否在圆内
        public bool CheckHit(int x, int y)
        {
            int d = (this.x - x) * (this.x - x) + (this.y - y) * (this.y - y);
            return d <= r * r;
        }

        //判断圆形是否与矩形发生了碰撞
        public bool CheckHit(RectCollider rect)
        {
            return rect.CheckHit(this);
        }

        //判断圆形是否与圆形发生了碰撞
        public bool CheckHit(CircleCollider circle)
        {
            int dx = x - circle.x;
            int dy = y - circle.y;
            int distSqr = dx * dx + dy * dy;
            int drSqr = (r + circle.r) * (r + circle.r);
            return distSqr < drSqr;
        }
    }
}

标签: Algorithms

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号