一,原理介绍

这回有点复杂,不过看懂了还是很好理解的。当然,我不敢保证这种算法在任何情况下都会起效果,如果有同学测试时,发现出现错误,请及时联系我。

我们首先来建立一个以圆心为原点的坐标系:

然后要检测碰撞就只有两种情况了。

情况一,矩形全部都在一个象限内,如图:

当然,图中只是举个例子,不一定是只在第二象限,任何一个象限都行,只要是矩形全在该象限。

这种情况比较好解决,首先,我们计算出矩形每个角的坐标,然后用勾股定律依次算出这个角到圆心的距离是否小于或者等于半径。设这个角与圆心横坐标之差为d1,纵坐标之差为d2,半径为r,公式表达如下:

如果有一个角满足要求说明产生碰撞,返回true。

但是有朋友懵了,怎么判断矩形是不是在一个象限内呢?很简单,只要判断这个矩形左上角和右下角是否在同一个象限内就可以了。于是我们得写个函数来实现判断某两个角是否在同一象限。

函数代码如下:

1. function isSameQuadrant(cood,objA,objB){
2. var coodX = cood.x;
3. var coodY = cood.y;
4. var xoA = objA.x
5. ,yoA = objA.y
6. ,xoB = objB.x
7. ,yoB = objB.y;
8.
9. if(xoA-coodX>0 && xoB-coodX>0){
10. if((yoA-coodY>0 && yoB-coodY>0) || (yoA-coodY<0 && yoB-coodY<0)){
11. return true;
12. }
13. return false;
14. }else if(xoA-coodX<0 && xoB-coodX<0){
15. if((yoA-coodY>0 && yoB-coodY>0) || (yoA-coodY<0 && yoB-coodY<0)){
16. return true;
17. }
18. return false;
19. }else{
20. return false;
21. }
22. }

这个函数原本是准备写到lufylegend中LMath静态类中的,参数原本是LPoint对象,但是这里可以用json,因为LPoint里的x,y属性可以写到json里,函数也就同样取得出值了。函数参数介绍:[cood创建的坐标系原点坐标, objA第一个点坐标, objB第二个点坐标] 这几个参数均为json对象,格式为:

 {x:点的x坐标, y:点的y坐标}  

函数中的代码还是很好理解的,就是判断一下两个点的x坐标都分别减去原点x坐标,看得出的数正负符号是否相同,然后又用同样的办法算出y轴上的符号是否相同,如果都相同就在同一象限。

有了这个函数,剩下得就好办了,直接代入开头给出的公式进行计算即可。

情况二,矩形跨度两个象限或者两个象限以上

这种情况更好办,我们就可以直接把圆看作一个边长为2r正方形,然后用矩形碰撞算法检测正方形和矩形的碰撞,如下图所示:

矩形碰撞的算法是什么呢?很easy,如图:

如果要横向判断碰撞的话,判断(x1-x2)的绝对值是否小于或者等于w1/2+w2/2,如果是则横向则有碰撞。纵向判断是一样的,判断(y1-y2)的绝对值是否小于或等于h1/2+h2/2即可。

有了这些算法,我们就可以实现情况2了。

二,Javascript版算法&测试代码

先上代码吧:

1. function hitTestRectArc(rectObj,arcObj,rectVec,arcR){
2. var rw = rectObj.getWidth()
3. ,rh = rectObj.getHeight()
4. ,ar = arcObj.getWidth()*0.5
5. ,rx = rectObj.x
6. ,ry = rectObj.y
7. ,ax = arcObj.x
8. ,ay = arcObj.y;
9.
10. if(typeof rectVec != UNDEFINED){
11. rx += (rw - rectVec[0])*0.5;
12. ry += (rh - rectVec[1])*0.5;
13. rw = rectVec[0];
14. rh = rectVec[1];
15. }
16. if(typeof arcR != UNDEFINED){
17. ax += (ar - arcR);
18. ay += (ar - arcR);
19. ar = arcR;
20. }
21.
22. var rcx = rx+rw*0.5,rcy = ry+rh*0.5;
23. var rltx = rx
24. ,rlty = ry
25. ,rlbx = rx
26. ,rlby = ry+rh
27. ,rrtx = rx+rw
28. ,rrty = ry
29. ,rrbx = rx+rw
30. ,rrby = ry+rh;
31.
32. if(
33. isSameQuadrant(
34. {x:ax,y:ay},
35. {x:rltx,y:rlty},
36. {x:rrbx,y:rrby}
37. )
38. ){
39. var dX1 = Math.abs(ax-rltx),dY1 = Math.abs(ay-rlty);
40. var dX2 = Math.abs(ax-rlbx),dY2 = Math.abs(ay-rlby);
41. var dX3 = Math.abs(ax-rrtx),dY3 = Math.abs(ay-rrty);
42. var dX4 = Math.abs(ax-rrbx),dY4 = Math.abs(ay-rrby);
43.
44. if(
45. (((dX1*dX1) + (dY1*dY1)) <= (ar*ar))
46. ||(((dX2*dX2) + (dY2*dY2)) <= (ar*ar))
47. ||(((dX3*dX3) + (dY3*dY3)) <= (ar*ar))
48. ||(((dX4*dX4) + (dY4*dY4)) <= (ar*ar))
49. ){
50. return true;
51. }
52. return false;
53. }else{
54. var result = false;
55. var squareX = ax
56. ,squareY = ay
57. ,squareW = ar*2
58. ,squareH = squareW;
59. if(
60. (Math.abs(squareX-rcx) <= (squareW+rw)*0.5)
61. &&(Math.abs(squareY-rcy) <= (squareH+rh)*0.5)
62. ){
63. result = true;
64. }
65. return result;
66. }
67. }

由于是为lufylegend设计的函数,所以参数为 [ rectObj矩形对象(LSprite或者LShape对象), arcObj圆形对象(LSprite或者LShape对象), rectVec矩形规定大小(可不填), arcR圆形半径(可不填)] 当然,或许些朋友不懂这几行代码:

1. var rw = rectObj.getWidth()
2. ,rh = rectObj.getHeight()
3. ,ar = arcObj.getWidth()*0.5
4. ,rx = rectObj.x
5. ,ry = rectObj.y
6. ,ax = arcObj.x
7. ,ay = arcObj.y;

好吧,我告诉你,这里用到的是lufylegend中LSprite和LShape,这两个类有x、y属性,还有获取宽度和高度的getWidth()和getHeight(),这里看不懂没关系,你知道是取高度和宽度还有x,y坐标的就行了。当然你要深究,那就看看lufylegend.js的API文档吧:http://lufylegend.com/lufylegend/api ,以下测试代码也用到了lufylegend.js,据说这个引擎是个不错的引擎,想了解的同学,去官方网站看看吧:http://lufylegend.com/lufylegend/ 或者看看我的文章,大多数是讲解有关lufylegend开发的。

示例代码:

1. init(50,"mylegend",500,250,main);
2.
3. function main(){
4. LGlobal.setDebug(true);
5.
6. var back = new LSprite();
7. back.graphics.drawRect(5,"green",[0,0,LStage.width,LStage.height],true,"lightblue");
8. addChild(back);
9.
10. var cObj = new LSprite();
11. cObj.x = 200;
12. cObj.y = 120;
13. cObj.graphics.drawArc(0,"",[0,0,50,0,2*Math.PI],true,"red");
14. back.addChild(cObj);
15.
16. var rObj = new LSprite();
17. rObj.x = 250;
18. rObj.y = 70;
19. rObj.alpha = 0.8;
20. rObj.graphics.drawRect(0,"",[0,0,100,100],true,"green");
21. back.addChild(rObj);
22.
23. trace(hitTestRectArc(rObj,cObj));
24.
25. back.addEventListener(LMouseEvent.MOUSE_DOWN,function(e){
26. rObj.x = e.offsetX-rObj.getWidth()*0.5;
27. rObj.y = e.offsetY-rObj.getHeight()*0.5;
28. trace(hitTestRectArc(rObj,cObj));
29. });
30. }

测试链接:http://www.cnblogs.com/yorhom/articles/hitTestRectArc.html

2D游戏中的碰撞检测:圆形与矩形碰撞检测(Javascrip版)的更多相关文章

  1. 地图四叉树一般用在GIS中,在游戏寻路中2D游戏中一般用2维数组就够了

    地图四叉树一般用在GIS中,在游戏寻路中2D游戏中一般用2维数组就够了 四叉树对于区域查询,效率比较高. 原理图

  2. Unity3D 2D游戏中寻径算法的一些解决思路

    需求 unity3d的3d开发环境中,原生自带了Navigation的组件,可以很便捷快速的实现寻路功能.但是在原生的2d中并没有相同的功能. 现在国内很多手机游戏都有自动寻路的功能,或者游戏中存在一 ...

  3. 2d游戏中的射线与矩形检测碰撞

    cc.exports.LineCollideRect(startLine,endLine,rect)--向量与矩形检测碰撞 --获取矩形的四个顶点位置 local p = {cc.p(rect.x,r ...

  4. 虚幻4:2D游戏中实现二级或多级跳跃

    转自:http://www.52vr.com/article-729-1.html 闲来无事,想做个二级跳跃或者多级跳跃的方法.. 如下所示.即可实现.   第一步:角色蓝图中.设置跳跃事件 第二部: ...

  5. 在2d游戏中常用的向量方式

    function cc.exports.VectorRotateByAngle(vector,angle)--计算向量旋转后的向量,angle:正数逆时针,负输顺时针 angle = angle*ma ...

  6. 2d游戏中求出一个向量的两个垂直向量

    function cc.exports.VerticalVector(vec)--求出两个垂直向量 local result = {} result[1] = cc.p(vec.y/vec.x,-1) ...

  7. 《MFC游戏开发》笔记十 游戏中的碰撞检测进阶:地图类型&障碍物判定

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9394465 作者:七十一雾央 新浪微博:http:// ...

  8. 2D游戏模型中动态分层的处理 及解决方案 (适用于 webgame 手游等资源控制较严格类型)

    文章若非特别注明转载,皆是原创,转载请注明出处. 本文地址:http://www.cnblogs.com/bobolive/p/3537215.html 2D游戏中模型一般都有换装逻辑,特别是联网游戏 ...

  9. UWP简单示例(三):快速开发2D游戏引擎

    准备 IDE:VisualStudio 2015 Language:VB.NET/C# 图形API:Win2D MSDN教程:UWP游戏开发 游戏开发涉及哪些技术? 游戏开发是一门复杂的艺术,编码方面 ...

随机推荐

  1. memcached server LRU 深入分析

    Memcached,人所皆知的remote distribute cache(不知道的可以javaeye一下下,或者google一下下,或者baidu一下下,但是鉴于baidu的排名商业味道太浓(从最 ...

  2. WCF服务三:svc文件详解

    在前面的文章中讲述过WCF服务的宿主程序主要包括:三种,在那篇文章中,简单的描述了如何把一个WCF服务寄宿到IIS上面,这篇文章中将具体讲述如何把一个WCF服务寄宿到IIS上面. 一.新建一个WCF服 ...

  3. Java运行结果测试

  4. 【BZOJ】1617: [Usaco2008 Mar]River Crossing渡河问题(dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1617 裸dp,很好做. 设f[i]表示i头牛到对岸所需最小时间.sum[i]表示运i头牛到对岸的时间 ...

  5. Think Python: How to Think Like a Computer Scientist

    Think Python: How to Think Like a Computer Scientist:http://greenteapress.com/thinkpython/html/index ...

  6. 【Debian】时间设置

    http://blog.linuxphp.org/archives/567/ http://www.dedecms.com/knowledge/servers/linux-bsd/2012/0819/ ...

  7. 表达式树在LINQ动态查询

    动态构建表达式树,最佳实践版,很实用! public class FilterCollection : Collection<IList<Filter>> { public F ...

  8. WPF - 绑定及惯用法(一)

    写在前面:这仍然是一些没有经过严格审阅的文字.虽然我的确执行了初稿.复稿以及审阅等一系列用以保证文章质量的方法,但是仍然担心其中是否有错误.希望您能帮助指出,以在下一次我在版本更新时进行修正.所有的错 ...

  9. pybot/robot命令参数说明【dos下执行命令pybot.bat --help查看】

    Robot Framework -- A generic test automation framework Version: 3.0 (Python 3.4.0 on win32) Usage: r ...

  10. M451例程讲解之按键

    /**************************************************************************//** * @file main.c * @ve ...