Writing a game loop
kenmasters1976

I'm writing a skeleton for use in SpeedHack and I'm wondering if what I have so far is a good way of doing it as it is really the first time I'm using events instead of states. Basically the main loop looks like this right now:

#SelectExpand
1init(); 2 3while (!game_over) { 4 timer_count = al_get_timer_count(timer); 5 while (timer_count > 0) { 6 mode_count++; 7 // Cheap FPS calculator 8 if (mode_count % 30 == 0) { 9 fps = frame_count - pframe_count; 10 pframe_count = frame_count; 11 } 12 // Logic goes here 13 if (!al_is_event_queue_empty(key_events)) { 14 al_get_next_event(key_events, &event); 15 if (event.type == ALLEGRO_EVENT_KEY_UP && event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 16 game_over = TRUE; 17 if (event.type == ALLEGRO_EVENT_KEY_UP && event.keyboard.keycode == ALLEGRO_KEY_SPACE) 18 al_rest(2); 19 } 20 timer_count--; 21 al_add_timer_count(timer, -1); 22 } 23// Drawing goes here 24 al_clear_to_color(al_map_rgb(0, 128, 128)); 25 al_draw_textf(font, al_map_rgb(255, 255, 255), 0, 0, 0, "%d total frames (%d FPS)", frame_count, fps); 26 al_flip_display(); 27// If the timer event queue is empty, take a rest 28 al_wait_for_event(timer_events, NULL); 29 al_flush_event_queue(timer_events); 30 31 frame_count++; 32}

The init() function does basic initialization tasks. It also sets a timer and creates two event queues, one for the keyboard and one for the timer. The thing is that I'm using the timer event queue only to check when I can let the application take a rest and that might be consider as a waste but I couldn't figure a better solution.

So, does this look as a good game loop?. I'm attaching the full code and all necessary files so that you can try it if you want. As you can see, in the logic part I added some simple checks; Escape quits the program and I added Space to simulate a logic step taking a long time to see how it works.
If you try it, let me know if the fps was steady and the CPU usage on your machine. Oh, and it should run at 30 fps as the value is hardcoded right now.

kazzmir

Except you shouldn't draw when the timer counter is 0 because you are just redrawing a world that hasn't changed.

ok sorry, i guess the wait for event thing takes care of that.

Thomas Fjellstrom
al_wait_for_event(timer_events, NULL);
al_flush_event_queue(timer_events);

Wait what? So first you wait for an event, then you ignore it? Is that really what you want to do?

The following from the wiki tutorial might make more sense: (note that a timer is setup to send an event 60 times a second)

#SelectExpand
1 while(1) 2 { 3 ALLEGRO_EVENT ev; 4 al_wait_for_event(event_queue, &ev); 5 6 if(ev.type == ...) { 7 ... 8 } 9 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 10 break; 11 } 12 13 if(redraw && al_is_event_queue_empty(event_queue)) { 14 redraw = false; 15 16 al_clear_to_color(al_map_rgb(0,0,0)); 17 18 al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0); 19 20 al_flip_display(); 21 } 22 }

kenmasters1976

Wait what? So first you wait for an event, then you ignore it? Is that really what you want to do?

That part was exactly what I found to be a bit odd in my code. I wanted the loop to don't waste CPU unnecessarily. And since it is the first time I'm actually using events I was lost.
Thanks for pointing out the wiki tutorial. I guess I should have looked there in the first place. I'm going to check it and adapt the changes to my code.

Thanks again.

Thread #607799. Printed from Allegro.cc