Creating smooth acceleration and deceleration effects is a common requirement in game development, especially for character movement or vehicle simulations. By using time deltas, we can ensure these effects are consistent across different frame rates. Let's explore how to implement this:
The simplest form of acceleration is linear. Here's how you can implement it:
#include <SDL.h>
#include <iostream>
class MovingObject {
private:
float position = 0.0f;
float velocity = 0.0f;
// Units per second squared
float acceleration = 5.0f;
// Maximum velocity
float maxVelocity = 10.0f;
public:
void update(float dt) {
// Apply acceleration
velocity += acceleration * dt;
// Clamp velocity to maximum
if (velocity > maxVelocity) velocity =
maxVelocity;
// Update position
position += velocity * dt;
std::cout << "Position: " << position <<
", Velocity: " << velocity << "\n";
}
};
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
MovingObject obj;
Uint64 previousTime = SDL_GetTicks64();
for (int i = 0; i < 100; ++i) {
Uint64 currentTime = SDL_GetTicks64();
float dt = (currentTime - previousTime) /
1000.0f;
previousTime = currentTime;
obj.update(dt);
SDL_Delay(16); // Simulate ~60 FPS
}
SDL_Quit();
return 0;
}
Position: 0, Velocity: 0
Position: 0.001445, Velocity: 0.085
Position: 0.004335, Velocity: 0.17
Position: 0.008335, Velocity: 0.25
Position: 0.01403, Velocity: 0.335
Position: 0.02067, Velocity: 0.415
...
This creates a linear acceleration effect. The object starts from rest and gradually increases its speed until it reaches the maximum velocity.
For a smoother, more natural-feeling acceleration and deceleration, we can use easing functions. One common approach is to use a sigmoid function:
#include <SDL.h>
#include <cmath>
#include <iostream>
class SmoothMovingObject {
private:
float position = 0.0f;
float targetPosition = 100.0f;
// Maximum speed
float maxSpeed = 50.0f;
// Higher values make the motion smoother
float smoothness = 2.0f;
public:
void update(float dt) {
float distanceToTarget = targetPosition -
position;
float speed =
maxSpeed *
(2 / (1 + std::exp(
-smoothness * distanceToTarget /
maxSpeed)) - 1);
position += speed * dt;
std::cout << "Position: " << position <<
", Speed: " << speed << "\n";
}
};
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
SmoothMovingObject obj;
Uint64 previousTime = SDL_GetTicks64();
for (int i = 0; i < 600; ++i) {
Uint64 currentTime = SDL_GetTicks64();
float dt = (currentTime - previousTime) /
1000.0f;
previousTime = currentTime;
obj.update(dt);
SDL_Delay(16); // Simulate ~60 FPS
}
SDL_Quit();
return 0;
}
This implementation uses a sigmoid function to create a smooth S-curve for acceleration and deceleration. In this example, the object decelerates as it approaches the target position.
Position: 0, Speed: 48.2014
Position: 0.819423, Speed: 48.2014
Position: 1.63785, Speed: 48.1426
Position: 2.45524, Speed: 48.0819
Position: 3.27157, Speed: 48.0194
...
Another approach is to use interpolation, which can create very smooth movement between two points:
#include <SDL.h>
#include <iostream>
class InterpolatingObject {
private:
float startPosition = 0.0f;
float endPosition = 100.0f;
// Interpolation factor
float t = 0.0f;
// Time to complete the movement
float duration = 2.0f;
public:
void update(float dt) {
t += dt / duration;
if (t > 1.0f) t = 1.0f;
// Smooth step function for easing
float smoothT = t * t * (3 - 2 * t);
float position = startPosition + (
endPosition - startPosition) * smoothT;
std::cout << "Position: " << position <<
", T: " << t << "\n";
}
};
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
InterpolatingObject obj;
Uint64 previousTime = SDL_GetTicks64();
while (true) {
Uint64 currentTime = SDL_GetTicks64();
float dt = (currentTime - previousTime) /
1000.0f;
previousTime = currentTime;
obj.update(dt);
SDL_Delay(16); // Simulate ~60 FPS
// Stop after 2 seconds
if (dt >= 2.0f) break;
}
SDL_Quit();
return 0;
}
Position: 0, T: 0
Position: 0.0215522, T: 0.0085
Position: 0.0807766, T: 0.0165
Position: 0.184375, T: 0.025
...
Position: 99.9332, T: 0.985
Position: 99.9874, T: 0.9935
Position: 100, T: 1
This method uses a smooth step function to interpolate between the start and end positions, creating a smooth acceleration and deceleration effect.
By using these techniques with time deltas, you can create smooth, frame-rate independent acceleration and deceleration effects in your games. Remember to experiment with different easing functions and parameters to find the feel that best suits your game's needs.
Answers to questions are automatically generated and may not have been reviewed.
Learn how to create smooth, time-aware game loops that behave consistently across different hardware configurations