从Vector2位置到另一个位置的弯曲移动

本文关键字:位置 弯曲 移动 Vector2 另一个 | 更新日期: 2023-09-27 18:00:40

目前,为了将苍蝇从一个位置移动到另一个位置,我使用的是:

    DirectionNormalized = (positionTarget - position).Normalize;

    position += DirectionNormalized *
            vitesseP2P *
            (float)gameTime.ElapsedGameTime.TotalMilliseconds;

所以,苍蝇从a点飞到B点,从C点飞到D点,等等

但我想弯曲它的轨迹。这太不可思议了,我以为这很容易,但我被困了好几个小时。

希望你能帮忙。

从Vector2位置到另一个位置的弯曲移动

实现这一点的最常见方法是使用贝塞尔曲线。Bezier算法取一组点——两个端点和多个控制点——并在由这些点定义的曲线上的不同位置产生一系列点。

Bezier算法的广义形式是迭代归约,但我们可以针对特定的4点情况展开它,并生成如下的BezierInterpolate函数:

public static Vector2 BezierInterpolate(Vector2 p0, Vector2 p1, Vector2 c0, Vector2 c1, float fraction)
{
    // first stage, linear interpolate point pairs: [p0, c0], [c0, c1], [c1, p1]
    Vector2 p0c0 = Vector2.Lerp(p0, c0, fraction);
    Vector2 c0c1 = Vector2.Lerp(c0, c1, fraction);
    Vector2 c1p1 = Vector2.Lerp(c1, p1, fraction);
    // second stage, reduce to two points
    Vector2 l = Vector2.Lerp(p0c0, c0c1, fraction);
    Vector2 r = Vector2.Lerp(c0c1, c1p1, fraction);
    // final stage, reduce to result point and return
    return Vector2.Lerp(l, r, fraction);
}

这将为您提供一个点的位置,该点是沿着曲线的某个分数。例如,如果你有动画的开始和结束时间,你可以使用上面的生成你的苍蝇的当前位置。

不过,首先,您需要定义控制点。我会用这样的东西:

static System.Random prng = new System.Random();
public static Vector2 genControlPoint(Vector2 l, Vector2 r)
{
    // get a random angle between +/-(15..90) degrees off line
    float angle = (float)((((prng.NextDouble() * 5) + 1) / 12) * Math.PI * (prng.Next(0, 2) * 2 - 1));
    // create rotation matrix
    Matrix rot = Matrix.CreateRotationZ(angle);
    // get point offset half-way between two points
    Vector2 ofs = Vector2.op_Multiply(Vector2.op_Subtract(l, r), 0.5);
    // apply rotation
    ofs = Vector2.Transform(ofs, rot);
    // return point as control
    return Vector2.op_Add(l, ofs);
}
....
Vector2 p0 = FlyStartPoint();
Vector2 p1 = FlyEndPoint();
// generate randomized control points for flight path
Vector2 c0 = genControlPoint(p0, p1);
Vector2 c1 = genControlPoint(p1, p0);

在这一点上,您有一组四个点,适合作为BezierInterpolate方法的前4个参数传递,从中您可以确定"苍蝇"在特定时间的位置。

贝塞尔曲线一开始很可怕,但一旦你了解了它们,它们就会成为有用的工具。当您调用Vector2.HermiteVector2.CatmullRom时,像我在这里所做的那样手动操作可以让您更多地了解后台实际发生的事情。

您可以计算一个样条曲线和沿着该样条曲线的位置(随着时间的推移)。

请参阅http://www.c-sharpcorner.com/UploadFile/apundit/DrawingCurves11182005012515AM/DrawingCurves.aspx

另一种方法是使用物理引擎。你可以给你的苍蝇一个质量和速度,并通过改变它的速度来改变运动。

Xna框架有一个内置的Curve类来实现这一点。

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.curve.aspx

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.curve(v=XNAGameStudio.35).aspx

这里有一个带有代码的示例:

http://msdn.microsoft.com/en-us/library/bb203908.aspx

他们甚至创建了一个特殊的曲线编辑器,可以轻松地将曲线输入代码:http://xbox.create.msdn.com/en-US/education/catalog/utility/curve_editor