Creating Cursor Trail Effects

How can I implement a cursor trail effect, where the cursor leaves a temporary trail as it moves?

A cursor trail effect can be implemented by keeping track of recent cursor positions and rendering them with decreasing opacity. Here's a complete implementation:

Trail Position Storage

First, we'll create a structure to store trail positions and their age:

#include <SDL.h>
#include <deque>
#include <cmath>

struct TrailPoint {
  int x, y;
  Uint32 timestamp;
};

class CursorTrail {
public:
  static constexpr size_t MAX_POINTS{20};
  static constexpr Uint32 TRAIL_DURATION{500};// milliseconds

  void Update(int mouseX, int mouseY) {
    auto now{SDL_GetTicks()};

    // Add new point
    TrailPoints.push_front({mouseX, mouseY, now});

    // Remove old points
    while (!TrailPoints.empty() &&
           now - TrailPoints.back().timestamp > TRAIL_DURATION) {
      TrailPoints.pop_back();
    }

    // Limit total points
    while (TrailPoints.size() > MAX_POINTS) {
      TrailPoints.pop_back();
    }
  }

  void Render(SDL_Renderer* renderer) {
    auto now{SDL_GetTicks()};

    // Render trail points
    for (size_t i{1}; i < TrailPoints.size(); ++i) {
      const auto& current{TrailPoints[i - 1]};
      const auto& prev{TrailPoints[i]};

      // Calculate alpha based on age
      float age{static_cast<float>(
        now - current.timestamp) / TRAIL_DURATION
      };
      Uint8 alpha{static_cast<Uint8>(
        255 * (1.0f - age)
      )};

      SDL_SetRenderDrawBlendMode(
        renderer, SDL_BLENDMODE_BLEND);
      SDL_SetRenderDrawColor(
        renderer, 255, 255, 255, alpha);

      SDL_RenderDrawLine(
        renderer,
        current.x, current.y,
        prev.x, prev.y
      );
    }
  }

private:
  std::deque<TrailPoint> TrailPoints;
};

Using the Trail

Here's how to use the trail in your game loop:

#include <SDL.h>
#include <iostream>

int main() {
  SDL_Init(SDL_INIT_VIDEO);

  SDL_Window* window{SDL_CreateWindow(
    "Cursor Trail",
    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
    800, 600,
    SDL_WINDOW_SHOWN
  )};

  SDL_Renderer* renderer{SDL_CreateRenderer(
    window, -1, SDL_RENDERER_ACCELERATED
  )};

  CursorTrail trail;
  bool running{true};

  while (running) {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
      if (event.type == SDL_QUIT) {
        running = false;
      }
    }

    // Update trail
    int mouseX, mouseY;
    SDL_GetMouseState(&mouseX, &mouseY);
    trail.Update(mouseX, mouseY);

    // Render
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);

    trail.Render(renderer);

    SDL_RenderPresent(renderer);
  }

  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);
  SDL_Quit();
  return 0;
}

This implementation creates a smooth trail effect that fades out over time. The trail length and duration are configurable through the constants in the CursorTrail class.

Customising Mouse Cursors

Learn how to control cursor visibility, switch between default system cursors, and create custom cursors

Questions & Answers

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

Changing Cursor Appearance on Hover
Can I make the cursor change appearance when it hovers over different game objects? Like showing a sword over enemies?
Animating Custom Cursors
Can I animate my custom cursor by loading multiple images? How would I implement a cursor that changes appearance?
Preventing Cursor Blur When Scaling
Why does my custom cursor look blurry/pixelated when I scale my window? How can I make it stay sharp?
Adding Physics to Cursor Movement
Is there a way to limit how fast the cursor can move across the screen? Like adding weight/momentum to it?
Or Ask your Own Question
Purchase the course to ask your own questions