Reputation: 698
I decided to move my game from windowed to fullscreen mode and that's the first problem I face. I'm looking for a way of resizing all of my sprites based on screen resolution. My background is now in the (0, 0)
coordinates, but I need to have it and all sprites to scale with some kind of fixed aspect ratio (16:9
preferred). And resize them to that portion that the background is stretched to fill the screen. And not more, not less.
I've looked into some online tutorials but I really couldn't understand the concept they used. Can you explain how you would to that? I read using a RenderTarget2D
and passing it to a spriteBatch.Begin()
call, has some kind of effect, but there's got to be more code.
I'm not looking to supporting resolution change option, but adapting the sprites to the current resolution.
Upvotes: 4
Views: 5355
Reputation: 9957
It sounds like you're talking about resolution independence.
The general idea is to make your game using a virtual resolution and scale it up or down to fit the actual resolution of the screen.
var scaleX = (float)ActualWidth / VirtualWidth;
var scaleY = (float)ActualHeight / VirtualHeight;
var matrix = Matrix.CreateScale(scaleX, scaleY, 1.0f);
_spriteBatch.Begin(transformMatrix: matrix);
For example, if your virtual resolution was 800x480 you would simply render all your sprites relative to that. Then before rendering the sprite batch, create a transformation matrix to pass into the Begin
call.
The other thing you should know is that you'll need to scale the mouse / touch input coordinates in reverse to deal with them in the virtual resolution. In the Update
method you can scale the mouse position in reverse like this:
var mouseState = Mouse.GetState(); // you're probably already doing this
var mousePosition = new Vector2(mouseState.X, mouseState.Y);
var scaledMousePosition = Vector2.Transform(mousePosition, Matrix.Invert(matrix));
Then you can use the scaled value in all the places you're currently using mouseState.X
and mouseState.Y
.
It gets more complicated if want to implement letterboxing or pillarboxing. Take a look at the Viewport Adapters in MonoGame.Extended if you want to know how that works.
Upvotes: 10
Reputation: 2986
You have a texture with size (W, H)
, to be put in the position (X, Y)
, according to a scale (sW, sH)
. Initially, the scale was (1, 1)
, so the sprite would be positioned in the rectangle (X, Y, W, H)
.
Now, let's say the initial resolution was 800x600, but you now want a resolution of 1440x900. If 800 -> sW = 1
, 1440 -> sW = 1440/800 = 1.8
. Similar, our new sH is 1.5.
What this is saying is: if something was supposed to be on the X-coordinate 500 on the initial resolution, it is now on 500*1.8 = 900 X position on the new resolution. This is clear for the edge: if something was on X=800 previously, it is now on 800*1.8 = 1440, still on the edge of the screen!
All said and done, we simply have to multiply. Going back to the first paragraph, we can say that a rectangle (X, Y, W, H)
can be rescaled by a scale (sW, sH)
to (X * sW, Y * sH, W * sW, H * sH)
.
This is of course calculated by assuming the original resolution is scaled by (1, 1)
, don't forget this!
Upvotes: 1