根据分辨率调整屏幕上所有精灵的比例

4
我决定将我的游戏从窗口模式切换到全屏模式,这是我面临的第一个问题。我正在寻找一种基于屏幕分辨率调整所有精灵大小的方法。我的背景现在处于坐标(0, 0)位置,但我需要它和所有精灵按比例缩放(16:9为首选)。并将它们调整到背景被拉伸以填充屏幕的那个部分大小,不多也不少。
我已经查看了一些在线教程,但我真的无法理解他们使用的概念。您能解释一下您如何做到这一点吗?我读到使用RenderTarget2D并将其传递给spriteBatch.Begin()调用具有某种效果,但必须有更多代码。
我不打算支持分辨率更改选项,而是将精灵调整为当前分辨率。

您可以在 SpriteBatch.Draw(Texture2D, Rectangle, Color)(或其重载)中使用矩形来将任何纹理调整为任意大小。剩下的就是数学。 - Mephy
你能提供一个例子吗?我猜你的意思是给出Texture2D.Width/.Height的重载乘以某些东西,如果是这样,请问乘以什么? - Johny P.
2个回答

10

听起来你在谈论分辨率独立性

总体思路是使用虚拟分辨率来制作游戏,并将其缩放以适应屏幕的实际分辨率

var scaleX = (float)ActualWidth / VirtualWidth;
var scaleY = (float)ActualHeight / VirtualHeight;
var matrix = Matrix.CreateScale(scaleX, scaleY, 1.0f);

_spriteBatch.Begin(transformMatrix: matrix);
例如,如果您的虚拟分辨率为800x480,您只需相对于它来渲染所有精灵。然后,在渲染精灵批处理之前,创建一个变换矩阵传递到Begin方法中。
另外,您需要知道的一件事是,您需要对鼠标/触摸输入坐标进行反向缩放以便在虚拟分辨率中处理它们。在Update方法中,您可以像这样反向缩放鼠标位置:
var mouseState = Mouse.GetState(); // you're probably already doing this
var mousePosition = new Vector2(mouseState.X, mouseState.Y);
var scaledMousePosition = Vector2.Transform(mousePosition, Matrix.Invert(matrix));
然后你可以在目前使用 mouseState.XmouseState.Y 的所有地方使用缩放值。
如果想要实现信封式或柱式式布局,则会变得更加复杂。如果想了解其工作原理,请查看MonoGame.Extended 中的视口适配器。

我现在正在阅读它。另外,如果我将上述代码放在Draw()中,如果那是为了Update(),我就不能使用临时变量matrixscaledMousePosition了,对吗? - Johny P.
没错。我发布的代码只是为了给你一个想法。你需要将矩阵变成一个成员变量或者移动到一个类中。 - craftworkgames
由于某种奇怪的原因,使用 GraphicsDevice.Viewport.WidthGraphicsDevice.Viewport.Height 会抛出异常,我不得不使用 GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width.Height。然而,这个简单的实现完美地工作了。此外,该博客中的代码仅适用于 Monogame.Extended?我想尝试一下这个库,以实现那里描述的更复杂的实现。 - Johny P.
@craftworkgames- 你是如何使用这个scaledMousePosition的,我的意思是在哪个方法(update或draw)中使用。你是如何将其与触摸输入相关联的。 - uncle_scrooge
@uncle_scrooge 我已经更新了答案并加入了更多细节。我记不清使用触摸输入的确切代码,但是概念与使用鼠标相同。 - craftworkgames
显示剩余6条评论

1
你有一个大小为(W, H)的纹理,需要放置在位置(X, Y),根据比例(sW, sH)调整。最初比例为(1, 1),因此精灵将定位在矩形(X, Y, W, H)中。
现在,假设初始分辨率为800x600,但您现在想要1440x900的分辨率。如果800 -> sW = 1,则1440 -> sW = 1440/800 = 1.8。类似地,我们的新sH为1.5。
这是在说什么:如果某物应该在初始分辨率上的X坐标500上,那么它现在在新分辨率上的900 X位置上的500 * 1.8 =。对于边缘来说,这很清楚:如果以前某物在X = 800上,那么它现在仍然在屏幕边缘的800 * 1.8 = 1440上!
说到底,我们只需要进行乘法运算。回到第一段,我们可以说一个矩形 (X, Y, W, H) 可以通过缩放比例 (sW, sH) 缩放为 (X * sW, Y * sH, W * sW, H * sH)
当然,这是在假设原始分辨率按比例 (1, 1) 缩放的情况下计算的,不要忘记这一点!

所以我要像“1366/800 = 1.7075”和“768/600 = 1.28”这样编写游戏分辨率。现在我有了new Rectangle(0 * 1.7075, 0 * 1.28, 800 * 1.7075, 600 * 1.28)作为我的背景,当然(0, 0)位置乘以任何数都会返回0,所以我可以在那里使用0。那么输入呢?我不能在检查鼠标点击是否相距500个像素的地方硬编码我的Point变量,对吧? - Johny P.
@JohnyP. 输入数据已经在新的坐标系中,应该与矩形转换到新坐标系后进行检查。我建议静态更改大小(在Photoshop或其他工具中调整纹理大小),而不是在运行时进行更改。 - Mephy

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