6

私は最初のxna2dゲームで重力をシミュレートしようとしています。私は以下を持っています

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

そのため、経過したAirTime <maxAirTimeの間にスプライトを一定量上に移動しようとしていますが、コードがこの時間のセグメント中にスプライトを1回だけ上に移動し、複数回移動しないように見える問題があります。これが私の「player.cs」クラスのコード、またはクラスのupdateメソッドです。

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 クラスに速度と加速度を追加する必要があります。次に、スプ​​ライトの Update メソッドを作成し、更新ごとに加速度を速度に追加し、速度を更新ごとに位置に追加します。位置は、経過した通信時間に基づくべきではありません。加速度を一定の重力値に設定し、ジャンプするたびにスプライトの速度を追加できます。これにより、見栄えのする流れるような放物線ジャンプが作成されます。タイミングを含めたい場合は、GameTime をスプライトの Update メソッドに渡し、それを速度の修飾子として使用できます。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);

これにより、スプライトの位置が想像よりも速く更新されることがわかると思います。スプライトは、Game.IsFixedTimeStep == true10 分の 1 秒のリアルタイムである 10 回の更新で画面の上に 330 ピクセル移動します ( と仮定します)。

&& position.Y < 3これは更新が非常に速いため、条件が開始されて playerState が変更される前に、変更を確認できない可能性があります。

あなたが言おうとしているように見えます-スペースが保持されている限り、最大8.5秒間、毎秒xピクセルの速度でジャンプします。

そのために必要なのは、計算を に変更することですthis.position.y -= (float) (30 * gameTime.ElapsedGameTime.TotalSeconds)。これにより、ジャンプ アクションに非常に直線的な動きが与えられますが、スプライトが 1 秒あたり正確に 30 ピクセルでジャンプすることを意味します。

デフォルトの場合Game.IsFixedTimeStep == true、更新は毎秒 60 回呼び出されるため、gameTime.ElapsedGameTime.TotalSeconds は更新ごとに約 0.1 になります。何かが発生して更新がスキップされた場合 (レンダリングの問題など)、更新が遅れ、gameTime.ElapsedGameTime.TotalSeconds が 0.3 (2 つの更新がスキップされた) になる場合がありますが、フォーミュラーは正しいジャンプ レートを計算します。

于 2011-02-06T22:22:57.227 に答える