第四章 碰撞模块

2019-04-14 12:55发布

声明:此文章翻译自Box2D v2.2.0用户手册,仅供学习参考。 4.1 关于 碰撞模块包括了形状以及操作形状的方法。模块也包括了动态树(dynamic tree)和broad-phase算法来提高大系统碰撞检测的速度。 碰撞模块的设计独立于动力学系统之外。例如,你可以在游戏中除了物理系统之外的其他方面单独使用动态树(dynamic tree)。 4.2 形状 形状描述了碰撞几何体,在物理模拟中可独立使用,你可以对形状进行多种操作。 b2Shape作为Box2D形状的基类,定义了如下方法:
  • 判断一个点是否与形状重叠
  • 向形状投射一条射线
  • 计算形状的AABB
  • 计算形状的质量属性
另外,每一个形状有一个类型成员和对应的半径。半径甚至会应用于多边形中,下面还将会对此进行讨论。 4.3 圆形(Circle Shapes) 圆形有坐标点和半径。 圆形是实心的。你不能够创建一个空心的圆形。即便如此,你还可以使用多边形形状来创建线段链。 1 2 3 b2CircleShape circle; circle.m_p.Set(2.0f, 3.0f); circle.m_radius = 0.5f; 4.4 多边形(Polygon Shapes) 多边形形状是实心凸多边形。所谓一个多边形为凸多边形,即多边形上所有线段中任意两个顶点间的连线都与此多边形的边无交点。多边形是实心的,永远都不会是空心。一个多边形至少需要由3个或更多顶点组成。 pic 你必须按照逆时针(counter clockwise winding,CCW)的方向创建一个多边形。对于这一点我们需要小心,逆时针是相对于右手坐标系统而言的,其中z轴指向平面外面。在你的屏幕上可能是顺时针方向,这取决于你的坐标系统是如何约定的。 pic 虽然多边形的成员变量的访问权限是public,但是你仍然需要使用相应的初始化方法来创建一个多边形。初始化方法会创建法向量并验证其合法性。 你可以通过一个顶点数组来创建多边形。数组的最大值被b2_maxPolygonVertices所控制,它的默认值是8,这足以描述大多数凸多边形。 1 2 3 4 5 6 7 8 //This defines a triangle in CCW order. b2Vec2 vertices[3]; vertices[0].Set(0.0f, 0.0); vertices[1].Set(1.0f, 0.0f); vertices[2].Set(0.0f, 1.0f); int32 count = 3; b2PolygonShape polygon; polygon.Set(vertices, count); 多边形有一些定义好的创建盒子(boxes)的初始化方法。 1 2 void SetAsBox(float32 hx, float32 hy); void SetAsBox(float32 hx, float32 hy, const v2Vec2& center, float32 angle); 多边形从b2Shape继承了半径。半径围绕多边形创建了一个外壳(skin)。在多边形重叠的情况下,外壳可以保持多边形之间短距离分离。这使得核心多边形(译者注:外壳包裹着的多边形)可以进行持续碰撞。 pic 多边形的外壳可以通过保持多边形的分离防止隧道效应(译者注:所谓隧道效应就是在单个时间步长内两个多边形瞬间互相穿透的情况,示意图可见4.13)的发生。两个形状之间存在细微的差距。多边形会隐藏任何细微的差距,在你的眼前只会有更大的视觉范围。 pic 4.5 边缘形状(Edge Shape) 边缘由多条线段组成。它可以自由的让你为游戏创建一个静态的环境。边缘形状的一个主要限制是不能和自己进行碰撞检测,只能与圆形和多边形进行碰撞检测。Box2D中使用的碰撞算法涉及到的两个碰撞形状中至少有一个形状要有体积(volume)。边缘形状没有体积,所以边缘与边缘之间不能够进行碰撞。 1 2 3 4 5 //This an edge shape. b2Vec2 v1(0.0f, 0.0f); b2Vec2 v2(1.0f, 0.0f); b2EdgeShape edge; edge.Set(v1, v2); 在很多游戏环境中,会把多个边缘形状的点与点之间进行首尾连接。当一个多边形沿着边缘链滑动的时候会出现莫名其妙的效果。在下图中我们看到一个盒子正要和内部顶点进行碰撞。一个幽灵(ghost)碰撞借此将会发生,当盒子与内部顶点进行相撞的同时,会产生一个内部碰撞法向量。 pic 如果edge1不产生这次碰撞看起来效果会很好。但是当前的edge1产生的这个碰撞看起来就像是一个bug。但是正常情况下Box2D中两个形状的碰撞,看起来就像是把两个形状进行了隔离。 幸运的是,边缘形状提供了通过存储相邻的幽灵(ghost)顶点机制来消除幽灵(ghost)碰撞。Box2D使用存储后的幽灵(ghost)顶点来防止内部碰撞。 pic 1 2 3 4 5 6 7 8 9 10 11 //This an edge shape with ghost vertices b2Vec2 v0(1.7f, 0.0f); b2Vec2 v1(1.0f, 0.25f); b2Vec2 v2(0.0f, 0.0f); b2Vec2 v3(-1.7f, 0.4f); b2EdgeShape edge; edge.Set(v1,v2); edge.m_hasVertex0 = true; edge.m_hasVertex3 = true; edge.m_vertex0 = v0; edge.m_vertex3 = v3; 一般情况下,将边缘形状拼接在一起这种方法看起来有些浪费和繁琐。这也将引出我们下一个形状类型。 4.6 链形状(Chain Shapes) 链形状提供了一种高效的方法来同时连接多条边儿,从而为你的游戏创建静态的游戏世界。链形状自动消除幽灵(ghost)碰撞并提供了两面碰撞。 pic 1 2 3 4 5 6 7 8 //This a chain shape with isolated vertices b2Vec2 vs[4]; vs[0].Set(1.7f, 0.0f); vs[1].Set(1.0f, 0.25); vs[2].Set(0.0f, 0.0f); vs