-
Notifications
You must be signed in to change notification settings - Fork 8
Porting Allegro 4 to 5
Incomplete: This article is incomplete and needs some revision or has some pending TODOs. Please help by editing and finishing it. When the article becomes complete, you may remove this block.
Versions of Allegro 4.9.19 and greater started shipping with a basic compatibility layer that translates Allegro 4 function calls (actually rewrites the functions) into Allegro 5 calls. The files are located in demos/speed and are named a4_aux.c and a4_aux.h. These could be helpful porting aids. The game "Speed" written by Shawn Hargreaves for Speedhack 1999 has been ported (as you may have already guessed) to Allegro 5 using this thin wrapper. Check out the source releases or svn for these files.
Just like with A4, also in A5 the developers try to maintain a high quality and up-to-date reference manual - it always should be your first stop to look up how something is supposed to work: http://liballeg.org/a5docs/trunk
Your A4 mainloop likely looked like:
volatile int ticks;
void timer(void) {ticks++;}
...
install_int(timer, 1000.0 / FPS);
...
while (1) {
if (game_ticks < ticks) {
poll_input();
handle_game_tick();
game_ticks++;
need_redraw = true;
}
else if (need_redraw) {
render_last_frame();
need_redraw = false;
}
rest(1);
}
With various variations as how to handle frame skipping and other things. The main points are that input was polled, timing was done by installing a timer, and the loop was constructed so rest(1) would be executed whenever nothing else was to do.
With A5, everything is events based, so you would do something like:
al_install_timer(1.0 / FPS);
...
while (1) {
al_wait_for_event(queue, &event);
/* handle input events */
if (event.type == ALLEGRO_EVENT_TIMER) {
handle_game_tick();
need_redraw = true;
}
if (need_draw && al_event_queue_is_empty(queue)) {
render_last_frame();
need_redraw = false;
}
}
Once you understand what is happening, this is a much cleaner solution. Whenever any input occurs, you get an event instantly. So you could have more fine-controlled input handling than in A4, or otherwise just collect input until the next game tick so it would work like A4. Similar, you get an event now at the exact time the timer ticks. There is no more need for something like rest(1), as your program will not even run as long as there are no events (al_wait_for_event will only return once there is a new event). There are again various ways to deal with frame skipping and other things - everything possible in A4 is still possible in A5.
A5 uses floating point coordinates. While it needs some time to get used to, it often leads to clearer code, and is the only way to properly deal with sub-pixel accuracy (which was impossible with A4).
A detailed explanation can be found at in the manual.
All graphics are blitted to the last selected target bitmap, which you can change with:
al_set_target_bitmap(bmp)
Some general changes:
- Colors:
int color = makecol(r, g, b)
will beALLEGRO_COLOR color = al_map_rgb(r, g, b)
- Components of color:
r = getr(color); g = getg(color); b = getb(color)
will beal_unmap_rgb(color, &r, &g, &b);
- Change pixel:
putpixel(bmp, x, y, c)
will be `al_put_pixel(x, y, c) - Clear bitmaps:
clear(bmp);
will beal_clear_to_color(al_map_rgb(0, 0, 0))
You need the primitives addon, to draw following figures. To run the code, you need initialize it before: