3

プレーヤーを垂直方向と水平方向の両方で追跡する 2D カメラを作成しようとしています。カメラはプレーヤーを水平方向にのみ追跡しています。私の方法では、Y部分とX部分を更新するように言われましたScrollCamera()が、それを行う方法がわかりませんでした(最終的には大混乱になりました)。

コードは次のとおりです。

private void ScrollCamera(Viewport viewport)
        {
#if ZUNE
const float ViewMargin = 0.45f;
#else
            const float ViewMargin = 0.5f;
#endif

            // Calculate the edges of the screen.
            float marginWidth = viewport.Width * ViewMargin;
            float marginLeft = cameraPosition + marginWidth;
            float marginRight = cameraPosition + viewport.Width - marginWidth;



            // Calculate how far to scroll when the player is near the edges of the screen.
            float cameraMovement = 0.0f;
            if (Player.Position.X < marginLeft)
                cameraMovement = Player.Position.X - marginLeft;
            else if (Player.Position.X > marginRight)
                cameraMovement = Player.Position.X - marginRight;

            // Update the camera position, but prevent scrolling off the ends of the level.
            float maxCameraPositionWidth = Tile.Width * Width - viewport.Width;
            cameraPosition = MathHelper.Clamp(cameraPosition + cameraMovement, 0.0f, maxCameraPositionWidth);


        }

これは、レベル クラスの draw メソッドです。

public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            spriteBatch.Begin();
            for (int i = 0; i <= EntityLayer; ++i)
                layers[i].Draw(spriteBatch, cameraPosition);
            spriteBatch.End();

            ScrollCamera(spriteBatch.GraphicsDevice.Viewport);
            Matrix cameraTransform = Matrix.CreateTranslation(-cameraPosition, 0.0f, 0.0f);
            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default,
                RasterizerState.CullCounterClockwise, null, cameraTransform);

            DrawTiles(spriteBatch);

            Player.Draw(gameTime, spriteBatch);

            foreach (Enemy enemy in enemies)
                enemy.Draw(gameTime, spriteBatch);

            spriteBatch.End();

            spriteBatch.Begin();
            for (int i = EntityLayer + 1; i < layers.Length; ++i)
                layers[i].Draw(spriteBatch, cameraPosition);
            spriteBatch.End();
        }

私は Xna と C# にかなり慣れていないので、楽しみのためにこれを行っていますが、誰かがその方法を教えてくれたらうれしいです :)

私が試してみました:

private void ScrollCamera(Viewport viewport)
        {
#if ZUNE
const float ViewMargin = 0.45f;
#else
            const float ViewMargin = 0.5f;
            const float ViewHeight = 0.3f;
#endif

            // Calculate the edges of the screen.
            float marginHeight = viewport.Height * ViewHeight;
            float marginTop = cameraPosition + marginHeight;
            float marginBottom = cameraPosition + marginHeight;

            float marginWidth = viewport.Width * ViewMargin;
            float marginLeft = cameraPosition + marginWidth;
            float marginRight = cameraPosition + viewport.Width - marginWidth;


            // Calculate how far to scroll when the player is near the edges of the screen.
            float cameraMovement = 0.0f;
            if (Player.Position.X < marginLeft)
                cameraMovement = Player.Position.X - marginLeft;
            else if (Player.Position.X > marginRight)
                cameraMovement = Player.Position.X - marginRight;

            if (Player.Position.Y < marginTop)
                cameraMovement = Player.Position.Y - marginTop;
            else if (Player.Position.Y > marginBottom)
                cameraMovement = Player.Position.X - marginBottom;



            // Update the camera position, but prevent scrolling off the ends of the level.
            float maxCameraPositionWidth = Tile.Width * Width - viewport.Width;
            cameraPosition = MathHelper.Clamp(cameraPosition + cameraMovement, 0.0f, maxCameraPositionWidth);

        }

これはまったく正しくありませんでした。

4

1 に答える 1

2

あなたが提供したコードから、「cameraPosition」はX位置のみを追跡するフロートであると結論付けています。これには Vector2 を使用することをお勧めします。これは技術的には 2 つのフロートを 1 つにまとめたものです。1 つは X 位置用、もう 1 つは Y 用です。これを行うと、Y 値の計算を繰り返す必要があります。Vector2 を使用したくない場合は、代わりに Y 位置の 2 つ目の変数を作成できます。

あなたが cameraPosition で何をしているのか見ることができないので、Y のその部分についてはお手伝いできません。

編集 カメラ位置の変数が 1 つしかないため、作成した描画関数は正しくありません。X 位置用の変数と、Y 位置用の 2 つ目の変数が必要です。上で述べたように、XNA でこれを行う一般的な方法は、Vector2 構造を使用することです。構造体 (またはクラス) に慣れていない場合は、オブジェクト指向プログラミングで非常に重要であるため、できるだけ早く読むことをお勧めします。Microsoft Vector2 ドキュメントへのリンク: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.vector2.aspx

あなたが基本的に行うことは、最初に持っていた計算を取ることです。

float cameraMovement = 0.0f;
if (Player.Position.X < marginLeft)
    cameraMovement = Player.Position.X - marginLeft;
else if (Player.Position.X > marginRight)
    cameraMovement = Player.Position.X - marginRight;

// Update the camera position, but prevent scrolling off the ends of the level.
float maxCameraPositionWidth = Tile.Width * Width - viewport.Width;
cameraPosition = MathHelper.Clamp(cameraPosition + cameraMovement, 0.0f, maxCameraPositionWidth);

これは、カメラの X 位置の計算です。Vector2 を使用したコードは次のようになります。

// Declare a Vector2 cameraPosition where you are now declaring a float cameraPosition right now.

Vector2 cameraMovement = new Vector2(0,0);
if (Player.Position.X < marginLeft)
    cameraMovement.X = Player.Position.X - marginLeft;
else if (Player.Position.X > marginRight)
    cameraMovement.X = Player.Position.X - marginRight;

float maxCameraPositionWidth = Tile.Width * Width - viewport.Width;
cameraPosition.X = MathHelper.Clamp(cameraPosition.X + cameraMovement.X, 0.0f, maxCameraPositionWidth);

cameraMovement.Y と cameraPosition.Y についても同様の計算を行う必要があります。

これらがあれば、描画関数で変更する必要があるのは Y 変換だけです。現在、次のものがあります。

Matrix cameraTransform = Matrix.CreateTranslation(-cameraPosition, 0.0f, 0.0f);

ご覧のとおり、X 軸でのみ移動しています。Y 軸を追加すると、次のようになります。

Matrix cameraTransform = Matrix.CreateTranslation(-cameraPosition.X, -cameraPosition.Y, 0.0f);

あなたが今それを理解することを願っています。幸運を!

于 2013-07-01T14:57:56.137 に答える