How can I get my objects to move at the same speed regardless of frame rate?

I tried using the methods on lazyfoo's site for frame rate independence. One problem I'm having though is that my game is running at different speeds on different computers. The differences are drastic. For example, on a Core 2 Duo 2.4 ghz 2gb ram PC, the ball will move extremely fast, but the paddle moves slowly. On an Intel Centrino laptop running Win7 w/plenty of ram, the ball moves slowly, but the paddle moves fast. On older computers like a Pentium 4 2.4 ghz, 768 ram computer, the ball moves realllllllllyyyyyyy sllllooowwww. Yes, that slow.

What might be some reasons this is happening, and how can I fix it? I can only assume that the code I wrote that deals with frame rate independence is wrong. Here are the relevant parts of the code. (btw, it's a breakout clone).

Code to move the ball

bool Ball::MoveBall( Uint32 deltaTicks )
{
// X-COORDINATE
xOffset += cos( radians ) * ( ballVelocity / 1000.f ) * flipx;
ballPosition.x = (Sint16)xOffset;

.......

// Y-COORDINATE
yOffset += sin( radians ) * ( ballVelocity / 1000.f ) * flipy;
ballPosition.y = (Sint16)yOffset;

.....
}


void Paddle::Move( Uint32 deltaTicks )
{
xOffset += xVel * ( deltaTicks / 1000.f );
}


Main loop

    while ( SDL_PollEvent( &gEvent ) )
{

if ( gEvent.type == SDL_QUIT || gEvent.key.keysym.sym == SDLK_ESCAPE )
quit = true;
}
stick.Move( time.GetTicks() );

if ( ball.MoveBall( time.GetTicks() ) )
wallSound.Play();

if ( ball.CheckPaddleCollision( stick ) )

if ( ball.CheckBrickCollision( brickmap ) )
brickSound.Play();

ball.ResetBallPosition();
launched = false;
draw.GameObjects( lvl, brickmap, stick, ball );
}

draw.GameObjects( lvl, brickmap, stick, ball );
time.Start();
draw.Refresh();

• Man, the code thing is formatting it weird. Can't get the function name and parameters into the code box... – ShrimpCrackers Aug 19 '11 at 7:18
• I know that for the ball movement I don't factor in time. I tried ballVelocity * sin(radians) * (deltaTicks/1000.f) but the problem with that is that if the velocity of the ball is 30pix/sec, the ball is suddenly drawn 30 pixels in the direction of the angle when the ball is launched. – ShrimpCrackers Aug 19 '11 at 7:22
• just paste your code in, highlight it, and click the {} button. It just adds 4 spaces to each line. – Tetrad Aug 19 '11 at 7:25
• – Jonathan Connell Aug 19 '11 at 7:49

The movement of your ball varies from platform to platform because you're not using the delta-time at all for your movement calculation.

First of all you should convert your ticks to seconds in your update loop and then call the Move functions with the delta-time in seconds.. otherwise you'll have to convert to seconds in every Move function.

All your speed definitions should be in units per second. Eg. ballVelocity would be 100 if your ball should move at a rate of 100 units (pixels) per second.

Then a simple Move method could look like this:

bool Ball::MoveBall(float dt)
{
ballPosition.x += cos(radians) * ballVelocity * dt;
ballPosition.y += sin(radians) * ballVelocity * dt;
}


A further optimization would be to not always calculate cos/sin, but rather have a direction vector that you only recalculate whenever the direction changes... Then it would turn into: ballPosition.x += direction.x * ballVelocity * dt;

• Or store the orientation directly in a velocity vector: ballPosition.x += ballVelocity.x * dt etc. Another advice: use matrix and vector classes. ballPosition += ballVelocity * dt. – sam hocevar Aug 19 '11 at 8:09
• @Sam Hocevar: Having a normalized direction vector around can be useful as well though. For example to calculate angles with dot-product or just to have the velocity independent from the direction (so you can alter velocity easily without having to factor in rotation). – bummzack Aug 19 '11 at 14:18
• Although I've worked with vectors in calculus, I'm not really understanding how I can transform that into code. Is direction.x the same thing as the value of cos(radians), except that I'm not calculating every single time (since cos() has overhead cost)? – ShrimpCrackers Aug 19 '11 at 19:29
• @ShrimpCrackers Yes, that's it. direction.x = cos(radians); direction.y = sin(radians);. – bummzack Aug 19 '11 at 19:34
• I made the changes and it's running better on the other computers I've tested except one. The ball that moved really slow on one pc moves really fast now, and there is a lag between input and paddle movement. Does frame independence not necessarily mean that it will run the same speed on all computers? The computers that run it much better know still have slightly different speeds. – ShrimpCrackers Aug 20 '11 at 18:29