cocos2d-xAABB碰撞检测

1.AABB包围盒

在游戏中,为了简化物体之间的碰撞检测运算,通常会对物体创建一个规则的几何外形将其包围。

其中,AABB(axis-alignedboundingbox)包围盒被称为轴对其包围盒


二维场景中的AABB包围盒具备特点:(注:由于Cocos2d-x是基于OpenglES的,所以下图中的所有坐标系均采用右手直角坐标系)

(1)表现形式为四边形,即用四边形包围物体。

(2)四边形的每一条边,都会与坐标系的轴垂直。

如图1-1所示:

图1-1

三维场景中的AABB包围盒特点:

(1)表现形式为六面体。

(2)六面体中的每条边都平行于一个坐标平面。

如图1-2所示:

图1-2(图片来源百度)

在图1-2中,为了更明显的展示AABB包围盒的特点,在最右侧展示了一个OBB(OrientedBoundingBox)包围盒,也称作有向包围盒。

可以看出,AABB包围盒与OBB包围盒的最直接的区别就是,AABB包围盒是不可以旋转的,而OBB包围盒是可以旋转的,也就是有向的。

2.二维场景中的AABB碰撞检测原理

首先来看一张二维场景中的物体碰撞图:

图2-1

在图2-1中,分别做物体A与物体B在X,Y轴方向的投影,物体A的Y轴方向最大点坐标为Y1,最小点坐标Y2,X轴方向最小点坐标X1,最大点坐标X2,物体B同理。图中红色区域为物体A与物体B投影的重叠部分。

可以看出,AABB碰撞检测具有如下规则:

物体A与物体B分别沿两个坐标轴做投影,只有在两个坐标轴都发生重叠的情况下,两个物体才意味着发生了碰撞。

所以,在程序中做二维游戏的AABB碰撞检测时,只需验证物体A与物体B是否满足如下条件:

(1)物体A的Y轴方向最小值大于物体B的Y轴方向最大值;

(2)物体A的X轴方向最小值大于物体B的X轴方向最大值;

(3)物体B的Y轴方向最小值大于物体A的Y轴方向最大值;

(4)物体B的X轴方向最小值大于物体A的X轴方向最大值;

若满足上述条件,则证明物体A与物体B并未发生重合,反之,则证明物体A与物体B重合。

3.三维场景中的AABB碰撞检测原理

首先,再来看一下图2-1中的二维物体A和物体B的包围盒,可以发现实际上判断物体A与物体B是否发生重合只需要知道两个信息:

(1)物体A的最小点的信息,即图2-1中A的左下角点;以及物体A的最大点的信息,即图2-1中A的右上角点。

(2)物体B的最小点的信息,物体B的最大点的信息。

也就是说在二维场景的碰撞检测中,每个物体的顶点坐标信息都可以由两个坐标来确定,即两个坐标就可以标识一个物体了,所以两个物体的碰撞检测只需要获得到四个点坐标就可以了。

之前在图1-2中已经看到,三维场景中物体的AABB包围盒是一个六面体,其坐标系对于二维坐标系来讲只是多了一个Z轴,所以实际上在三维场景中物体的AABB碰撞检测依然可以采用四个点信息的判定来实现。即从物体A的八个顶点与物体B的八个顶点分别选出两个最大与最小的顶点进行对比。三维物体的AABB包围盒的八个顶点依旧可以用两个顶点来标识,如图3-1所示:

图3-1

只要确定了图中黑色点部分的坐标,就可以确定八个顶点的全部信息了。

在Cocos2d-x3.x版本中,为开发者提供了AABB类,用于保存包围盒的最大顶点与最小顶点的信息,并且为每个Sprite3D对象提供了获取AABB包围盒的接口,在AABB类同时提供了判断相应的碰撞检测的方法。

下面对AABB的源码进行分析:

CCAABB.h文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
class CC_3D_DLLAABB
{
public :
/**
*构造函数
*/
AABB();
/**
*构造函数参数:最小顶点坐标,最大顶点坐标
*/
AABB( const Vec3&min, Vec3&max);
/**
*构造函数参数:AABB包围盒
*/
AABB&box);
/**
*获取包围盒中心点坐标
*/
Vec3getCenter();
/*获取包围盒八个顶点信息
*Z轴正方向的面
*verts[0]:左上顶点
*verts[1]:左下顶点
*verts[2]:右下顶点
*verts[3]:右上顶点
*
*Z轴负方向的面
*verts[4]:右上顶点
*verts[5]:右下顶点
*verts[6]:左下顶点
*verts[7]:左上顶点
*/
void getCorners(Vec3*dst) ;
/**
*判断两个包围盒是否重合
*/
bool intersects( AABB&aabb) ;
/**
*判断一个点是否在包围盒内
*/
containPoint( Vec3&point) ;
/**
由两个包围盒生成一个能同时包围这两个包围盒的最小包围盒
*/
merge( AABB&box);
/**
*设置包围盒的最大顶点与最小顶点
*/
set( Vec3&max);
/**
*复位函数初始化最大最小顶点信息
*/
reset();
isEmpty() ;
/**
*更新最大顶点与最小顶点信息
*/
updateMinMax( Vec3*point,ssize_tnum);
/**
*由一个矩阵对对包围盒进行顶点变换
*/
transform( Mat4&mat);
:
Vec3_min; //三维向量保存最小点坐标
Vec3_max; //三维向量保存最大点坐标
};
NS_CC_END


CCAABB.cpp文件

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include"3d/CCAABB.h"
NS_CC_BEGIN
//构造函数
AABB::AABB()
{
reset(); //初始化最大顶点与最小顶点
}
AABB::AABB( Vec3&max)
{
set(min,max); //设置最大顶点与最小顶点
}
AABB&box)
{
set(box._min,box._max); //设置最大顶点与最小顶点
}
//获取包围盒中心点坐标
Vec3AABB::getCenter()
{
Vec3center;
center.x=0.5f*(_min.x+_max.x);
center.y=0.5f*(_min.y+_max.y);
center.z=0.5f*(_min.z+_max.z);
return center;
}
//获取包围盒八个顶点信息
AABB::getCorners(Vec3*dst) const
{
assert (dst);
//朝着Z轴正方向的面
//左上顶点坐标
dst[0].set(_min.x,_max.y,_max.z);
//左下顶点坐标
dst[1].set(_min.x,_min.y,_max.z);
//右下顶点坐标
dst[2].set(_max.x,_max.z);
//右上顶点坐标
dst[3].set(_max.x,_max.z);
//朝着Z轴负方向的面
//右上顶点坐标
dst[4].set(_max.x,_min.z);
//右下顶点坐标
dst[5].set(_max.x,_min.z);
//左下顶点坐标
dst[6].set(_min.x,_min.z);
//左上顶点坐标
dst[7].set(_min.x,_min.z);
}
//判断两个包围盒是否碰撞
AABB::intersects( const
{
((_min.x>=aabb._min.x&&_min.x<=aabb._max.x)||(aabb._min.x>=_min.x&&aabb._min.x<=_max.x))&&
((_min.y>=aabb._min.y&&_min.y<=aabb._max.y)||(aabb._min.y>=_min.y&&aabb._min.y<=_max.y))&&
((_min.z>=aabb._min.z&&_min.z<=aabb._max.z)||(aabb._min.z>=_min.z&&aabb._min.z<=_max.z));
}
//判断点和包围盒是否碰撞
AABB::containPoint( const
{
if (point.x<_min.x) return false ;
(point.y<_min.y) ;
(point.z<_min.z) ;
(point.x>_max.x) ;
(point.y>_max.y) ;
(point.z>_max.z) ;
true ;
}
//生成一个新的包围盒同时容纳两个包围盒
AABB::merge( AABB&box)
{
//计算新的最小点坐标
_min.x=std::min(_min.x,box._min.x);
_min.y=std::min(_min.y,box._min.y);
_min.z=std::min(_min.z,box._min.z);
//计算新的最大点坐标
_max.x=std::max(_max.x,box._max.x);
_max.y=std::max(_max.y,box._max.y);
_max.z=std::max(_max.z,box._max.z);
}
//设置最大顶点与最小顶点
AABB::set( Vec3&max)
{
this ->_min=min;
->_max=max;
}
//顶点复位初始化信息
AABB::reset()
{
_min.set(99999.0f,99999.0f,99999.0f);
_max.set(-99999.0f,-99999.0f,-99999.0f);
}
//检测坐标信息是否有误
AABB::isEmpty() const
{
_min.x>_max.x||_min.y>_max.y||_min.z>_max.z;
}
//由给定点坐标点重新确定最大最小的坐标向量
AABB::updateMinMax( {
for (ssize_ti=0;i<num;i++)
{
//最小x坐标
(point[i].x<_min.x)
_min.x=point[i].x;
//最小y坐标
(point[i].y<_min.y)
_min.y=point[i].y;
//最小z坐标
(point[i].z<_min.z)
_min.z=point[i].z;
//最大x坐标
(point[i].x>_max.x)
_max.x=point[i].x;
//最大y坐标
(point[i].y>_max.y)
_max.y=point[i].y;
//最大z坐标
(point[i].z>_max.z)
_max.z=point[i].z;
}
}
//通过给定的变换矩阵对包围盒进行变换
AABB::transform( Mat4&mat)
{
Vec3corners[8]; //保存包围盒八个顶点
//朝向z轴正方向的面
//左上顶点坐标
corners[0].set(_min.x,_max.z);
//左下顶点坐标
corners[1].set(_min.x,_max.z);
//右下顶点坐标
corners[2].set(_max.x,_max.z);
//右上顶点坐标
corners[3].set(_max.x,_max.z);
//朝向z轴负方向的面
//右上顶点坐标
corners[4].set(_max.x,_min.z);
//右下顶点坐标
corners[5].set(_max.x,_min.z);
//左下顶点坐标
corners[6].set(_min.x,_min.z);
//左上顶点坐标
corners[7].set(_min.x,_min.z);
//顶点变换
( int i=0;i<8;i++)
mat.transformPoint(&corners[i]);
//复位最大顶点最小顶点
reset();
//重新计算最大最小点信息
updateMinMax(corners,8);
}
4.总结

最后,AABB碰撞检测算法虽然计算方法简单,速度快,但是仅适用于精度不搞的游戏中。相对于AABB碰撞检测,还有一种更逼近物体并更为精确的一种算法——OBB碰撞检测。在Cocos2d-x中同样提供了OBB碰撞检测的相应方法,如图4-1所示:

图4-1

来源网址:http://www.jb51.cc/article/p-okjneale-bcr.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是