#include <FastLED.h>
#define LED_PIN 5
#define NUM_LEDS 59
#define BRIGHTNESS 255
#define ROCKET_LEDS 14
#define TAIL_LEDS 9
#define NUM_TAILS 5
CRGB leds[NUM_LEDS];
int tailStart[NUM_TAILS] = {14, 23, 32, 41, 50};
byte currentEffect = 0;
// =====================================================
// ===================== EFFECT 1 ======================
// =====================================================
byte r1_pos=0, r2_pos=255;
byte r1_hue, r2_hue;
bool r1_exploding=false, r2_exploding=false;
byte r1_expStep=0, r2_expStep=0;
bool effect1Done=false;
void resetEffect1(){
r1_pos=0; r2_pos=255;
r1_hue=random8();
r1_exploding=false; r2_exploding=false;
r1_expStep=0; r2_expStep=0;
effect1Done=false;
}
void effect1(){
fadeToBlackBy(leds, NUM_LEDS, 35);
// ROCKET 1
if(!r1_exploding){
leds[r1_pos] = CHSV(r1_hue,255,255);
r1_pos++;
if(r2_pos==255 && r1_pos>=ROCKET_LEDS-4){
r2_pos=0;
r2_hue=random8();
}
if(r1_pos>=ROCKET_LEDS) r1_exploding=true;
}
else{
if(r1_expStep<TAIL_LEDS){
for(int t=0;t<NUM_TAILS;t++)
leds[tailStart[t]+r1_expStep]=CHSV(r1_hue,255,255);
r1_expStep++;
}
}
// ROCKET 2
if(r2_pos!=255){
if(!r2_exploding){
leds[r2_pos]=CHSV(r2_hue,255,255);
r2_pos++;
if(r2_pos>=ROCKET_LEDS) r2_exploding=true;
}
else{
if(r2_expStep<TAIL_LEDS){
for(int t=0;t<NUM_TAILS;t++)
leds[tailStart[t]+r2_expStep]=CHSV(r2_hue,255,255);
r2_expStep++;
}
else{
effect1Done=true; // ✅ kết thúc effect 1
}
}
}
}
// =====================================================
// ===================== EFFECT 2 ======================
// =====================================================
int e2_rocketPos=0;
bool e2_exploded=false;
bool e2_sparkle=false;
int e2_radius=0;
int e2_timer=0;
bool effect2Done=false;
CRGB aqua = CRGB(0,255,180);
CRGB gold = CRGB(255,180,0);
void resetEffect2(){
e2_rocketPos=0;
e2_exploded=false;
e2_sparkle=false;
e2_radius=0;
e2_timer=0;
effect2Done=false;
}
void effect2(){
fadeToBlackBy(leds, NUM_LEDS, 28);
if(!e2_exploded && !e2_sparkle){
leds[e2_rocketPos]=aqua;
e2_rocketPos++;
if(e2_rocketPos>=ROCKET_LEDS) e2_exploded=true;
}
else if(e2_exploded && !e2_sparkle){
if(e2_radius<TAIL_LEDS){
for(int t=0;t<NUM_TAILS;t++)
leds[tailStart[t]+e2_radius]=aqua;
e2_radius++;
}
else e2_sparkle=true;
}
else{
for(int i=0;i<4;i++){
int t=random(NUM_TAILS);
int p=random(TAIL_LEDS);
leds[tailStart[t]+p]=gold;
}
e2_timer++;
if(e2_timer>40) effect2Done=true; // ✅ kết thúc effect 2
}
}
// =====================================================
// ===================== EFFECT 3 ======================
// =====================================================
int e3_rocketPos=0;
bool e3_exploded=false;
int e3_radius=0;
uint8_t e3_hue;
bool effect3Done=false;
void resetEffect3(){
e3_rocketPos=0;
e3_exploded=false;
e3_radius=0;
e3_hue=random8();
effect3Done=false;
}
void effect3(){
fadeToBlackBy(leds, NUM_LEDS, 30);
if(!e3_exploded){
leds[e3_rocketPos]=CHSV(e3_hue,255,255);
e3_rocketPos++;
if(e3_rocketPos>=ROCKET_LEDS) e3_exploded=true;
}
else{
if(e3_radius<TAIL_LEDS){
for(int t=0;t<NUM_TAILS;t++)
leds[tailStart[t]+e3_radius]=CHSV(e3_hue,255,255);
e3_radius++;
}
else{
effect3Done=true; // ✅ kết thúc effect 3
}
}
}
// =====================================================
// ======================= SETUP =======================
// =====================================================
void setup(){
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
randomSeed(analogRead(0));
resetEffect1();
}
// =====================================================
// ======================== LOOP =======================
// =====================================================
void loop(){
switch(currentEffect){
case 0:
effect1();
if(effect1Done){
currentEffect=1;
FastLED.clear();
resetEffect2();
}
break;
case 1:
effect2();
if(effect2Done){
currentEffect=2;
FastLED.clear();
resetEffect3();
}
break;
case 2:
effect3();
if(effect3Done){
currentEffect=0;
FastLED.clear();
resetEffect1();
}
break;
}
FastLED.show();
delay(25);
}