2

背景:最近、xna についてよく勉強しています。私は自分のゲーム構造を完成させ、平均的なゲームに不可欠なクラスを作成し、いくつかの記事を読み、多数のビデオを見て、持っている本を少し読んでいます。それで、良いゲーム構造を作成した後、私は実際のゲームであるプラットフォーマーに移りました。現在、通常のブロックとプレーヤーがありますが、問題はプレーヤーにあります。

問題/質問:通常、ブロックとの衝突は問題ありませんが、衝突が奇妙な動作をすることがあります。IE: プレーヤーがブロック内 (通常は 1 ピクセル内) にどのように配置されているか、これは大きな問題です。これにより、プレーヤーがマップ上のどこかに押し出される可能性があるためです。

プレーヤーのゲーム ロジック:プレーヤーの動きは状態に基づいています。状態は、「地面、ジャンプ、および落下」の列挙子です。今のところ、問題は落下状態の中にあるようです。衝突が正しく機能する場合もあれば、プレイヤーがブロックの 1 ピクセル内に入ってしまう場合もあります。これは、プレイヤーがジャンプすると、距離に関係なく、プレイヤーの上の最初のブロックに即座に押し出されることを意味します。

衝突ロジック:落下状態では、プレーヤーは重力によって床に向かって押し出されます。重力はフレームごとにフォースによって追加されます。位置を変更する前に、その動作範囲内のブロック間に衝突があったかどうかを確認する際に衝突メソッドが呼び出されます。これは落下状態であるため、プレイヤーは下に移動しているため、衝突すると、while ループがフレームごとにプレイヤーを 1 ピクセルずつ押し下げ、ブロックにぶつかります。そしてバックアップとして、プレーヤーをブロックの外に押し出すループがあります。次に、現在の状態をグラウンドに設定します。ジャンプ状態も同様の理論に従います。

Falling State Script:このコードの説明については、上記をお読みください。

case PlayerState.Fall:
    // falling sprite
        mySpriteManager.mySpriteCurrent = mySpriteManager.mySpriteIndex["PlayerSprites/player_fall"];
    // fall velocity change
        myVelocity.Y += myDforce;

    if ( Collision( otObjectList.wallIndex, myPosition.X + 1, myPosition.Y, myPosition.X + myWidth - 1, myPosition.Y + myHeight + myVelocity.Y) )
    {
        while( !Collision( otObjectList.wallIndex, myPosition.X + 1, myPosition.Y, myPosition.X + myWidth - 1, myPosition.Y + myHeight) )
            myPosition.Y += 1;
        while ( Collision(otObjectList.wallIndex, myPosition.X + 1, myPosition.Y, myPosition.X + myWidth - 1, myPosition.Y + myHeight))
            myPosition.Y -= 1;
        myVelocity.Y = 0;
        myCurrentState = PlayerState.Ground;
    }
    else
    {
            myPosition.Y += myVelocity.Y;
    }
break;

衝突スクリプト:これは、衝突が発生するまですべてのソリッド オブジェクトに対して実行され、衝突が発生した場合は true を返します。

private bool Collision( List<ObjWall> otWalls, float x1, float y1, float x2, float y2)
{
    myBoundingBox.X = (int)Math.Ceiling(x1);
    myBoundingBox.Y = (int)Math.Ceiling(y1);
    myBoundingBox.Width = (int)Math.Ceiling(Math.Abs( x2 - x1));
    myBoundingBox.Height = (int)Math.Ceiling(Math.Abs( y2 - y1));
    foreach (ObjWall wall in otWalls)
    {
        if ( Box.Intersects( wall.Box ) )
        {
            return true;
        }
    }
    return false;
}

変数の説明:

myBoundingBox - すべての通常のオブジェクトは、この抽象クラスから構築されます。したがって、すべてのオブジェクトには外接する長方形があります。

Box - 抽象オブジェクト クラスに由来する特性で、外接する四角形を返すだけです。

myVelocity - プレイヤーの速度です。これは Vector2 です。これは、フロートがよりクリーンな重力を提供するためです。

myDforce - 正の力で yvelocity を変更するフロートです。私はそれを定数にするべきだと信じています。

ObjectList - これは、すべての通常のオブジェクト ロジックを実行するクラスであり、ルーム内に存在する可能性のあるすべてのオブジェクトのリストが含まれています。

myPosition - これは、通常のオブジェクトが駆動される抽象クラスによって提供される別の保護変数です。これはベクトル 2 であるため、Float を使用して機能します。

コード内のこれ以上の説明については、お尋ねください! 事前に、お時間をいただきありがとうございます。 ケイ。

4

1 に答える 1

0

への 2 回目の呼び出しCollisionは、現在の位置のみを確認し、そのアクションが衝突を引き起こすかどうかに関係なく、プレーヤーを下に移動します。

Collision への 3 回目の呼び出しでこれに対処し、プレーヤーを元に戻す必要があることがわかりますが、コードから複雑さを (わずかに) 取り除くために、2 回目の呼び出しで位置 + 1 をチェックし、動かないようにすることができます。 true の場合はプレイヤー。

これにより、 への 3 回目の呼び出しが不要になり、Collisionほとんどの落下に使用しているロジックと衝突の最初の呼び出しが一致します (つまり、重力によって移動しますが、移動が壁に衝突する場合はそうではありません)、エラーの場所を減らします。発生する可能性があります。

于 2013-01-16T08:25:18.607 に答える