@@ -8958,6 +8958,104 @@ uint16_t mode_particleblobs(void) {
89588958 return FRAMETIME;
89598959}
89608960static 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->setWallHardness (255 ); // bounce forever
8981+ PartSys->setWallRoughness (200 ); // randomize wall bounce
8982+ }
8983+ else {
8984+ PartSys = reinterpret_cast <ParticleSystem2D *>(SEGENV.data ); // if not first call, just set the pointer to the PS
8985+ }
8986+ if (PartSys == nullptr )
8987+ return mode_static (); // something went wrong, no data!
8988+ // Particle System settings
8989+ PartSys->updateSystem (); // update system properties (dimensions and data pointers)
8990+ uint8_t particlesize = SEGMENT.custom1 ;
8991+ if (SEGMENT.check3 )
8992+ particlesize = SEGMENT.custom1 ? 1 : 0 ; // set size to 0 (single pixel) or 1 (quad pixel) so motion blur works and adds streaks
8993+ PartSys->setParticleSize (particlesize); // set size globally
8994+ PartSys->setMotionBlur (250 * SEGMENT.check3 ); // adds trails to single/quad pixel particles, no effect if size > 1
8995+
8996+ if ((SEGMENT.call % ((33 - SEGMENT.custom3 ) >> 1 )) == 0 ) // change hue of emitted particles
8997+ PartSys->sources [0 ].source .hue +=2 ;
8998+
8999+ if (hw_random8 () < (10 + (SEGMENT.intensity >> 1 ))) // 5%-55% chance to emit a particle in this frame
9000+ PartSys->sprayEmit (PartSys->sources [0 ]);
9001+
9002+ if ((SEGMENT.call & 0x3 ) == 0 ) // every 4th frame, move the emitter
9003+ PartSys->particleMoveUpdate (PartSys->sources [0 ].source , PartSys->sources [0 ].sourceFlags , &sourcesettings);
9004+
9005+ // move alive particles in a spiral motion (or almost straight in fast starfield mode)
9006+ for (uint32_t i = 0 ; i < PartSys->usedParticles ; i++) { // check all particles
9007+ if (PartSys->particles [i].ttl == 0 ) continue ; // skip dead particles
9008+
9009+ int32_t centerx = PartSys->maxX >> 1 ; // center of matrix in subpixel coordinates
9010+ int32_t centery = PartSys->maxY >> 1 ;
9011+ // (dx/dy): vector pointing from particle to center
9012+ int32_t dx = centerx - PartSys->particles [i].x ;
9013+ int32_t dy = centery - PartSys->particles [i].y ;
9014+ // speed towards center:
9015+ int32_t distance = sqrt32_bw (dx * dx + dy * dy); // absolute distance to center
9016+ if (distance < 20 ) distance = 20 ; // avoid division by zero, keep a minimum
9017+ int32_t speedfactor;
9018+ if (SEGMENT.check2 ) { // starfield mode
9019+ PartSys->setKillOutOfBounds (true );
9020+ PartSys->sources [0 ].source .hue = hw_random16 (); // start with random color
9021+ PartSys->sources [0 ].var = 7 ; // emiting variation
9022+ PartSys->sources [0 ].source .x = PartSys->maxX >> 1 ; // set emitter to center
9023+ PartSys->sources [0 ].source .y = PartSys->maxY >> 1 ;
9024+ speedfactor = 1 + (1 + (SEGMENT.speed >> 1 )) * distance; // speed increases towards edge
9025+ PartSys->particles [i].x += (-speedfactor * dx) / 400000 - (dy >> 6 );
9026+ PartSys->particles [i].y += (-speedfactor * dy) / 400000 + (dx >> 6 );
9027+ }
9028+ else {
9029+ PartSys->setKillOutOfBounds (false );
9030+ PartSys->sources [0 ].var = 1 ; // emiting variation
9031+ speedfactor = 2 + (((50 + SEGMENT.speed ) << 6 ) / distance); // speed increases towards center
9032+ // rotate clockwise
9033+ int32_t tempVx = (-speedfactor * dy); // speed is orthogonal to center vector
9034+ int32_t tempVy = (speedfactor * dx);
9035+ // add speed towards center to make particles spiral in
9036+ int vxc = (dx << 9 ) / (distance - 19 ); // subtract value from distance to make the pull-in force a bit stronger (helps on faster speeds)
9037+ int vyc = (dy << 9 ) / (distance - 19 );
9038+ // apply velocity
9039+ PartSys->particles [i].x += (tempVx + vxc) / 1024 ; // note: cannot use bit shift as that causes asymmetric rounding
9040+ PartSys->particles [i].y += (tempVy + vyc) / 1024 ;
9041+
9042+ if (distance < 128 ) { // close to center
9043+ if (PartSys->particles [i].ttl > 3 )
9044+ PartSys->particles [i].ttl -= 4 ; // age fast
9045+ PartSys->particles [i].sat = distance << 1 ; // turn white towards center
9046+ }
9047+ }
9048+ 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
9049+ PartSys->particles [i].hue = PartSys->particles [i].ttl >> 2 ;
9050+ else if (SEGMENT.custom3 == 0 ) // color by distance
9051+ PartSys->particles [i].hue = map (distance, 20 , (PartSys->maxX + PartSys->maxY ) >> 2 , 0 , 180 ); // color by distance to center
9052+ }
9053+
9054+ PartSys->update (); // update and render
9055+ return FRAMETIME;
9056+ }
9057+ static const char _data_FX_MODE_PARTICLEGALAXY[] PROGMEM = " PS Galaxy@!,!,Size,,Color,,Starfield,Trace;;!;2;pal=59,sx=80,c1=2,c3=4" ;
9058+
89619059#endif // WLED_DISABLE_PARTICLESYSTEM2D
89629060#endif // WLED_DISABLE_2D
89639061
@@ -10657,6 +10755,7 @@ void WS2812FX::setupEffectData() {
1065710755 addEffect (FX_MODE_PARTICLECENTERGEQ, &mode_particlecenterGEQ, _data_FX_MODE_PARTICLECIRCULARGEQ);
1065810756 addEffect (FX_MODE_PARTICLEGHOSTRIDER, &mode_particleghostrider, _data_FX_MODE_PARTICLEGHOSTRIDER);
1065910757 addEffect (FX_MODE_PARTICLEBLOBS, &mode_particleblobs, _data_FX_MODE_PARTICLEBLOBS);
10758+ addEffect (FX_MODE_PARTICLEGALAXY, &mode_particlegalaxy, _data_FX_MODE_PARTICLEGALAXY);
1066010759#endif // WLED_DISABLE_PARTICLESYSTEM2D
1066110760#endif // WLED_DISABLE_2D
1066210761
0 commit comments