Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Using timers

This thread is locked; no one can reply to it. rss feed Print
Using timers
Vanneto
Member #8,643
May 2007

Hello!

Is there any comprehensive tutorial on how to use timers? Im making a space-invaders style game and I need to know how to use them... But the current tutorials arent helping. Should I post the code?

Thanks!

In capitalist America bank robs you.

miran
Member #2,407
June 2002

Almost all you need to know:

1int timer;
2void timer_f() {
3 ++timer;
4}
5 
6int main() {
7 ...
8 install_timer();
9 install_int_ex(timer_f, BPS_TO_TIMER(100));
10 timer = 0;
11 
12 while (!done) {
13 // this will happen 100 times per second
14 while (timer) {
15 do_logic();
16 --timer;
17 }
18 
19 draw_stuff();
20 }
21 ...
22}

EDIT: Made sure timer is 0 before entering the main loop.

--
sig used to be here

spellcaster
Member #1,493
September 2001
avatar

Just make sure to set "timer" to 0 before entering the loop shown above.

--
There are no stupid questions, but there are a lot of inquisitive idiots.

Vanneto
Member #8,643
May 2007

Can you manage how many times a second should the loop go?

EDIT: Yeah im stupid. Found that out! Thanks!

In capitalist America bank robs you.

spellcaster
Member #1,493
September 2001
avatar

Yes.
Try clicking the function name in the source code below:

install_int_ex(timer_f, BPS_TO_TIMER(100));

--
There are no stupid questions, but there are a lot of inquisitive idiots.

Vanneto
Member #8,643
May 2007

What if I have such code:

        while(!key[KEY_ESC])
        {
            while(timer)
            {
                // Print and Clear the buffer so no 'drawing' occurs
                blit(buffer, screen, 0,0,0,0,SCREEN_W,SCREEN_H);
                clear_bitmap(buffer);

                // Timer...
                timer--;
            }
        }

If I press escape I cant get out. Should I do it like this:

while(timer || !key[KEY_ESC])
{
    /// code .......
}

Because if I press ESCAPE more times and it doesent work the program will crash.
Any suggestions?

P.S. My timer functions are like those above in miran's example. I set the timer to 0 before the loop. I used LOCKED_FUNCTION,LOCK_VARIABLE and END_OF_FUNCTION appropriately..

In capitalist America bank robs you.

spellcaster
Member #1,493
September 2001
avatar

What you want to do is something like this:

1while (running ) {
2 
3 if (timer) {
4 int maxSkip = 4;
5 while(timer && maxSkip) {
6 // logic
7 --timer;
8 --maxSkip;
9 }
10 } else {
11 // good place to return some time to the system
12 // not sure what's currently the best way to do it,
13 // so check if this is still ok:
14 rest(0);
15 }
16 
17 running = ! key[KEY_ESC];
18}

Normally, your code above should also work, unless your computer is very slow.

--
There are no stupid questions, but there are a lot of inquisitive idiots.

miran
Member #2,407
June 2002

Don't put drawing code in the timed section! You only need to keep the logic rate down to 100 FPS (or whatever) but draw as many times as possible (or cap to logic framerate if you want). What happens with your code is that your computer isn't fast enough to draw 100 frames per second (remember, this is fullscreen software blitting), so the timer callback does ++timer faster than you can do --timer which means you never break out of the inner while. The solution is to add a check inside the inner while to see if the value of timer is some high unexpected number and if it is, reset it to 0 and break out of the while (effectively dropping frames). But unless you do some heavy processing in the timed section, this should never happen (except in situations you can't control, like some other program stealing the CPU or something).

In code this would look like this:

1while(!key[KEY_ESC])
2{
3 while(timer)
4 {
5 get_player_input();
6 run_physics_engine();
7 do_ai_processing();
8 etc();
9 
10 // Timer...
11 timer--;
12 
13 scene_needs_to_be_redrawn = true;
14 
15 if (timer > frame_drop_threshold) // like 20 or something
16 {
17 timer = 0;
18 break;
19 }
20 }
21 
22 if (scene_needs_to_be_redrawn) {
23 clear_bitmap(buffer);
24 draw_scene_to(buffer);
25 
26 // blast the buffer onto the visible screen
27 blit(buffer, screen, 0,0,0,0,SCREEN_W,SCREEN_H);
28 
29 scene_needs_to_be_redrawn = false;
30 }
31}

Now that's really almost all you need. All that's missing now is giving up the CPU when you can so you don't eat 100% and maybe handle the window close icon click and that's it as far as the main loop is concerned.

EDIT: Beaten by spellcaster. His code is a little better too... :-X

--
sig used to be here

spellcaster
Member #1,493
September 2001
avatar

Quote:

EDIT: Beaten by spellcaster.

But I forgot to mention the that he needs to separate logic and drawing. So let's call it a draw ;)

EDIT:
Could somebody reply in the transitions thread? I need to post the examples on how to use the fade code ;)

--
There are no stupid questions, but there are a lot of inquisitive idiots.

miran
Member #2,407
June 2002

Quote:

Could somebody reply in the transitions thread? I need to post the examples on how to use the fade code

Done. But you can click "send to top" if it's been more than an hour and it will go to the top anyway. I think.

--
sig used to be here

spellcaster
Member #1,493
September 2001
avatar

The problem was that my last post in that thread got too big. And I still wanted to post the examples. Since I can't double-post, I needed somebody to post in between ;)

--
There are no stupid questions, but there are a lot of inquisitive idiots.

Vanneto
Member #8,643
May 2007

Now, the code works fine. But I have a problem. When I press Escape, the program exits. But then, I dont know if it exits like exits, or if it crashes. When I press ESC the program exits and then the "This application has encountered ... and must close..." message appears.

I have included all the source if someone can find the problem. Im still looking...

Thanks!

In capitalist America bank robs you.

miran
Member #2,407
June 2002

Your program crashes, that's what getting that dialog means. No one will go through your code for you though...

--
sig used to be here

Vanneto
Member #8,643
May 2007

No, mogoče pa bi bil kdo dovolj nor... :D

Anyways im gonna keep looking. Thanks for the help with the timers miran & spellcaster! :)

In capitalist America bank robs you.

miran
Member #2,407
June 2002

:o:o:o Uuu, končn spet en Slowenc tuki gor! :o:o:o

EDIT:

Problem:

    destroy_bitmap(title_image);
    unload_datafile(data);

Ne smeš uničit podatkov iz datafilea, ker unload_datafile() to naredi avtomatsko in potem sproščaš en in isti pointer dvakrat in potem se program sesuje.

English: You mustn't destroy data that was loaded from a datafile because unload_datafle() does that automatically. If you do that, you destroy the same pointer twice which crashes your program.

--
sig used to be here

Vanneto
Member #8,643
May 2007

Ni kaj, bom še kr nekaj časa tu! :)
Kak me razjezijo take napake!! Pa tak se skrije! Hvala ti!

Thanks for the help miran, I wouldnt spot the bug whitout you! :)

In capitalist America bank robs you.

Kibiz0r
Member #6,203
September 2005
avatar

I see you two have everything under control...

I think timer should be volatile int, not just int.
Shouldn't there be END_OF_FUNCTION() in there?
Also, LOCK_VARIABLE and LOCK_FUNCTION...

I don't know what the last two truly do, but the manual says to use them... That's usually a bad reason to do anything, though.

Vanneto
Member #8,643
May 2007

I have added END_OF_FUNCTION,LOCK_VARIABLE and LOCK_FUNCTION!

In capitalist America bank robs you.

Onewing
Member #6,152
August 2005
avatar

Quote:

I don't know what the last two truly do, but the manual says to use them...

As far as I know, the LOCK_whatever calls are used because when you install the timers, you're creating a hardware interrupt. So, at a given interval, the hardware takes over and runs whatever functions/variables used in the install. I assume the LOCK_whatever calls help protect bad things from happening in this process (don't want other things fiddling with this portion of memory). So, really, it's just good practice.

I could be wrong though...

------------
Solo-Games.org | My Tech Blog: The Digital Helm

Matthew Leverton
Supreme Loser
January 1999
avatar

MacOS 9 and DOS are the only platforms that need the macros. The #defines are empty for all other platforms.

From allegro/platform/aldjgpp.h:

#define END_OF_FUNCTION(x)          void x##_end(void) { }
#define END_OF_STATIC_FUNCTION(x)   static void x##_end(void) { }
#define LOCK_DATA(d, s)             _go32_dpmi_lock_data((void *)d, s)
#define LOCK_CODE(c, s)             _go32_dpmi_lock_code((void *)c, s)
#define UNLOCK_DATA(d,s)            _unlock_dpmi_data((void *)d, s)
#define LOCK_VARIABLE(x)            LOCK_DATA((void *)&x, sizeof(x))
#define LOCK_FUNCTION(x)            LOCK_CODE((void *)x, (intptr_t)x##_end - (intptr_t)x)

aadfo824
Member #7,265
May 2006

I've implemented the interupt timing system and it works to keep the logic control. However, I get those nasty looking vertical refresh lines. Shouldn't the drawing also be slowed down? If not, do I have to use vsync() shudders?

Go to: