Cell Clearing Animations in Minesweeper
How can we add animations for cell clearing or mine explosions?
Adding animations to our Minesweeper game can greatly enhance the user experience. Let's explore how we can implement animations for cell clearing and mine explosions using SDL2.
Basic Animation Framework
First, we'll create a simple animation framework:
#include <SDL.h>
#include <functional>
#include <vector>
class Animation {
public:
Animation(
int duration,
std::function<void(float)> updateFunc) :
Duration{duration},
UpdateFunc{updateFunc}, ElapsedTime{0} {}
bool Update(int deltaTime) {
ElapsedTime += deltaTime;
float progress =
std::min(1.0f,
static_cast<float>(ElapsedTime) /
Duration);
UpdateFunc(progress);
return ElapsedTime >= Duration;
}
private:
int Duration;
std::function<void(float)> UpdateFunc;
int ElapsedTime;
};
class AnimationManager {
public:
void AddAnimation(Animation animation) {
Animations.push_back(std::move(animation));
}
void Update(int deltaTime) {
Animations.erase(
std::remove_if(
Animations.begin(), Animations.end(),
[deltaTime](Animation &anim) {
return anim.Update(deltaTime);
}),
Animations.end());
}
private:
std::vector<Animation> Animations;
};
Cell Clearing Animation
Now, let's modify our MinesweeperCell
class to include an animation when clearing:
class MinesweeperCell : public Engine::Button {
public:
// ... existing code ...
void ClearCell() {
if (isCleared) return;
isCleared = true;
SetIsDisabled(true);
// Start clearing animation
AnimationManager.AddAnimation(Animation(
500, // Duration in milliseconds
[this](float progress) {
// Interpolate between initial and
// cleared color
SDL_Color initialColor =
Config::BUTTON_COLOR;
SDL_Color targetColor =
Config::BUTTON_CLEARED_COLOR;
Color.r = initialColor.r +
(targetColor.r - initialColor.r) *
progress;
Color.g = initialColor.g +
(targetColor.g - initialColor.g) *
progress;
Color.b = initialColor.b +
(targetColor.b - initialColor.b) *
progress;
}));
ReportEvent(UserEvents::CELL_CLEARED);
}
void Update(int deltaTime) {
AnimationManager.Update(deltaTime);
}
private:
AnimationManager AnimationManager;
};
Mine Explosion Animation
For mine explosions, we can create a more dramatic animation:
class MinesweeperCell : public Engine::Button {
public:
// ... existing code ...
void ExplodeMine() {
if (isExploded) return;
isExploded = true;
SetIsDisabled(true);
AnimationManager.AddAnimation(Animation(
1000, // Duration in milliseconds
[this](float progress) {
// Pulsating red effect
float intensity =
(std::sin(progress * 10) + 1) / 2;
Color.r = 255;
Color.g = Color.b = static_cast<Uint8>(
255 * (1 - intensity));
// Expand cell size
float scale = 1 + progress * 0.2f;
SetSize(static_cast<int>(OriginalWidth *
scale),
static_cast<int>(
OriginalHeight * scale));
}));
ReportEvent(UserEvents::MINE_EXPLODED);
}
private:
bool isExploded{false};
int OriginalWidth, OriginalHeight;
};
Integrating Animations
To integrate these animations into our game loop, we need to update our main game class:
class MinesweeperGame {
public:
void Update(int deltaTime) {
for (auto &cell : Grid.Children) {
cell.Update(deltaTime);
}
}
void Render(SDL_Surface *Surface) {
Grid.Render(Surface);
}
private:
MinesweeperGrid Grid;
};
And in our main loop:
int main() {
// ... initialization code ...
Uint32 lastTime = SDL_GetTicks();
while (Running) {
// ... event handling ...
Uint32 currentTime = SDL_GetTicks();
int deltaTime = currentTime - lastTime;
lastTime = currentTime;
Game.Update(deltaTime);
Game.Render(WindowSurface);
SDL_UpdateWindowSurface(Window);
SDL_Delay(16); // Cap at roughly 60 FPS
}
// ... cleanup code ...
}
These animations add visual flair to our Minesweeper game. The cell clearing animation provides a smooth transition, while the mine explosion creates a dramatic effect.
Remember to adjust the animation durations and effects to suit your game's style and pacing. You can also extend this system to include other animations, such as flagging cells or revealing the entire board at game end.
Creating the Grid
Building a two-dimensional grid of interactive minesweeper cells