139 lines
4.1 KiB
C++
139 lines
4.1 KiB
C++
#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_8BIT(fasttrigon::fastcos(fasttrigon::LUT_SIZE / 12 + i * fasttrigon::LUT_SIZE / m_flareXPos.size())) / 2;
|
|
int speedY = FASTTRIGON_8BIT(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;
|
|
}
|