6

我试图在我的第一个 xna 2d 游戏中模拟重力。我有以下

        //Used for Jumping
    double elapsedAirTime = 0.0;
    double maxAirTime = 8.35;
    //End Jumping

所以我试图在 elapsedAirTime < maxAirTime 时将精灵向上移动一定量但是,在这段时间里,我的代码似乎只向上移动精灵一次而不是多次。这是我的“player.cs”类中的代码,或者类的更新方法。

if (newState.IsKeyDown(Keys.Space))
        {
            if(oldState.IsKeyUp(Keys.Space))
            {
                //if we are standing or jumping then change the velocity
                if (playerState == PlayerStates.Standing)
                {
                    playerState = PlayerStates.Jumping;
                    this.position.Y -= (float)(30.0 + ((1.2)*elapsedAirTime)*elapsedAirTime);
                }
            }
        }
        //if we are jumping give it some time
        if (playerState == PlayerStates.Jumping)
        {
            if ((elapsedAirTime < maxAirTime) && position.Y < 3)
            {
                this.position.Y -= (float)(30.0 + ((1.2) * elapsedAirTime)*elapsedAirTime);
                elapsedAirTime += gameTime.ElapsedGameTime.TotalSeconds;
            }
            //otherwise time to fall
            else
            {
                playerState = PlayerStates.Falling;
            }

        }

        //add gravity to falling objects
        if (playerState == PlayerStates.Falling || playerState == PlayerStates.Standing)
        {
            //if we are above the ground
            if (this.position.Y < windowBot - 110)
            {
                //chnage state to falling
                playerState = PlayerStates.Falling;
                this.position.Y += 3.0f + ((float)(gameTime.ElapsedGameTime.TotalSeconds));
            }
            else
            {
                playerState = PlayerStates.Standing;
                elapsedAirTime = 0.0f;
            }
        }

任何帮助都非常感谢,请,谢谢!

4

2 回答 2

11

为了让你的精灵有重力的感觉,你应该在你的 Sprite 类中添加速度和加速度。然后,为 Sprite 创建一个 Update 方法,并为每次更新的速度添加加速度,并为每次更新的位置添加速度。位置不应基于经过的空中时间量。您可以将加速度设置为恒定的重力值,然后在您跳跃时添加到 Sprite 的速度。这将创建一个看起来不错的流动抛物线跳跃。如果要包括计时,可以将 GameTime 传递给 Sprite 的 Update 方法,并将其用作速度的修改器。这是一个示例更新方法:

void Update(GameTime gt)
{
    int updateTime = gt.ElapsedGameTime.TotalMilliseconds - oldgt.ElapsedGameTime.TotalMilliseconds;
    float timeScalar = updateTime / AVG_FRAME_TIME;
    this.velocity += this.acceleration * timeScalar;
    this.position += this.velocity;
    oldgt = gt;
}

如果使用计时,这个方法有点复杂。您必须跟踪更新花费了多少时间,然后将其除以更新或帧应该花费的平均时间,以获得您应该调整速度的量。不用计时,方法很简单:

void Update()
{
    this.velocity += this.acceleration;
    this.position += this.velocity;
}

我建议您使用更简单的方法,直到您确切了解计时的工作原理以及为什么需要实施它。

于 2011-02-07T00:03:11.947 回答
2

看起来这条线有问题:

this.position.Y -= (float)(30.0 + ((1.2) * elapsedAirTime)*elapsedAirTime);

我想你会发现更新精灵位置的速度比你想象的要快,精灵将在 10 次更新中向上移动 330 像素(假设Game.IsFixedTimeStep == true),即十分之一秒的实时更新

这很可能只是更新得太快了,以至于在&& position.Y < 3条件启动并更改 playerState 之前您没有看到它上升。

看起来您想说的是 - 只要保持空间,就可以以每秒 x 像素的速度跳跃最多 8.5 秒。

您需要将计算更改为this.position.y -= (float) (30 * gameTime.ElapsedGameTime.TotalSeconds),这将为跳跃动作提供非常线性的运动,但这意味着精灵以每秒 30 像素的速度跳跃。

如果Game.IsFixedTimeStep == true- 这是默认值 - 更新每秒被调用 60 次,因此每次更新 gameTime.ElapsedGameTime.TotalSeconds 大约为 0.1。如果发生某些事情导致更新跳过(例如渲染问题),那么更新将被延迟,并且 gameTime.ElapsedGameTime.TotalSeconds 可能为 0.3(跳过 2 次更新),但公式仍然可以计算出正确的跳跃率。

于 2011-02-06T22:22:57.227 回答