簡體   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