图形碰撞检测 圆与矩形

先建立我们需要的数据模型:

1. 向量:

  1 /**
  2      * 向量类,默认使用正交基
  3      */ 
  4     public class SHVector
  5     {
  6         public var x:Number;
  7         public var y:Number;
  8         public var z:Number;
  9         
 10         /**
 11          * 构造函数
 12          */ 
 13         public function SHVector(x:Number, y:Number, z:Number = 0)
 14         {
 15             this.x = x;
 16             this.y = y;
 17             this.z = z;
 18         }
 19         
 20         /**
 21          * 向量的模
 22          */
 23         public function model():Number
 24         {
 25             return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
 26         }
 27         
 28         /**
 29          * 加法
 30          */ 
 31         public function add(vector:SHVector):SHVector
 32         {
 33             return new SHVector(
 34                 this.x + vector.x,
 35                 this.y + vector.y,
 36                 this.z + vector.z
 37             );
 38         }
 39         
 40         /**
 41          * 减法
 42          */ 
 43         public function sub(vector:SHVector, reverse:Boolean = false):SHVector
 44         {
 45             if (!reverse) {
 46                 return new SHVector(
 47                     this.x - vector.x,
 48                     this.y - vector.y,
 49                     this.z - vector.z
 50                 );
 51             }
 52             else {
 53                 return new SHVector(
 54                     vector.x - this.x,
 55                     vector.y - this.y,
 56                     vector.z - this.z
 57                 );
 58             }
 59         }
 60         
 61         /**
 62          * 点乘(内积)
 63          */
 64         public function dot(vector:SHVector):Number
 65         {
 66             return this.x * vector.x + this.y * vector.y + this.z * vector.z;
 67         }
 68         
 69         /**
 70          * 叉乘(外积)
 71          */ 
 72         public function cross(vector:SHVector):SHVector
 73         {
 74             var resultVector:SHVector = new SHVector(
 75                 this.y * vector.z - this.z * vector.y,
 76                 this.z * vector.x - this.x * vector.z,
 77                 this.x * vector.y - this.y * vector.x
 78             );
 79             
 80             return resultVector;
 81         }
 82         
 83         /**
 84          * 求两条向量的夹角,以弧度为单位
 85          */ 
 86         public function angle(vector:SHVector):Number
 87         {
 88             if (this.model() == 0 ||
 89                 vector.model() == 0)
 90                 return 0;
 91             
 92             return Math.acos(this.dot(vector) / (this.model() * vector.model()));
 93         }
 94         
 95         /**
 96          * 对象信息
 97          */ 
 98         public function toString():String
 99         {
100             return "x:" + this.x + "," +
101                    "y:" + this.y + "," +
102                    "z:" + this.z + "," +
103                    "model:" + this.model();
104         }

2. 圆:

 1 /**
 2      * 圆形类
 3      */ 
 4     public class SHCircle extends RigidityObject
 5     {
 6         public var r:Number;
 7         
 8         public var vector:SHVector;
 9         
10         /**
11          * 构造函数
12          */ 
13         public function SHCircle(x:Number, y:Number, r:Number)
14         {
15             super();
16             
17             this.x = x;
18             this.y = y;
19             this.r = r;
20             
21             this.vector = new SHVector(x, y);
22             
23             this.leftBorder = this.x - this.r;
24             this.rightBorder = this.x + this.r;
25             this.topBorder = this.y - this.r;
26             this.bottomBorder = this.y + this.r;
27             
28             this.draw();
29         }
30         
31         /**
32          * 更新
33          */ 
34         override public function update():void
35         {
36             this.x += this.speedX;
37             this.y += this.speedY;
38             
39             this.vector.x = this.x;
40             this.vector.y = this.y;
41 
42             this.leftBorder = this.x - this.r;
43             this.rightBorder = this.x + this.r;
44             this.topBorder = this.y - this.r;
45             this.bottomBorder = this.y + this.r;
46         }
47         
48         /**
49          * 绘制
50          */ 
51         override protected function draw():void
52         {
53             this.graphics.clear();
54             this.graphics.lineStyle(1, 0x000000);
55             this.graphics.drawCircle(this.x, this.y, this.r);
56         }
57     }

3. 矩形:

 1 /**
 2      * 矩形类
 3      */ 
 4     public class SHRect extends RigidityObject
 5     {
 6         public var vx1:Number;
 7         public var vy1:Number;
 8         public var vx2:Number;
 9         public var vy2:Number;
10         public var vx3:Number;
11         public var vy3:Number;
12         public var vx4:Number;
13         public var vy4:Number;
14         
15         public var vector1:SHVector;
16         public var vector2:SHVector;
17         public var vector3:SHVector;
18         public var vector4:SHVector;
19         
20         /**
21          * 构造函数
22          */ 
23         public function SHRect(vx1:Number, vy1:Number, vx2:Number, vy2:Number, vx3:Number, vy3:Number, vx4:Number, vy4:Number)
24         {
25             super();
26             
27             this.vx1 = vx1;
28             this.vy1 = vy1;
29             this.vx2 = vx2;
30             this.vy2 = vy2;
31             this.vx3 = vx3;
32             this.vy3 = vy3;
33             this.vx4 = vx4;
34             this.vy4 = vy4;
35             
36             this.vector1 = new SHVector(vx1, vy1);
37             this.vector2 = new SHVector(vx2, vy2);
38             this.vector3 = new SHVector(vx3, vy3);
39             this.vector4 = new SHVector(vx4, vy4);
40             
41             this.leftBorder = this.x + vx1;
42             this.rightBorder = this.x + vx2;
43             this.topBorder = this.y + vy1;
44             this.bottomBorder = this.y + vy3;
45             
46             this.draw();
47         }
48         
49         /**
50          * 更新
51          */ 
52         override public function update():void
53         {
54             this.x += this.speedX;
55             this.y += this.speedY;
56             
57             this.vector1.x = this.x + this.vx1;
58             this.vector1.y = this.y + this.vy1;
59             this.vector2.x = this.x + this.vx2;
60             this.vector2.y = this.y + this.vy2;
61             this.vector3.x = this.x + this.vx3;
62             this.vector3.y = this.y + this.vy3;
63             this.vector4.x = this.x + this.vx4;
64             this.vector4.y = this.y + this.vy4;
65             
66             this.leftBorder = this.x + this.vx1;
67             this.rightBorder = this.x + this.vx2;
68             this.topBorder = this.y + this.vy1;
69             this.bottomBorder = this.y + this.vy3;
70         }
71         
72         /**
73          * 绘制
74          */ 
75         override protected function draw():void
76         {
77             this.graphics.clear();
78             this.graphics.lineStyle(1, 0x000000);
79             this.graphics.moveTo(this.vx1, this.vy1);
80             this.graphics.lineTo(this.vx2, this.vy2);
81             this.graphics.lineTo(this.vx3, this.vy3);
82             this.graphics.lineTo(this.vx4, this.vy4);
83             this.graphics.lineTo(this.vx1, this.vy1);
84         }
85     }

 

  为了更清楚的说明矩形和圆的是否相交的情况,先绘制一张图形:

  从图中可以看出圆和矩形位置的三种情况:

  1. 完全不相交:圆形的位置在左上角的两条灰色直线左方,这种情况的判断方式可以通过计算圆心到两条红色直线的距离来得到,图中的黑色箭头实线就代表距离d1和d2,假如我们知道矩形的长是w,宽是h,圆的半径r:

  那么只要满足d1 > r + w / 2 或者 d2 > r + h / 2,圆和矩形就必然不会相交。我们通常会首先使用这个条件进行判断,得出是否肯定不相交的结论。如果这个判断失败,那么圆和矩形有可能相交但也可能不相交(从图中可以清楚看出),我们就需要进行接下来两种情况的判断。

  注:两条红色直线是穿过矩形中心,并分别与矩形的长宽边平行的直线,我们知道矩形中心坐标,和两边的中点坐标就可以得出这两条直线的方程。因为我们知道了矩形4个顶点的坐标,很容易就可以求的矩形中心点和矩形边中点的坐标;

  2. 圆与矩形的边相交:在通过了情况1的验证后,只要满足d1 <= w / 2 或者 d2 <= h / 2,就表明了圆和矩形的某条边一定相交了;

  3. 圆与矩形的顶点相交:如果情况2判断失败,就只剩下和顶点相交的情况了,这个判断很简单,只需要计算圆心到4个顶点的距离是否小于半径r即可;

具体实现:

 1 /**
 2          * 求出点到某条直线的距离
 3          */ 
 4         static public function computeDistanceBetweenPointAndLine(x:Number, y:Number, x1:Number, y1:Number, x2:Number, y2:Number):Number
 5         {
 6             var a:Number = y2 - y1;
 7             var b:Number = x1 - x2;
 8             var c:Number = x2 * y1 - x1 * y2;
 9 
10             return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
11         }
12         /**
13          * 检测圆和矩形的相交
14          */ 
15         static public function detectCircleAndRectCollision(circle:SHCircle, rect:SHRect):Boolean
16         {
17             var ABLength:Number = (rect.vector2.sub(rect.vector1)).model(); // 求AB边的长度
18             var DALength:Number = (rect.vector1.sub(rect.vector4)).model(); // 求AD边的长度
19             var halfABLength:Number = ABLength / 2;
20             var halfDALength:Number = DALength / 2;
21             
22             var vectorAB:SHVector = rect.vector2.sub(rect.vector1);
23             var vectorAC:SHVector = rect.vector3.sub(rect.vector1);
24             var vectorAD:SHVector = rect.vector4.sub(rect.vector1);
25             
26             // 矩形中心坐标
27             var rectCenterX:Number = rect.x + vectorAC.x / 2;
28             var rectCenterY:Number = rect.y + vectorAC.y / 2;
29             // AB边的中点坐标
30             var ABCenterX:Number = rect.x + vectorAB.x / 2;
31             var ABCenterY:Number = rect.y + vectorAB.y / 2;
32             // AD边的中点坐标
33             var ADCenterX:Number = rect.x + vectorAD.x / 2;
34             var ADCenterY:Number = rect.y + vectorAD.y / 2;
35             
36             // 圆心到两条直线的距离
37             var d1:Number = CollisionDetectionUtil.computeDistanceBetweenPointAndLine(circle.x, circle.y, rectCenterX, rectCenterY, ADCenterX, ADCenterY);
38             if (d1 > (halfDALength + circle.r))
39                 return false;
40             var d2:Number = CollisionDetectionUtil.computeDistanceBetweenPointAndLine(circle.x, circle.y, rectCenterX, rectCenterY, ABCenterX, ABCenterY);
41             if (d2 > (halfABLength + circle.r))
42                 return false;
43             
44             trace(d1, halfDALength); 
45             trace(d2, halfABLength);
46             
47             // 与矩形某条边相交
48             if ((d1 <= halfDALength) ||
49                 (d2 <= halfABLength))
50                 return true;
51             
52             trace(circle.vector.sub(rect.vector1).model());
53             trace(circle.vector.sub(rect.vector2).model());
54             trace(circle.vector.sub(rect.vector3).model());
55             trace(circle.vector.sub(rect.vector4).model());
56             
57             // 与矩形顶点相交
58             if (circle.vector.sub(rect.vector1).model() <= circle.r ||
59                 circle.vector.sub(rect.vector2).model() <= circle.r ||
60                 circle.vector.sub(rect.vector3).model() <= circle.r ||
61                 circle.vector.sub(rect.vector4).model() <= circle.r)
62                 return true;
63             
64             return false;
65         }

 

  

转载于:https://www.cnblogs.com/iRidescent-ZONE/p/4210881.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#中实现碰撞检测通常需要使用到几何图形的概念。常见的几何图形包括点、线、矩形形、多边形等。下面介绍一些常见的碰撞检测算法: 1.点与矩形碰撞检测 ```csharp public static bool IsPointInRect(PointF point, RectangleF rect) { if (point.X >= rect.Left && point.X <= rect.Right && point.Y >= rect.Top && point.Y <= rect.Bottom) { return true; } return false; } ``` 2.矩形矩形碰撞检测 ```csharp public static bool IsRectIntersect(RectangleF rect1, RectangleF rect2) { if (rect1.Left <= rect2.Right && rect1.Right >= rect2.Left && rect1.Top <= rect2.Bottom && rect1.Bottom >= rect2.Top) { return true; } return false; } ``` 3.形与形的碰撞检测 ```csharp public static bool IsCircleIntersect(Circle circle1, Circle circle2) { float distance = (float)Math.Sqrt(Math.Pow(circle1.Center.X - circle2.Center.X, 2) + Math.Pow(circle1.Center.Y - circle2.Center.Y, 2)); if (distance <= circle1.Radius + circle2.Radius) { return true; } return false; } ``` 4.多边形与多边形的碰撞检测 ```csharp public static bool IsPolygonIntersect(Polygon polygon1, Polygon polygon2) { for (int i = 0; i < polygon1.Points.Count; i++) { for (int j = 0; j < polygon2.Points.Count; j++) { if (IsLineIntersect(polygon1.Points[i], polygon1.Points[(i + 1) % polygon1.Points.Count], polygon2.Points[j], polygon2.Points[(j + 1) % polygon2.Points.Count])) { return true; } } } return false; } public static bool IsLineIntersect(PointF p1, PointF p2, PointF p3, PointF p4) { float denominator = (p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y); if (denominator == 0) { return false; } float ua = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / denominator; float ub = ((p2.X - p1.X) * (p1.Y - p3.Y) - (p2.Y - p1.Y) * (p1.X - p3.X)) / denominator; if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) { return true; } return false; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值