I'm developing a Breakout style game in C++ using SDL. The problem so far is that the ball slows down and speeds up for no particular reason.
The slowdowns usually last a few seconds.
EDIT : When running fullscreen I noticed that the ball movement seems to be a tiny bit jerky as well. This leads me to believe that the timing should be more finely granulated. But at the same time, it shouldn't be necessary to have µs precision...
Here is my code for calculation the movement of the ball :
double deltaMovement = tick * speed;
rect.x += static_cast<int> ( deltaMovement * dirX );
rect.y += stnecessearyatic_cast<int> ( deltaMovement * dirY );
I tried changing it to help prevent float to in truncation, but this affects the speed to much, making the ball move only move horizontally or vertically ( which never happens with the above code. )
double movementX = ( deltaMovement * dirX );
double movementY = ( deltaMovement * dirY );
movementX += ( movementX > 0.0f )? 0.5f: -0.5f;
movementY += ( movementY > 0.0f )? 0.5f: -0.5f;
rect.x += static_cast<int> ( movementX );
rect.y += static_cast<int> ( movementX );
rect
is an SDL_Rect
and holds the ball's position. dirX
and dirY
are double
and holds the direction of the ball, the values range from -1.0
to 1.0
I'm not sure if the issue is with the float
to int
conversion. I guess it could also be something with SDL internally, but I am quite sure SDL should be capable of smooth animation.
Here's my main game loop ( I have removed some irrelevant parts of it ) while ( !quit ) { while ( SDL_PollEvent( &event ) ) { // Handle input, move paddle, check if user pressed esc // Yes I have a means of escaping the outer while loop. } double delta = timer.GetDelta( );
// Update the ball, check for collisions with wall/paddle/tiles
UpdateBalls( delta );
// Redraws everything
UpdateGUI();
}
I'm quite sure the issue is not with my delta time, since it's fairly consistant at 1 - 4 msec. And even if it did change a lot, it shouldn't matter. But just in case, here's the code I use for calculating delta time :
double Timer::GetDelta( )
{
timespec tmCurrent;
clock_gettime( CLOCK_MONOTONIC_RAW, &tmCurrent);
// Get current time in nanoseconds
unsigned long long deltaCurrent = static_cast< unsigned long long > ( tm.tv_sec * 1000000000 + tm.tv_nsec );
// Get diff. Delta is an unsigned long long that holds previous tick ( see below)
unsigned long long diff = deltaCurrent - delta;
// Convert into ms and assign to a double
double deltaMSec = static_cast< float > ( diff / 1000000.0f );
// Reset delta so that it can be used the next time delta is calculated
delta = deltaCurrent;
return deltaMSec;
}
What am I doing wrong?
gettimeofday (...)
provides enough resolution and granularity on all major *UX platforms your game is likely to run on (OS X, Linux, BSD). You should also use double-precision instead of single-precision FP for the deltaMSec. \$\endgroup\$#ifdef
s to add support for other platforms. Alsogettimeofday (...)
seems to be hardware dependant : lehman.cuny.edu/cgi-bin/man-cgi?gettimeofday+3 I will change resolution todouble
, though. \$\endgroup\$clock_gettime (...)
is also hardware-dependent. The only condition it adds (when using MONOTONIC) is that the value returned is always non-decreasing. This avoids issues withrdtsc
-like instructions when the thread your timer is running on changes scheduled processors. However, despite being POSIX, it is not implemented on platforms like OS X. Also, MONOTONIC_RAW is a Linux-only extension. \$\endgroup\$