// g++ -std=c++23 -O2 -Wall -Wextra animated_cursor.hpp.cpp $(pkg-config --cflags --libs sdl3 sdl3-image) -o cursor_particles && ./cursor_particles #pragma once #include #include #include #include #include #include enum class CursorState : uint32_t { NORMAL, ANIMATED, HIDDEN }; struct Pixel { int srcX, srcY; float currentAngle; // Current angle in sphere float currentRadius; // Current radius in sphere float targetAngle; // Target angle for movement float targetRadius; // Target radius for movement float angleSpeed; // Speed of angle change float radiusSpeed; // Speed of radius change SDL_Color originalColor; SDL_Color shuffledColor; }; class AnimatedCursor { private: SDL_Texture* spriteTexture; SDL_Surface* spriteSurface; std::vector pixels; std::vector> allFrames; // Store all 8 frames bool isReversing; float reverseProgress; float time; // For continuous animation float clickX, clickY; // Position where click happened int currentFrame; // 0-7 for the 8 frames bool isPlayingAnimation; // True when playing through frames const int FRAME_WIDTH = 64; // 512 / 8 frames const int FRAME_HEIGHT = 64; const int SPHERE_RADIUS = 16; // 32px diameter sphere const size_t TOTAL_FRAMES = 8; const float ANIMATION_DURATION = 1.2f; // Total time for unshuffle + frame play public: CursorState state = CursorState::NORMAL; float mouseX, mouseY; // Sphere follows cursor AnimatedCursor(); ~AnimatedCursor(); bool Init(SDL_Renderer* renderer, const char* filename); void set_State(const CursorState& state_new); void frame_ExtractFirst(); void state_GenerateShuffle(); void Render(SDL_Renderer* renderer); void Update(float deltaTime, float mx, float my); void mouse_OnClick(); void Cleanup(); };