我想在較大的窗口上創建低分辨率遊戲。 (例如,在960x540大小的窗口上96x54 res)。XNA在不提高分辨率的情況下調整窗口大小
我該怎麼辦?有沒有辦法調整獨立於首選後緩衝區寬度和高度的窗口大小?或者我應該只保留一個低分辨率渲染目標,然後在完成最近紋理採樣調整後,將其作爲全屏幕四邊形繪製在我的窗口上?
由於提前,
xoorath
我想在較大的窗口上創建低分辨率遊戲。 (例如,在960x540大小的窗口上96x54 res)。XNA在不提高分辨率的情況下調整窗口大小
我該怎麼辦?有沒有辦法調整獨立於首選後緩衝區寬度和高度的窗口大小?或者我應該只保留一個低分辨率渲染目標,然後在完成最近紋理採樣調整後,將其作爲全屏幕四邊形繪製在我的窗口上?
由於提前,
xoorath
使用你在談論可能是一個好主意(另外,如果你想要做的後期處理着色器這將是您更容易)的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);
我傾向於選擇在「渲染到紋理「解決方案,以便我可以允許像全屏幕一樣沒有扭曲的情況。
我用它來實現這一目標的類通常看起來是這樣的:
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);
}
有了這個,我基本上可以停止關心分辨率,只關注遊戲。
非常感謝lzcd。這是一個非常好的參考,現在有了這兩種解決方案,希望這個線程能夠幫助其他人偶然發現它。我很欣賞你爲此付出的時間。 – Xoorath
謝謝兄弟,這就是我一直在尋找。我不確定我是否可以解決這個問題,這樣抽樣就會更加接近和清晰(對我的比賽來說是可取的)。但是,如果沒有,那麼我會執行渲染目標方法。 – Xoorath
不客氣:) – Panos