圆形矩形碰撞parsing

在我的游戏中,我有一个非轴alignment的矩形,就像一辆汽车。 我必须检查和解决矩形和圆形之间的碰撞,这是静止的。

我find了很多方法来确定碰撞,但找不到任何解决办法。 很显然,如果发生碰撞,我必须将矩形推回去,但是我找不到合适的方法。

有办法处理和解决矩形和圆形之间的碰撞? 像algorithm?

我正在开发的C + +。

@ErikEsTT:OP特意要求的不仅仅是一个布尔“相交”,他们需要最近的点或穿透深度或其他有意义的碰撞测量,而不仅仅是一个是/否。

为了回答OP的问题,可以使用矩形和圆形之间的有符号距离查询来实现圆形与矩形。 可能最简单的做法是将圆转换为矩形的本地空间(它是一个轴alignment的框),然后执行点对AABB带符号的距离查询。

这里有一个很好的(但是相当混乱的)签名框距离函数,或者任何好的书(例如RTCD或者GeomTools)都应该有类似的查询。

我把这个答案 ,这是AABB – 圆交点,改成OBB – 圆交点,并加上交点计算。

struct Vec2 { Vec2(): x( 0.0f ), y( 0.0f ) { } Vec2( float _x, float _y ): x( _x ), y( _y ) { } float x, y; }; struct Box { Vec2 Position, Size; float rotation; }; struct Circle { Vec2 Position; float radius; }; Vec2 TranslatePointOnBox( const Vec2& BoxPosition, const Vec2& BoxRotation, const Vec2& Point, const Vec2& Sign ) { Vec2 LocalPoint( Point.x * Sign.x, Point.y * Sign.y ); Vec2 WorldPoint; // rotate WorldPoint.x = LocalPoint.x * BoxRotation.x - LocalPoint.y * BoxRotation.y + BoxPosition.x; WorldPoint.y = LocalPoint.y * BoxRotation.x + LocalPoint.x * BoxRotation.y + BoxPosition.y; // translate WorldPoint.x += BoxPosition.x; WorldPoint.y += BoxPosition.y; return WorldPoint; } bool Itersects( const Circle& circle, const Box& box, Vec2& OutputPoint ) { Vec2 Diff1; // difference in world coord. Vec2 Diff2; // difference in local coord. Vec2 Rotation; Vec2 HalfSize; Vec2 Sign; // for restoring intersection quadrant Diff1.x = circle.Position.x - box.Position.x; Diff1.y = circle.Position.y - box.Position.y; Rotation.x = cos( box.rotation ); Rotation.y = sin( box.rotation ); Diff2.x = Diff1.x * Rotation.x - Diff1.y * Rotation.y; Diff2.y = Diff1.y * Rotation.x + Diff1.x * Rotation.y; Sign.x = Diff2.x < 0.0f ? -1.0f : 1.0f; Sign.y = Diff2.y < 0.0f ? -1.0f : 1.0f; Diff2.x = abs( Diff2.x ); Diff2.y = abs( Diff2.y ); HalfSize.x = box.Size.x / 2.0f; HalfSize.y = box.Size.y / 2.0f; // intersection AABB - circle if( Diff2.x > HalfSize.x + circle.radius || Diff2.y > HalfSize.y + circle.radius ) { OutputPoint = Vec2( 0.0f, 0.0f ); return false; } if( Diff2.x <= HalfSize.x ) { OutputPoint = TranslatePointOnBox( box.Position, Rotation, Vec2( HalfSize.x, Diff2.y ), Sign ); return true; } if( Diff2.y <= HalfSize.y ) { OutputPoint = TranslatePointOnBox( box.Position, Rotation, Vec2( Diff2.x, HalfSize.y ), Sign ); return true; } float CornerDistSquared = pow( Diff2.x - HalfSize.x, 2.0f ) + pow( Diff2.y - HalfSize.y, 2.0f ); if( CornerDistSquared <= circle.radius * circle.radius ) { OutputPoint = TranslatePointOnBox( box.Position, Rotation, HalfSize, Sign ); return true; } else { OutputPoint = Vec2( 0.0f, 0.0f ); return false; } } 

注意:

交点位于箱体表面,最靠近圆心。

Vec2 rotation;保持Box旋转更好Vec2 rotation; 反而float rotation; ,所以你不需要计算sin / cos每个交点(只有当旋转改变时才计算)。

你可以省略OutputPoint = Vec2( 0.0f, 0.0f ); ,它在不交集的情况下返回零向量。

我在这里回答了这个问题,除了代码是在Java(math很容易翻译)。

https://stackoverflow.com/questions/18704999/how-to-fix-circle-and-rectangle-overlap-in-collision-response/18790389#18790389

我的解决scheme处理轴alignment的框,但是您可以轻松地将其转换为处理定向框,方法是将圆的当前位置和将来位置围绕矩形的中心旋转,直到矩形alignment轴。

上述代码说明了高速运动的圆形,所以它们不能穿过矩形而不能跳过角落。