繁体   English   中英

创建固定角度的抛物线轨迹

[英]Create a parabolic trajectory with fixed angle

我正在尝试在XNA游戏中投箭,但是我很难尝试实现一个好的抛物线。

我需要的:

  • 你越握输入更强的箭头去。
  • 箭头角度将始终相同,为45度

这是我已经拥有的:

private float velocityHeld = 1f;
protected override void Update(GameTime gameTime)
{

    if (Keyboard.GetState().IsKeyDown(Keys.Enter) && !released)
    {
        timeHeld += velocityHeld;
        holding = true;
    }
    else
    {
        if (holding)
        {
            released = true;
            holding = false;
            lastTimeHeld = timeHeld;
        }
    }


    if (released && timeHeld > 0)
    {
        float alpha = MathHelper.ToRadians(45f);
        double vy = timeHeld * Math.Sin(alpha);
        double vx = timeHeld * Math.Cos(alpha);

        ShadowPosition.Y -= (int)vy;
        ShadowPosition.X += (int)vx;
        timeHeld -= velocityHeld;
    }
    else
    {
        released = false;
    }
}

我的问题是,当箭头失去速度( timeHeld )以制作出完美的抛物线时,我该怎么做才能使其箭头走到底?

注意:到目前为止,我从未听说过XNA,但我确实使用C#。 让我知道这是否行得通,尽管它的要旨应该在那里。

在您的最后一个if语句中,松开Enter键后,您希望每次调用Update时都将向下速度增加一定的(小常数)(我假设增加y坐标会使事物在屏幕上“向下”移动) 。 为此,请在释放Enter后立即进行操作,而不是每次都调用double vy = timeHeld * Math.Sin(alpha) ,将结果保存到以后可以引用的变量中,然后使用bool值来跟踪何时计算该值,只有在释放Enter之后才可以。

换句话说,它是这样的:

// extra variables
bool justReleased = false;
double vy, vx;
...
protected override void Update(GameTime gameTime)
{
    // ...
        if (holding)
        {
            released = true;
            holding = false;
            lastTimeHeld = timeHeld;
            justReleased = true; // add this here
        }
    // ...

    if (released && timeHeld > 0)
    {
        float alpha = MathHelper.ToRadians(45f);

        // not local variables anymore. Also I flipped the sign - my intention is that initial vertical velocity is "upwards"
        if(justReleased)
        {
            vy = -1 * timeHeld * Math.Sin(alpha); 
            vx = timeHeld * Math.Cos(alpha);
            justReleased = false;
        }

        ShadowPosition.Y += (int)vy; // Note: I flipped this operator
        ShadowPosition.X += (int)vx;
        timeHeld -= velocityHeld;

        // increase the downward velocity
        vy += 2; // or some constant. I can't test this. :\
    }
    else
    {
        released = false;
    }
}

希望这可以奏效,尽管可能会有更有效的方法来做到这一点。 虽然这不是一个物理站点,请参见参考;-)

上面讨论的解决方案依赖于您在每次迭代中计算新的速度,然后计算前一位置的增量(变化)以确定当前位置。

这符合游戏循环的正常逻辑。 但是,它在计算上比需要的更为复杂,并且可能由于舍入误差而变得不稳定。

更简单,更稳定的解决方案是确定抛物线方程,并用其直接计算发射后时刻t的位置。

让箭头从x = 0,y = 0开始。 假设发射速度为v。在发射后的时间t,箭头的坐标为x = kt,其中k = v * cos(45)= v / sqrt(2)。

y位置是二次的,y = at ^ 2 + bt + c,我们不知道a,b,c。

但是当t = 0时y = 0所以c = 0

当t = 0时,初始向下速度为v * sin(45)= v / sqrt(2)

在t = 0时使用微积分(求位置的微分)

v / sqrt(2)= 2at + b = b

通过微分速度获得加速度,我们得到t = 0时的初始加速度为2a。 但是唯一的加速度是由于重力引起的,所以2a = -g,其中g是您的重力常数。

在时间t将这两个方程放在一起

x(t)= v / sqrt(2); y(t)=-(g / 2)t ^ 2 + vt / sqrt(2)

您知道v和t,定义了g,因此可以直接从该方程式计算出在时间t处的x和y坐标。

这是一种更直接,更可靠的方法(舍入误差不会累积)。 这就是我个人的方式。 我的手榴弹始终遵循完美的抛物线弧,并且以计算有效的方式进行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM