tags:

views:

138

answers:

1

Is there a way that I could basically develop my XNA game at 1080p (or 720p) as my default resolution and then depending upon the set resolution just scale everything in the game to the proper size, without having to set the scaling factor in every Sprite Draw() method?

My thought is that, I could develop all the graphics, configure coordinates, etc based on a resolution of 1080p but then for the XBOX just set the res to 720p and scale down (so that the XBOX sees everything as being at 720 and therefore handles all resolutions as mentioned in the developer docs) and on PC scale to any needed resolution or aspect ratio by automatically letterboxing the view for resolutions that are not 16:9.

I already had my game setup so that spritebatch.begin() and end() were called at the highest level, around all the other Draw calls, so that I could technically just pass in the scaling matrix there, but whenever I do that it will do something weird like make the view off center, or only take up a quarter of the screen.

Is there a best practice way for achieving this?

+1  A: 

If you set a scaling matrix in SpriteBatch.Begin, then it will scale the sizes and positions of every single sprite you draw, with that SpriteBatch, up until you call End.

SpriteBatch uses a client space where zero is the upper left corner of the Viewport, and one unit in that space is equivalent to one pixel in the viewport.

When you give SpriteBatch a transformation, the sprites that you draw will have that transformation applied to them for you, before they are drawn. So you can (and should) use this same technique to translate your scene (to centre it on your player, for example).

For Example:

Your game is developed at 720p and you're using SpriteBatch without a transformation. You have a sprite centred at the bottom right corner. Let's say its texture is (32, 32) pixels and the sprite's origin is (16, 16) (origin is specified in texture space, so this is the centre of the sprite). The sprite's position is (1280, 720). The sprite's scale is 1, which makes its resulting size (32, 32). You will see the top left quarter of the sprite at the bottom-right corner of your screen.

Now you move to a screen that is 1080p (1.5 times bigger than 720p). If you don't add a scaling matrix to SpriteBatch, you can see the whole sprite, with its at two-thirds of the screen, rightwards and downwards.

But you want to scale up your whole scene so that at 1080p it looks just like it did at 720p. So you add the matrix Matrix.CreateScale(1.5f, 1.5f, 1f) (note using 1 for Z axis, because this is 2D not 3D) to your SpriteBatch.Begin, and do nothing else.

Now your scene of sprites will be scaled 1.5 times bigger. Without making any changes to the actual Draw call, your sprite will be drawn at position (1920, 1080) (the bottom right corner of the screen), its size will be (48, 48) (1.5 times bigger), and its origin will still be the centre. You will see the sprite's top-left quadrant at the bottom-right corner of your screen, just like you did at 720p, and at the same relative size.

Andrew Russell
So, I ended up doing this exact thing. And it worked in a really simple game with only one code file. But as soon as I added sub-classes based on DrawableGameComponent, the scaling fell apart. It would scale everything TOO small, except those drawn in the main class. I only called Begin() at the highest level as well, so I'm not sure what's wrong. Working on getting some boiled down example code.
Adam Haile
@Adam: That is very strange. You should perhaps create a small example program and (if the exercise itself doesn't illuminate the problem) post it here. I generally avoid using DrawableGameComponent myself, you get much more control doing things directly. Also: how are you getting your SpriteBatch into your DGC?
Andrew Russell
I've based everything off the GameStateManagement example so I could have menus, and the "ScreenManager" is a DGC and in it's Draw method, it calls everything else. Spritebatch is created in there and passed along. I'm guessing this has something to do with my issue?
Adam Haile
You were completely right... I was just apparently dumb.I didn't realize that I still had most of my coordinate calculations based off of GraphicsDevice.Viewport, so it was doing exactly what I told it to. As soon as I made variables for the "intended" resolution available and used those, it all scales properly. <Smacks Forehead>
Adam Haile