tags:

views:

60

answers:

2

I know that when developing for Xbox in XNA, you basically just set the resolution to 1280x720 and the Xbox will just take care of things, but on PC I'm having some trouble getting the resolution handled correctly.

I would like it to be able to run at other resolutions, but I'm actually happy to make the game always widescreen and just be letterboxed on 4:3 screens. I can already handle scaling the game and it's components but I cannot figure out how to get it letterboxed.

Obviously, this will not be necessary in windowed mode, but when running in fullscreen I just need to figure out how to get the game to only draw on part of the screen.

What's the best way to do this?

+2  A: 

You could use GraphicsDevice.Viewport to get the aspect ratio, which you can use to construct a scaling matrix for use with SpriteBatch, and maybe use an affine translation to position your sprite batch center screen.

You can call GraphicsDevice.Clear every frame, but if that seems a bit wasteful to you, then just draw a black rectangle instead of clearing over the new viewport.

For instance, assuming you want a 16:9 aspect ratio, you can do this (bear with me, I'm using XNA 4 so it might be a little different):

float aspect = 16.0f / 9.0f;

GraphicsDevice.Clear(Color.Black);
Matrix transform = Matrix.CreateScale(1, GraphicsDevice.Viewport.AspectRatio / aspect, 1) * Matrix.CreateTranslation(0, (GraphicsDevice.Viewport.Height - GraphicsDevice.Viewport.Height / aspect) / 4.0f, 0);
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null, null, transform);

// do your drawing here

sBatch.End()

There's no need to reconstruct transform every time so you could just store it as a private member variable in Game.

rfw
Of course this does seem a little hacky at best...
rfw
I tried this out and like the general idea that it would scale everything, but can't see to get it to work... the whole screen is skewed and everything is off center.
Adam Haile
+2  A: 

You can set GraphicsDevice.Viewport to the viewport that you want to use.

The documentation has an example of how to do this (it does it for split-screen, but letter-boxing a single view is the same concept).

The GPU will handle clipping to this viewport for you.

Additionally your projection space will cover that viewport, so you don't need to worry about doing any transformations (excepting that SpriteBatch works in a space that is the pixel-size of the viewport, not projection space, so you may have to do scaling if your viewport is larger or smaller than 1280x720; I describe more about the various spaces involved in this answer).

To get black bars, simply do a GraphicsDevice.Clear(Color.Black) with the viewport set to the full screen.

Andrew Russell
That worked PERFECTLY. Thank you!
Adam Haile
Well...almost, no I realize that it's making scaling not work so well....
Adam Haile
@Adam: it should work fine. Perhaps you have some screen-dependent stuff in your `Draw` calls? I've answered your follow-up question.
Andrew Russell