diff --git a/include/Animation/AllAnimations.h b/include/Animation/AllAnimations.h index 3a2b3ca..bd0e38e 100644 --- a/include/Animation/AllAnimations.h +++ b/include/Animation/AllAnimations.h @@ -6,3 +6,4 @@ #include "SnowfallAnimation.h" #include "FadeToColorAnimation.h" #include "ImageScrollerAnimation.h" +#include "MatrixCodeAnimation.h" diff --git a/include/Animation/AnimationController.h b/include/Animation/AnimationController.h index aa2338f..1380d32 100644 --- a/include/Animation/AnimationController.h +++ b/include/Animation/AnimationController.h @@ -16,6 +16,7 @@ class AnimationController FIRE_COLD = 1, SNOWFALL = 2, FONT_TEST = 3, + MATRIX_CODE = 4, NUM_DEFAULT_ANIMATIONS }; @@ -24,7 +25,8 @@ class AnimationController "Hot Fire", "Cold Fire", "Snowfall", - "Font Test" + "Font Test", + "Matrix Code" }; AnimationController(Fader *fader); diff --git a/include/Animation/MatrixCodeAnimation.h b/include/Animation/MatrixCodeAnimation.h new file mode 100644 index 0000000..8324f57 --- /dev/null +++ b/include/Animation/MatrixCodeAnimation.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +#include "Animation.h" + +class MatrixCodeAnimation : public Animation +{ + public: + MatrixCodeAnimation(Fader *fader, int vspeed = 80, int spawn_rate = 8); + + void loop(uint64_t frame) override; + + void stop(void) override + { + m_stopping = true; + } + + void reset(void) override; + + private: + struct Pixel + { + int x; // position in 1/1 led + int y; // position in 1/256 led + int vspeed; // vertical speed in 1/256 leds per frame + }; + + std::default_random_engine m_gen; + + std::list m_pixels; + int m_vspeed; + int m_spawnRate; // average pixels per second + + bool m_stopping; +}; diff --git a/src/Animation/AnimationController.cpp b/src/Animation/AnimationController.cpp index 4a23da0..784fa44 100644 --- a/src/Animation/AnimationController.cpp +++ b/src/Animation/AnimationController.cpp @@ -49,6 +49,10 @@ void AnimationController::changeAnimation(AnimationController::DefaultAnimation changeAnimation(std::unique_ptr(new SnowfallAnimation(m_fader)), transition); break; + case MATRIX_CODE: + changeAnimation(std::unique_ptr(new MatrixCodeAnimation(m_fader)), transition); + break; + case FONT_TEST: { Bitmap bmp(0, 0); diff --git a/src/Animation/MatrixCodeAnimation.cpp b/src/Animation/MatrixCodeAnimation.cpp new file mode 100644 index 0000000..53adb0c --- /dev/null +++ b/src/Animation/MatrixCodeAnimation.cpp @@ -0,0 +1,57 @@ +#include "Animation/MatrixCodeAnimation.h" + +#include + +MatrixCodeAnimation::MatrixCodeAnimation(Fader *fader, int vspeed, int spawn_rate) + : Animation(fader), + m_vspeed(vspeed), + m_spawnRate(spawn_rate) +{ + reset(); +} + +void MatrixCodeAnimation::loop(uint64_t frame) +{ + int nled = m_fader->modules_per_strip(); + int nstrip = m_fader->strips(); + + if(frame == 0) { + m_fader->set_fadestep(8); + } + + // create new pixels + std::uniform_int_distribution spawnRNG(0, (60*nstrip / m_spawnRate) - 1); + std::uniform_int_distribution vspeedRNG(m_vspeed - 32, m_vspeed + 32); + + if(!m_stopping) { + for(int i = 0; i < nstrip; i++) { + if(spawnRNG(m_gen) == 0) { + m_pixels.emplace_back(Pixel{i, 256*nled-1, vspeedRNG(m_gen)}); + } + } + } + + m_fader->fade_color(Fader::Color{0, 0, 0, 0}); + + // move all pixels down and render them + for(auto &px: m_pixels) { + px.y -= px.vspeed; + if(px.y >= 0) { + m_fader->set_color(px.x, px.y/256, Fader::Color{0, 192, 0, 16}); + } + } + + m_pixels.remove_if( + [](const Pixel &px) { return px.y < 0; }); + + m_fader->update(); + m_running = !m_stopping || m_fader->something_changed(); +} + +void MatrixCodeAnimation::reset(void) +{ + m_pixels.clear(); + + m_stopping = false; + m_running = true; +}