ImageVerifierCode 换一换
格式:DOCX , 页数:27 ,大小:72.66KB ,
资源ID:10071975      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10071975.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(碰撞检测教程C++.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

碰撞检测教程C++.docx

1、碰撞检测教程C+简介本文是阐述如何在2D动作游戏中进行精确而高效的碰撞检测。这里的碰撞是基于多边形而不是基于精灵的。这两者之间在设计上会有不同。基于精灵的碰撞检测是通过精灵之间的重叠的像素来完成的。而多边形使用向量数学来精确计算交点,时间和碰撞方向。虽然多边形仅仅是精灵的一个近似,但是它比精灵系统要高级。可以精确模拟逼真的简单物理学,例如反弹,摩擦,斜面的滑行碰撞检测可以更精确的用于高速精灵系统。在基于精灵的系统中,如果物体移动过快就会在跳过另一个物体。基于向量数学因此可以扩展到3D,然而精灵碰撞系统被严格限制在2D的情况下。特性本文使用的算法只适用于凸多边形,例如三角形,四边形,六边形,圆形

2、。对于非凸多边形,你可以将其分解为多个凸多边形,例如三角形。算法可以用于快速移动或慢速移动的多边形。不管物体移动多快,碰撞都不会丢失。它也可以处理重叠的问题,并促使交叠物体分离。演示也支持分割多边形交叉。这可以用于子弹的建模。同时提供了简单的物体系统,弹力,一些基本的摩擦和静摩擦力。用于确保物体不会从斜面上滑落。有一个刚体系统的例子,使用了Chrsi Hecker的物理教程。限制有序碰撞。就是说并不是有序的进行碰撞。这对于快速移动的物体会出现一定的问题。一旦碰撞被检测到,它就被直接处理了。理想状态下你可能需要找到一个碰撞点并处理它,然后寻找更多的碰撞。但是对于2D动作游戏,这通常是不必要的。一

3、、分离坐标轴方法这个方法是碰撞检测的核心。它的规则非常简单并且非常易于实现。这个方法也非常快并且非常可靠,因为计算中没有使用除法操作,下面给出一个简单的基于两个BOX的碰撞检测的例子。算法试图在两个物体之间找到一个合适平面,如果这个平面存在,那么物体就没有相交。为了测试物体是否是分开的,简单的方法是投影这个物体到平面的法线上,并比较两者之间的间距看二者是否重叠。显然有无数的平面可以用来分割两个物体。但是已经经过证明的是:你只需要使用一部分平面来进行测试,对于BOX从上图中可以看出平面的法线为BOX B的长轴。对于BOX来说需要测试的分割平面是那些法线等于两个BOX的轴向的平面。因此对于两个BO

4、X来说,你只需要测试4个分割平面即可。在这四个平面里,一旦发现一个分割平面可以分割BOX那么你就可以断定这两个BOX是不相交的。如果四个平面都不能分割BOX,那么这两个BOX一定是相交的,也就是出现了碰撞。可以扩展这个算法到普通的多边形,算法是相同的,只用需要测试的平面的数量改变了。并且分割平面在每个多边形边的垂直方向上又有一个法线。在下图中,你可以看到两个分割平面用于测试。在红色的平面上你可以看到两个间隔是重叠的。然而,在蓝色的平面上间隔是不重叠的,因此,蓝色的平面的是分割平面,因此物体是不相交的。现在,我们有一个算法来检测两个多边形是否是相交的。代码可以分为三个部分:a) 生成需要测试的分

5、离轴b) 计算每一个多边形在分离轴法线上的投影c) 检测这些投影是否相交bool Intersect(Polygon A, Polygon B) for(I = 0; I A.num_edges; I +) Vector N = Vector(-A.EdgeDirI.y, A.EdgeDirI.x);if (AxisSeparatePolygons(N, A, B) return false; for(I = 0; I B.num_edges; I +) Vector N = Vector(-B.EdgeDiri.y, B.EdgeDirI.x); if (AxisSeparatePolygo

6、ns (N, A, B) return false; return true; void CalculateInterval(Vector Axis, Polygon P, float& min, float& max) float d = Axis dot P.vertex0; /从坐标原点开始计算向量 min = max = d; for(I = 0; I P.num_vertices; I +) float d = P.vertexI dot Axis; if (d max) max = d; 算法检测2D多边形之间的碰撞,这个算法非常的快速和适用。边的方向不需要单位化,因此你可以避免存

7、贮边的方向,并通过多边形的顶点直接得到边的方向。for(J = A.num_vertices-1, I = 0; I A.num_vertices; J = I, I +) Vector E = A.vertexI - A.vertexJ; Vector N = Vector(-E.y, E.x); if (AxisSeparatePolygons(N, A, B) return false; 二、用于碰撞响应的扩展分离坐标轴方法检测多边形相交是非常有用的方法,但是可以做更多的事情。当多边形相交时,我想将他们移开以避免他们相交。分离轴的方法可以非常好的用于这种情况,但是还需要作一些额外的工作。

8、必须返回相交的深度,和推开多边形将它们分离的方向。相交的深度和方向的组合称为MTD,或者最小平移距离。这是用于将物体分离的的最小向量。为了计算MTD,我们可以使用分离坐标轴。当物体相交时,我们可以计算两个物体在每一个分离轴上的投影间隔。两个间隔交叠的部分提供了一个推动向量,你需要将其应用到其中一个物体上以便物体在轴上的投影停止交叠“推动向量”你需要应用于A上将A推开,这样就可以使A和B分开。显然,不能沿着一个随机的轴来推开物体。候选轴是投影在该轴上两个间隔之间交叠最小的那个。并且这个推动向量提供了最小平移距离。bool Intersect(Polygon A, Polygon B, Vecto

9、r& MTD) / 电位分离轴。他们被转换成推动 vectors Vector Axis32; / 每个多边形最大的16个顶点的 int iNumAxis = 0; for(J = A.num_vertices - 1, I = 0; I A. num_vertices; J = I, I +) Vector E = A.vertexI - A.vertexJ; AxisiNumAxis+ = Vector(-E.y, E.x); if (AxisSeparatePolygons(N, A, B) return false; for(J = B. num_vertices - 1, I = 0

10、; I B.num_vertices; J = I, I +) Vector E = B.vertexI - B.vertexJ; AxisiNumAxis+ = Vector(-E.y, E.x); if (AxisSeparatePolygons (N, A, B) return false; / 找到所有的分离向量之间的MTD MTD = FindMTD(Axis, iNumAxis); / 确保将向量a推动远离b Vector D = A.Position - B.Position; if (D dot MTD maxb | minb maxa) return true; / 查找间隔

11、重叠 float d0 = maxa - minb; float d1 = maxb - mina; float depth = (d0 d1)? d0 : d1; / 将分离轴为推力矢量(重新恢复正常的轴乘区间重叠) float axis_length_squared = Axis dot Axis; Axis *= depth / axis_length_squared; return false; Vector FindMTD(Vector* PushVectors, int iNumVectors) Vector MTD = PushVector0; float mind2 = Pus

12、hVector0 dot PushVector0; for(int I = 1; I iNumVectors; I +) float d2 = PushVectorI * PushVectorI; if (d2 0.00001f) if (!IntervalIntersect( A, Anum, B, Bnum, xAxisiNumAxes, xOffset, xVel, taxisiNumAxes, t) return false; iNumAxes+; / 测试分离轴A for(int j = Anum-1, i = 0; i Anum; j = i, i +) Vector E0 = A

13、j; Vector E1 = Ai; Vector E = E1 - E0; xAxisiNumAxes = Vector(-E.y, E.x); if (!IntervalIntersect( A, Anum, B, Bnum, xAxisiNumAxes, xOffset, xVel, taxisiNumAxes, t) return false; iNumAxes+; / 测试分离轴B for(int j = Bnum-1, i = 0; i Bnum; j = i, i +) Vector E0 = Bj; Vector E1 = Bi; Vector E = E1 - E0; xAx

14、isiNumAxes = Vector(-E.y, E.x); if (!IntervalIntersect( A, Anum, B, Bnum, xAxisiNumAxes, xOffset, xVel, taxisiNumAxes, t) return false; iNumAxes+; if (!FindMTD(xAxis, taxis, iNumAxes, N, t) return false; / 确保多边形被彼此推开。 if (N * xOffset 0.0f) N = -N; return true; bool AxisSeparatePolygons ( Vector N, P

15、olygon A, Polygon B, Vector Offset, Vector Vel, float &t, float tmax) float min0, max0; float min1, max1; CalculateInterval(N, A, min0, max0); CalculateInterval(N, B, min1, max1); float h = Offset dot N; min0 += h; max0 += h; float d0 = min0 - max1; / 如果重叠, do 0 / 分离,测试动态间隔 if (d0 0.0f | d1 0.0f) fl

16、oat v = Vel dot N; / 速度很小,所以只能进行重叠测试。 if (fabs(v) t1) float temp = t0; t0 = t1; t1 = temp; / 取最小值 taxis = (t0 0.0f)? t0 : t1; / 交叉时间太晚或时间,没有碰撞 if (taxis tmax) return true; return false; else / 重叠。得到的区间,作为最小的|D0|和|D1| / 返回负数以标记为重叠 taxis = (d0 d1)? d0 : d1; return false; bool FindCollisionPlane (Vecto

17、r* Axis, float* taxis, int iNumAxes, Vector& Ncoll, float& tcoll) / 先找到碰撞 int mini = -1; tcoll = 0.0f; for(int i = 0; i 0.0f) if (taxisi tcoll) mini = i; tcoll = taxisi; Ncoll = Axisi; Ncoll.Normalise(); / 将轴 / 发现了碰撞 if (mini != -1) return true; / 不,找到重叠 mini = -1; for(int i = 0; i tcoll) mini = i;

18、tcoll = taxisi; Ncoll = Axisi; return (mini != -1); 现在,你拥有了一个可以检测未来碰撞的的检测系统,或者当重叠的时候,返回碰撞平面和碰撞深度/时间四、基本弧碰撞响应下面要作的是用给定的量将两个物体分离,并添加一点摩擦和一些静态摩擦,以便使物体静止在斜面上。该部分使用简单的速度影响算法。同样,为了使碰撞响应更加真实,物体被赋予了质量(更好的是质量的倒数)。质量的倒数是比较常用的,该值为零意味着该物体具有无穷大的质量,并因此不能移动。同时速度响应中使用质量的倒数具有更好的物理精确性。现在我们知道多边形A在位置PA具有速度VA,与位置PB速度VB的

19、多边形B发生碰撞。Ncoll和tcoll定义了碰撞平面。如果碰撞前是交叠的,首先分离两个物体,如下:if (tcoll 0) if (A.InvMass = 0) PB += Ncoll * tcoll; else if (B.InvMass = 0) PA -= Ncoll * tcoll; else PA -= Ncoll * (tcoll *0.5f); PB += Ncoll * (tcoll *0.5f); 然后可以调用碰撞响应的代码,为了简化,我们可以考虑一个粒子碰到一个平面上这里V表示粒子的进入速度,V是粒子发生碰撞后的速度,N为平面的法向。V = V - (2 * (V . N) * N理想状态下,碰撞前后粒子的能量是相同的。但是我们可以给粒子的碰撞加入弹性系数V = V - (1 + elasticity) * (V . N) * N弹性系数的范围为0,1如果为零意味着粒子将沿着平面滑动,如果为1,粒子将没有能量损耗的弹开。同样我们可以加入一些摩擦。如果

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1