Resolution after scale with spritebatch

I have a game graphics that are made for resolution 1920x1080 or Full HD quality.

The phone resolution I have currentlly is 2560x1440 which is QHD I am using spriterbatch to scale using this thing:

float screenscale =
                [2560] (float)ScreenManager.GraphicsDevice.PresentationParameters.BackBufferWidth / [1080]ScreenManager.GameRect.Width;
SpriteScale = Matrix.scale(screenscale ,screenscale ,1);
spriteBatch.Begin(0, null, null, null, null, null, SpriteScale);

But for example if I have object at position {X:100,Y:100} and I scale it to resolution 2560 but when I move that object and I want to detect the out of screen which is {X:0,Y:0,Width:2560,Height:1440} after 1800 of X position my object is going out of screen I mean that my device is telling me my resolution is 2560 but in fact that thing is 1800 - 1900 over X position why that thing is happening ?

Your question is confusing, but if you want to scale a 1920x1080 game to 2560x1440 screen, you need to have a ScaleMatrix = Matrix.CreateScale(2560/1920, 1440/1080, 1); to scale all your objects when draw on the screen, and also scale your mouse position by ScaleVector2 = new Vector2(ScaleMatrix.M11, ScaleMatrix.M22); for the mouse inputs to work properly.

I think for mouse coordinates I can get the Matrix.Inverse(SpriteScale);

Vector2 mousePosition = Vector2.transform(mouseposition,Matrix.Inverse(SpriteScale)); ?

No that’s not right, i already told you the right way to do it. It is new Vector2(2560/1920, 1440/1080), or new Vector2(ScaleMatrix.M11, ScaleMatrix.M22)

Oh so my error is that when I scale to 2560 in order to draw something to the right side I have to divide to the scale which is 1.33 to get the write position I get it now :smile:

the only steps you had to take would be

have a ScaleMatrix = Matrix.CreateScale(2560/1920, 1440/1080, 1);

scale your mouse position by ScaleVector2 = new Vector2(ScaleMatrix.M11, ScaleMatrix.M22);

You shouldn’t need anything more. If you do, then you are doing something wrong.

Well its exactlly the same ScaleMatrix.M11, ScaleMatrix.M22 equals 1.33,1.33

I use a code that is very similar to that in order to scale all my gfx to 800x480, and it has been working for years. Maybe the problem is not on the matrix but on the way you try to detect the end of the screen, or the value returned by BackBufferWidth may not be correct. (disappearing at 1800-1900 is very close to 1920, which is a quite common width resolution)

Ok but what happens if I want to keep the screen ratio, how to scale with the same ratio using the matrix ?
My problem was that I scale from resolution 1920x1080 and when I want to obtain position I have to devide the current Vector2 to ScaleVector2.

@KakCAT What if I have Ipad Mini and the game is designed for resolution 1920x1080 will I do again CreateScale(1920/1024,1080/768,1) ?

Because I did it and the image is not scaling nice on the y axes.

remember that CreateScale requires a float and with that code you’re feeding it with integers. Try CreateScale(1920/1024.0f,1080/768.0f,1) instead.

If you already are using them as floats and the pasted code is just pseudocode, then no idea what could be happening :frowning:

It was pseudo code,yes.
Well it’s not scaling the whole image by y don’t know why now I am checking the math behind because I need to fix that if anyone have any ideas, please share it

Rather than scaling and re-positioning everything on the run, you might find it easier to create a RenderTarget2D of your “working” resolution, rendering everything to it in your Game.BeginDraw() method, then simply rendering this RenderTarget2D to your screen with the appropriate scaling in Game.Draw().

Hi Ben, maybe you could point to some code how exacty to do it your way? :smile:

In it’s simplest form:

  1. Add a private variable of type RenderTarget2D to your Game1 class:

    private RenderTarget2D _backBuffer;
  2. Initialise this in Game1.LoadContent to your “optimum” dimensions (I use 900x1600):

    _backBuffer = new RenderTarget2D(GraphicsDevice, [optimum width], [optimum height]);
  3. Add the following method to Game1:

    protected override bool BeginDraw()
    {
        GraphicsDevice.SetRenderTarget(_backBuffer);
        GraphicsDevice.Clear(Color.Black);

    // Draw all your game objects* here!

    return base.BeginDraw();
}

… with appropriate logic to render everything where the comment is. If you’re using DrawableGameComponents, convert these into GameComponents and manually call the Draw methods in this function.

  1. Update Game1.Draw to the following:

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.SetRenderTarget(null);
        GraphicsDevice.Clear(Color.Black);

    // Calculate Rectangle of required size and offset to scale and display _backBuffer

    spriteBatch.Begin();
    spriteBatch.Draw(_backBuffer, [destination rectangle], Color.White);
    spriteBatch.End();

    base.Draw(gameTime);
}

The exact calculation of [destination rectangle] is up to you, dependent on how you want your display to deal with different aspect ratios. For example, in my latest project I want the full width of a portrait screen to be filled, so my [destination rectangle] will have an X of 0 and a width of GraphicsDevice.Viewport.Bounds.Width, with the Y set to whatever negative offset is required to ensure that the centre chunk of my _backBuffer is in the middle of the screen.

PM me if you want more info and I’ll throw a simple example together.

what’s the difference between the sprite batch scaling matrix and ^this ?

you need to have a ScaleMatrix = Matrix.CreateScale(2560/1920, 1440/1080, 1); to scale all your objects when draw on the screen

When using a scaling matrix, the position and scale of everything you draw has to be modified by the scaling matrix ie: every time you call SpriteBatch.Draw, you have to apply the matrix to the destination Vector2 or Rectangle, and the Scale float.

When using a RenderTarget2D back buffer, you don’t need to worry about this - all your draw calls are based on a fixed size “canvas”, which is then scaled to the appropriate size for the screen.

Of course, in both cases, you still need to scale and translate any touchscreen input accordingly. But the RenderTarget2D option not only removes a load of matrix calculations (which can have an impact on performance on lower spec devices), but also makes “visual debugging” easier, as you will never be in a situation where you’ve forgotten to scale something you’re drawing and thus have is render at the wrong size or off screen.

Got it,thanks for your reply

No problem, hope it helps! :slight_smile:

Thanks for taking time to answer me ;-).