在我的游戏中,我有一个非轴对齐矩形,就像一辆汽车。我必须检查并解决矩形和圆形之间的碰撞,这是静止的。
我已经找到了很多确定碰撞的方法,但是在解决这个问题上找不到任何东西。很明显,如果发生碰撞,我必须把矩形往后推,但我找不到合适的方法。
有办法处理和解决矩形和圆圈之间的碰撞吗?像算法一样?
我正在c++开发。
发布于 2012-08-10 20:53:28
@ErikEsTT: OP特别要求的不仅仅是布尔值“是相交的”,它们需要最近的点或穿透深度,或者其他有意义的碰撞度量,而不仅仅是是/否。
要回答OP的问题,可以使用rect和圆形之间的带符号距离查询来实现圆形-vs-矩形。可能最简单的方法是将圆圈转换成rect的局部空间(其中它是一个轴对齐框),然后执行点-vs有符号距离查询。
这里有一个非常出色(但相当混乱)的签名框距离函数:http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm或任何好书(例如RTCD或GeomTools)都应该有类似的查询解释。
发布于 2012-08-04 06:41:20
我取了这个回答,它是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旋转,而不是在float rotation;
中,这样就不需要计算sin/cos每个交叉口(只有当旋转发生变化时才计算)。
你可以省略OutputPoint = Vec2( 0.0f, 0.0f );
,它在没有交集的情况下返回零向量。
发布于 2013-09-13 09:06:54
我在这里回答了这个问题,但代码是用Java编写的(数学很容易翻译)。
我的解决方案处理轴对齐框,但您可以轻松地将其转换为面向方向的框,方法是将圆圈、当前和未来位置围绕矩形中心旋转,直到矩形对齐为止。
上述代码代表高速移动圆,因此它们不能通过矩形,也不能跳过拐角。
https://gamedev.stackexchange.com/questions/33546
复制