diff --git a/wled00/FX.cpp b/wled00/FX.cpp index c257e5d5e..dac4aade4 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -2437,3 +2437,118 @@ uint16_t WS2812FX::mode_candle() return FRAMETIME; } + + +/* +/ Fireworks in starburst effect +/ based on the video: https://www.reddit.com/r/arduino/comments/c3sd46/i_made_this_fireworks_effect_for_my_led_strips/ +/ Speed sets frequency of new starbursts, intensity is the intensity of the burst +*/ +#define STARBURST_MAX_FRAG 12 + +typedef struct particle { + CRGB color; + uint32_t birth =0; + uint32_t last =0; + float vel =0; + uint16_t pos =-1; + float fragment[STARBURST_MAX_FRAG]; +} star; + +uint16_t WS2812FX::mode_starburst(void) { + uint32_t it = millis(); + + const uint8_t numStars = 15; + static star stars[numStars]; + float maxSpeed = 375.0f; // Max velocity + float particleIgnition = 250.0f; // How long to "flash" + float particleFadeTime = 1500.0f; // Fade out time + + for (int j = 0; j < numStars; j++) + { + // speed to adjust chance of a burst, max is nearly always. + if (random8((144-(SEGMENT.speed >> 1))) == 0 && stars[j].birth == 0) + { + // Pick a random color and location. + uint16_t startPos = random16(SEGLEN-1); + float multiplier = (float)(random8())/255.0 * 1.0; + + stars[j].color = col_to_crgb(color_wheel(random8())); + stars[j].pos = startPos; + stars[j].vel = maxSpeed * (float)(random8())/255.0 * multiplier; + stars[j].birth = it; + stars[j].last = it; + // more fragments means larger burst effect + int num = random8(3,6 + (SEGMENT.intensity >> 5)); + + for (int i=0; i < STARBURST_MAX_FRAG; i++) { + if (i < num) stars[j].fragment[i] = startPos; + else stars[j].fragment[i] = -1; + } + } + } + + fill(SEGCOLOR(1)); + + for (int j=0; j> 1; + + if (stars[j].fragment[i] > 0) { + //all fragments travel right, will be mirrored on other side + stars[j].fragment[i] += stars[j].vel * dt * (float)var/3.0; + } + } + stars[j].last = it; + stars[j].vel -= 3*stars[j].vel*dt; + } + + CRGB c = stars[j].color; + + // If the star is brand new, it flashes white briefly. + // Otherwise it just fades over time. + float fade = 0.0f; + float age = it-stars[j].birth; + + if (age < particleIgnition) { + c = col_to_crgb(color_blend(WHITE, crgb_to_col(c), 254.5f*((age / particleIgnition)))); + } else { + // Figure out how much to fade and shrink the star based on + // its age relative to its lifetime + if (age > particleIgnition + particleFadeTime) { + fade = 1.0f; // Black hole, all faded out + stars[j].birth = 0; + c = col_to_crgb(SEGCOLOR(1)); + } else { + age -= particleIgnition; + fade = (age / particleFadeTime); // Fading star + byte f = 254.5f*fade; + c = col_to_crgb(color_blend(crgb_to_col(c), SEGCOLOR(1), f)); + } + } + + float particleSize = (1.0 - fade) * 2; + + for (uint8_t index=0; index < STARBURST_MAX_FRAG*2; index++) { + bool mirrored = index & 0x1; + uint8_t i = index >> 1; + if (stars[j].fragment[i] > 0) { + float loc = stars[j].fragment[i]; + if (mirrored) loc -= (loc-stars[j].pos)*2; + int start = loc - particleSize; + int end = loc + particleSize; + if (start < 0) start = 0; + if (start == end) end++; + if (end > SEGLEN) end = SEGLEN; + for (int p = start; p < end; p++) { + setPixelColor(SEGMENT.start+p, c.r, c.g, c.b); + } + } + } + } + return FRAMETIME; +} diff --git a/wled00/FX.h b/wled00/FX.h index 8f2ba95ba..bb33741d0 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -91,7 +91,7 @@ #define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE ) #define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED ) -#define MODE_COUNT 89 +#define MODE_COUNT 90 #define FX_MODE_STATIC 0 #define FX_MODE_BLINK 1 @@ -182,6 +182,7 @@ #define FX_MODE_SPOTS_FADE 86 #define FX_MODE_GLITTER 87 #define FX_MODE_CANDLE 88 +#define FX_MODE_STARBURST 89 class WS2812FX { @@ -350,6 +351,7 @@ class WS2812FX { _mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade; _mode[FX_MODE_GLITTER] = &WS2812FX::mode_glitter; _mode[FX_MODE_CANDLE] = &WS2812FX::mode_candle; + _mode[FX_MODE_STARBURST] = &WS2812FX::mode_starburst; _brightness = DEFAULT_BRIGHTNESS; currentPalette = CRGBPalette16(CRGB::Black); @@ -532,7 +534,8 @@ class WS2812FX { mode_spots(void), mode_spots_fade(void), mode_glitter(void), - mode_candle(void); + mode_candle(void), + mode_starburst(void); private: @@ -607,9 +610,9 @@ const char JSON_mode_names[] PROGMEM = R"=====([ "Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Red & Blue","Stream", "Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","Police","Police All", "Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet", -"Scanner Dual ","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", +"Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise", "Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple", -"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle" +"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst" ])====="; diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 6a1a7b072..c77eae7ac 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -98,7 +98,7 @@ //version code in format yymmddb (b = daily build) -#define VERSION 1912311 +#define VERSION 1912312 char versionString[] = "0.9.0-b2";