【问题标题】:Uniformly Resizing a Window in XNA在 XNA 中统一调整窗口大小
【发布时间】:2011-12-06 07:40:55
【问题描述】:

好吧,我正在尝试让我的游戏窗口能够统一调整大小。我到处检查过,但似乎找不到任何相关信息。

有什么想法吗?

由于字数限制,我无法发布代码。如果有人能帮我看看我做错了什么,将不胜感激:)

当这种情况发生时如何调整后备缓冲区的大小也很有帮助,因为我认为只有一半的精灵可见时游戏是无法玩的:)

   void Window_ClientSizeChanged( object sender, EventArgs e )
   {
       int new_width = graphics.GraphicsDevice.Viewport.Width;
       int new_height = graphics.GraphicsDevice.Viewport.Height;

       if (new_width != Variables.SCREEN_WIDTH)
       {
           Variables.SCREEN_HEIGHT = (int)(new_width * ascept_ratio);
           Variables.SCREEN_WIDTH = new_width;
       }
       if (new_height != Variables.SCREEN_HEIGHT)
       {
           Variables.SCREEN_WIDTH = (int)(new_height / ascept_ratio);
           Variables.SCREEN_HEIGHT = new_height;
       }

       UpdateParameters();
   }

...

   public void UpdateParameters()
   {
       graphics.PreferredBackBufferWidth = Variables.SCREEN_WIDTH;
       graphics.PreferredBackBufferHeight = Variables.SCREEN_HEIGHT;
       graphics.ApplyChanges();
   }

谢谢,

亲切的问候,Daresium

【问题讨论】:

  • 为什么这段代码不起作用?它做了什么不受欢迎的事情?

标签: c# xna window


【解决方案1】:

你的意思是保持纵横比?

您可以像任何 WinForms 项目一样执行此操作:

当表单加载时,存储方面广播:(float)Width/(float)Height。在 XNA 中,这可能在您游戏的 LoadContent 中(因为此时会创建窗口)。

然后,处理表单的sizechanged 事件。您需要跟踪用户是否正在更改高度、宽度或两者。如果是高度,则设置Width = Height / AspectRatio,如果宽度变化设置Height = Width * AspectRatio

如果两者都改变​​,则决定宽度或高度,(我的意思是在设计中选择一个,而不是每次调整大小)并按上述操作。


完成此操作后,您可能必须执行特定于 XNA 的操作,例如调整后缓冲区的大小等。但这不是针对此问题的,因此我将其省略(如果需要,请询问另一个问题是)。


编辑。下面是一个最小的工作示例:

它保持纵横比,并通过绘制到渲染目标窗口的原始大小来调整图形大小,然后绘制缩放以适应新窗口。如果您不想这样做,请删除覆盖的 BeginDrawEndDraw 方法。

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace WindowsGame1
{
    public class Game1 : Game
    {
        GraphicsDeviceManager Graphics;
        float AspectRatio;
        Point OldWindowSize;
        Texture2D BlankTexture;
        RenderTarget2D OffScreenRenderTarget;
        SpriteBatch SpriteBatch;

        public Game1()
        {
            Graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            Graphics.IsFullScreen = false;
            Window.AllowUserResizing = true;
            Window.ClientSizeChanged += new EventHandler<EventArgs>(Window_ClientSizeChanged);
        }

        void Window_ClientSizeChanged(object sender, EventArgs e)
        {
            // Remove this event handler, so we don't call it when we change the window size in here
            Window.ClientSizeChanged -= new EventHandler<EventArgs>(Window_ClientSizeChanged);

            if (Window.ClientBounds.Width != OldWindowSize.X)
            { // We're changing the width
                // Set the new backbuffer size
                Graphics.PreferredBackBufferWidth = Window.ClientBounds.Width;
                Graphics.PreferredBackBufferHeight = (int)(Window.ClientBounds.Width / AspectRatio);
            }
            else if (Window.ClientBounds.Height != OldWindowSize.Y)
            { // we're changing the height
                // Set the new backbuffer size
                Graphics.PreferredBackBufferWidth = (int)(Window.ClientBounds.Height * AspectRatio);
                Graphics.PreferredBackBufferHeight = Window.ClientBounds.Height;
            }

            Graphics.ApplyChanges();

            // Update the old window size with what it is currently
            OldWindowSize = new Point(Window.ClientBounds.Width, Window.ClientBounds.Height);

            // add this event handler back
            Window.ClientSizeChanged += new EventHandler<EventArgs>(Window_ClientSizeChanged);
        }

        protected override void LoadContent()
        {
            // Set up initial values
            AspectRatio = GraphicsDevice.Viewport.AspectRatio;
            OldWindowSize = new Point(Window.ClientBounds.Width, Window.ClientBounds.Height);

            BlankTexture = new Texture2D(GraphicsDevice, 1, 1);
            BlankTexture.SetData(new Color[] { Color.FromNonPremultiplied(255, 255, 255, 255) });
            SpriteBatch = new SpriteBatch(GraphicsDevice);

            OffScreenRenderTarget = new RenderTarget2D(GraphicsDevice, Window.ClientBounds.Width, Window.ClientBounds.Height);
        }

        protected override void UnloadContent()
        {
            if (OffScreenRenderTarget != null)
                OffScreenRenderTarget.Dispose();

            if (BlankTexture != null)
                BlankTexture.Dispose();

            if (SpriteBatch != null)
                SpriteBatch.Dispose();

            base.UnloadContent();
        }

        protected override bool BeginDraw()
        {
            GraphicsDevice.SetRenderTarget(OffScreenRenderTarget);
            return base.BeginDraw();
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            SpriteBatch.Begin();
            SpriteBatch.Draw(BlankTexture, new Rectangle(100, 100, 100, 100), Color.White);
            SpriteBatch.End();
            base.Draw(gameTime);
        }

        protected override void EndDraw()
        {
            GraphicsDevice.SetRenderTarget(null);
            SpriteBatch.Begin();
            SpriteBatch.Draw(OffScreenRenderTarget, GraphicsDevice.Viewport.Bounds, Color.White);
            SpriteBatch.End();
            base.EndDraw();
        }
    }
}

【讨论】:

  • 哇!谢谢 :)。但一切似乎都有效,但对角线和高度调整大小:(
  • 修正了导致问题的错字。
  • 如果用户调整宽度和高度,它只是选择宽度,并相应地调整高度。交换ifs 的顺序,让它使用高度,并计算宽度。
  • 哇!谢谢你是上帝 :) 但是你知道要显示的东西也可以调整大小吗?
  • 我没有测试图纸,明天快速看一下。你的意思是你想要它,所以如果窗口越大,图形就越大?
【解决方案2】:

我的猜测是这段代码不会工作,因为它会一直调用自己,因为 ClientSizeChanged 事件会触发 ClientSizeChanged 事件。

也许你需要检查一下窗口是否已经在正确的纵横比中,而不是进一步改变它。

【讨论】:

  • 有人有其他想法吗?因为我似乎完全不在他们之中;)并且对上一篇文章感到抱歉,我不知道我可以编辑这样的文章。
  • @Darestium 如果您描述了您在当前代码中看到的行为,将会很有帮助。
  • 嗯...它只是没有正确调整窗口大小,或者在其他情况下不允许我调整它的大小。有时它什么也没做:)
猜你喜欢
  • 2011-04-11
  • 2012-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-15
  • 1970-01-01
  • 2012-08-02
相关资源
最近更新 更多