Yes, there are several ways to implement notification pausing. Let's explore a few approaches, starting with the simplest and moving to more sophisticated solutions.
The simplest approach is to add a boolean flag to control whether notifications are active:
class Player {
public:
using DamageDelegate = std::function<void(
int NewHealth)>;
void SetDelegate(DamageDelegate D) {
OnDamage = D;
}
void PauseNotifications() {
NotificationsPaused = true;
}
void ResumeNotifications() {
NotificationsPaused = false;
}
void TakeDamage(int Damage) {
Health -= Damage;
if (!NotificationsPaused && OnDamage) {
OnDamage(Health);
}
}
private:
DamageDelegate OnDamage;
bool NotificationsPaused{false};
int Health{100};
};
A more robust approach uses RAII to ensure notifications are always resumed:
class Player {
public:
class NotificationGuard {
public:
NotificationGuard(Player& P) : Subject{P} {
Subject.PauseNotifications();
}
~NotificationGuard() {
Subject.ResumeNotifications();
}
private:
Player& Subject;
};
// ... rest of Player implementation
};
void GameLogic() {
Player P;
// Notifications active
P.TakeDamage(10);
{
// Notifications paused
Player::NotificationGuard Guard{P};
P.TakeDamage(20);
// Even if we throw an exception here,
// notifications will resume
} // Guard destroyed, notifications resume
P.TakeDamage(30);
}
For more granular control, we can track pause state per observer:
class Player {
public:
using DamageDelegate = std::function<void(
int NewHealth)>;
int AddDelegate(DamageDelegate D) {
Observers[NextKey] = {D, false};
return NextKey++;
}
void PauseObserver(int Key) {
if (
auto It = Observers.find(Key);
It != Observers.end()
) {
It->second.Paused = true;
}
}
void ResumeObserver(int Key) {
if (
auto It = Observers.find(Key);
It != Observers.end()
) {
It->second.Paused = false;
}
}
void TakeDamage(int Damage) {
Health -= Damage;
for (auto& [Key, Observer] : Observers) {
if (!Observer.Paused) {
Observer.Callback(Health);
}
}
}
private:
struct Observer {
DamageDelegate Callback;
bool Paused;
};
std::unordered_map<int, Observer> Observers;
int NextKey{0};
int Health{100};
};
Choose the approach that best matches your needs:
Remember that paused observers still consume memory, so if you need to permanently disable an observer, you should remove it completely rather than just pausing it.
Answers to questions are automatically generated and may not have been reviewed.
An overview of the options we have for building flexible notification systems between game components