Yes, it's absolutely possible to have different objects in the game world update at different rates. This technique can be useful for optimizing performance, creating interesting gameplay effects, or simulating systems with different time scales. Let's explore how we can implement this:
One approach is to use timers for each object or group of objects that need to update at a different rate. Here's an example:
#include <SDL.h>
#include <iostream>
#include <memory>
#include <vector>
class GameObject {
public:
virtual void update(float dt) = 0;
virtual ~GameObject() = default;
};
class FastObject : public GameObject {
public:
void update(float dt) override {
// Update logic for fast objects
std::cout << "Fast object updated\n";
}
};
class SlowObject : public GameObject {
public:
void update(float dt) override {
// Update logic for slow objects
std::cout << "Slow object updated\n";
}
};
class World {
private:
std::vector<std::unique_ptr<
GameObject>> objects;
float fastUpdateTimer = 0.0f;
float slowUpdateTimer = 0.0f;
// 20 times per second
const float FAST_UPDATE_INTERVAL = 0.05f;
// 2 times per second
const float SLOW_UPDATE_INTERVAL = 0.5f;
public:
void addObject(
std::unique_ptr<GameObject> obj) {
objects.push_back(std::move(obj));
}
void update(float dt) {
fastUpdateTimer += dt;
slowUpdateTimer += dt;
if (fastUpdateTimer >=
FAST_UPDATE_INTERVAL) {
for (auto& obj : objects) {
if (dynamic_cast<FastObject*>(obj.
get())) {
obj->update(fastUpdateTimer);
}
}
fastUpdateTimer = 0.0f;
}
if (slowUpdateTimer >=
SLOW_UPDATE_INTERVAL) {
for (auto& obj : objects) {
if (dynamic_cast<SlowObject*>(obj.
get())) {
obj->update(slowUpdateTimer);
}
}
slowUpdateTimer = 0.0f;
}
}
};
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
World gameWorld;
gameWorld.addObject(
std::make_unique<FastObject>());
gameWorld.addObject(
std::make_unique<SlowObject>());
Uint64 previousTime = SDL_GetTicks64();
while (true) {
Uint64 currentTime = SDL_GetTicks64();
float dt = (currentTime - previousTime) /
1000.0f;
previousTime = currentTime;
gameWorld.update(dt);
SDL_Delay(16); // Roughly 60 FPS
}
SDL_Quit();
return 0;
}
Fast object updated
Fast object updated
Fast object updated
Fast object updated
Slow object updated
Fast object updated
Fast object updated
...
In this example, FastObject
instances update 20 times per second, while SlowObject
instances update only 2 times per second.
Another approach is to use update counters for each object:
class GameObject {
protected:
int updateFrequency;
int updateCounter = 0;
public:
GameObject(int freq) : updateFrequency(freq) {
}
virtual void update(float dt) {
updateCounter++;
if (updateCounter >= updateFrequency) {
updateCounter = 0;
performUpdate(dt * updateFrequency);
}
}
virtual void performUpdate(float dt) = 0;
};
class FastObject : public GameObject {
public:
// Update every frame
FastObject() : GameObject(1) {}
void performUpdate(float dt) override {
// Fast update logic here
}
};
class SlowObject : public GameObject {
public:
// Update every 10 frames
SlowObject() : GameObject(10) {}
void performUpdate(float dt) override {
// Slow update logic here
}
};
This approach allows for more flexibility in setting update frequencies and doesn't require separate timers for each update rate.
When implementing different update rates, keep these points in mind:
By implementing different update rates for game objects, you can create more efficient and dynamic game worlds, tailoring the update frequency to the needs of each object or system in your game.
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