[A5] Fixed Aspect Ratio with Black Bars
Jeremiah Griffin

I am currently reworking an SDL 1.2/OpenGL codebase to use Allegro 5. My artist and I like to keep things simple and easy (for us), so we typically design our games to use a fixed resolution. However, to prevent the display from being stretched to a different aspect ratio, I implemented a fixed aspect ratio with letter/column boxes. This would fit a box of the given aspect ratio inside the display, taking up as much space as possible, and then adding black bars to the top/bottom or left/right as necessary. I used glViewport, glScissor, and glOrtho to accomplish this effect, like so:

float const aspectRatio = (float)VIEW_WIDTH / (float)VIEW_HEIGHT;
int clipWidth = width, clipHeight = width / aspectRatio;
int clipX = 0, clipY = (height - clipHeight) / 2;
if (clipY < 0)
{
    clipHeight = height;
    clipWidth = height * aspectRatio;
    clipX = (width - clipWidth) / 2;
    clipY = 0;
}
glViewport(clipX, clipY, clipWidth, clipHeight);
glScissor(clipX, clipY, clipWidth, clipHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, clipWidth, clipHeight, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);

And like this in Allegro 5:

#SelectExpand
1float const aspectRatio = (float)VIEW_WIDTH / (float)VIEW_HEIGHT; 2int clipWidth = width, clipHeight = width / aspectRatio; 3int clipX = 0, clipY = (height - clipHeight) / 2; 4if (clipY < 0) 5{ 6 clipHeight = height; 7 clipWidth = height * aspectRatio; 8 clipX = (width - clipWidth) / 2; 9 clipY = 0; 10} 11al_set_clipping_rectangle(clipX, clipY, clipWidth, clipHeight); 12 13float scaleX = (float)clipWidth / (float)VIEW_WIDTH, 14 scaleY = (float)clipHeight / (float)VIEW_HEIGHT; 15ALLEGRO_TRANSFORM projection; 16al_build_transform(&projection, clipX, clipY, scaleX, scaleY, 0.0f); 17al_use_transform(&projection);

Now, this works fine, until the size is drastically different from the "view" size (in this case, 736x768). Then my test function starts to fall apart. Literally.

for (float x = 0; x < 32; ++x)
    for (float y = 0; y < 32; ++y)
        al_draw_pixel(x, y, al_map_rgb(rand() % 255, rand() % 255, rand() % 255));

When the scale gets too big, the pixels start to move away from each other. I've attached 2 pictures demonstrating this problem (beware: one of them is rather large). I'm assuming this is due to the way Allegro transforms each individual pixel, and that the issue would go away when using bitmaps--however, I'd like to find a way to do this that works as expected with pixel-level drawing.

P.S. I am new to Allegro as a whole, this being my first time using it, so if anyone knows an all around better way of accomplishing this, I'd love to hear it.

SiegeLord

that the issue would go away when using bitmaps

It does.

Quote:

I'd like to find a way to do this that works as expected with pixel-level drawing.

It depends on what you want to happen when you zoom in. If you want to get big blocky pixels, you should draw pixels with al_draw_rectangle:

void draw_scalable_pixel(float x, float y, ALLEGRO_COLOR col)
{
    al_draw_filled_rectangle(x, y, x + 1, y + 1, col);
}

If not, you'll want to transform the vector representation of your pixel primitve. In this case you'd multiply the 32 in your loops by scaleX and scaleY for x and y respectively and then scale the coordinates you pass to al_draw_pixel:

for (float x = 0; x < 32 * scaleX; ++x)
    for (float y = 0; y < 32 * scaleY; ++y)
        al_draw_pixel(x / scaleX, y / scaleY, al_map_rgb(rand() % 255, rand() % 255, rand() % 255));

Jeremiah Griffin

It never occurred to me to emulate pixels using vertices. Thanks!

Thread #609395. Printed from Allegro.cc