重力により地面から跳ね返るキャラクター


7

ゲームに重力を実装すると、キャラクターが地面にぶつかったときにキャラクターがわずかに上下にバウンドし続けます。デバッグすると、キャラクターは基本的に地面の上と外でバウンドします。この問題を解決する方法がわからない場合は、ここで助けていただければ幸いです。

定数値

private float gravity = 0.09f;

キャラクターが地面にいる場合は速度に追加

if (!isOnGround)
 velocity.Y += gravity;

キャラクター全体の速度を全体の位置に追加します。

position += velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

キャラクターが地面にあるかどうかを決定する衝突方法の一部。

for (int y = topTile; y <= bottomTile; ++y)
            {
                for (int x = leftTile; x <= rightTile; ++x)
                {
                    // If this tile is collidable,
                    TileCollision collision = Level.GetCollision(x, y, tileMap);
                    if (collision != TileCollision.Passable)
                    {
                        // Determine collision depth (with direction) and magnitude.
                        Rectangle tileBounds = Level.GetBounds(x, y);
                        Vector2 depth = RectangleExtensions.GetIntersectionDepth(bounds, tileBounds);
                        float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

                        if (depth != Vector2.Zero)
                        {
                            float absDepthX = Math.Abs(depth.X);
                            float absDepthY = Math.Abs(depth.Y);

                            // Resolve the collision along the shallow axis.
                            if (absDepthY <= absDepthX || collision == TileCollision.Platform)
                            {
                                // If we crossed the top of a tile, we are on the ground.
                                if (previousBottom <= tileBounds.Top)
                                    isOnGround = true;

1
既存の物理エンジンを使用しないのはなぜですか?Farseerは慣れるまでに約1日かかり、必要なことなら何でもできます。
ClassicThunder

回答:


12

申し訳ありませんが、コリジョンコードを完全に理解できていません。1ピクセルずつずれているエラーがどこかにあると、特定が困難になります。ただし、物理コードにはすでにいくつかの修正が必要です。

  • 重力が一定であっても、速度の更新はタイムステップに依存する必要があります
  • 地面にいる場合、垂直速度はゼロに設定する必要があります
  • 「全体速度」の追加は正しくありません。それはだ平均を追加する必要があり、最後のフレームの持続時間に対する速度。この記事では、その理由を説明する必要があります。

次のコードにつながる:

Vector2 oldvelocity = velocity;

if (!isOnGround)
    // This will require tweaking the gravity value
    velocity.Y += gravity * (float)gameTime.ElapsedGameTime.TotalSeconds;
else
    velocity.Y = 0.0;

position += 0.5 * (oldvelocity + velocity)
                * (float)gameTime.ElapsedGameTime.TotalSeconds;

+1オイラー統合ではなくベルレット統合を使用することについて少し。私はこれまでいつも見落としていたり​​、忘れていました。
David Gouveia
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.