diff --git a/code/espurna/garland.cpp b/code/espurna/garland.cpp index f748ce79..7866035d 100644 --- a/code/espurna/garland.cpp +++ b/code/espurna/garland.cpp @@ -139,7 +139,7 @@ Adafruit_NeoPixel pixels = Adafruit_NeoPixel(GARLAND_LEDS, GARLAND_D_PIN, NEO_GR Scene scene(&pixels); Anim* anims[] = {new AnimGlow(), new AnimStart(), new AnimPixieDust(), new AnimSparkr(), new AnimRun(), new AnimStars(), new AnimSpread(), - new AnimRandCyc(), new AnimFly(), new AnimComets(), new AnimAssemble(), new AnimDolphins(), new AnimSalut()}; + new AnimRandCyc(), new AnimFly(), new AnimComets(), new AnimAssemble(), new AnimDolphins(), new AnimSalut(), new AnimFountain()}; constexpr size_t animsSize() { return sizeof(anims)/sizeof(anims[0]); } diff --git a/code/espurna/garland/animations/anim_dolphins.h b/code/espurna/garland/animations/anim_dolphins.h index 5c083bef..bb03acdd 100644 --- a/code/espurna/garland/animations/anim_dolphins.h +++ b/code/espurna/garland/animations/anim_dolphins.h @@ -90,7 +90,7 @@ class AnimDolphins : public Anim { return false; } else { - // dolphin accupy space for future movement + // dolphin occupy space for future movement int s = p < 0 ? 0 : p; for (int i = s; i < len; ++i) { seq[start + i * dir] = 1; diff --git a/code/espurna/garland/animations/anim_fountain.h b/code/espurna/garland/animations/anim_fountain.h new file mode 100644 index 00000000..971d50f5 --- /dev/null +++ b/code/espurna/garland/animations/anim_fountain.h @@ -0,0 +1,122 @@ +#if GARLAND_SUPPORT + +#include + +#include "../anim.h" +#include "../color.h" +#include "../palette.h" + +//------------------------------------------------------------------------------ +class AnimFountain : public Anim { + public: + AnimFountain() : Anim("Fountain") { + cycleFactor = 4; + } + + void SetupImpl() override { + fountains.clear(); + for (int i = 0; i < 3; ++i) + fountains.emplace_back(palette, numLeds); + } + + void Run() override { + for (int i = 0; i < numLeds; ++i) { + leds[i] = 0; + seq[i] = 0; + } + + // Run fountains animation. Fill seq (occupied space) + for (auto& d : fountains) + d.Run(leds, seq); + + // Try to recreate finished fountains + for (auto& d : fountains) { + if (d.done) { + for (int i = 1; i < 5; ++i) { + Fountain new_fountain(palette, numLeds); + if (new_fountain.HaveEnoughSpace(seq)) { + std::swap(d, new_fountain); + break; + } + } + } + } + } + + private: + struct Fountain { + bool done = false; + int len = secureRandom(5, 10); + int speed = secureRandom(1, 3); + int dir = 1; + int head = 0; + int start; + // Color color; + std::vector points; + Fountain(Palette* pal, uint16_t numLeds) : start(secureRandom(len, numLeds - len)), /*color(pal->getRndInterpColor()),*/ points(len) { + // DEBUG_MSG_P(PSTR("[GARLAND] Fountain created start = %d len = %d dir = %d cr = %d cg = %d cb = %d\n"), start, len, dir, color.r, color.g, color.b); + if (secureRandom(10) > 5) { + start = numLeds - start; + dir = -1; + } + + // int halflen = len / 2; + for (int i = 0; i < len; ++i) { + points[i] = pal->getRndInterpColor(); + // DEBUG_MSG_P(PSTR("[GARLAND] Fountain i=%d cr = %d cg = %d cb = %d\n"), i, points[i].r, points[i].g, points[i].b); + } + } + + bool Run(Color* leds, byte* seq) { + if (done) + return false; + + int p = 0; + for (int i = 0; i < len; ++i) { + p = head - i; + if (p >= 0 && p < len) { + if (dir == 1) { + leds[start + p] = points[i]; + leds[start - p] = points[i]; + } else { + leds[start + len - p] = points[i]; + leds[start - len + p] = points[i]; + } + } + } + + head += speed; + + // if tail moved out of len then fountain is done + if (p >= len) { + done = true; + return false; + } + else { + // fountain occupy space for future movement + int s = p < 0 ? 0 : p; + for (int i = s; i < len; ++i) { + seq[start + i] = 1; + seq[start - i] = 1; + } + } + + return true; + } + + // Decide that fountain have ehough space if seq of len before it is empty + bool HaveEnoughSpace(byte* seq) { + for (int i = 0; i < len; ++i) { + if (seq[start + i] != 0 && seq[start - i] != 0) { + // DEBUG_MSG_P(PSTR("[GARLAND] Fountain chaven't enouhg space to move.\n")); + return false; + } + } + return true; + } + }; + + std::vector fountains; +}; + +#endif // GARLAND_SUPPORT diff --git a/code/espurna/garland/scene.h b/code/espurna/garland/scene.h index 0d72c537..5a66b9e5 100644 --- a/code/espurna/garland/scene.h +++ b/code/espurna/garland/scene.h @@ -16,6 +16,7 @@ Inspired by https://github.com/Vasil-Pahomov/ArWs2812 (currently https://github. #include "animations/anim_assemble.h" #include "animations/anim_comets.h" #include "animations/anim_dolphins.h" +#include "animations/anim_fountain.h" #include "animations/anim_fly.h" #include "animations/anim_glow.h" #include "animations/anim_pixiedust.h"