The Allegro Wiki is migrating to github at

Achieving Resolution Independence

From Allegro Wiki
Jump to: navigation, search

This tutorial will teach you two techniques to achieve resolution independence using Allegro 5.

By resolution independence we mean that, for example, if you design your game for a resolution of 640x480 and you want to support fullscreen resolutions it shouldn't matter what resolution the player actually uses, you just stretch the intended resolution of 640x480 so it fits with whatever resolution the player is using.

These techniques of course also applies to whether you simply want a low resolution but want to stretch it in a windowed display too. For example, if you're designing a retro game with a target resolution of 320x240 and want the game to be windowed at a size of say 800x600, then you do basically the same things as described below.

Using transformations

This technique is preferred if your game is using a lot of primitives.

We create a fullscreen windowed display, which means that we create a window that covers the entire screen and thus automatically using the user's native resolution. We then calculate the scaling factors (sx and sy) by dividing the width and height of the created display by the width and height of the resolution we're designing the game for. Then we scale the display using a transformation. This needs to only be done once during initialization.

display = al_create_display(windowWidth, windowHeight);

windowWidth = al_get_display_width(display);
windowHeight = al_get_display_height(display);
int screenWidth = 640;
int screenHeight = 480;

float sx = windowWidth / (float)screenWidth;
float sy = windowHeight / (float)screenHeight;

al_scale_transform(&trans, sx, sy);

Using a stretched buffer

This technique is preferred if your game is using a lot of bitmaps.

We make use of a bitmap buffer which we then scale to cover the screen using al_draw_scaled_bitmap(). We need some more complex scaling calculations here, as we're essentially doing something called letterboxing. We can't just stretch the buffer onto the entire resolution as a game designed for 4:3 screens will look weird on widescreens and vice versa. Thus, we calculate the maximum we can stretch the buffer - and if it doesn't fit the entire screen then we're simply left with black bars on top and bottom and/or left and right.

// initialization
display = al_create_display(windowWidth, windowHeight);
buffer = al_create_bitmap(screenWidth, screenHeight);

// calculate scaling factor
int sx = windowWidth / screenWidth;
int sy = windowHeight / screenHeight;
int scale = std::min(sx, sy);

// calculate how much the buffer should be scaled
scaleW = screenWidth * scale;
scaleH = screenHeight * scale;
scaleX = (windowWidth - scaleW) / 2;
scaleY = (windowHeight - scaleH) / 2;

So, the last four variables are what we use when we update the screen every frame:

// render a frame
al_clear_to_color(al_map_rgb(0, 0, 0));
// draw everything in between here
al_clear_to_color(al_map_rgb(0, 0, 0));
al_draw_scaled_bitmap(buffer, 0, 0, screenWidth, screenHeight, scaleX, scaleY, scaleW, scaleH, 0);