Last active
November 1, 2024 12:52
-
-
Save kriegsman/68929cbd1d6de4535b20 to your computer and use it in GitHub Desktop.
FireworksXY: a quick and dirty 2-D fireworks simulation using FastLED
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "FastLED.h" | |
// FireworksXY | |
// Quick and dirty 2-D fireworks simulation using FastLED. | |
// | |
// Originaly designed an Adafruit 5x8 WS2811 shield, but works fine | |
// on other XY matricies. | |
// | |
// by Mark Kriegsman, July 2013 | |
// (and not updated too much since then, so it's a little stale, | |
// but it's a good starting point, if rather uncommented.) | |
#define PIXEL_WIDTH 8 | |
#define PIXEL_HEIGHT 8 | |
#define LED_TYPE WS2811 | |
#define COLOR_ORDER GRB | |
#define DATA_PIN 10 | |
//#define CLK_PIN 4 | |
#define BRIGHTNESS 255 | |
#define NUM_LEDS (PIXEL_WIDTH * PIXEL_HEIGHT) | |
CRGB leds[NUM_LEDS]; | |
#define MODEL_BORDER 1 | |
#define MODEL_WIDTH (MODEL_BORDER + PIXEL_WIDTH + MODEL_BORDER) | |
#define MODEL_HEIGHT (MODEL_BORDER + PIXEL_HEIGHT + MODEL_BORDER) | |
#define PIXEL_X_OFFSET ((MODEL_WIDTH - PIXEL_WIDTH ) / 2) | |
#define PIXEL_Y_OFFSET ((MODEL_HEIGHT - PIXEL_HEIGHT) / 2) | |
#define WINDOW_X_MIN (PIXEL_X_OFFSET) | |
#define WINDOW_X_MAX (WINDOW_X_MIN + PIXEL_WIDTH - 1) | |
#define WINDOW_Y_MIN (PIXEL_Y_OFFSET) | |
#define WINDOW_Y_MAX (WINDOW_Y_MIN + PIXEL_HEIGHT - 1) | |
CRGB overrun; | |
CRGB& XY( byte x, byte y) | |
{ | |
x -= PIXEL_X_OFFSET; | |
y -= PIXEL_Y_OFFSET; | |
if( x < PIXEL_WIDTH && y < PIXEL_HEIGHT) { | |
return leds[ (x * PIXEL_HEIGHT) + y ] ; | |
} else | |
return overrun; | |
} | |
void 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); | |
return; | |
} | |
void plot88( byte x, byte y, CRGB& color) | |
{ | |
byte ix = scale8( x, MODEL_WIDTH); | |
byte iy = scale8( y, MODEL_HEIGHT); | |
CRGB& px = XY( ix, iy); | |
px = color; | |
} | |
static int16_t scale15by8_local( int16_t i, fract8 scale ) | |
{ | |
int16_t result; | |
result = (int32_t)((int32_t)i * scale) / 256; | |
return result; | |
} | |
saccum78 gGravity = 10; | |
fract8 gBounce = 200; | |
fract8 gDrag = 255; | |
bool gSkyburst = 0; | |
accum88 gBurstx; | |
accum88 gBursty; | |
saccum78 gBurstxv; | |
saccum78 gBurstyv; | |
CRGB gBurstcolor; | |
#define NONE 0 | |
#define SHELL 1 | |
#define SPARK 2 | |
class Dot { | |
public: | |
byte show; | |
byte theType; | |
accum88 x; | |
accum88 y; | |
saccum78 xv; | |
saccum78 yv; | |
accum88 r; | |
CRGB color; | |
Dot() | |
{ | |
show = 0; | |
theType = 0; | |
x = 0; | |
y = 0; | |
xv = 0; | |
yv = 0; | |
r = 0; | |
color.setRGB( 0, 0, 0); | |
} | |
void Draw() | |
{ | |
if( !show) return; | |
byte ix, xe, xc; | |
byte iy, ye, yc; | |
screenscale( x, MODEL_WIDTH, ix, xe); | |
screenscale( y, MODEL_HEIGHT, iy, ye); | |
yc = 255 - ye; | |
xc = 255 - xe; | |
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)) | |
); | |
XY(ix, iy) += c00; | |
XY(ix, iy + 1) += c01; | |
XY(ix + 1, iy) += c10; | |
XY(ix + 1, iy + 1) += c11; | |
} | |
void Move() | |
{ | |
saccum78 oyv = yv; | |
if( !show) return; | |
yv -= gGravity; | |
xv = scale15by8_local( xv, gDrag); | |
yv = scale15by8_local( yv, gDrag); | |
if( theType == SPARK) { | |
xv = scale15by8_local( xv, gDrag); | |
yv = scale15by8_local( yv, gDrag); | |
color.nscale8( 255); | |
if( !color) { | |
show = 0; | |
} | |
} | |
// if we'd hit the ground, bounce | |
if( yv < 0 && (y < (-yv)) ) { | |
if( theType == SPARK ) { | |
show = 0; | |
} else { | |
yv = -yv; | |
yv = scale15by8_local( yv, gBounce); | |
if( yv < 500 ) { | |
show = 0; | |
} | |
} | |
} | |
if( (yv < -300) /* && (!(oyv < 0))*/ ) { | |
// pinnacle | |
if( theType == SHELL ) { | |
if( (y > (uint16_t)(0x8000)) /*&& (random8() < 64)*/) { | |
// boom | |
LEDS.showColor( CRGB::White); | |
//delay( 1); | |
LEDS.showColor( CRGB::Black); | |
} | |
show = 0; | |
gSkyburst = 1; | |
gBurstx = x; | |
gBursty = y; | |
gBurstxv = xv; | |
gBurstyv = yv; | |
gBurstcolor = color; | |
} | |
} | |
if( theType == SPARK) { | |
if( ((xv > 0) && (x > xv)) || | |
((xv < 0 ) && (x < (0xFFFF + xv))) ) { | |
x += xv; | |
} else { | |
show = 0; | |
} | |
} else { | |
x += xv; | |
} | |
y += yv; | |
} | |
void GroundLaunch() | |
{ | |
yv = 600 + random16(300 + (25 * PIXEL_HEIGHT)); | |
xv = (int16_t)random16(600) - (int16_t)300; | |
y = 0; | |
x = 0x8000; | |
hsv2rgb_rainbow( CHSV( random8(), 240, 200), color); | |
show = 1; | |
} | |
void Skyburst( accum88 basex, accum88 basey, saccum78 basedv, CRGB& basecolor) | |
{ | |
yv = (int16_t)0 + (int16_t)random16(1500) - (int16_t)500; | |
xv = basedv + (int16_t)random16(2000) - (int16_t)1000; | |
y = basey; | |
x = basex; | |
color = basecolor; | |
color *= 4; | |
theType = SPARK; | |
show = 1; | |
} | |
}; | |
#define NUM_SPARKS 12 | |
Dot gDot; | |
Dot gSparks[NUM_SPARKS]; | |
void setup() { | |
delay(2000); | |
LEDS.setBrightness(BRIGHTNESS); | |
LEDS.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS) | |
.setCorrection(TypicalLEDStrip) | |
.setDither(BRIGHTNESS<255); | |
} | |
void loop() | |
{ | |
random16_add_entropy( random() ); | |
CRGB sky1(0,0,2); | |
CRGB sky2(2,0,2); | |
memset8( leds, 0, NUM_LEDS * 3); | |
#if 1 | |
for( uint16_t v = 0; v < NUM_LEDS; v++) { | |
leds[v] = sky1; | |
} | |
for( byte u = 0; u < 1; u++) { | |
leds[random8(NUM_LEDS)] = sky2; | |
} | |
#endif | |
gDot.Move(); | |
gDot.Draw(); | |
for( byte b = 0; b < NUM_SPARKS; b++) { | |
gSparks[b].Move(); | |
gSparks[b].Draw(); | |
} | |
LEDS.show(); | |
static uint16_t launchcountdown = 0; | |
if( gDot.show == 0 ) { | |
if( launchcountdown == 0) { | |
gDot.GroundLaunch(); | |
gDot.theType = SHELL; | |
launchcountdown = random16( 350) + 1; | |
} else { | |
launchcountdown --; | |
} | |
} | |
if( gSkyburst) { | |
byte nsparks = random8( NUM_SPARKS / 2, NUM_SPARKS + 1); | |
for( byte b = 0; b < nsparks; b++) { | |
gSparks[b].Skyburst( gBurstx, gBursty, gBurstyv, gBurstcolor); | |
gSkyburst = 0; | |
} | |
} | |
delay(10); | |
} |
random16_add_entropy( random() );
no matching function for call to 'random()'
the random doesn't work. Is there anything missing??
Running this code on single 150 LED WS2812 strip, need to change background blue color as background is only ON at brightness levels greater than 135; would like to change this to brightness level of 25.
What do I need to modify?
Thank you
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
CRGB& XY( byte x, byte y)
{
x -= PIXEL_X_OFFSET;
y -= PIXEL_Y_OFFSET;
if( x < PIXEL_WIDTH && y < PIXEL_HEIGHT) {
if( y & 0x01) {
// Odd rows run backwards
uint8_t reverseX = (PIXEL_WIDTH - 1) - x;
return leds[(y * PIXEL_WIDTH) + reverseX];
} else {
// Even rows run forwards
return leds[ (y * PIXEL_HEIGHT) + x ] ;
}
} else
return overrun;
}