# What is the proper way of handling resolution and size units on a 2D game?

So I started to learn SDL2 and I want to make a simple 2D game.

Now when I render a texture I have to specify in pixels the size of the element I want to draw and also the position in pixels on the window.

It doesn't feels like a good practice to hardcode pixel values because if I want to change the resolution of the window or the aspect ratio it will look really bad.

There is any recommended approach to follow?

• Yes, calculate instead of hardcoding. – Ocelot Dec 20 '19 at 21:34
• How would you do that? – ellipticaldoor Dec 20 '19 at 23:52

## 2 Answers

Generally it's up to you. Think about it in a abstract way. Read some articles and extract the ideas. Give it some time and gather the experiences.

Imagine that games have something like GameObjects(player, enemy, bonus, wall, trap, weapon, etc.) Each such a object have some properties and methods like position, rotation, moveTo, scaleUp, etc.

Those properties and methods should use coordinates which are called the "game" coordinates and they should be somehow mapped to the screen when rendered.

So what do you need?

Basically you need two coordinate systems and some functions that allow you to do the conversion between those two coordinate systems.

For example:

void gameCoordinates2ScreenCoordinates(const game_coord& from, screen_coord) {...} - called when object is sent to renderer

and vice versa

void screenCoordinated2GameCoordinates(const screen_coord& from, game_coord& to) {...} - e.x. called when mouse click happen

If your game is very simple app you can even start with mapping 1:1 and later on you can always refactor it according to your current needs.

Perhaps later on you want to map your x-axis of the screen to float between 0.0f(left edge of screen) to 1.0f(right edge of the screen) or -1.f to 1.0f or .0f to 10.f or whatever suits your needs.

Keep in mind following hints regarding the conversion functions:

• they should be generic
• they are called often so
• do only the necessary math
• avoid memory allocation

Old graphics have to be in powers of two. New graphics have a split. If the file is in the DirectDraw Surface format, then images need to be in multiples of four, otherwise images needs to be in multiples of eight. Therefore, for portability, images needs to be multiples of eight.

Note that it is the sprite sheet that needs to have multiples of eight in dimension. The individual sprites do not have to be so if they are packed, but requiring correct offsets, width, and height. Of course, evenly spaced sprites are easier to load, but uses more memory with padding.

The ideal tile sizing is based on the square root of vertical resolution in landscape, or horizontal resolution in portrait mode. Round up the square root of selected resolution to the nearest multiples of eight. This is the minimum resolution that a tile should be. Tiles may be larger especially for handheld devices. However, no tiles shall be smaller than the suggested minimum resolution.

As an example, a chess board requires a minimum of 8x8 pixel tile (a square of the board) would need a resultion of 64 pixel tall screen. If the chess board requires a minimum of 16x16 pixel tile, then it would need 128 to 256 pixel tall screen. If the chess board requires a minimum of 24x24 pixel tile, then it would need 192 to 576 pixel tall screen. If the chess board requires a minimum of 32x32 pixel tile, then it would need 256 to 1024 pixel tall screen. Every tile size has a minimum and maximum range of screen resolution they could support, but the maximum resolution could be ignored if you scale up the tiles with resolution instead of pixel perfect.

The ideal sprite size should be integer multiples of the tile size. For a three-quarter viewport that most games have or isometric viewport, the ideal size is two tiles tall and one tile wide for medium sized characters. All top-down viewport have medium size sprites equal tiles in size. For side-scrollers, medium size characters should be four to six tiles tall and one tile wide for more realistic looks. Of course, if you like the chibi style, keep the two tiles tall and one tile wide.

Heads tall ratio

• chibi - two heads tall
• infantile - three heads tall
• toddler - four heads tall
• children - five heads tall
• young adult - six heads tall
• adult - seven heads tall
• hero - eight heads tall
• superhero - nine heads tall
• fashion - ten heads tall

Use SDL_GetWindowSize() (some cannot see without syntax highlight) and adjust the tile size accordingly. It is better not using pixel perfect if you want scalable to higher resolution, 4K and up. Remember that there is a maximum resolution in pixel perfect based upon my suggestions of ideal tile size.

Remember that for most humans, we could only see upto 2M resolution. 1K (SD), 2K (HD), 4K (UHD), 8K, 16K, 32K, 64K, 128K, 256K, 512K, 1M, 2M, and a single screen only covers about 1/4 of our horizontal span, so 512K is the maximum resolution that we need to deal with.

• 1K (SD) - 24x24
• 2K (HD) - 40x40
• 4K - 48x48
• 8K - 72x72
• 16K - 96x96
• 32K - 136x136
• 64K - 192x192
• 128K - 264x264
• 256K - 376x376
• 512K - 528x528
• 1M - 744x744
• 2M - 1056x1056 pixel perfect realistic graphics

Visibility is an issue. When screen resolution goes up, the pixel density tends to also go up, so the minimum resolution needs to increase.

When talking about non-pixel perfect, it means to be pixel perfect to the game resolution, but the game resolution is scaled up to the screen resolution. Not all games need to have an extra step in scaling up. Games could be made directly to access the screen resolution.

Of course, with a game resolution, then the resolution is fixed to a certain perspective, and it would scale to most devices. It is common for developers to use 640x360 resolution as a base because it scales to 1280x720 and 1920x1080 in integer increments, so it does not deal with anti-aliasing.


void scale2coordinates( SDL_Window * Window, int & MinimumTileSize )
{
int x, y;
SDL_GetWindowSize( Window, &x, &y );
MinimumTileSize = int( sqrt( float( min( x, y ) ) ) ) + 7 & ~7;
}

void scaleSprite( SpriteStruct Sprite, int MinimumTileSize )
{
SDL_Rect RenderSize = { Sprite.x * MinimumTileSize.y, Sprite, Sprite.WidthInTiles * MinimumTileSize, Sprite.HeightInTiles * MinimumTileSize };
SDL_RenderCopy( Renderer, Sprite.Texture, & Sprite.Rect, & RenderSize );
}


You scale based on the rect's of the sprite and tile size. Look up Render to texture tutorials.

void GetScale( SDL_Window * Window, int & ScaleScreenResolution )
{
int x, int y;
SDL_GetWindowSize( Window, &x, &y );
ScaleScreenResolution= min( x / MinRows, y / MinColumns );
}

void ScaleToScreen( TileStuff, int ScaleScreenResolution, int ScaleTileResolution )
{
ScreenStuff = TileStuff * ScaleScreenResolution / ScaleTileResolution;
}

void ScaleToTiles( ScreenStuff, int ScaleScreenResolution, int ScaleTileResolution )
{
TileStuff = ScreenStuff * ScaleTileResolution / ScaleScreenResolution;
}


Here, Stuff refers to what needs to be scaled to screen and scale to tiles. I assume that most 2D games are tiled based and not using giant bitmaps. I also assume that tiles are squares, but there are rectangular tiles engines as well, so there might need to be separate x and y scales. Also, I assume that not all games are fixed in 4:3 or 16:9 aspect ratio.

Usually the art scale from image to screen, and input is scaled from screen to tiles.

• This is all nice, but I'm not totally sure it is after that that the OP was after. Also, this answer could benefit from explaining why those tiles should be those sizes/proportions. – Vaillancourt Jan 8 at 15:58
• SDL_GetWindowSize() cannot get screen coordinates, game coordinates, or even window coordinates according to Vaillancourt. – Abraham Le Jan 8 at 19:20
• I ain't sure it answers the question, but I like the answer :) – ColdSteel Jan 14 at 11:46