137 lines
3.1 KiB
C++
137 lines
3.1 KiB
C++
#ifndef NEW_YEAR_FIREWORK_H
|
|
#define NEW_YEAR_FIREWORK_H
|
|
|
|
#include "BASICS.h"
|
|
#include "display/Vector.h"
|
|
#include "display/Display.h"
|
|
|
|
class Firework {
|
|
|
|
enum State {
|
|
INITIAL, RISE, EXPLODE, SPARKLE
|
|
};
|
|
|
|
Display *display{};
|
|
|
|
uint32_t color{};
|
|
|
|
State state = RISE;
|
|
|
|
Vector position;
|
|
|
|
double destinationHeight = 0;
|
|
|
|
double explosionRadius = 0;
|
|
|
|
double sparkleMax = 0;
|
|
|
|
double explosion{};
|
|
|
|
double sparkle{};
|
|
|
|
public:
|
|
|
|
void init(Display *_display) {
|
|
this->display = _display;
|
|
reset();
|
|
}
|
|
|
|
void reset() {
|
|
position.set((double) random(display->width), display->height);
|
|
color = random(16777216);
|
|
state = INITIAL;
|
|
|
|
destinationHeight = display->height / 2.0 + (double) random(5) - 2;
|
|
explosionRadius = (double) random(3) + 1;
|
|
sparkleMax = 100;
|
|
|
|
explosion = 0.0;
|
|
sparkle = 0.0;
|
|
}
|
|
|
|
void launch() {
|
|
if (state != INITIAL) {
|
|
Serial.println("ERROR: Cannot start Firework. Already started.");
|
|
return;
|
|
}
|
|
state = RISE;
|
|
}
|
|
|
|
void step(microseconds_t dt) {
|
|
switch (state) {
|
|
case INITIAL:
|
|
break;
|
|
case RISE:
|
|
if (position.y <= destinationHeight) {
|
|
state = EXPLODE;
|
|
}
|
|
break;
|
|
case EXPLODE:
|
|
if (explosion >= explosionRadius) {
|
|
state = SPARKLE;
|
|
}
|
|
break;
|
|
case SPARKLE:
|
|
if (sparkle >= sparkleMax) {
|
|
reset();
|
|
}
|
|
break;
|
|
}
|
|
switch (state) {
|
|
case INITIAL:
|
|
break;
|
|
case RISE:
|
|
position.y = doStep(position.y, 0.0, display->height, 1000, -dt);
|
|
break;
|
|
case EXPLODE:
|
|
explosion = doStep(explosion, 0.0, explosionRadius, 500, +dt);
|
|
break;
|
|
case SPARKLE:
|
|
sparkle = doStep(sparkle, 0.0, sparkleMax, 1000, +dt);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void draw() {
|
|
Vector p;
|
|
switch (state) {
|
|
case INITIAL:
|
|
break;
|
|
case RISE:
|
|
display->set(&position, COLOR_YELLOW);
|
|
break;
|
|
case EXPLODE:
|
|
drawParticle(p, +0.0, +1.0);
|
|
drawParticle(p, +0.7, +0.7);
|
|
drawParticle(p, +1.0, +0.0);
|
|
drawParticle(p, +0.7, -0.7);
|
|
drawParticle(p, +0.0, -1.0);
|
|
drawParticle(p, -0.7, -0.7);
|
|
drawParticle(p, -1.0, +0.0);
|
|
drawParticle(p, -0.7, +0.7);
|
|
break;
|
|
case SPARKLE:
|
|
if (randomBool(2)) drawParticle(p, +0.0, +1.0);
|
|
if (randomBool(2)) drawParticle(p, +0.7, +0.7);
|
|
if (randomBool(2)) drawParticle(p, +1.0, +0.0);
|
|
if (randomBool(2)) drawParticle(p, +0.7, -0.7);
|
|
if (randomBool(2)) drawParticle(p, +0.0, -1.0);
|
|
if (randomBool(2)) drawParticle(p, -0.7, -0.7);
|
|
if (randomBool(2)) drawParticle(p, -1.0, +0.0);
|
|
if (randomBool(2)) drawParticle(p, -0.7, +0.7);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void drawParticle(Vector &p, double x, double y) {
|
|
display->set(p.set(position)->add(x * explosion, y * explosion), color);
|
|
}
|
|
|
|
bool isAlive() {
|
|
return state != INITIAL;
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|