Added Fireworks animation – Happy new year!
This commit is contained in:
parent
6a71074b4b
commit
905c3fce7b
|
@ -7,3 +7,4 @@
|
|||
#include "FadeToColorAnimation.h"
|
||||
#include "ImageScrollerAnimation.h"
|
||||
#include "MatrixCodeAnimation.h"
|
||||
#include "FireworkAnimation.h"
|
||||
|
|
|
@ -17,6 +17,7 @@ class AnimationController
|
|||
SNOWFALL = 2,
|
||||
FONT_TEST = 3,
|
||||
MATRIX_CODE = 4,
|
||||
FIREWORK = 5,
|
||||
|
||||
NUM_DEFAULT_ANIMATIONS
|
||||
};
|
||||
|
@ -26,7 +27,8 @@ class AnimationController
|
|||
"Cold Fire",
|
||||
"Snowfall",
|
||||
"Font Test",
|
||||
"Matrix Code"
|
||||
"Matrix Code",
|
||||
"Fireworks"
|
||||
};
|
||||
|
||||
AnimationController(Fader *fader);
|
||||
|
|
64
include/Animation/FireworkAnimation.h
Normal file
64
include/Animation/FireworkAnimation.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
|
||||
#include <random>
|
||||
#include <list>
|
||||
#include <array>
|
||||
|
||||
#include "Animation.h"
|
||||
|
||||
class FireworkRocket
|
||||
{
|
||||
private:
|
||||
enum LaunchPhase {
|
||||
PHASE_RISING,
|
||||
PHASE_SPREADING,
|
||||
PHASE_DONE
|
||||
};
|
||||
|
||||
std::array<int, 6> m_flareXPos;
|
||||
std::array<int, 6> m_flareYPos;
|
||||
|
||||
LaunchPhase m_phase;
|
||||
|
||||
int m_rocketXPos;
|
||||
int m_rocketYPos;
|
||||
|
||||
int m_targetHeight;
|
||||
int m_riseSpeed;
|
||||
|
||||
uint64_t m_spreadStartFrame;
|
||||
|
||||
Fader::Color m_color;
|
||||
|
||||
public:
|
||||
FireworkRocket(int start_x, int target_height, int rise_speed, const Fader::Color &color);
|
||||
|
||||
void move(uint64_t frame);
|
||||
void render(Fader *fader);
|
||||
|
||||
bool done(void) const { return m_phase == PHASE_DONE; }
|
||||
};
|
||||
|
||||
class FireworkAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
FireworkAnimation(Fader *fader, int vspeed = 128, int spawn_rate = 8);
|
||||
|
||||
void loop(uint64_t frame) override;
|
||||
|
||||
void stop(void) override
|
||||
{
|
||||
m_stopping = true;
|
||||
}
|
||||
|
||||
void reset(void) override;
|
||||
|
||||
private:
|
||||
std::default_random_engine m_gen;
|
||||
|
||||
std::list<FireworkRocket> m_rockets;
|
||||
int m_vspeed;
|
||||
int m_spawnRate; // average pixels per second
|
||||
|
||||
bool m_stopping;
|
||||
};
|
|
@ -53,6 +53,10 @@ void AnimationController::changeAnimation(AnimationController::DefaultAnimation
|
|||
changeAnimation(std::unique_ptr<Animation>(new MatrixCodeAnimation(m_fader)), transition);
|
||||
break;
|
||||
|
||||
case FIREWORK:
|
||||
changeAnimation(std::unique_ptr<Animation>(new FireworkAnimation(m_fader, 64, 1)), transition);
|
||||
break;
|
||||
|
||||
case FONT_TEST:
|
||||
{
|
||||
Bitmap bmp(0, 0);
|
||||
|
|
138
src/Animation/FireworkAnimation.cpp
Normal file
138
src/Animation/FireworkAnimation.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
#include "Animation/FireworkAnimation.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "fasttrigon.h"
|
||||
|
||||
FireworkRocket::FireworkRocket(int start_x, int target_height, int rise_speed, const Fader::Color &color)
|
||||
: m_phase(PHASE_RISING), m_rocketXPos(start_x*256), m_rocketYPos(0*256), m_targetHeight(target_height*256), m_riseSpeed(rise_speed), m_color(color)
|
||||
{
|
||||
}
|
||||
|
||||
void FireworkRocket::move(uint64_t frame)
|
||||
{
|
||||
switch(m_phase) {
|
||||
case PHASE_RISING:
|
||||
if(m_rocketYPos < m_targetHeight) {
|
||||
m_rocketYPos += m_riseSpeed;
|
||||
} else {
|
||||
for(size_t i = 0; i < m_flareXPos.size(); i++) {
|
||||
m_flareXPos[i] = m_rocketXPos;
|
||||
m_flareYPos[i] = m_rocketYPos;
|
||||
}
|
||||
|
||||
m_spreadStartFrame = frame;
|
||||
m_phase = PHASE_SPREADING;
|
||||
}
|
||||
break;
|
||||
|
||||
case PHASE_SPREADING:
|
||||
for(size_t i = 0; i < m_flareXPos.size(); i++) {
|
||||
int speedX = fasttrigon::fastcos(fasttrigon::LUT_SIZE / 12 + i * fasttrigon::LUT_SIZE / m_flareXPos.size()) / 2;
|
||||
int speedY = fasttrigon::fastsin(fasttrigon::LUT_SIZE / 12 + i * fasttrigon::LUT_SIZE / m_flareXPos.size()) / 2;
|
||||
|
||||
m_flareXPos[i] += speedX;
|
||||
m_flareYPos[i] += speedY;
|
||||
}
|
||||
|
||||
if((frame - m_spreadStartFrame) >= 20) {
|
||||
m_phase = PHASE_DONE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PHASE_DONE:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void FireworkRocket::render(Fader *fader)
|
||||
{
|
||||
uint32_t nled = fader->modules_per_strip();
|
||||
uint32_t nstrip = fader->strips();
|
||||
|
||||
switch(m_phase) {
|
||||
case PHASE_RISING:
|
||||
fader->add_color(m_rocketXPos/256, m_rocketYPos/256, Fader::Color{32, 16, 0, 0});
|
||||
break;
|
||||
|
||||
case PHASE_SPREADING:
|
||||
for(size_t i = 0; i < m_flareXPos.size(); i++) {
|
||||
int x = (m_flareXPos[i]/256 + nstrip) % nstrip;
|
||||
int y = (m_flareYPos[i]/256);
|
||||
|
||||
if(y >= nled || y < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fader->add_color(x, y, m_color);
|
||||
}
|
||||
break;
|
||||
|
||||
case PHASE_DONE:
|
||||
// nothing more
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FireworkAnimation::FireworkAnimation(Fader *fader, int vspeed, int spawn_rate)
|
||||
: Animation(fader),
|
||||
m_vspeed(vspeed),
|
||||
m_spawnRate(spawn_rate)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void FireworkAnimation::loop(uint64_t frame)
|
||||
{
|
||||
//int nled = m_fader->modules_per_strip();
|
||||
int nstrip = m_fader->strips();
|
||||
|
||||
if(frame == 0) {
|
||||
m_fader->set_fadestep(16);
|
||||
}
|
||||
|
||||
m_fader->fade_color(Fader::Color{0,0,0,0});
|
||||
|
||||
// create new pixels
|
||||
std::uniform_int_distribution<int> spawnRNG(0, (60*nstrip / m_spawnRate) - 1);
|
||||
std::uniform_int_distribution<int> vspeedRNG(m_vspeed - 16, m_vspeed + 16);
|
||||
|
||||
for(int i = 0; i < nstrip; i++) {
|
||||
if(spawnRNG(m_gen) == 0) {
|
||||
std::uniform_int_distribution<int> stripRNG(0, nstrip-1);
|
||||
std::uniform_int_distribution<int> heightRNG(5, 13);
|
||||
std::uniform_int_distribution<int16_t> colorRNG(0, 15);
|
||||
|
||||
int16_t colorMask = colorRNG(m_gen);
|
||||
|
||||
m_rockets.emplace_back(FireworkRocket{stripRNG(m_gen), heightRNG(m_gen), vspeedRNG(m_gen),
|
||||
Fader::Color{
|
||||
255 * ((colorMask >> 3) & 0x01),
|
||||
255 * ((colorMask >> 2) & 0x01),
|
||||
255 * ((colorMask >> 1) & 0x01),
|
||||
128 * ((colorMask >> 0) & 0x01)
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
// move all pixels down and render them
|
||||
for(auto &rocket: m_rockets) {
|
||||
rocket.move(frame);
|
||||
rocket.render(m_fader);
|
||||
}
|
||||
|
||||
m_rockets.remove_if(
|
||||
[](const FireworkRocket &r) { return r.done(); });
|
||||
|
||||
m_fader->update();
|
||||
m_running = !m_stopping || m_fader->something_changed();
|
||||
}
|
||||
|
||||
void FireworkAnimation::reset(void)
|
||||
{
|
||||
m_rockets.clear();
|
||||
|
||||
m_stopping = false;
|
||||
m_running = true;
|
||||
}
|
Loading…
Reference in a new issue