Joe*_*oel 8 algorithm 2d collision-detection
在游戏程序的上下文中,我有一个移动的圆圈和一个固定的线段.该段可以具有任意大小和方向.

我在尝试计算时遇到困难:
我将用伪算法回答 - 没有任何代码.我看到它的方式有两种情况我们可能会返回true,如下图所示:

这里的蓝色是你的圆圈,虚线是轨迹线,红线是你的给定线.

从轨迹开始,我们将法线建立到每个点A和B.然后将这些线切割或延伸到辅助线(Ha和Hb)中,使得它们的长度A和B圆正好是圆的半径.然后我们检查这些辅助线中的每一条是否与轨迹线相交.如果他们确实回归真实.
看这里:
如果 x 或 y 计算的平方根下得到的值为负数,则该线段不相交。除此之外,您可以在获得 x 和 y 后停止计算(注意:您可能会得到两个答案)
更新我已经修改了我的答案以非常具体地解决您的问题。我将此解决方案归功于Doswa,因为我几乎是按照 C# 编写的。基本策略是我们要找到线段最接近圆心的点。基于此,我们将查看最近点的距离,如果它在半径内,则沿方向找到该点到位于圆半径处的最近点。
// I'll bet you already have one of these.
public class Vec : Tuple<double, double>
{
public Vec(double item1, double item2) : base(item1, item2) { }
public double Dot(Vec other)
{ return Item1*other.Item1 + Item2*other.Item2; }
public static Vec operator-(Vec first, Vec second)
{ return new Vec(first.Item1 - second.Item1, first.Item2 - second.Item2);}
public static Vec operator+(Vec first, Vec second)
{ return new Vec(first.Item1 + second.Item1, first.Item2 + second.Item2);}
public static Vec operator*(double first, Vec second)
{ return new Vec(first * second.Item1, first * second.Item2);}
public double Length() { return Math.Sqrt(Dot(this)); }
public Vec Normalize() { return (1 / Length()) * this; }
}
public bool IntersectCircle(Vec origin, Vec lineStart,
Vec lineEnd, Vec circle, double radius, out Vec circleWhenHit)
{
circleWhenHit = null;
// find the closest point on the line segment to the center of the circle
var line = lineEnd - lineStart;
var lineLength = line.Length();
var lineNorm = (1/lineLength)*line;
var segmentToCircle = circle - lineStart;
var closestPointOnSegment = segmentToCircle.Dot(line) / lineLength;
// Special cases where the closest point happens to be the end points
Vec closest;
if (closestPointOnSegment < 0) closest = lineStart;
else if (closestPointOnSegment > lineLength) closest = lineEnd;
else closest = lineStart + closestPointOnSegment*lineNorm;
// Find that distance. If it is less than the radius, then we
// are within the circle
var distanceFromClosest = circle - closest;
var distanceFromClosestLength = distanceFromClosest.Length();
if (distanceFromClosestLength > radius) return false;
// So find the distance that places the intersection point right at
// the radius. This is the center of the circle at the time of collision
// and is different than the result from Doswa
var offset = (radius - distanceFromClosestLength) *
((1/distanceFromClosestLength)*distanceFromClosest);
circleWhenHit = circle - offset;
return true;
}
Run Code Online (Sandbox Code Playgroud)