#include <FastLED.h>
#define LED_PIN 2
#define NUM_LEDS 60 // Adjust to match your strip
#define BRIGHTNESS 200
#define GRAVITY -0.15 // Simulated gravity
#define NUM_SPARKS 20 // Sparks per explosion
#define COOLING 80
CRGB leds[NUM_LEDS];
struct Spark {
float pos;
float speed;
CRGB color;
bool active;
};
Spark sparks[NUM_SPARKS];
bool exploding = false;
float flarePos = 0;
float flareSpeed = 1.8;
uint8_t hue = 0;
void setup() {
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
randomSeed(analogRead(0));
}
void loop() {
fadeToBlackBy(leds, NUM_LEDS, COOLING);
if (!exploding) {
// Launch flare
flarePos += flareSpeed;
leds[(int)flarePos] = CHSV(hue, 255, 255);
if (flarePos >= NUM_LEDS - 10) {
// Begin explosion
exploding = true;
for (int i = 0; i < NUM_SPARKS; i++) {
sparks[i].pos = flarePos;
sparks[i].speed = random(-30, 30) / 10.0;
sparks[i].color = CHSV(hue + random(0, 64), 255, 255);
sparks[i].active = true;
}
}
} else {
// Exploding sparks
bool anyActive = false;
for (int i = 0; i < NUM_SPARKS; i++) {
if (sparks[i].active) {
sparks[i].speed += GRAVITY;
sparks[i].pos += sparks[i].speed;
int pos = (int)sparks[i].pos;
if (pos >= 0 && pos < NUM_LEDS) {
leds[pos] += sparks[i].color;
sparks[i].color.fadeToBlackBy(25); // Dim over time
anyActive = true;
} else {
sparks[i].active = false;
}
}
}
if (!anyActive) {
// Restart
exploding = false;
flarePos = 0;
hue += 32;
}
}
FastLED.show();
delay(30);
}