Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Complications when drawing FPS

This thread is locked; no one can reply to it. rss feed Print
Complications when drawing FPS
pryon_
Member #16,596
November 2016

I am working on a Blasteroids clone in Allegro 5 (Win32, MSVC), courtesy of Head First C's last C Lab Project.

So far I've gotten to the point of successfully drawing the spaceship on the display, and I can move it around as well with transformations.

However, when I wanted to add an FPS display in the top right corner, I've hit a roadblock. Apparently, when using al_draw_textf() to display the current FPS, it uses the already set transformations from the spaceship. So when I move the ship, the FPS display moves with it.

I am using separate functions to move the spaceship and to draw the FPS, and they are in different files as well (but the same thread).

I'm guessing this has to do with bitmaps, and everything that I draw on the screen and want to have behaving independently from other objects has to be drawn to their respective bitmaps. (Please correct me if I'm wrong.)

I've gone through the several example programs bundled with Allegro but couldn't find a clean-cut solution as the code in those included extra noise/features that made it difficult to extract the only information that I need. Also learned about hardware and software rendering, and now got confused on which one to use (to be honest I have no idea which one I'm using right now either).

Now unfortunately I don't know too much about bitmaps, hardware/software rendering, etc. to solve this myself, so I ask for your help.

Drawing from spaceship.c:

#SelectExpand
1void draw_spaceship(Spaceship *ship) 2{ 3 ALLEGRO_TRANSFORM transform; 4 al_identity_transform(&transform); 5 al_rotate_transform(&transform, ship->heading); 6 al_translate_transform(&transform, ship->sx, ship->sy); 7 al_use_transform(&transform); 8 al_draw_line(-8, 9, 0, -11, ship->color, 3.0f); 9 al_draw_line(0, -11, 8, 9, ship->color, 3.0f); 10 al_draw_line(-6, 4, -1, 4, ship->color, 3.0f); 11 al_draw_line(6, 4, 1, 4, ship->color, 3.0f); 12}

Relevant parts of main.c:

#SelectExpand
1static ALLEGRO_DISPLAY *display = NULL; 2static ALLEGRO_EVENT_QUEUE *event_queue = NULL; 3static ALLEGRO_TIMER *timer = NULL; 4static ALLEGRO_BITMAP *dbuf = NULL; 5static Spaceship *theShip = NULL; 6static ALLEGRO_FONT *font = NULL; 7 8const float FPS = 60; 9const int screenWidth = 640; 10const int screenHeight = 480; 11 12void init_game(void) 13{ 14 if(!al_init()) 15 abort_game("Failed to initialize allegro"); 16 17 if(!al_install_keyboard()) 18 abort_game("Failed to install keyboard"); 19 20 timer = al_create_timer(1.0 / FPS); 21 if(!timer) 22 abort_game("Failed to create timer"); 23 24 al_set_new_display_flags(ALLEGRO_WINDOWED); 25 display = al_create_display(screenWidth, screenHeight); 26 if (!display) 27 abort_game("Failed to create display"); 28 29 event_queue = al_create_event_queue(); 30 if(!event_queue) 31 abort_game("Failed to create event queue"); 32 33 al_init_font_addon(); 34 35 font = al_create_builtin_font(); 36 if (!font) 37 abort_game("Failed to initialize builtin font"); 38 39 al_register_event_source(event_queue, al_get_display_event_source(display)); 40 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 41 al_register_event_source(event_queue, al_get_keyboard_event_source()); 42} 43 44void drawFPS(double *old_time) 45{ 46 double new_time = al_get_time(); 47 double delta = new_time - *old_time; 48 double fps = (1 / (delta * 1000)) * 1000; 49 al_draw_textf(font, al_map_rgb(255, 255, 255), 0, 0, ALLEGRO_ALIGN_RIGHT, "FPS: %d", (int) fps); 50 *old_time = new_time; 51} 52 53void update_graphics(double *old_time) 54{ 55 // full redraw 56 al_clear_to_color(al_map_rgba_f(0, 0, 0, 0)); 57 draw_spaceship(theShip); 58 // draw bullets 59 // draw asteroids 60 // draw GUI 61 drawFPS(old_time); 62 al_flip_display(); 63} 64 65void init_bitmap(void) 66{ 67 if (!al_init_primitives_addon()) 68 abort_game("Failed to initialize the primitives addon"); 69 70 dbuf = al_create_bitmap(screenWidth, screenHeight); 71 if (!dbuf) 72 abort_game("Failed to create bitmap"); 73 74 al_set_target_bitmap(dbuf); 75 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO); 76 al_draw_bitmap(dbuf, 0.0, 0.0, 0); 77 al_set_target_backbuffer(display); 78} 79 80void game_loop(void) 81{ 82 bool redraw = true; 83 bool isRunning = true; 84 85 init_bitmap(); 86 al_start_timer(timer); 87 theShip = init_spaceship(); 88 89 // initial ship position 90 theShip->sx = screenWidth / 2; 91 theShip->sy = screenHeight / 2; 92 93 double old_time = al_get_time(); 94 95 /* start game loop */ 96 while (isRunning) { 97 ALLEGRO_EVENT event; 98 99 al_wait_for_event(event_queue, &event); 100 101 if (event.type == ALLEGRO_EVENT_KEY_DOWN) 102 // input handling 103 104 else if (event.type == ALLEGRO_EVENT_KEY_UP) 105 // input handling 106 107 else if (event.type == ALLEGRO_EVENT_TIMER) { 108 redraw = true; 109 // acting on input 110 } 111 112 else if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 113 isRunning = false; 114 115 if (redraw && al_is_event_queue_empty(event_queue)) { 116 redraw = false; 117 update_graphics(&old_time); 118 } 119 } 120}

Any help would be greatly appreciated! :)

Rodolfo Lam
Member #16,045
August 2015

Make a new identity transform, and use it for your fps code. To allegro it does not matter if you have drawing code on different places. All of them share the same transformation. If you change it on one part of your code, all the next drawing calls will use the new one.

By making a new identity transform, you are resetting the transform. It does not matter you lost the previous one because your spaceship will create a new one in its drawing code.

By the looks of it, you are using hardware rendering. Software rendering uses the CPU, and Hardware uses the GPU. Allegro 4 used software, Allegro 5 by default uses hardware. If you try really hard, you can use software on 5… but it will be really slow.

pryon_
Member #16,596
November 2016

Thank you for your answer!

I added a new transformation and everything works perfectly now. Apparently I was wrong with the bitmap theory.

I'm guessing this also means that I don't need to create a bitmap for each asteroid/blast, I just need separate transformations for each of them, which is really good news.

Edgar Reynaldo
Member #8,592
May 2007
avatar

More specifically, there are two active transformations in use at any one time. They are linked to the target bitmap. When you change the target bitmap, you change the transformations. There is a view transform, and a projection transform for each bitmap.

You can draw each asteroid with it's own transformation, but you can achieve the same thing through regular allegro functions like al_draw_rotated_bitmap and the like...

Go to: