[Solved]Scaling/zooming game window?

Hello again!

The game I’m working on have a resolution of 160x144 pixels (like a gameboy one). I’ve been searching how to “zoom” or “scale” the windows (like, x2, x3 or x4) , but I don’t find anything, only how to change the game resolution.

Any clues on how to work with that? Thanks in advance.

1 Like

You can draw to a small render target first and then render that to the backbuffer in the size you want. You may want to set the sampler state of the graphicsdevice to pointclamp so it doesn’t interpolate when scaling up.

I’ve found this http://stackoverflow.com/questions/7602852/scaling-entire-screen-in-xna (that seems that would serve me), but I don’t understand when to initialize the rendertarget and how to use it.

Sorry for so many questions, but I’m a little lost now.

Sorry can I jump in and ask a very similar topic. I have a 480x280 game that I want to scale 1-4X depending on options.Any help GREATLY appreciated.

I am trying to do this by rt, but currently it seems to be in reverse and my window gets bigger but my game shrinks in half lol. EDIT: since almost got it working.

so screenwidth and height are constant 480x280 and screenScale is a multiplier 1-4x. Changing scale simply makes graphics.prefferedbackbuffer… 480 and 280 * multiplier. This works fine for windowed and my game just doubles in size as you expect, however in full screen it is still stretching to any display. I thought I really had the answer here :frowning:

            rt = new RenderTarget2D(graphics.GraphicsDevice, screenWidth, screenHeight);
            GraphicsDevice.SetRenderTarget(rt);

            spriteBatch.Begin(transformMatrix: camera.GetViewMatrix(), sortMode: SpriteSortMode.FrontToBack);

            ScreenManager.Instance.Draw(spriteBatch);

            spriteBatch.End();

            GraphicsDevice.SetRenderTarget(null);

            spriteBatch.Begin(transformMatrix: camera.GetViewMatrix(), sortMode: SpriteSortMode.FrontToBack);

            spriteBatch.Draw(rt, new Rectangle(0, 0, screenWidth * screenScale, screenHeight * screenScale), Color.White);

            spriteBatch.End();

To create a render target you should pass in a GraphicsDevice and the size (which in this case would be your native resolution.

new RenderTarget2D(GraphicsDevice, 160, 144);

By default a GraphicsDevice renders to the backbuffer, but you can change that by using

GraphicsDevice.SetRenderTarget(someRenderTargetHere);

If you pass null as a render target the GraphicsDevice will render to the backbuffer again. So in your game instance you’ll want to do something like:

// Initialization
_nativeRenderTarget = new RenderTarget2d(GraphicsDevice, 160, 144);


// Draw call
GraphicsDevice.SetRenderTarget(_nativeRenderTarget);
GraphicsDevice.Clear(_backgroundColor);
// now render your game like you normally would, but if you change the render target somewhere,
// make sure you set it back to this one and not the backbuffer
...
// after drawing the game at native resolution we can render _nativeRenderTarget to the backbuffer!
// First set the GraphicsDevice target back to the backbuffer
GraphicsDevice.SetRenderTarget(null);
// RenderTarget2D inherits from Texture2D so we can render it just like a texture
spriteBatch.Begin(samplerState: SamplerState.PointClamp);
spriteBatch.Draw(_nativeRenderTarget, _actualScreenRectangle);
spriteBatch.End();

_actualScreenRectangle would be a Rectangle like (x: 0, y: 0, width: a * 160, height: a * 144), where a is 1, 2, 3 or whatever scale factor you want.
EDIT: you’ll actually have to set the backbuffer size to the size of this rectangle by using PreferredBackBufferWidth and PreferredBackBufferHeight of your GraphicsDeviceManager. If you don’t do this in your game constructor, but later through settings or what not, you need to call GraphicsDeviceManager.ApplyChanges() for the window to actually resize.

3 Likes

Might be because you’re drawing with the transformMatrix the second time too. Since you already applied it once, you just have to render the texture with spritebatch to the backbuffer without additional transformation.

I have tried with taking that out as well I noticed that.

In your example where you draw to the “_actualScreenRectangle” my understanding is that it should draw the RT to a rectangle of 160x144 or 320x288 and if you then resize the screen, you should still have that 320x288 rectangle and just get blackness beyond it, however the image stretches with it.

I have tried messing with sourc/dest rectangles such as

spriteBatch.Draw(rt, new Rectangle(0, 0, 480, 280), new Rectangle(0, 0, screenWidth * ScreenScale, screenHeight * ScreenScale), Color.White);

Later at home I will try remove the transformation from the first spritebatch too (but then if that works how do I use a camera in my main drawing spritebatch :frowning:)

Is it anything to do with this do you think @Jjagg

If it is looks like it only just got a fix 5 days ago.

I will get the latest dev build or build it myself and see what goes on.

And yes for the record this is a DirectX project, may test my same code on an GL one too.

The problem was exactly what you described here, so that will probably solve your issue :slight_smile:

I wil try it now, but, you are saying that would be better to work with OpenGL instead or DirectX right now?

If you’re not on the latest develop, there’s a bug in DX which will cause the drawing to rescale when the window is resized. I’m not sure if it’s also messed up if you do this through code (with graphicsdevicemanager as I said before).

Thanks Jjagg :slightly_smiling:

I can’t believe this (probably) has been my problem for quite some time now, hopefully I can move on and try get a game off the ground and stop worrying about this meta stuff.

That would explain what happened to me yesterday with reescaling (as you can see here http://gamedev.stackexchange.com/questions/124565/there-are-spritebatch-drawing-limitations-on-monogame?noredirect=1#comment218009_124565 )

EDIT: NOPE; I didn’t say nothing. I’ve tried to port it to OpenGL and happens the same issue as I was having in DirectX. I’m going to try the RenderTarget thing. If I have any issue, I will ask again here. Thanks!

Yeah, if you want to render scaled directly you’d have to account for it in everything position related. Just using an intermediary rendertarget is a lot easier IMO

I’m having more problems with the rectangle than anything hahaha.

The rectangle code = Rectangle _actualScreenRectangle = new Rectangle(0, 0, 160, 144);

Because, if it says I need a vector, I can’t assign the “scaling”. What is happening here.

I have achieved it…somehow.

If I do reescaling, I also need to change the PreferredBackBufferWidth/Height to the new resolution?

Sorry for posting again.

IT WORKS! HAHAHA, thank you all of you! I’ve lost an entire day working on this, and it was really easy.

Haha, thanks again. I only did what Jjagg told me to do. I think this post will help many people like me haha

1 Like

So are you using windows directx or gl?

Did you have to download latest dev build?

I’m using DirectX in this build. And I didn’t need to download the latest dev build, I’m using the last stable release (3.5.1 I think it is?)

Oh but you aren’t resizing your window?

Just drawing to a set render target rectangle size and scaling it up or down.