(XNA/MonoGame) 实现屏幕拖动相机移动

问题描述 投票:0回答:1

我正在使用自上而下的 2D 图形制定策略。我实现了通过按住 LMB 然后“拖动”屏幕来移动视图的方法。它工作得很好,除了运动有点太快,而且我不知道如何正确计算运动。

相机移动(和缩放)的代码是

class CameraControls : WGComponent
{
    public override void Update(GameTime gameTime)
    {
        if (WGame.userInput.mouse.LeftButton == ButtonState.Pressed) WGame.camera.position -= (WGame.userInput.mouse.Position - WGame.userInput.prevMouse.Position).ToVector2().InvertY() * WGame.camera.scale;

        WGame.camera.scale = Math.Max(WGame.camera.scale - WGame.userInput.frameScroll * 0.1f, 1f);
    }
}

WGame
是我的
Game
类,它保存我希望只有一个实例作为静态变量的对象。
WGComponent
只是重写构造函数以使用存储在静态变量中的
WGame
实例。

WGame.userInput.mouse
是当前帧的
MouseState
,而
WGame.userInput.prevMouse
是前一帧的。
WGame.userInput.frameScroll
frameScroll = mouse.ScrollWheelValue - prevMouse.ScrollWheelValue

计算

相机代码是

public class Camera
{
    public Vector2 position = new();
    public float scale = 1;
}

并且其位置在WGame的Update方法中使用

protected override void Update(GameTime gameTime)
{
    translationMatrix = Matrix.CreateTranslation(-camera.position.X, camera.position.Y, 0);
    scaleMatrix = Matrix.CreateScale(100 / (camera.scale * camera.scale));
    screenSizeMatrix = Matrix.CreateTranslation(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2, 0);
    resultMatrix = translationMatrix * scaleMatrix * screenSizeMatrix; //This one is later used in SpriteBatch.Begin()

    base.Update(gameTime);
}

那么,我做的一切正确吗?如果我做对了,有没有办法让屏幕的拖动量与鼠标移动的量完全相同?

[UPD] 相机比例计算代码现在是

WGame.camera.scale = Math.Max(WGame.camera.scale - WGame.userInput.frameScroll * MathF.Abs(WGame.userInput.frameScroll) * 0.01f, 1f);

尺度矩阵计算为

scaleMatrix = Matrix.CreateScale(100 / camera.scale);

xna monogame
1个回答
0
投票

我快速创建了一个测试项目来验证数学。正如我所假设的,您必须将与 scaleMatrix 相同的比例“应用”到鼠标移动,在本例中除以 100。我建议为此创建一个变量,甚至更好,将其合并到比例变量中。

至少对于自上而下的 2D 精灵来说,解释比例的“更正确”方法是:

  • 比例 = 1:1 个屏幕像素包含 1 个纹理像素 (100 %)

  • Scale = 0.5:1个屏幕像素包含2个纹理像素(纹理大小为50%)

  • 比例 = 2:1 个纹理像素“填充”2 个屏幕像素(纹理大小 200%)

等等。

无论如何,下面是我针对您的情况测试的代码(我使用略有不同的输入类,但名称应该是不言自明的):

// Camera zoom
CamScale *= 1 - Sign(Input.MouseWheelDelta) * .25f;
CamScale = Math.Clamp(CamScale, 0.1f, 1f);

// Camera movement
if (Input.IsMiddleMouseButtonDown) {
    CamPos.X -= Input.MousePositionDelta.X * CamScale / 100;
    CamPos.Y += Input.MousePositionDelta.Y * CamScale / 100;
}

Matrix resultMatrix;
var translationMatrix = Matrix.CreateTranslation(-CamPos.X, CamPos.Y, 0);
var scaleMatrix = Matrix.CreateScale(100 / (CamScale));
var screenSizeMatrix = Matrix.CreateTranslation(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2, 0);
resultMatrix = translationMatrix * scaleMatrix * screenSizeMatrix;

SpriteBatch.Begin(transformMatrix: resultMatrix);
{
    SpriteBatch.Draw(DB.Textures.Get("Markings"), new Vector2(0, 0), new Color(1f, 1f, 1f, 1f));
}
SpriteBatch.End();
© www.soinside.com 2019 - 2024. All rights reserved.