Search code examples
c#scalefullscreenscreen-resolutionmonogame

Scale all sprites on screen based on resolution


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.


Solution

  • 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.