mirror of
https://github.com/wled/WLED.git
synced 2025-07-15 14:56:32 +00:00
add new effect: PS Galaxy
- parameters tuned to make it look good on most settings
This commit is contained in:
parent
d9b086cbe9
commit
0fe722e478
@ -8958,6 +8958,104 @@ uint16_t mode_particleblobs(void) {
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_PARTICLEBLOBS[] PROGMEM = "PS Blobs@Speed,Blobs,Size,Life,Blur,Wobble,Collide,Pulsate;;!;2v;sx=30,ix=64,c1=200,c2=130,c3=0,o3=1";
|
||||
|
||||
/*
|
||||
Particle Galaxy, particles spiral like in a galaxy
|
||||
Uses palette for particle color
|
||||
by DedeHai (Damian Schneider)
|
||||
*/
|
||||
uint16_t mode_particlegalaxy(void) {
|
||||
ParticleSystem2D *PartSys = nullptr;
|
||||
PSsettings2D sourcesettings;
|
||||
sourcesettings.asByte = 0b00001100; // PS settings for bounceY, bounceY used for source movement (it always bounces whereas particles do not)
|
||||
if (SEGMENT.call == 0) { // initialization
|
||||
if (!initParticleSystem2D(PartSys, 1, 0, true)) // init using 1 source and advanced particle settings
|
||||
return mode_static(); // allocation failed or not 2D
|
||||
PartSys->sources[0].source.vx = -4; // will collide with wall and get random bounce direction
|
||||
PartSys->sources[0].source.x = PartSys->maxX >> 1; // start in the center
|
||||
PartSys->sources[0].source.y = PartSys->maxY >> 1;
|
||||
PartSys->sources[0].sourceFlags.perpetual = true; //source does not age
|
||||
PartSys->sources[0].maxLife = 4000; // lifetime in frames
|
||||
PartSys->sources[0].minLife = 800;
|
||||
PartSys->setWallHardness(255); //bounce forever
|
||||
PartSys->setWallRoughness(200); //randomize wall bounce
|
||||
}
|
||||
else {
|
||||
PartSys = reinterpret_cast<ParticleSystem2D *>(SEGENV.data); // if not first call, just set the pointer to the PS
|
||||
}
|
||||
if (PartSys == nullptr)
|
||||
return mode_static(); // something went wrong, no data!
|
||||
// Particle System settings
|
||||
PartSys->updateSystem(); // update system properties (dimensions and data pointers)
|
||||
uint8_t particlesize = SEGMENT.custom1;
|
||||
if(SEGMENT.check3)
|
||||
particlesize = SEGMENT.custom1 ? 1 : 0; // set size to 0 (single pixel) or 1 (quad pixel) so motion blur works and adds streaks
|
||||
PartSys->setParticleSize(particlesize); // set size globally
|
||||
PartSys->setMotionBlur(250 * SEGMENT.check3); // adds trails to single/quad pixel particles, no effect if size > 1
|
||||
|
||||
if ((SEGMENT.call % ((33 - SEGMENT.custom3) >> 1)) == 0) // change hue of emitted particles
|
||||
PartSys->sources[0].source.hue+=2;
|
||||
|
||||
if (hw_random8() < (10 + (SEGMENT.intensity >> 1))) // 5%-55% chance to emit a particle in this frame
|
||||
PartSys->sprayEmit(PartSys->sources[0]);
|
||||
|
||||
if ((SEGMENT.call & 0x3) == 0) // every 4th frame, move the emitter
|
||||
PartSys->particleMoveUpdate(PartSys->sources[0].source, PartSys->sources[0].sourceFlags, &sourcesettings);
|
||||
|
||||
// move alive particles in a spiral motion (or almost straight in fast starfield mode)
|
||||
for (uint32_t i = 0; i < PartSys->usedParticles; i++) { //check all particles
|
||||
if (PartSys->particles[i].ttl == 0) continue; //skip dead particles
|
||||
|
||||
int32_t centerx = PartSys->maxX >> 1; // center of matrix in subpixel coordinates
|
||||
int32_t centery = PartSys->maxY >> 1;
|
||||
// (dx/dy): vector pointing from particle to center
|
||||
int32_t dx = centerx - PartSys->particles[i].x;
|
||||
int32_t dy = centery - PartSys->particles[i].y;
|
||||
//speed towards center:
|
||||
int32_t distance = sqrt32_bw(dx * dx + dy * dy); // absolute distance to center
|
||||
if (distance < 20) distance = 20; // avoid division by zero, keep a minimum
|
||||
int32_t speedfactor;
|
||||
if (SEGMENT.check2) { // starfield mode
|
||||
PartSys->setKillOutOfBounds(true);
|
||||
PartSys->sources[0].source.hue = hw_random16(); // start with random color
|
||||
PartSys->sources[0].var = 7; // emiting variation
|
||||
PartSys->sources[0].source.x = PartSys->maxX >> 1; // set emitter to center
|
||||
PartSys->sources[0].source.y = PartSys->maxY >> 1;
|
||||
speedfactor = 1 + (1 + (SEGMENT.speed >> 1)) * distance; // speed increases towards edge
|
||||
PartSys->particles[i].x += (-speedfactor * dx) / 400000 - (dy >> 6);
|
||||
PartSys->particles[i].y += (-speedfactor * dy) / 400000 + (dx >> 6);
|
||||
}
|
||||
else {
|
||||
PartSys->setKillOutOfBounds(false);
|
||||
PartSys->sources[0].var = 1; // emiting variation
|
||||
speedfactor = 2 + (((50 + SEGMENT.speed) << 6) / distance); // speed increases towards center
|
||||
// rotate clockwise
|
||||
int32_t tempVx = (-speedfactor * dy); // speed is orthogonal to center vector
|
||||
int32_t tempVy = (speedfactor * dx);
|
||||
//add speed towards center to make particles spiral in
|
||||
int vxc = (dx << 9) / (distance - 19); // subtract value from distance to make the pull-in force a bit stronger (helps on faster speeds)
|
||||
int vyc = (dy << 9) / (distance - 19);
|
||||
//apply velocity
|
||||
PartSys->particles[i].x += (tempVx + vxc) / 1024; // note: cannot use bit shift as that causes asymmetric rounding
|
||||
PartSys->particles[i].y += (tempVy + vyc) / 1024;
|
||||
|
||||
if (distance < 128) { // close to center
|
||||
if (PartSys->particles[i].ttl > 3)
|
||||
PartSys->particles[i].ttl -= 4; //age fast
|
||||
PartSys->particles[i].sat = distance << 1; // turn white towards center
|
||||
}
|
||||
}
|
||||
if(SEGMENT.custom3 == 31) // color by age but mapped to 1024 as particles have a long life, since age is random, this gives more or less random colors
|
||||
PartSys->particles[i].hue = PartSys->particles[i].ttl >> 2;
|
||||
else if(SEGMENT.custom3 == 0) // color by distance
|
||||
PartSys->particles[i].hue = map(distance, 20, (PartSys->maxX + PartSys->maxY) >> 2, 0, 180); // color by distance to center
|
||||
}
|
||||
|
||||
PartSys->update(); // update and render
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_PARTICLEGALAXY[] PROGMEM = "PS Galaxy@!,!,Size,,Color,,Starfield,Trace;;!;2;pal=59,sx=80,c1=2,c3=4";
|
||||
|
||||
#endif //WLED_DISABLE_PARTICLESYSTEM2D
|
||||
#endif // WLED_DISABLE_2D
|
||||
|
||||
@ -10657,6 +10755,7 @@ void WS2812FX::setupEffectData() {
|
||||
addEffect(FX_MODE_PARTICLECENTERGEQ, &mode_particlecenterGEQ, _data_FX_MODE_PARTICLECIRCULARGEQ);
|
||||
addEffect(FX_MODE_PARTICLEGHOSTRIDER, &mode_particleghostrider, _data_FX_MODE_PARTICLEGHOSTRIDER);
|
||||
addEffect(FX_MODE_PARTICLEBLOBS, &mode_particleblobs, _data_FX_MODE_PARTICLEBLOBS);
|
||||
addEffect(FX_MODE_PARTICLEGALAXY, &mode_particlegalaxy, _data_FX_MODE_PARTICLEGALAXY);
|
||||
#endif // WLED_DISABLE_PARTICLESYSTEM2D
|
||||
#endif // WLED_DISABLE_2D
|
||||
|
||||
|
@ -353,7 +353,8 @@ extern byte realtimeMode; // used in getMappedPixelIndex()
|
||||
#define FX_MODE_PS1DSONICSTREAM 214
|
||||
#define FX_MODE_PS1DSONICBOOM 215
|
||||
#define FX_MODE_PS1DSPRINGY 216
|
||||
#define MODE_COUNT 217
|
||||
#define FX_MODE_PARTICLEGALAXY 217
|
||||
#define MODE_COUNT 218
|
||||
|
||||
|
||||
#define BLEND_STYLE_FADE 0x00 // universal
|
||||
|
Loading…
x
Reference in New Issue
Block a user