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

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Vector vs 2D Array in Minesweeper
Why do we use a vector to store the cells instead of a 2D array?
Custom Grid Shapes in Minesweeper
Can we implement a custom grid shape instead of just rectangular?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant