# How do I make a 2D game resolution independent?

I'm working on a simple 2D game. I've finished the mobile phone version.

However, my boss wants the game to works on his RT. I'm doing the "conversion" but my buttons are in the wrong places, because I hard-coded the screen size, like this:

 texture = game.Content.Load<Texture2D>("StartScreen");
mainFrame = new Rectangle(0, 0, game.GraphicsDevice.Viewport.Width, game.GraphicsDevice.Viewport.Height);

// button definitions
startbrect = new Rectangle(300, 258, 88, 88);


In this example, mainframe is fine, but startbrect isn't, because I defined the size to match a Windows phone's screen. How can I handle responsive design when all Windows 8 phones' screens are different? Is there a formula or macro to calculate each time the good size?

• You could check what percentage of the Windows Phone screensize your buttons used, and then use that percentage to calculate correct screensize for every other resolution. But I'm sure there are more elegant ways than this. – Christian Dec 12 '13 at 13:07
• Im' looking for a more elegant way, but i ll try with percentage for the moment. – Gabson Dec 12 '13 at 13:29
• You should be able to do it by manipulating the camera. – ashes999 Dec 12 '13 at 21:33
• My solution was to deal with percentage didn't find better. – Gabson Dec 13 '13 at 8:40

I use a reference screen size, and scale everything according to it, while keeping the ratio of everything the same.

private static float CalcRatio(Vector2 Sizes)
{
return Sizes.y/Sizes.x;
}

public static Vector2 CalculateNewPos(Vector2 RefPos, Vector2 RefScreenSize,
Vector2 CurrentScreenSize)
{
return new Vector2((RefPos.x/RefScreenSize.x) * CurrentScreenSize.x,
(RefPos.y/RefScreenSize.y) * CurrentScreenSize.y);
}

public static Vector2 CalculateNewSize(Vector2 RefSize, Vector2 RefScreenSize,
Vector2 CurrentScreenSize)
{
float origRatio = CalcRatio(RefSize);
float perW = RefSize.x * 100f / RefScreenSize.x;
float newW = perW / 100f * CurrentScreenSize.x;
float newH = newW * origRatio;
return new Vector2(newW, newH);
}


To make sure the game looks good on resolutions with ratios substantially different from your reference resolution's, define a "playable area", that fits into any kind of screen, and put all of the gameplay critical visuals there. Fill everything outside of it with background. Usually, my reference playable area is as big as the reference screen size itself.

On portrait orientations, I calculate the (new) playable area so that the screen is filled vertically, and the space it takes horizontally is just as big as it is required to keep the ratio. On landscape orientations, I fill the screen horizontally, and keep the ratio when setting the vertical size.

For more, see http://en.wikipedia.org/wiki/Safe_area_(television) as it's a similar, if not identical, concept.

I think the easiest and most natural approach to resolution independent layouts is a relative (percentage) scheme. So from the start do not work with the real resolution but only in a uniform [0,1]x[0,1] square wherever possible.

That means that for a given screen_size and a given object_size and a given relative position (px, py) (for example (0.5, 0.5) for the center of the screen), the upper, left corner of the object is calculated by:

x = px * screen_size.width - 0.5 * object_size.width
y = py * screen_size.height - 0.5 * object_size.height


The idea should be clear. A ready abstraction would be

x = cx1 * screen_size.width + cx2 * object_size.width + cx3
y = cy1 * screen_size.height + cy2 * object_size.height + cy3


and every position is defined then by (cxi, cyi). By this one could place objects in corners with or without borders, etc.

Please make sure that the single elements size (buttons, labels, ...) are scaled too.

Specialy for MonoGame i have platform independent solution for this problem called IRR (Independent Resolution Renderer). It has very simple usage:

1. Create IRR in Initialize() method

_irr = new ResolutionRenderer(this, VirtualResolutionWidth, VirtualResolutionHeight, _gfx.PreferredBackBufferWidth, _gfx.PreferredBackBufferHeight);

2. Call _irr.Draw() each cycle in Draw() call
3. Supply _irr.GetTransformationMatrix() in any SpriteBatch.Begin() call you want to use IRR.

Description is here: http://panthernet.ru/forum/index.php?/topic/17-monogamexna-examples-v14/?p=44

Code is here: https://github.com/panthernet/Monogame-Examples