我正试图在我的XNA游戏中投掷箭头,但我很难想要实现一个好的抛物线。
我需要什么:
这就是我已经拥有的:
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
)以制作完美的抛物线时,我需要做些什么才能让箭头走到尽头?
答案 0 :(得分:0)
注意:我从未听说过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;
}
}
希望这有效,尽管可能有更有效的方法来实现这一点。虽然这不是物理站点,但请参阅this以供参考; - )
答案 1 :(得分:0)
上面讨论的解决方案依赖于您在每次迭代时计算新的速度,然后计算前一个位置的增量(变化)以确定当前位置。
这符合游戏循环的正常逻辑。然而,它在计算上比它需要的更复杂,并且由于舍入误差而可能不稳定。
更简单,更稳定的解决方案是确定抛物线的方程,并使用它在发射后的时间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坐标。
这是一种更直接的方法,更强大(舍入错误不会累积)。这就是我亲自做的事情。我的手榴弹始终遵循完美的抛物线弧,并以计算效率的方式进行。