更新2D相机的X和Y位置

3

我正在尝试制作一个2D相机,可以在垂直和水平方向上跟随我的角色。目前相机只能水平跟随我的角色。有人告诉我要在ScrollCamera()方法中更新Y部分和X部分,但我不知道如何做到(最终搞得一团糟)。

以下是代码:

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);


        }

这是我等级类中的绘制方法:

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);

        }

这完全不正确。

你能否详细告诉我们你已经尝试过什么?这样可以避免我们再犯同样的错误。 - 4444
1
好的,我会发布它。 - user2539369
1个回答

2
根据您提供的代码,我得出结论'cameraPosition'是一个浮点数,您只跟踪X位置。我建议您使用Vector2来代替。这实际上是两个浮点数;一个用于X位置,另一个用于Y位置。如果您这样做,您将不得不重复计算Y值。如果您不想使用Vector2,您可以为Y位置创建第二个变量。
我无法看到您如何处理cameraPosition,因此我无法帮助您处理Y部分。 编辑 您编写的draw函数不正确,因为您只有一个变量用于相机位置。您将需要一个变量用于X位置,以及第二个变量用于Y位置。如我上面所述,在XNA中典型的方法是通过Vector2结构。如果您不熟悉结构(或类),我建议您尽快阅读相关内容,因为它们在面向对象编程中非常重要。微软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);

我希望你现在能够理解了,祝你好运!

我所说的重复是指使用marginHeight、marginTop、marginBottom、viewport.Height、Player.Position.Y等。 - Aart Stuurman
cameraPosition 是一个浮点数。我可以同时提供绘制方法,这样你就可以看到我如何使用 cameraPosition 了吗? - user2539369
如果您需要进一步的帮助,我需要绘制函数。是的,我看到您已经添加了它们,让我们来看看。 - Aart Stuurman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接