I've read two other threads here on movement: Time based movement Vs Frame rate based movement?, and When should I use a fixed or variable time step?
but I think I'm lacking a basic understanding of frame independent movement because I don't understand what either of those threads are talking about.
I'm following along with lazyfoo's SDL tutorials and came upon the frame independent lesson. http://lazyfoo.net/SDL_tutorials/lesson32/index.php
I'm not sure what the movement part of the code is trying to say but I think it's this (please correct me if I'm wrong): In order to have frame independent movement, we need to find out how far an object (ex. sprite) moves within a certain time frame, for example 1 second. If the dot moves at 200 pixels per second, then I need to calculate how much it moves within that second by multiplying 200 pps by 1/1000 of a second.
Is that right? The lesson says:
"velocity in pixels per second * time since last frame in seconds. So if the program runs at 200 frames per second: 200 pps * 1/200 seconds = 1 pixel"
But...I thought we were multiplying 200 pps by 1/1000th of a second. What is this business with frames per second?
I'd appreciate if someone could give me a little bit more detailed explanation as to how frame independent movement works.
Thank you.
ADDITION:
SDL_Rect posRect;
posRect.x = 0;
posRect.y = 0;
float y, yVel;
y = 0;
yVel = 0;
Uint32 startTicks = SDL_GetTicks();
bool quit = false;
SDL_Event gEvent;
while ( quit == false )
{
while ( SDL_PollEvent( &gEvent ) )
{
if ( gEvent.type == SDL_QUIT )
quit = true;
}
if ( y <= 580 )
{
yVel += DOT_VEL;
y += (yVel * (SDL_GetTicks() - startTicks)/1000.f);
posRect.y = (int)y;
}
startTicks = SDL_GetTicks();
SDL_BlitSurface( bg, NULL, screen, NULL );
SDL_BlitSurface( dot, NULL, screen, &posRect );
SDL_Flip( screen );
}
That's code that moves a dot down the screen. I think I have everything correct so far. It moves down the screen but there is a bit of an odd thing that happens that I can't explain. The dot is supposed to stay at the y=580 when it gets to greater than that y-value. However, every time I run the program, the dot will end up in a different location, meaning a little bit to a lot more than 580, so the dot is halfway or more than halfway off the screen (the dot is 20 pixels, screen dimensions 800x600). If I do something like click and hold the title-bar of the program, and then release, the dot disappears off the screen. How come it's variable each time? As for the titlebar problem I think it's because when I hold on to the titlebar, the timer is still running, and the time elapsed gets larger, resulting in a larger distance the dot moves in the next frame. Is that right?
Answer
NOTE: All fractions are meant to be floats.
Frame independent movement works by basing movement off of time. You get the amount of time that is spend since the last frame (so if there are 60 frames in one second, each frame takes 1.0/60.0 seconds, if all the frames took the same amount of time) and find out how much movement that translates into.
If you want your entity to move a certain amount of space for a specified unit of time (we will say 100 pixels for every second of time) then you can find out how many pixels you should move per frame by multiplying the amount of movement per second (100 pixels) by the amount of time passed in seconds (1.0/60.0) in order to figure out how much movement should take place in the current frame.
It works by figuring out how much movement you should perform per frame by using the amount of time elapsed and a speed that is defined with some unit of time (seconds or milliseconds are preferable). So your calculation might look like: movementPerSecond * (timeElapsedInMilliseconds / 1000.0)
I hope that made some kind of sense to you.
I want to move my guy 200 pixels to the right every second. If the current frame is run 50 milliseconds after the previous frame, then I should move my guy a fraction of the speed previously specified (which was 200 pixels). I should move him 50/1000th of the distance because only a 1/20th (50/1000 = 1/20) of time has passed. Therefore it would make sense to only move him 10 pixels (if 19 more frames occurred, 50 milliseconds apart from each other, then the total amount of movement in that second would be 200 pixels, the amount we wanted).
The way frame independent movement works is that frames usually occur at variable time steps (there is a different amount of time that takes place between subsequent frames). If we constantly move an entity a constant distance every frame, then the movement is based on the frame rate. If there is a lot of time between frames, the game will seem to move too slow and if there is not a lot of time between frames, the game will seem to be going to fast. (too little time between frames = a lot of frames = more movement) To overcome this, we use a speed in terms of time and keep track of the time between frames. That way we know how long it's been since we last updated the position and how much further we should move the entity. By using time we can eliminate the dependence on the frame rate and our game will look more or less the same on different frame rates.
Frames per second : This is the amount of frames that take place per second. Usually a frame rate is either how many times the game is drawn/rendered a second or how many times the game loop is completed a second.
Fixed Verse Variable Time Step : This refers to the amount of time between frames. Usually, the time between frames will not be constant. Certain systems/cores like physics will need some unit of time in order to simulate/run something. Usually, physics systems are more stable/scalable if the time step is fixed. The difference between fixed/variable time steps are in the names. Fixed time steps are what they sound like: time steps that occur at a fixed rate of time. Variable time steps are time steps that occur at varying/different rates of time.
No comments:
Post a Comment