diff --git a/src/animations/Rain.cpp b/src/animations/Rain.cpp new file mode 100644 index 0000000..42a4f2a --- /dev/null +++ b/src/animations/Rain.cpp @@ -0,0 +1,45 @@ +#include "Rain.h" +#include "../Static.h" + +RainAnimation::RainAnimation() : Figment("Rain") +{ +} + +void +RainAnimation::render(Display* dpy) const +{ + Surface sfc = Surface(dpy, {0, 0}, {255, 255}); + uint8_t noiseY = sin8(m_noiseOffset % 255); + uint8_t noiseX = cos8(m_noiseOffset % 255); + sfc.paintShader([=](CRGB& pixel, const VirtualCoordinates& coords, const PhysicalCoordinates, const VirtualCoordinates& surfaceCoords) { + pixel = CHSV(m_hue, inoise8(noiseX + coords.x, coords.y), inoise8(m_noiseOffset + coords.x, noiseY + coords.y)); + }); + m_drops.render(dpy); +} + +void +RainAnimation::loop() +{ + EVERY_N_MILLISECONDS(250) { + m_drops.update(); + } + EVERY_N_MILLISECONDS(60) { + m_hue.update(1); + m_curColor.h = m_hue; + } + m_noiseOffset += 1; +} + +void +RainAnimation::handleEvent(const InputEvent& evt) { + if (evt.intent == InputEvent::SetColor) { + CHSV next = rgb2hsv_approximate(evt.asRGB()); + m_hue.set(next.h); + m_drops.forEach([=](Raindrop& drop) { + drop.nextColor = next; + }); + } +} + +STATIC_ALLOC(RainAnimation); +STATIC_TASK(RainAnimation); diff --git a/src/animations/Rain.h b/src/animations/Rain.h new file mode 100644 index 0000000..7debb58 --- /dev/null +++ b/src/animations/Rain.h @@ -0,0 +1,48 @@ +#pragma once +#include + +class RainAnimation: public Figment { +private: + struct Raindrop { + int size = 20; + int x = random(255); + int y = random(255); + CHSV fg{180, 255, 255}; + CHSV nextColor{180, 255, 255}; + + void render(Display* dpy) const { + Surface sfc{dpy, {x - size, y - size}, {x + size, y + size}}; + paint(sfc); + } + + void paint(Surface& sfc) const { + sfc.paintShader([=](CRGB& pixel, const VirtualCoordinates& coords, const PhysicalCoordinates, const VirtualCoordinates& surfaceCoords) { + int distance = 255 - (min(128, abs(128 - surfaceCoords.x)) + min(128, abs(128 - surfaceCoords.y))); + pixel += CHSV{fg.h, fg.s, scale8_video(fg.v, distance)}; + }); + } + + void update() { + if (random(255) >= 100) { + y++; + if (y >= 255) { + y = 0; + x += 13; + x %= 255; + fg = nextColor; + } + } + } + }; + + SpriteList m_drops; + uint16_t m_noiseOffset; + CHSV m_curColor{180, 255, 255}; + AnimatedNumber m_hue; +public: + RainAnimation(); + //void handleEvent(const InputEvent& evt) override; + void loop() override; + void render(Display* dpy) const override; + void handleEvent(const InputEvent& evt) override; +};