Archived

This topic is now archived and is closed to further replies.

cow_in_the_well

fps independant sprite animation

Recommended Posts

I''m using timeGetTime () function for timing. i''m using a float to increase bit by bit and gets rounded to an int (i dunno, whats the ''best'' way?) (this ain''t doing looping yet)
  
// updates the frame according to frame rate


// get time difference

DWORD delta_time = timeGetTime () - Sprite->last_frame_time;

// increase the float frame count

Sprite->fcurrentframe += (float)Sprite->frame_rate / (float)delta_time;

Sprite->current_frame = (int)Sprite->fcurrentframe;
  
yes, i know i should be watching out for a divide by zero there suggestions? comments? post here! ----------------------------- -cow_in_the_well ''When in doubt, empty your magazine.'' - Murphy''s Combat Law

Share this post


Link to post
Share on other sites
I'd store the last_frame_time as a float or you will have some minor consistency problems, take the difference and then round to figure out the framte.

Actually, I wouldn't store the last_frame_time, I'd store the first_frame_time, and dead reckon the current frame based off a frames_per_time rate, which eliminates the dangerous / and replaces it with * for the animation.


If you're in a 3D world, and want to step it up another notch, instead of building frames of animation, calculate the positioning of the object based on parametric time functions - skeletal animation.

Edited by - Magmai Kai Holmlor on January 27, 2001 9:59:06 PM

Share this post


Link to post
Share on other sites
Here is a timing related question for you:

Suppose I am calling timeGetTime every frame, checking it to see if it is more than or equal to than say, 30ms later than when I drew the last frame. Will timeGetTime reset after a certain period of time and start back at zero?

Never cross the thin line between bravery and stupidity.

Share this post


Link to post
Share on other sites
quote:
Original post by Magmai Kai Holmlor

I''d store the last_frame_time as a float or you will have some minor consistency problems, take the difference and then round to figure out the framte.

Actually, I wouldn''t store the last_frame_time, I''d store the first_frame_time, and dead reckon the current frame based off a frames_per_time rate, which eliminates the dangerous / and replaces it with * for the animation.

If you''re in a 3D world, and want to step it up another notch, instead of building frames of animation, calculate the positioning of the object based on parametric time functions - skeletal animation.



uhh...so you would use the QueryPerformanceCounter stuff instead so 60ms would be 0.006seconds?
could you elaborate a bit more about first_frame_time and the dead reackoning stuff?
oh, and this is just 2d stuff

quote:
Original post by Moe

Will timeGetTime reset after a certain period of time and start back at zero?




yeah, after windows has been running for 2^32 milliseconds which is approximately uhh...49.71 days...d''you reackon windows could run that long without crashing?





-----------------------------
-cow_in_the_well

''When in doubt, empty your magazine.'' - Murphy''s Combat Law

Share this post


Link to post
Share on other sites
This:

Sprite->fcurrentframe += (float)Sprite->frame_rate / (float)delta_time;

should be

Sprite->fcurrentframe += (float)Sprite->frame_rate * (float)delta_time;

And no more problems . (just look at the new formula: now bigger delta_time leads in bigger adding)

Share this post


Link to post
Share on other sites
uhm....

say Sprite->frame_rate == 10;
and delta_time = timeGetTime () - Sprite->last_frame_time = say about 50;
and Sprite->fcurrentframe == 1.0;

therefore
Sprite->fcurrentframe += (float)Sprite->frame_rate / (float)delta_time;

results in fcurrentframe being 501.0....i don''t think thats 10 frames per second



-----------------------------
-cow_in_the_well

''When in doubt, empty your magazine.'' - Murphy''s Combat Law

Share this post


Link to post
Share on other sites
The biggest worry you have using clock() based timing, is it only has a resolution of 10ms. If less than 10ms elapses, you get 0, which is why you *must* dead reckon if you use clock(). And you don''t want the kernal mode switch performance hit for each loop for each animation. So in this case, I think you shouldn''t use QueryPerformanceCounter.

Sprite->Frames=55;
Sprite->FrameRate_Hz=10;
float Sprite->Time_per_Frame_sec = 1.0f / float(FrameRate_Hz);
float Sprite->Duration_sec = Frames * Time_per_Frame;

StartAnimation(...)
Sprite->StartTime_ms = clock();
//load the first frame

//pass in render time
//don''t keep calling clock each time you need the time, call it once and use that time for the whole frame
Animate(DWORD dwTime_ms)
float fElapsed_sec = float(dwTime_ms - Sprite->StartTime_ms) / 1000.0f; //convert ms to sec
int Sprite->CurrentFrame = round(fElapsed_sec * Time_per_Frame);
if(CurrentFrame>Frames)
StopAnimation(...)
else
LoadFrame(CurrentFrame);

PS Learn from NASA, use unit labels in your variables. Go read about why the Mars Lander failed.

Magmai Kai Holmlor
- The disgruntled & disillusioned

Share this post


Link to post
Share on other sites


quote:

say Sprite->frame_rate == 10;
and delta_time = timeGetTime () - Sprite->last_frame_time = say about 50;
and Sprite->fcurrentframe == 1.0;

therefore
Sprite->fcurrentframe += (float)Sprite->frame_rate / (float)delta_time;

results in fcurrentframe being 501.0....i don''t think thats 10 frames per second



Let''s convince you of the multiplication vs. division thing by going back to physics and using units.
Your framerate is in FPS, that''s obviously frames/sec.
Your time is in ms.
Your currentframe is in frames.

Now what''s the correct formula? If you do:
currentframe = currentframe + framerate / time you get the units: frames = frames + (frames/sec) / sec => frames = frames + (frames/sec^2)
Now you can''t add up frames and frames per seconds squared, can you?

The correct formula is:
currentframe + framerate*time => frames + (frames/sec) * msec
Note that we''re talking secs vers msecs here, so let''s convert this to frames + (frames/sec) * (sec/1000)
Ergo your code has to be:
currentframe += frametime * time / 1000;

There you go..

cu,
Prefect

---
Sanity is the trademark of a weak mind.

Share this post


Link to post
Share on other sites
Magmai:

I used your way and it works just great! just had to change the mul in


Sprite->current_frame = round (fElapsed_sec * Sprite->time_per_frame_sec);


to a div. i was wondering why it only updated to the next frame every 15 seconds.

Working off the start time seems much more practical to me now .
With looping should I calculate the overlap or just reset the start time when it gets to the end of the animation?

thanks

-----------------------------
-cow_in_the_well

''When in doubt, empty your magazine.'' - Murphy''s Combat Law

Share this post


Link to post
Share on other sites