【问题标题】:Change and scale resolution of XNA gameXNA游戏的改变和缩放分辨率
【发布时间】:2013-09-09 19:14:31
【问题描述】:

我有一个游戏,初始化为 1920x1080。所有精灵、矢量等都经过专门放置,以匹配 1920x1080 类型。

我有一个enum,说明游戏被告知使用什么资源。 1920x1080 将是标准。 有没有办法,比如说,有 1280x960 的分辨率,以这种方式:

  • 游戏窗口为 1280x960
  • 游戏分辨率(后缓冲)仍为 1920x1080,但已按比例缩小以适应窗口 - 1280x960。

有点像,就在绘制事件之前,将屏幕捕获到Texture2D,并适当缩放以适应游戏窗口。

【问题讨论】:

  • 如果您将后缓冲区保持在该分辨率,并且仅将显示的视图移植到较低的分辨率,您是不是有点浪费大量 GPU 时间,如果用户的机器可以,您的游戏可能会滞后'在全高清下运行不好吗?
  • 您可以拥有基于代码用于绘制和缩放精灵的分辨率的变量。您可以使用Rectangle Destination = new Rectangle(0,0,width/2,height/2) 而不是Rectangle Destination = new Rectangle(0,0,1920/2,1080/2) 之类的东西,其中widthheight 是等于屏幕分辨率的公共变量。

标签: c# xna resolution


【解决方案1】:

实际上有一个非常简单的解决方案。正如 Pinckerman 指出的那样,您需要知道纵横比(屏幕比例),但您将在 SpriteBatch.Begin 方法中使用它,在该方法中,您将通过 Matrix.CreateScale(Vector3 这里,Z 是1),并将其用作 SpriteBatch.Begin 方法中的最终参数。

在这种情况下,大多数其他参数都可以保留为 Null。

基本上它的作用是,它告诉 spritebatch 绘制所有内容,并将偏移量(比例)应用于位置和大小。这意味着,就我而言,当我在 640x400 上放置一些东西时,无论我在屏幕上运行什么分辨率,它仍然从屏幕的死点开始。如果你问我,这很有用。

我当前项目的示例:

/// <summary>
/// Resolution
/// </summary>
public static class Resolution
{
    private static Vector3 ScalingFactor;
    private static int _preferredBackBufferWidth;
    private static int _preferredBackBufferHeight;

    /// <summary>
    /// The virtual screen size. Default is 1280x800. See the non-existent documentation on how this works.
    /// </summary>
    public static Vector2 VirtualScreen = new Vector2(1280, 800);

    /// <summary>
    /// The screen scale
    /// </summary>
    public static Vector2 ScreenAspectRatio = new Vector2(1, 1);

    /// <summary>
    /// The scale used for beginning the SpriteBatch.
    /// </summary>
    public static Matrix Scale;

    /// <summary>
    /// The scale result of merging VirtualScreen with WindowScreen.
    /// </summary>
    public static Vector2 ScreenScale;

    /// <summary>
    /// Updates the specified graphics device to use the configured resolution.
    /// </summary>
    /// <param name="device">The device.</param>
    /// <exception cref="System.ArgumentNullException">device</exception>
    public static void Update(GraphicsDeviceManager device)
    {
        if (device == null) throw new ArgumentNullException("device");

        //Calculate ScalingFactor
        _preferredBackBufferWidth = device.PreferredBackBufferWidth;
        float widthScale = _preferredBackBufferWidth / VirtualScreen.X;

        _preferredBackBufferHeight = device.PreferredBackBufferHeight;
        float heightScale = _preferredBackBufferHeight / VirtualScreen.Y;

        ScreenScale = new Vector2(widthScale, heightScale);

        ScreenAspectRatio = new Vector2(widthScale / heightScale);
        ScalingFactor = new Vector3(widthScale, heightScale, 1);
        Scale = Matrix.CreateScale(ScalingFactor);
        device.ApplyChanges();
    }


    /// <summary>
    /// <para>Determines the draw scaling.</para>
    /// <para>Used to make the mouse scale correctly according to the virtual resolution,
    /// no matter the actual resolution.</para>
    /// <para>Example: 1920x1080 applied to 1280x800: new Vector2(1.5f, 1,35f)</para>
    /// </summary>
    /// <returns></returns>
    public static Vector2 DetermineDrawScaling()
    {
        var x = _preferredBackBufferWidth / VirtualScreen.X;
        var y = _preferredBackBufferHeight / VirtualScreen.Y;
        return new Vector2(x, y);
    }
}

及用法:

    /// <summary>
    /// Draws the game objects to the screen. Calls Root.Draw.
    /// </summary>
    /// <param name="gameTime">The game time.</param>
    protected override void Draw(GameTime gameTime)
    {
        // TODO: Camera
        SpriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, null, Resolution.Scale);
        Root.Draw(SpriteBatch, gameTime);
        SpriteBatch.End();

        base.Draw(gameTime);
    }

希望此示例代码对您有所帮助。

注意:按照 Pinckerman 建议的方式做这件事并没有错,但是我被引导相信除了显而易见的(最初更多的代码,但从长远来看会更少)之外,Pinckerman 的建议也可能需要提高性能。这只是一种预感,它只是基于 GPU 在与屏幕位置相关的计算方面可能比 CPU 更有效。

但不要挂断我。

@编辑:

获取鼠标相对于屏幕上对象的坐标:

public Vector2 GetMouseCoords()
{
    var screenCoords = Mouse.GetPosition(); // Or whatever it's called.
    var sceneCoords = screenCoords / Resolution.ScreenScale;
    return sceneCoords;
}

【讨论】:

  • 谢谢,这真的很棒。您是否发现鼠标受到此代码的影响,如果游戏不是全屏的,它会在游戏区域之外?是否有快速简便的解决方法,例如。捕获鼠标?
  • 我更新了我的答案来回答你的问题(我认为)
  • 谢谢!太棒了。
  • 不客气!记得投票(如果您是问题的作者)将回复标记为答案
【解决方案2】:

我认为您必须手动修改每个 Vector2Rectangle 您需要使它们与您的分辨率相关,或者(如果可以)使用基于 Window.ClientBounds.WidthWindow.ClientBounds.Height 的变量,如 davidsbro 写道。
像这样的:

Vector2 largeResolution = new Vector2(1920, 1080);
Vector2 smallResolution = new Vector2(1280, 960);
// you should have already set your currentResolution previously
Vector2 screenRatio = currentResolution / largeResolution;

现在你的初始化变成了:

Vector2 position = new Vector2(200, 400) * screenRatio;
Rectangle imageRect = new Rectangle((int)(100 * screenRatio.X), (int)(200 * screenRatio.Y), ... );

这样,你只需要添加那个产品,所以如果你当前的分辨率是大的,你的变量仍然是一样的,否则如果它是小的,每个变量都会被缩放。

【讨论】:

    猜你喜欢
    • 2012-11-20
    • 2014-01-24
    • 1970-01-01
    • 1970-01-01
    • 2012-05-08
    • 1970-01-01
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多