I have a couple of sprites with simple animation: just 3 different frames.
Just to test if it works, I written a test program in which, inside a loop I do
vsync(); rest(80); draw_sprite(...);
Everything goes right, the animations change with regularity and the effect is enough for me.
Naturally, in the final game there will not be any vsync() and rest().
I'm wondering if installing a timer with MSECS_TO_TIMER(80) will be precise enough or if there's another way to do that.
Basically the timer will increase the index in the sprite's array.
Courtesy of Chris Barry, a generic timing framework for games:
1 | volatile int game_time = 0; |
2 | |
3 | ..... |
4 | |
5 | // Timer function |
6 | |
7 | void Timer(void) |
8 | { |
9 | game_time++; |
10 | }END_OF_FUNCTION(Timer); |
11 | |
12 | ..... |
13 | |
14 | int main() |
15 | { |
16 | // standard initialization |
17 | |
18 | allegro_init(); |
19 | install_keyboard(); |
20 | set_color_depth(16); |
21 | set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0); |
22 | |
23 | // usual timer setup |
24 | |
25 | LOCK_VARIABLE(game_time); |
26 | LOCK_FUNCTION((void*)Timer); |
27 | install_int_ex(Timer, BPS_TO_TIMER(120)); |
28 | |
29 | // the game loop |
30 | |
31 | do{ |
32 | while(game_time > 0) |
33 | { |
34 | // all game logic goes here |
35 | |
36 | |
37 | // necessary for keeping time |
38 | |
39 | game_time--; |
40 | } |
41 | |
42 | // all drawing code goes here |
43 | |
44 | |
45 | }while(!key[KEY_ESC]); // end of game loop |
46 | |
47 | |
48 | return 0; |
49 | }END_OF_MAIN() |
So you should only increase the sprite array num in the logic section of the code. Not in the timer routine, that should only increase the timer variable..
There have been many threads on timing, do a search on these forums if this code doesn't help you.
mmh... actually I was wondering if a timer in MSECS_TO_TIMER(80) does the same job (but better) as rest(80)...
ALWAYS use a timer over rest.
where as rest only pauses the program for n milliseconds, a timer calls a certain function n times per second, (in this case) increasing a variable that can then be used universially through your program for time-based operations.
rest wont actually make programs run the same speed at all computers either. The only(?) use for rest is to give back unused CPU cycles to the OS.
rest() used to be useful in the pre-multi-tasking era, when a single process occupied the whole machine. In those golden DOS days, rest() was sometimes used for actual resting.
Naturally, in the final game there will not be any vsync() and rest().
I'm wondering if installing a timer with MSECS_TO_TIMER(80) will be precise enough or if there's another way to do that.
Sometimes I feel you just red something else... sorry for that.
I suppose all your posts mean "Yes, that timer will do what rest() did in your test code".
Thanks
Uhm, no. Rest does not do the same thing as a timer would. Rest pauses the program, then executes the "frame" as normal. timer would (in some manner, depending on design) limit/control how often the frame is updated. Timer would give the same result (or near enough) on all computers, while rest would not (as it still takes diferent amount of time to execute the rest of the code depending on the computer it's run on etc)
Let me re-explain it, only this time.
I have a sprite with 3 animation frames. While testing other things I had to understand how many milliseconds should pass between one frame and another.
To speed up the testing I didn't go with setting timers and decide how to handle that specific animation, because halting the loop with rest(), a loop which just draws the sprite's frames, will be enough to understand if I should change frame every 80 milliseconds or 50 milliseconds or x milliseconds.
Now that the test has been done, I'll have to design the whole program.
It will naturally use a timer to handle overall speed, like Richard suggested and in the way it is described in the Allegro FAQ, so I'm not going to use rest() to wait to change the frame.
Beside that timer I'm thinking about a specific timer which will tick every 80 milliseconds (that's why I asked if a timer with MSECS_TO_TIMER(80) will be precise enough) to change the actual frame.
There are two different sprites and each has a three-frame animation, so that timer should be good. I think I should not change the animation frame during the logic cycle, because it may result in too fast animation or too slow logic updating, but then I'll see the results in the playtesting stage.
Again, thank you all for the help
So you're all set? Question dealt with?
No more, right now
Beside that timer I'm thinking about a specific timer which will tick every 80 milliseconds (that's why I asked if a timer with MSECS_TO_TIMER(80) will be precise enough) to change the actual frame.
You don't really need that. The best idea IMHO is to make the game logic independent from timer rate. Make a timer function that executes every n milliseconds, and increments a counter by n. This way, the counter will contain the number of milliseconds since the last check. Use this timer to update your logic*. You can always change n, with no real side-effect on the logic, except that with lower timer rates gameplay will become laggy and less fluid, while higher timer rates may increase system load. For the graphics update, I think the best plan is to lock in with the vertical retrace. This gives the smoothest results. How you do that depends on platform and buffer method.
Two options: Either make a variable-delta logic update, or do:
(while counter >= logic_delay) { update_logic(); counter -= logic_delay; }