![]() |
|
Strange frame skipping |
Frank Drebin
Member #2,987
December 2002
![]() |
Hey guys, please take a look at the following demonstration code and tell me if you get the same result as I do (tested on Win10): 1#include <allegro5/allegro.h>
2
3int delay=0;
4bool draw=0;
5bool quit=0;
6
7int main(int argc,char** argv)
8{
9 al_init();
10 al_install_mouse();
11
12 ALLEGRO_EVENT event;
13 ALLEGRO_MOUSE_STATE mouse;
14 ALLEGRO_DISPLAY* display=al_create_display(640,480);
15 ALLEGRO_EVENT_QUEUE* queue=al_create_event_queue();
16 ALLEGRO_TIMER* timer=al_create_timer(0.01);
17 al_start_timer(timer);
18 al_register_event_source(queue,al_get_timer_event_source(timer));
19
20 while (!quit)
21 {
22 al_wait_for_event(queue,&event);
23
24 if (event.timer.source==timer)
25 {
26 draw=0;
27 if (delay>0) delay--;
28
29 al_get_mouse_state(&mouse);
30 if ((al_mouse_button_down(&mouse,1)) && (delay==0))
31 {
32 draw=1;
33 delay=10;
34 }
35 if (al_mouse_button_down(&mouse,2)) quit=1;
36 }
37
38 if (al_is_event_queue_empty(queue))
39 {
40 al_clear_to_color(al_map_rgb(0,0,0));
41 if (draw) al_clear_to_color(al_map_rgb(0,128,0));
42 al_flip_display();
43 }
44 }
45
46 al_destroy_display(display);
47 al_destroy_event_queue(queue);
48 al_destroy_timer(timer);
49
50 return 0;
51}
So what this code should do is to show a green blinking screen if you hold down the left mouse button. When I hold down the left mouse button for some seconds, release it and start all over I get: Any idea what's going on here? |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
You should always redraw on the timer event, and then set redraw to false. Easier logic would be : 1while (have_events) {
2 if (timer_event) {
3 if (blink) {
4 green = !green;
5 }
6 redraw = true;
7 }
8 if (mouse_event) {
9 blink = mouse_button_down();
10 }
11}
12if (redraw) {
13 draw();
14 redraw = false;
15}
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Frank Drebin
Member #2,987
December 2002
![]() |
OK, your approach would avoid this effect. However, as I understand it (maybe I'm missing something |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
The approach you used is bad because if you have multiple timer events in the queue, they can skip the draw = 1 call and you don't turn green. If you get a timer event (a draw timer) then redraw. Process all the remaining events first and limit your logical update call to once per graphic frame. That will slow down gracefully if you get too many timer events, and won't skip any frames. Or process all your logic at once, thus possibly skipping frames and then redraw. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Izual
Member #2,756
September 2002
![]() |
You could also make it without polling the mouse. With events only. I have edited your code to add extra color to the flashing effect. Added another timer to the mix. 1#include <stdbool.h>
2#include <stdio.h>
3
4#include "allegro5/allegro.h"
5
6enum
7 {
8 MY_DELAY = 10
9 };
10
11int delay;
12
13bool draw = false;
14bool quit = false;
15bool b1 = false;
16
17ALLEGRO_COLOR color;
18
19int main(int argc,char** argv)
20 {
21 al_init();
22 al_install_mouse();
23
24 ALLEGRO_EVENT event;
25
26 ALLEGRO_DISPLAY* display=al_create_display(640,480);
27 ALLEGRO_EVENT_QUEUE* queue=al_create_event_queue();
28
29 ALLEGRO_TIMER* draw_timer = al_create_timer( 1.0 / 60.0 );
30 ALLEGRO_TIMER* other_timer = al_create_timer( 1.0 / 3.0 );
31
32 al_register_event_source(queue,al_get_timer_event_source(draw_timer));
33 al_register_event_source(queue,al_get_timer_event_source(other_timer));
34
35 al_register_event_source( queue, al_get_mouse_event_source() );
36
37 al_start_timer( draw_timer );
38 al_start_timer( other_timer );
39
40 while( !quit )
41 {
42 al_wait_for_event(queue,&event);
43
44 switch( event.type )
45 {
46 case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
47 if( event.mouse.button == 1 )
48 {
49 b1 = true;
50 delay = MY_DELAY;
51 color = al_map_rgb( 0, 128, 0 );
52 }
53
54 if( event.mouse.button == 2 )
55 quit = true;
56 break;
57
58 case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
59 if( event.mouse.button == 1 )
60 b1 = false;
61 break;
62
63 case ALLEGRO_EVENT_TIMER:
64 // Some other timer to do someting:
65 if( event.timer.source == other_timer )
66 {
67 printf( "Other timer ticked! Count = %ld\n", event.timer.count );
68 }
69
70 // Handle draw timer:
71 if( event.timer.source == draw_timer )
72 {
73 draw = true;
74
75 // Handle delay:
76 if( b1 )
77 {
78 if( delay > 0 )
79 delay--;
80 else
81 {
82 unsigned char r, g, b;
83
84 delay = MY_DELAY;
85
86 al_unmap_rgb( color, &r, &g, &b );
87
88 if( g != 0 )
89 color = al_map_rgb( 128, 0, 0 );
90 else
91 color = al_map_rgb( 0, 128, 0 );
92 }
93 }
94 }
95 break;
96
97 default:
98 /*
99 // Unhandled events:
100 printf( "Unhandled event type %d!\n" );
101 */
102 break;
103 }
104
105 // Draw stuff if we can:
106 if( draw && al_is_event_queue_empty( queue ) )
107 {
108 draw = false;
109
110 if( b1 )
111 al_clear_to_color( color );
112 else
113 al_clear_to_color( al_map_rgb( 0, 0, 0 ) );
114
115 al_flip_display();
116 }
117 }
118
119 al_destroy_display(display);
120 al_destroy_event_queue(queue);
121 al_destroy_timer(draw_timer);
122 al_destroy_timer( other_timer );
123
124 return 0;
125}
|
Frank Drebin
Member #2,987
December 2002
![]() |
Edgar, I see pros and cons for both approaches. I'm migrating from Allegro 4 where I am used to have frames skipped How_can_I_make_my_game_run_at_the_same_speed_on_any_computer_ and when using Allegro 4 this maked sense for me. I'm going to rethink that now working with Allegro 5... By the way, I still don't understand why in my approach the flashing is not visible sometimes event when some frames are skipped. If you modify the example and add one line to indicate frame skipping like this: if (al_is_event_queue_empty(queue)) { al_clear_to_color(al_map_rgb(0,0,0)); if (draw) al_clear_to_color(al_map_rgb(0,128,0)); al_flip_display(); } else printf("Frame skipped\n"); you'll see that frames are skipped rarely, but the flashing occurs 10 times per second so at a much higher frequency than frames are skipped so that's the strange thing for me. Izul, your approach looks quite similar to what Edgar suggested... [EDIT] 1#include <stdio.h>
2#include <allegro5/allegro.h>
3int delay=0;
4bool draw=0;
5bool quit=0;
6
7int main(int argc,char** argv)
8{
9 al_init();
10 al_install_mouse();
11 ALLEGRO_EVENT event;
12 ALLEGRO_MOUSE_STATE mouse;
13 ALLEGRO_DISPLAY* display=al_create_display(640,480);
14 ALLEGRO_EVENT_QUEUE* queue=al_create_event_queue();
15 ALLEGRO_TIMER* timer=al_create_timer(0.01);
16 al_start_timer(timer);
17 al_register_event_source(queue,al_get_timer_event_source(timer));
18
19 while (!quit)
20 {
21 al_wait_for_event(queue,&event);
22
23 if (event.timer.source==timer)
24 {
25 draw=0;
26 if (delay>0) delay--;
27
28 al_get_mouse_state(&mouse);
29 if ((al_mouse_button_down(&mouse,1)) && (delay==0))
30 {
31 draw=1;
32 delay=10;
33 }
34
35 if (al_mouse_button_down(&mouse,2)) quit=1;
36 }
37
38 if (al_is_event_queue_empty(queue))
39 {
40 al_clear_to_color(al_map_rgb(0,0,0));
41 printf(".");
42 if (draw)
43 {
44 al_clear_to_color(al_map_rgb(0,128,0));
45 printf("D");
46 }
47 al_flip_display();
48 }
49 else printf("FRAME SKIPPED\n");
50 }
51
52 al_destroy_display(display);
53 al_destroy_event_queue(queue);
54 al_destroy_timer(timer);
55 return 0;
56}
What I see is that "D" is printed to the console without blinking screen |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
You have two options - run one graphical frame per logical frame, slowing down gracefully, or run one graphical frame for all logic ticks, skipping frames. If there is more than one timer event when delay reaches zero, draw will be set to 1 in the first event, and then set to 0 in the second event, as if it never happened. You're skipping frames when you don't need to. I ran your latest example. I think it's probably just a case of unsynced output. I get 'D.......D.......D.......' too, and the green flash isn't visible sometimes. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Frank Drebin
Member #2,987
December 2002
![]() |
OK guys, I think I figured it out by playing around with the ALLEGRO_VSYNC option: Everything is actually drawn, however, sometimes it is not visible on the screen because Vsync is disabled by default. Therefore it may or may not happen that the green screen that should be shown for one frame only is "skipped" by the monitor refreshing. In any case, thanks for your input [EDIT] Edgar Reynaldo said: I think it's probably just a case of unsynced output OK somebody was faster than me... |
Chris Katko
Member #1,881
January 2002
![]() |
Aliasing: {"name":"alias.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/5\/d54a0a82e57d58d59ccbe5a77e9e25a5.png","w":477,"h":248,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/5\/d54a0a82e57d58d59ccbe5a77e9e25a5"} Notice how if you look at the red dots, it appears to be a lower frequency. -----sig: |
|