|
@ -0,0 +1,122 @@ |
|
|
|
|
|
#if GARLAND_SUPPORT |
|
|
|
|
|
|
|
|
|
|
|
#include <vector> |
|
|
|
|
|
|
|
|
|
|
|
#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<Color> 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<Fountain> fountains; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
#endif // GARLAND_SUPPORT |