Frame rate independent movement (again!) This one is really weird!
!!!UPDATED!!!
Here is the proof, frame rate independent movement that is framerate dependent (seems so anyway)
Grab it from http://bapelsin.ath.cx/smiley.zip (.exe + .bmp)
!!!UPDATED!!!
I can't get this to work. I understand the concept of using movement per sec instead of movement per frame.
My little smileman is moving very jerky.
It's velocity is changing all the time.
I think my framerate is pretty jumpy but that shouldn't have any effect right? ("Frame rate independent....")
This code should work!
Can you spot any errors in this ?
(I'll guess the names of the classes are self-explanatory.)
CBitmap bmpSmile;
CInput input;
CTime time;
double x, y, velx, vely;
int realx;
int realy;
double idTime;
double dSecondsPassed;
if( !(bmpSmile.SetupBitmap("smile.bmp", &dx)) )
add_log("bitmap loading failed");
time.Reset();
velx = 0;
vely = 0;
x = 1;
y = 1;
char buffer[50];
while(1)
{
if(PeekMessage(&msg,hwnd,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
idTime = time.GetMsEllapsed();
dSecondsPassed = (double) idTime / 1000 ;
dx.ClearBackSurface();
dx.GetBackSurface(&pp_DDSBackbuffer);
velx = 0.0; // Changed
vely = 0.0;
if( !pp_DDSBackbuffer )
add_log("Error! No surface!");
if( input.KeyPressed(VK_RIGHT) )
velx += 128 * dSecondsPassed;
if( input.KeyPressed(VK_LEFT) )
velx -= 128 * dSecondsPassed;
x += velx;
realx = (int)x;
realy = 200;
if( !bmpSmile.Draw(realx, realy, pp_DDSBackbuffer) )
add_log("Error while drawing!");
dx.Flip();
}
}
This is from the timer
int CTime::GetMsEllapsed(void)
{
m_iOldTime = m_iCurrTime;
m_iCurrTime = timeGetTime();
/* Return delta time */
return (m_iCurrTime - m_iOldTime);
}
Thanks in advance!
Edited by - zedd_ on February 23, 2002 3:26:58 PM
Edited by - zedd_ on February 23, 2002 5:08:49 PM
After a quick glance, it looks to me that you are technically doing it right. The most important thing is that you understand the concept. Many commercial games use more precise timing than the windows performance counter. I''m not an expert, but I think there are ways to use the number of clock cycles as an accurate measure of time. Also, many commercial games use some sort of "smoothing" in their animations by using interpolation.
I''ve have an example from the 2dgame-tutorial.com.
Patrick example there works smooth and with timeGetTime() function.
It''s so strange!
Patrick example there works smooth and with timeGetTime() function.
It''s so strange!
Jason,
Shouldn't matter..
Tried changing just to be sure.
It didn't
Thanks for your replies..
It must be connected somehow with my jumpy framerate...
My frametime have been jumping between 10 ms to 20 ms / frame
Otherwise, I can see nothing wrong with this code snippet.
Edited by - zedd_ on February 23, 2002 2:33:20 PM
Shouldn't matter..
Tried changing just to be sure.
It didn't
Thanks for your replies..
It must be connected somehow with my jumpy framerate...
My frametime have been jumping between 10 ms to 20 ms / frame
Otherwise, I can see nothing wrong with this code snippet.
Edited by - zedd_ on February 23, 2002 2:33:20 PM
I have a simpler method for this but this method requires you to figure a minimum frame rate... under this minimum frame rate the game would move slowly...
It is something like this: you use the timer (which with some effort you will be able to set to update a variable a given number of times every secund using an interrupt driven function) as a timer for your game engine but not for the bliting/drawing. what happens is that you update your animation/movement on the right time and don''t loose processing time (since your frame work is never stoping to wait for the time for the next frame to be drawn).
It goes something like this:
int timing=0,time; /*time is the variable that should be updated using an interrupt driven function*/
...
for(;
{
if (time>=timing)
{
timing+=1; /*suposing you wanna update your animation/movement/whatever every time timing is updated by your timer functions*/
*put your game code here*
*draw your sprites at the main mem buffer*
}
blitscreen();
}
mmmm.... i guess this method is worse than the method you are currently using....... but it works fine. The example above is considering a double buffer blitting engine...
you may also add some code to check if ''timing'' is way behind time (in which case you may want to skip a frame) or do it like: timing=time+1; which would end up being a little choppy, I guess.
It is something like this: you use the timer (which with some effort you will be able to set to update a variable a given number of times every secund using an interrupt driven function) as a timer for your game engine but not for the bliting/drawing. what happens is that you update your animation/movement on the right time and don''t loose processing time (since your frame work is never stoping to wait for the time for the next frame to be drawn).
It goes something like this:
int timing=0,time; /*time is the variable that should be updated using an interrupt driven function*/
...
for(;
{
if (time>=timing)
{
timing+=1; /*suposing you wanna update your animation/movement/whatever every time timing is updated by your timer functions*/
*put your game code here*
*draw your sprites at the main mem buffer*
}
blitscreen();
}
mmmm.... i guess this method is worse than the method you are currently using....... but it works fine. The example above is considering a double buffer blitting engine...
you may also add some code to check if ''timing'' is way behind time (in which case you may want to skip a frame) or do it like: timing=time+1; which would end up being a little choppy, I guess.
Weird. When you say your smileman is changing velocity all the time, how is it changing? Is it random, or is it constantly accelerating, or what?
The only thing I can think of is something I had assumed you meant to do. You have:
velx += 128 * dSecondsPassed;
Which would make the object constantly accelerate. If that''s what you meant to do, then obviously it''s correct, but if you only want it to move at a constant speed and not accelerate at a constant speed, then (I think) you''d need to have:
velx = 128 * dSecondsPassed;
But everything looks ok other than that, so unless that is the problem, I can''t see what''s wrong.
BTW, there is another way of dealing with frame-rate independant movement that you might want to look into if you ever want to do some kind of replay system. There was an article about replays on Gamasutra:
http://www.gamasutra.com/features/20010713/dickinson_01.htm
John B
The only thing I can think of is something I had assumed you meant to do. You have:
velx += 128 * dSecondsPassed;
Which would make the object constantly accelerate. If that''s what you meant to do, then obviously it''s correct, but if you only want it to move at a constant speed and not accelerate at a constant speed, then (I think) you''d need to have:
velx = 128 * dSecondsPassed;
But everything looks ok other than that, so unless that is the problem, I can''t see what''s wrong.
BTW, there is another way of dealing with frame-rate independant movement that you might want to look into if you ever want to do some kind of replay system. There was an article about replays on Gamasutra:
http://www.gamasutra.com/features/20010713/dickinson_01.htm
John B
JohnBSmall, totally random!
My mistake in code, I reset velx to 0 every frame.
Just a little typo I got when pasting this into the forum.
Didn''t change any behaviour..
I''ll check that link out!
nicolasldc, seems to an overkill.
What I''m doing now should work and it WILL WORK!! GRR! >
Why doesn''t it work!? Stupid #¤%"# comp!
(Just had to say it)
My mistake in code, I reset velx to 0 every frame.
Just a little typo I got when pasting this into the forum.
Didn''t change any behaviour..
I''ll check that link out!
nicolasldc, seems to an overkill.
What I''m doing now should work and it WILL WORK!! GRR! >
Why doesn''t it work!? Stupid #¤%"# comp!
(Just had to say it)
Have you looked at the log file?? When I ran it, and checked the log I saw about 40 "Error while drawing!" messages, even though it did display the smiley face. The movement did seem quite jerky, and it changed speed slightly throughout the run, but it didn't change very much. For some reason it seems faster going right than it is going left.
I didn't get any error messages or crashes apart from the 40 listed in the log.
It looks to me like it's a problem with drawing, and not with your timing code. That's partly based on the log, and partly based just on my intuition (which isn't particularly good, and definately isn't an objective test - but it's right occasionally).
You might want to replace your timeGetTime counter code with stuff using QueryPerformanceCounter. I don't know how much difference it will make, but QueryPerformanceCounter (on my machine, and it will vary with hardware) has a frequency of:
3579545
ticks per second. So it should be fairly accurate. It doesn't seem like that's the problem, but it might be worth a try (shouldn't take too long).
John B
Edited by - JohnBSmall on February 23, 2002 6:09:36 PM
I didn't get any error messages or crashes apart from the 40 listed in the log.
It looks to me like it's a problem with drawing, and not with your timing code. That's partly based on the log, and partly based just on my intuition (which isn't particularly good, and definately isn't an objective test - but it's right occasionally).
You might want to replace your timeGetTime counter code with stuff using QueryPerformanceCounter. I don't know how much difference it will make, but QueryPerformanceCounter (on my machine, and it will vary with hardware) has a frequency of:
3579545
ticks per second. So it should be fairly accurate. It doesn't seem like that's the problem, but it might be worth a try (shouldn't take too long).
John B
Edited by - JohnBSmall on February 23, 2002 6:09:36 PM
Oh, oops. I just realised that the 40 logged errors were just because I''d moved the smiley face out of the screen area, so they won''t be related to the problem.
However, I still think it''s something to do with the drawing code. It seems very flickery on my system. It get''s a constant FPS of 58-62. That''s because of WinXP forcing it to limit the drawing to the vsync (which changes from my setting of 85Hz, to the default of 60Hz whenever DX goes fullscreen - don''t ask me why).
My system specs are:
1.7 GHz Pentium 4
32mb GeForce2 MX
256 mb of RAM
So I doubt that your program is pushing the video card too hard
John B
However, I still think it''s something to do with the drawing code. It seems very flickery on my system. It get''s a constant FPS of 58-62. That''s because of WinXP forcing it to limit the drawing to the vsync (which changes from my setting of 85Hz, to the default of 60Hz whenever DX goes fullscreen - don''t ask me why).
My system specs are:
1.7 GHz Pentium 4
32mb GeForce2 MX
256 mb of RAM
So I doubt that your program is pushing the video card too hard
John B
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement