Rewrote effect firework. Now it kinda works.
This commit is contained in:
parent
6ba2854a8d
commit
711719921a
@ -1,7 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "prototypes.h"
|
||||
#include "functions.h"
|
||||
#include "Effect.h"
|
||||
|
||||
class FireworkEffect : public Effect {
|
||||
void loop();
|
||||
enum FireworkDotType { FIREWORK_DOT_NONE, FIREWORK_DOT_SHELL, FIREWORK_DOT_SPARK };
|
||||
|
||||
#define EFFECT_FIREWORK_DRAG 255
|
||||
#define EFFECT_FIREWORK_BOUNCE 200
|
||||
#define EFFECT_FIREWORK_GRAVITY 10
|
||||
#define EFFECT_FIREWORK_SPARKS 12
|
||||
|
||||
class FireworkEffect;
|
||||
|
||||
class FireworkEffectDot {
|
||||
private:
|
||||
Window* _window;
|
||||
FireworkEffect* _main;
|
||||
accum88 _x;
|
||||
accum88 _y;
|
||||
saccum78 _xv;
|
||||
saccum78 _yv;
|
||||
accum88 _r;
|
||||
CRGB _color;
|
||||
|
||||
void _screenscale(accum88 a, byte n, byte& screen, byte& screenerr);
|
||||
int16_t _scale15by8_local(int16_t i, fract8 scale);
|
||||
public:
|
||||
byte show;
|
||||
FireworkDotType type;
|
||||
|
||||
FireworkEffectDot(Window* w, FireworkEffect* e);
|
||||
void draw();
|
||||
void move();
|
||||
void ground_launch();
|
||||
void sky_burst(accum88 basex, accum88 basey, saccum78 basedv, CRGB& basecolor);
|
||||
};
|
||||
|
||||
class FireworkEffect : public Effect {
|
||||
private:
|
||||
Window* window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6);
|
||||
bool _skyburst = 0;
|
||||
|
||||
accum88 _burst_x;
|
||||
accum88 _burst_y;
|
||||
saccum78 _burst_xv;
|
||||
saccum78 _burst_yv;
|
||||
CRGB _burst_color;
|
||||
|
||||
FireworkEffectDot* _dot;
|
||||
FireworkEffectDot* _sparks[EFFECT_FIREWORK_SPARKS];
|
||||
public:
|
||||
FireworkEffect();
|
||||
~FireworkEffect();
|
||||
void skyburst(accum88 x, accum88 y, saccum78 xv, saccum78 yv, CRGB c);
|
||||
boolean supports_window = true;
|
||||
boolean can_be_shown_with_clock();
|
||||
void loop();
|
||||
};
|
||||
|
||||
|
@ -1,13 +1,183 @@
|
||||
// Based on https://gist.github.com/kriegsman/68929cbd1d6de4535b20
|
||||
#include "effect_firework.h"
|
||||
#include "my_fastled.h"
|
||||
#include "functions.h"
|
||||
#include "config.h"
|
||||
|
||||
FireworkEffectDot::FireworkEffectDot(Window* w, FireworkEffect* e) {
|
||||
_window = w;
|
||||
_main = e;
|
||||
show = 0;
|
||||
type = FIREWORK_DOT_NONE;
|
||||
_x = 0;
|
||||
_y = 0;
|
||||
_xv = 0;
|
||||
_yv = 0;
|
||||
_r = 0;
|
||||
_color.setRGB(0, 0, 0);
|
||||
}
|
||||
|
||||
void FireworkEffectDot::_screenscale(accum88 a, byte n, byte& screen, byte& screenerr) {
|
||||
byte ia = a >> 8;
|
||||
screen = scale8(ia, n);
|
||||
byte m = screen * (256 / n);
|
||||
screenerr = (ia - m) * scale8(255, n);
|
||||
}
|
||||
|
||||
int16_t FireworkEffectDot::_scale15by8_local(int16_t i, fract8 scale) {
|
||||
int16_t result;
|
||||
result = (int32_t)((int32_t) i*scale)/256;
|
||||
return result;
|
||||
}
|
||||
|
||||
void FireworkEffectDot::draw() {
|
||||
if (!show) return;
|
||||
byte ix, xe, xc;
|
||||
byte iy, ye, yc;
|
||||
_screenscale(_x, _window->width, ix, xe);
|
||||
_screenscale(_y, _window->height, iy, ye);
|
||||
xc = 255 - xe;
|
||||
yc = 255 - ye;
|
||||
|
||||
CRGB c00 = CRGB(dim8_video( scale8( scale8( _color.r, yc), xc)),
|
||||
dim8_video( scale8( scale8( _color.g, yc), xc)),
|
||||
dim8_video( scale8( scale8( _color.b, yc), xc)));
|
||||
CRGB c01 = CRGB(dim8_video( scale8( scale8( _color.r, ye), xc)),
|
||||
dim8_video( scale8( scale8( _color.g, ye), xc)),
|
||||
dim8_video( scale8( scale8( _color.b, ye), xc)));
|
||||
CRGB c10 = CRGB(dim8_video( scale8( scale8( _color.r, yc), xe)),
|
||||
dim8_video( scale8( scale8( _color.g, yc), xe)),
|
||||
dim8_video( scale8( scale8( _color.b, yc), xe)));
|
||||
CRGB c11 = CRGB(dim8_video( scale8( scale8( _color.r, ye), xe)),
|
||||
dim8_video( scale8( scale8( _color.g, ye), xe)),
|
||||
dim8_video( scale8( scale8( _color.b, ye), xe)));
|
||||
_window->addPixelColor(ix, iy, &c00);
|
||||
_window->addPixelColor(ix, iy+1, &c01);
|
||||
_window->addPixelColor(ix+1, iy, &c10);
|
||||
_window->addPixelColor(ix+1, iy+1, &c11);
|
||||
}
|
||||
|
||||
void FireworkEffectDot::move() {
|
||||
if (!show) return;
|
||||
_yv -= EFFECT_FIREWORK_GRAVITY;
|
||||
_xv = _scale15by8_local(_xv, EFFECT_FIREWORK_DRAG);
|
||||
_yv = _scale15by8_local(_yv, EFFECT_FIREWORK_DRAG);
|
||||
|
||||
if (type == FIREWORK_DOT_SPARK) {
|
||||
_xv = _scale15by8_local(_xv, EFFECT_FIREWORK_DRAG);
|
||||
_yv = _scale15by8_local(_yv, EFFECT_FIREWORK_DRAG);
|
||||
_color.nscale8(255);
|
||||
if (!_color) {
|
||||
show = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Bounce if we hit the ground
|
||||
if (_xv < 0 && _y < (-_yv)) {
|
||||
if (type == FIREWORK_DOT_SPARK) {
|
||||
show = 0;
|
||||
} else {
|
||||
_yv = -_yv;
|
||||
_yv = _scale15by8_local(_yv, EFFECT_FIREWORK_BOUNCE);
|
||||
if (_yv < 500) {
|
||||
show = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_yv < 300) {
|
||||
if (type == FIREWORK_DOT_SHELL) {
|
||||
if (_y > (uint16_t)0x8000) {
|
||||
// boom
|
||||
CRGB white(0xFFFFFF);
|
||||
_window->clear(&white);
|
||||
}
|
||||
show = 0;
|
||||
_main->skyburst(_x, _y, _xv, _yv, _color);
|
||||
}
|
||||
}
|
||||
|
||||
if (type == FIREWORK_DOT_SPARK) {
|
||||
if ((_xv > 0 && _x>_xv) || (_xv < 0 && _x<(0xFFFF+_xv))) {
|
||||
_x += _xv;
|
||||
} else {
|
||||
show = 0;
|
||||
}
|
||||
} else {
|
||||
_x += _xv;
|
||||
}
|
||||
_y += _yv;
|
||||
}
|
||||
|
||||
void FireworkEffectDot::ground_launch() {
|
||||
_xv = (int16_t)random16(600) - (int16_t)300;
|
||||
_yv = 600 + random16(300 + (25 * _window->height));
|
||||
_x = 0x8000;
|
||||
_y = 0;
|
||||
hsv2rgb_rainbow(CHSV(random8(), 240, 200), _color);
|
||||
show = 1;
|
||||
}
|
||||
|
||||
void FireworkEffectDot::sky_burst(accum88 basex, accum88 basey, saccum78 basedv, CRGB& basecolor) {
|
||||
_xv = basedv + (int16_t)random16(2000) - (int16_t)1000;
|
||||
_yv = (int16_t)random16(1500) - (int16_t)500;
|
||||
_x = basex;
|
||||
_y = basey;
|
||||
_color = basecolor;
|
||||
_color *= 4;
|
||||
type = FIREWORK_DOT_SPARK;
|
||||
show = 1;
|
||||
}
|
||||
|
||||
void FireworkEffect::skyburst(accum88 x, accum88 y, saccum78 xv, saccum78 yv, CRGB c) {
|
||||
_skyburst = 1;
|
||||
_burst_x = x;
|
||||
_burst_y = y;
|
||||
_burst_xv = xv;
|
||||
_burst_yv = yv;
|
||||
_burst_color = c;
|
||||
}
|
||||
|
||||
boolean FireworkEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void FireworkEffect::loop() {
|
||||
blur(EFFECT_FIREWORK_BLUR);
|
||||
fadeToBlackBy(leds, LED_COUNT, EFFECT_FIREWORK_FADEOUT_SPEED);
|
||||
|
||||
if (random8(EFFECT_FIREWORK_SHOT_CHANCE)==0) {
|
||||
leds[random16(LED_COUNT)] = CHSV(random8(), 255, 255);
|
||||
window->clear();
|
||||
_dot->move();
|
||||
_dot->draw();
|
||||
for (int i=0; i<EFFECT_FIREWORK_SPARKS; i++) {
|
||||
_sparks[i]->move();
|
||||
_sparks[i]->draw();
|
||||
}
|
||||
static uint16_t launch_countdown = 0;
|
||||
if (_dot->show == 0) {
|
||||
if (launch_countdown == 0) {
|
||||
_dot->ground_launch();
|
||||
_dot->type = FIREWORK_DOT_SHELL;
|
||||
launch_countdown = random16(350) + 1;
|
||||
} else {
|
||||
launch_countdown--;
|
||||
}
|
||||
}
|
||||
|
||||
if (_skyburst) {
|
||||
int nsparks = random8(EFFECT_FIREWORK_SPARKS / 2, EFFECT_FIREWORK_SPARKS + 1);
|
||||
for (int i=0; i<nsparks; i++) {
|
||||
_sparks[i]->sky_burst(_burst_x, _burst_y, _burst_yv, _burst_color);
|
||||
_skyburst = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FireworkEffect::FireworkEffect() {
|
||||
_dot = new FireworkEffectDot(window, this);
|
||||
for (int i=0; i<EFFECT_FIREWORK_SPARKS; i++) {
|
||||
_sparks[i] = new FireworkEffectDot(window, this);
|
||||
}
|
||||
}
|
||||
|
||||
FireworkEffect::~FireworkEffect() {
|
||||
delete window;
|
||||
for (int i=0; i<EFFECT_FIREWORK_SPARKS; i++) {
|
||||
delete _sparks[i];
|
||||
}
|
||||
delete _dot;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user