2011-09-29 92 views
1

我想在较大的窗口上创建低分辨率游戏。 (例如,在960x540大小的窗口上96x54 res)。XNA在不提高分辨率的情况下调整窗口大小

我该怎么办?有没有办法调整独立于首选后缓冲区宽度和高度的窗口大小?或者我应该只保留一个低分辨率渲染目标,然后在完成最近纹理采样调整后,将其作为全屏幕四边形绘制在我的窗口上?

由于提前,

xoorath

回答

1

使用你在谈论可能是一个好主意(另外,如果你想要做的后期处理着色器这将是您更容易)的RenderToTexture方法。 或者,您可以设置窗口的大小,但您的代码只能在桌面上使用。

您必须添加在你的项目中的2个引用:

using System.Drawing; 
using System.Windows.Forms; 

,然后在游戏类(在初始化方法即)

GraphicsDeviceManager.PreferredBackBufferWidth = 96; 
GraphicsDeviceManager.PreferredBackBufferHeight = 54; 
IntPtr ptr = this.Window.Handle; 
Form form = (Form) Control.FromHandle(ptr); 
form.Size = new Size(960, 540); 
+0

谢谢兄弟,这就是我一直在寻找。我不确定我是否可以解决这个问题,这样抽样就会更加接近和清晰(对我的比赛来说是可取的)。但是,如果没有,那么我会执行渲染目标方法。 – Xoorath

+0

不客气:) – Panos

7

我倾向于选择在“渲染到纹理“解决方案,以便我可以允许像全屏幕一样没有扭曲的情况。

我用它来实现这一目标的类通常看起来是这样的:

class VirtualScreen 
{ 
    public readonly int VirtualWidth; 
    public readonly int VirtualHeight; 
    public readonly float VirtualAspectRatio; 

    private GraphicsDevice graphicsDevice; 
    private RenderTarget2D screen; 

    public VirtualScreen(int virtualWidth, int virtualHeight, GraphicsDevice graphicsDevice) 
    { 
     VirtualWidth = virtualWidth; 
     VirtualHeight = virtualHeight; 
     VirtualAspectRatio = (float)(virtualWidth)/(float)(virtualHeight); 

     this.graphicsDevice = graphicsDevice; 
     screen = new RenderTarget2D(graphicsDevice, virtualWidth, virtualHeight, false, graphicsDevice.PresentationParameters.BackBufferFormat, graphicsDevice.PresentationParameters.DepthStencilFormat, graphicsDevice.PresentationParameters.MultiSampleCount, RenderTargetUsage.DiscardContents); 
    } 

    private bool areaIsDirty = true; 

    public void PhysicalResolutionChanged() 
    { 
     areaIsDirty = true; 
    } 

    private Rectangle area; 

    public void Update() 
    { 
     if (!areaIsDirty) 
     { 
      return; 
     } 

     areaIsDirty = false; 
     var physicalWidth = graphicsDevice.Viewport.Width; 
     var physicalHeight = graphicsDevice.Viewport.Height; 
     var physicalAspectRatio = graphicsDevice.Viewport.AspectRatio; 

     if ((int)(physicalAspectRatio * 10) == (int)(VirtualAspectRatio * 10)) 
     { 
      area = new Rectangle(0, 0, physicalWidth, physicalHeight); 
      return; 
     } 


     if (VirtualAspectRatio > physicalAspectRatio) 
     { 
      var scaling = (float)physicalWidth/(float)VirtualWidth; 
      var width = (float)(VirtualWidth) * scaling; 
      var height = (float)(VirtualHeight) * scaling; 
      var borderSize = (int)((physicalHeight - height)/2); 
      area = new Rectangle(0, borderSize, (int)width, (int)height); 
     } 
     else 
     { 
      var scaling = (float)physicalHeight/(float)VirtualHeight; 
      var width = (float)(VirtualWidth) * scaling; 
      var height = (float)(VirtualHeight) * scaling; 
      var borderSize = (int)((physicalWidth - width)/2); 
      area = new Rectangle(borderSize, 0, (int)width, (int)height); 
     } 
    } 

    public void BeginCapture() 
    { 
     graphicsDevice.SetRenderTarget(screen); 
    } 

    public void EndCapture() 
    { 
     graphicsDevice.SetRenderTarget(null); 
    } 

    public void Draw(SpriteBatch spriteBatch) 
    { 
     spriteBatch.Draw(screen, area, Color.White); 
    } 


} 

然后在我的比赛中,初始化往往是这样:

VirtualScreen virtualScreen; 

    protected override void Initialize() 
    { 
     virtualScreen = new VirtualScreen(96, 54, GraphicsDevice); 
     Window.ClientSizeChanged += new EventHandler<EventArgs>(Window_ClientSizeChanged); 
     Window.AllowUserResizing = true; 
     base.Initialize(); 
    } 

    void Window_ClientSizeChanged(object sender, EventArgs e) 
    { 
     virtualScreen.PhysicalResolutionChanged(); 
    } 

随着所有重要调用Update :

protected override void Update(GameTime gameTime) 
    { 
     virtualScreen.Update(); 

     base.Update(gameTime); 
    } 

然后绘制自己的行为:

protected override void Draw(GameTime gameTime) 
    { 
     virtualScreen.BeginCapture(); 


     GraphicsDevice.Clear(Color.CornflowerBlue); 
     // game rendering happens here... 


     virtualScreen.EndCapture(); 

     GraphicsDevice.Clear(Color.Black); 
     spriteBatch.Begin(); 
     virtualScreen.Draw(spriteBatch); 
     spriteBatch.End(); 

     base.Draw(gameTime); 
    } 

有了这个,我基本上可以停止关心分辨率,只关注游戏。

+0

非常感谢lzcd。这是一个非常好的参考,现在有了这两种解决方案,希望这个线程能够帮助其他人偶然发现它。我很欣赏你为此付出的时间。 – Xoorath

相关问题