You definitely need to integrate deltaTime into a float structure, but you can copy the newly modified location into an SDL_Rect for rendering. The player will still "teleport", but always and only by one, which may be acceptable in your game. My searches indicate that this is normal for SDL and the general solution seems to be to fallback on GL or DX and use orthographic projection to simulate the "2D" parts that benefit from floating point math.
deltaTime
and all of your constants should also be floats; i.e. 1000.0f
.
Scale:
Imagine driving a car with a speedometer labeled in integer "miles per minute". 60 MPH would be the only label "1". So you can drive at 1, faster than 1, or slower than 1. How do you put 0.833333333MPM (50MPH) on a speed-limit sign? Miles-per-minute is, clearly, not the most convenient scale for vehicle speed limits, even though both scales are equally accurate.
"Units per millisecond" is an equally undesirable scale because humans do not experience life as such.
- "Carpe diem" - Seize the day, not the millisecond
- "Day-to-day needs" - Again, days
- "Tomorrow" - 86.4 million milliseconds from now
- "Days of our lives" - Again, days
- "Give me a minute" - 60,000 milliseconds
- "Do it now; right this second" - 1000 milliseconds
Code:
Uint32 elapsedTime = 0; //Why not since SDL_GetTicks() returns Uint32
Uint32 lastFrameTimeElapsed = 0;
//Convert Uint32 milliseconds to float seconds
float deltaTime = (elapsedTime - lastFrameTimeElapsed) / 1000.0f; //Per-second is easy
Move(10.0f * deltaTime, 0.0f * deltaTime); //10 units per second
void Sprite::Move(float offsetX, float offsetY)
{
//Moving 10 units per second at 60 FPS, yields offsetX/Y of +-0.1666666f
//Since 0.1666666f rounds to 0, this won't work:
//m_rect.x += roundf(offsetX);
m_floatRect->x += offsetX;
m_floatRect->y += offsetY;
m_rect.x = roundf(m_floatRect->x);
m_rect.y = roundf(m_floatRect->y);
}