Skip to content

Commit 40653b0

Browse files
authored
Merge pull request wled#4682 from DedeHai/PS_galaxy
Add new effect: PS Galaxy
2 parents d9b086c + 608aff1 commit 40653b0

File tree

2 files changed

+105
-1
lines changed

2 files changed

+105
-1
lines changed

wled00/FX.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8958,6 +8958,108 @@ uint16_t mode_particleblobs(void) {
89588958
return FRAMETIME;
89598959
}
89608960
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";
8961+
8962+
/*
8963+
Particle Galaxy, particles spiral like in a galaxy
8964+
Uses palette for particle color
8965+
by DedeHai (Damian Schneider)
8966+
*/
8967+
uint16_t mode_particlegalaxy(void) {
8968+
ParticleSystem2D *PartSys = nullptr;
8969+
PSsettings2D sourcesettings;
8970+
sourcesettings.asByte = 0b00001100; // PS settings for bounceY, bounceY used for source movement (it always bounces whereas particles do not)
8971+
if (SEGMENT.call == 0) { // initialization
8972+
if (!initParticleSystem2D(PartSys, 1, 0, true)) // init using 1 source and advanced particle settings
8973+
return mode_static(); // allocation failed or not 2D
8974+
PartSys->sources[0].source.vx = -4; // will collide with wall and get random bounce direction
8975+
PartSys->sources[0].source.x = PartSys->maxX >> 1; // start in the center
8976+
PartSys->sources[0].source.y = PartSys->maxY >> 1;
8977+
PartSys->sources[0].sourceFlags.perpetual = true; //source does not age
8978+
PartSys->sources[0].maxLife = 4000; // lifetime in frames
8979+
PartSys->sources[0].minLife = 800;
8980+
PartSys->sources[0].source.hue = hw_random16(); // start with random color
8981+
PartSys->setWallHardness(255); //bounce forever
8982+
PartSys->setWallRoughness(200); //randomize wall bounce
8983+
}
8984+
else {
8985+
PartSys = reinterpret_cast<ParticleSystem2D *>(SEGENV.data); // if not first call, just set the pointer to the PS
8986+
}
8987+
if (PartSys == nullptr)
8988+
return mode_static(); // something went wrong, no data!
8989+
// Particle System settings
8990+
PartSys->updateSystem(); // update system properties (dimensions and data pointers)
8991+
uint8_t particlesize = SEGMENT.custom1;
8992+
if(SEGMENT.check3)
8993+
particlesize = SEGMENT.custom1 ? 1 : 0; // set size to 0 (single pixel) or 1 (quad pixel) so motion blur works and adds streaks
8994+
PartSys->setParticleSize(particlesize); // set size globally
8995+
PartSys->setMotionBlur(250 * SEGMENT.check3); // adds trails to single/quad pixel particles, no effect if size > 1
8996+
8997+
if ((SEGMENT.call % ((33 - SEGMENT.custom3) >> 1)) == 0) // change hue of emitted particles
8998+
PartSys->sources[0].source.hue+=2;
8999+
9000+
if (hw_random8() < (10 + (SEGMENT.intensity >> 1))) // 5%-55% chance to emit a particle in this frame
9001+
PartSys->sprayEmit(PartSys->sources[0]);
9002+
9003+
if ((SEGMENT.call & 0x3) == 0) // every 4th frame, move the emitter
9004+
PartSys->particleMoveUpdate(PartSys->sources[0].source, PartSys->sources[0].sourceFlags, &sourcesettings);
9005+
9006+
// move alive particles in a spiral motion (or almost straight in fast starfield mode)
9007+
int32_t centerx = PartSys->maxX >> 1; // center of matrix in subpixel coordinates
9008+
int32_t centery = PartSys->maxY >> 1;
9009+
if (SEGMENT.check2) { // starfield mode
9010+
PartSys->setKillOutOfBounds(true);
9011+
PartSys->sources[0].var = 7; // emiting variation
9012+
PartSys->sources[0].source.x = centerx; // set emitter to center
9013+
PartSys->sources[0].source.y = centery;
9014+
}
9015+
else {
9016+
PartSys->setKillOutOfBounds(false);
9017+
PartSys->sources[0].var = 1; // emiting variation
9018+
}
9019+
for (uint32_t i = 0; i < PartSys->usedParticles; i++) { //check all particles
9020+
if (PartSys->particles[i].ttl == 0) continue; //skip dead particles
9021+
// (dx/dy): vector pointing from particle to center
9022+
int32_t dx = centerx - PartSys->particles[i].x;
9023+
int32_t dy = centery - PartSys->particles[i].y;
9024+
//speed towards center:
9025+
int32_t distance = sqrt32_bw(dx * dx + dy * dy); // absolute distance to center
9026+
if (distance < 20) distance = 20; // avoid division by zero, keep a minimum
9027+
int32_t speedfactor;
9028+
if (SEGMENT.check2) { // starfield mode
9029+
speedfactor = 1 + (1 + (SEGMENT.speed >> 1)) * distance; // speed increases towards edge
9030+
//apply velocity
9031+
PartSys->particles[i].x += (-speedfactor * dx) / 400000 - (dy >> 6);
9032+
PartSys->particles[i].y += (-speedfactor * dy) / 400000 + (dx >> 6);
9033+
}
9034+
else {
9035+
speedfactor = 2 + (((50 + SEGMENT.speed) << 6) / distance); // speed increases towards center
9036+
// rotate clockwise
9037+
int32_t tempVx = (-speedfactor * dy); // speed is orthogonal to center vector
9038+
int32_t tempVy = (speedfactor * dx);
9039+
//add speed towards center to make particles spiral in
9040+
int vxc = (dx << 9) / (distance - 19); // subtract value from distance to make the pull-in force a bit stronger (helps on faster speeds)
9041+
int vyc = (dy << 9) / (distance - 19);
9042+
//apply velocity
9043+
PartSys->particles[i].x += (tempVx + vxc) / 1024; // note: cannot use bit shift as that causes asymmetric rounding
9044+
PartSys->particles[i].y += (tempVy + vyc) / 1024;
9045+
9046+
if (distance < 128) { // close to center
9047+
if (PartSys->particles[i].ttl > 3)
9048+
PartSys->particles[i].ttl -= 4; //age fast
9049+
PartSys->particles[i].sat = distance << 1; // turn white towards center
9050+
}
9051+
}
9052+
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
9053+
PartSys->particles[i].hue = PartSys->particles[i].ttl >> 2;
9054+
else if(SEGMENT.custom3 == 0) // color by distance
9055+
PartSys->particles[i].hue = map(distance, 20, (PartSys->maxX + PartSys->maxY) >> 2, 0, 180); // color by distance to center
9056+
}
9057+
9058+
PartSys->update(); // update and render
9059+
return FRAMETIME;
9060+
}
9061+
static const char _data_FX_MODE_PARTICLEGALAXY[] PROGMEM = "PS Galaxy@!,!,Size,,Color,,Starfield,Trace;;!;2;pal=59,sx=80,c1=2,c3=4";
9062+
89619063
#endif //WLED_DISABLE_PARTICLESYSTEM2D
89629064
#endif // WLED_DISABLE_2D
89639065

@@ -10657,6 +10759,7 @@ void WS2812FX::setupEffectData() {
1065710759
addEffect(FX_MODE_PARTICLECENTERGEQ, &mode_particlecenterGEQ, _data_FX_MODE_PARTICLECIRCULARGEQ);
1065810760
addEffect(FX_MODE_PARTICLEGHOSTRIDER, &mode_particleghostrider, _data_FX_MODE_PARTICLEGHOSTRIDER);
1065910761
addEffect(FX_MODE_PARTICLEBLOBS, &mode_particleblobs, _data_FX_MODE_PARTICLEBLOBS);
10762+
addEffect(FX_MODE_PARTICLEGALAXY, &mode_particlegalaxy, _data_FX_MODE_PARTICLEGALAXY);
1066010763
#endif // WLED_DISABLE_PARTICLESYSTEM2D
1066110764
#endif // WLED_DISABLE_2D
1066210765

wled00/FX.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,8 @@ extern byte realtimeMode; // used in getMappedPixelIndex()
353353
#define FX_MODE_PS1DSONICSTREAM 214
354354
#define FX_MODE_PS1DSONICBOOM 215
355355
#define FX_MODE_PS1DSPRINGY 216
356-
#define MODE_COUNT 217
356+
#define FX_MODE_PARTICLEGALAXY 217
357+
#define MODE_COUNT 218
357358

358359

359360
#define BLEND_STYLE_FADE 0x00 // universal

0 commit comments

Comments
 (0)