0

Xna 4 を使用して、Y 軸 = 0 平面上の 3D 世界を移動するゲーム オブジェクト (宇宙船) があるゲームを行っています。別名 2.5D ..

これまで、非常に複雑な角度計算を使用して 2 つのベクトル間の回転を作成していましたが、そのアルゴリズムには、オブジェクトが既に回転していることを考慮する機能がありませんでした。そのため、結果はファンキーになります..したがって、誰かが、マトリックスとベクトル計算を使用して、時間の経過とともにそのような回転を行うスマートで簡単に実装可能な方法を教えてくれることを望んでいました。

以前の検索で気付いたのは、オブジェクト クラスに次の変数があることです。

単純な現在の位置になぜそんなに多くの変数が必要なのか、よく自問します..または、理解できない..とにかく..

私は現在、位置、回転、および変換マトリックスを持っています。他に何が必要で、それを計算する方法、そして時間の経過とともに回転だけを実装する方法を知りたいです。

右クリックの移動コマンド trig によって呼び出されるメソッドは、クリックが発生した場所の Y = 0 平面上の vector3 位置を送信します。

public void MoveCommand(Vector3 pos){ }

これをテストしたところ、与えられた「pos」は正確です。どんな助けも高く評価されます..

4

3 に答える 3

0
Vector3 Position;
float Rotation;

Matrix World
{
    get
    {
        return Matrix.CreateRotationZ(Rotation) * Matrix.CreateTranslation(Position);
    }
}

public void RotateInstantly(Vector3 position)
{
    Rotation = Math.Atan2(Position.Y - position.Y, Position.x - position.x);
}

public void RotateIncremently(Vector3 position, float maxStep)
{
    float targetRotation = Math.Atan2(Position.Y - position.Y, Position.x - position.x);
    float diff = targetRotation - Rotation;

    if (Math.Abs(diff) > maxStep)
    {
        if (targetRotation > Rotation)
            Rotation += maxStep;
        else
            Rotation -= maxStep;
    }
    else
        Rotation = targetRotation;
}

RotateIncrementlyは、次のように使用できます。* float dt =(float)gameTime.ElapsedGameTime.TotalSeconds;

float maxRotationVelocity = Math.TwoPi; // 2*Piは1回転です。

RotateIncremently(target.Position、maxRotationVelocity * dt);

于 2013-02-20T11:40:03.037 に答える
0

必要な回転に応じて、Matrix.CreateRotationX Y または Z を確認する必要があります。X、Y、または Z は回転の軸です。Y を選択すると、深さとして使用している軸であるため、「2D」回転 (ヨー) が表示されます。X 軸または Z 軸を選択すると、「3D」回転 (ピッチとロール) が表示されます。

コードは次のようになります。

WorldMatrix = Rotations * Translation

どこで Rotations = Matrix.CreateRotationX(angleRadians) and Translation = Matrix.CreateTranslation(Position);

ワールド マトリックスは、モデルに影響を与えるマトリックスです。ビューと投影はカメラに依存します。

ベクトル間の角度を知りたい場合は、2D にいるため、内積または atan2 関数を確認する必要があります。

于 2013-02-19T21:01:19.097 に答える
0

Stig-Rune Skansgård の返信 (デンマーク語のhi5の場合) のおかげで、古い角度の計算を修正し、すべての場合に機能するようになりました。訪問者はそれを利用できます。これは、非常に大きな Ship クラスのスニペット + 角度を計算するヘルパー メソッドです。

public static float CalculateAngleFromVectors(Vector3 v1, Vector3 v2) {
        float x = 0;
        float X = v2.X - v1.X,
              Z = v2.Z - v1.Z;
        if (Z == 0) {
            x = (X < 0 ? 90 : 270);
        } else if (X == 0) {
            x = (Z < 0 ? 180 : -180);
        } else {
            float temp = MathHelper.ToDegrees((float)Math.Atan(X / Z));
            if (X < 0) {
                x = (Z < 0 ? Math.Abs(temp) : 180 - Math.Abs(temp));
            } else {
                x = (Z < 0 ? 360 - Math.Abs(temp) : Math.Abs(temp) + 180);
            }
        }
        return x;
    }

このメソッドは、(標準の 0 度の開始点から) 船を回転させるためのフロート角度 (度単位) を取得します。

それを使用するには、クラスで次のような更新/アニメーション メソッドを作成するだけです。

float desiredRotation = 0, currentRotation = 0, totalElapsed = 0, timePerFrame = 0.05f;
        if (desiredRotation != 0) {
            totalElapsed += elapsed;
            if (totalElapsed > timePerFrame) {
                if (isRotationComplete()) {
                    rotX += MathHelper.ToRadians(desiredRotation);
                    currentRotation = desiredRotation = 0;
                } else if (desiredRotation > currentRotation) {
                    currentRotation += shipTurnSpeed;
                } else if (desiredRotation < currentRotation) {
                    currentRotation -= shipTurnSpeed;
                }
                totalElapsed -= timePerFrame;
            }
        }

編集:および完了チェック:

private bool isRotationComplete() {
        bool b = false;
        if (desiredRotation > currentRotation && currentRotation + shipTurnSpeed > desiredRotation) {
            b = true;
        } else if (desiredRotation < currentRotation && currentRotation - shipTurnSpeed < desiredRotation) {
            b = true;
        }
        return b;
    }

基本的に、これが行うことは、DesiredRotation が 0 より大きいかどうかを常にチェックすることです。0 より大きい場合は、プレイヤーが回転するコマンド (または AI) を与えたことを意味します。回転コマンドが最後に与えられてから回転し、回転が完了すると 0 に設定されます..別の変数を使用して回転を表示する Rotations マトリックスが必要です..私のものは次のとおりです。

public float rotX { get; set; }
    public float rotY { get; set; }
    public Vector3 position { get; set; }
    public Matrix Transform {
        get {
            return (Matrix.Identity *
                    Matrix.CreateScale(scale) *
                    Matrix.CreateRotationY(MathHelper.Pi) *
                    Rotation *
                    Matrix.CreateTranslation(position));
        }
    }
    public float ShipCurRotation { get { return (rotX + MathHelper.ToRadians(currentRotation)); } }
    public Matrix Rotation { get { return (Matrix.CreateRotationY(ShipCurRotation) * Matrix.CreateRotationX(rotY)); } }

rotX 変数は、回転が完了するとアニメーションで設定され、初期化でも設定されます。最初のコード スニペットが生成する回転角度を使用する方法は次のとおりです。

public void MoveToPosition(Vector3 pos) {
        desiredRotation = (CalculateAngleFromVectors(position, pos) - MathHelper.ToDegrees(rotX));
        isMoving = true;
    }

.. これにより、スムーズにカスタマイズ可能な回転、変換、および移動の設定が行われます..c の XZ 平面では、Y 軸は UP であり、常に 0 です..

物事をさらに良くするための提案、変更、またはアイデアがある場合は、これについて自由にコメントしてください..私は常に改善を求めています..返信をありがとう、そしてこれが多くの新しい開発者に役立つことを願っています。ウェブから..

PS。回転は、アニメーションと回転速度をバイパスして、即時回転のために rotX に直接適用できます。

よろしくMatriXz

于 2013-02-26T14:41:06.853 に答える