Squashed commit of the following:

commit 84148ad07a
Author: Blaz Kristan <blaz@kristan-sp.si>
Date:   Sun Sep 3 12:34:17 2023 +0200

    Implement palette colors

commit af3c8f66f7
Author: Blaz Kristan <blaz@kristan-sp.si>
Date:   Tue Aug 1 18:18:41 2023 +0200

    revert wled00.ino

commit 3097a1b17e
Author: Blaz Kristan <blaz@kristan-sp.si>
Date:   Tue Aug 1 18:13:37 2023 +0200

    minor aesthetic fixes

commit 54b80f74b2
Author: Blaz Kristan <blaz@kristan-sp.si>
Date:   Tue Aug 1 18:09:32 2023 +0200

    remove unused variable

commit 9a78d28cd7
Merge: 56a74bc5 1ed81793
Author: Blaz Kristan <blaz@kristan-sp.si>
Date:   Tue Aug 1 18:08:29 2023 +0200

    Merge branch 'main' into PJH_ADD_Linearbounce

commit 56a74bc54c
Author: pjhatch <66844564+pjhatch@users.noreply.github.com>
Date:   Sat Aug 15 12:34:13 2020 -0500

    Update FX.cpp

    Added the improvements suggested by Gregor Hartmann

commit a20358b61b
Author: pjhatch <66844564+pjhatch@users.noreply.github.com>
Date:   Sun Jul 12 08:33:48 2020 -0500

    Adding 2 ball track modes

    With and without collisions

commit 341d9d1697
Author: pjhatch <66844564+pjhatch@users.noreply.github.com>
Date:   Sun Jul 5 14:55:14 2020 -0500

    Update FX.cpp

    Still 1 bug to fix - this was a test.

commit 9cee424383
Author: pjhatch <66844564+pjhatch@users.noreply.github.com>
Date:   Sun Jul 5 14:53:14 2020 -0500

    Update FX.cpp

commit 37cb51cfd6
Author: pjhatch <66844564+pjhatch@users.noreply.github.com>
Date:   Thu Jul 2 14:16:25 2020 -0500

    Adding Collision

    A couple of bugs still need sorting

commit 84b7bfb989
Author: pjhatch <66844564+pjhatch@users.noreply.github.com>
Date:   Sun Jun 28 19:59:46 2020 -0500

    update for lost balls

    Added some protection - so that when intensity is lowered and raised some time later balls that have moved way off the track are recovered.

commit 04d17e4839
Author: pjhatch <66844564+pjhatch@users.noreply.github.com>
Date:   Sun Jun 28 19:43:56 2020 -0500

    Added Ball Track V1

    In this version the balls bounce of the edges and do not interact with one another.
This commit is contained in:
Frank 2023-09-05 18:39:51 +02:00
parent ddbe883d47
commit 5110a8c636
2 changed files with 99 additions and 1 deletions

View File

@ -2834,6 +2834,103 @@ uint16_t mode_bouncing_balls(void) {
static const char _data_FX_MODE_BOUNCINGBALLS[] PROGMEM = "Bouncing Balls@Gravity,# of balls,,,,,Overlay;!,!,!;!;1;m12=1"; //bar
/*
* bouncing balls on a track track Effect modified from Aircoookie's bouncing balls
* Courtesy of pjhatch (https://github.com/pjhatch)
* https://github.com/Aircoookie/WLED/pull/1039
*/
// modified for balltrack mode
typedef struct RollingBall {
unsigned long lastBounceUpdate;
float mass; // could fix this to be = 1. if memory is an issue
float velocity;
float height;
} rball_t;
static uint16_t rolling_balls(void) {
//allocate segment data
const uint16_t maxNumBalls = 16; // 255/16 + 1
uint16_t dataSize = sizeof(rball_t) * maxNumBalls;
if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed
rball_t *balls = reinterpret_cast<rball_t *>(SEGENV.data);
// number of balls based on intensity setting to max of 16 (cycles colors)
// non-chosen color is a random color
uint8_t numBalls = SEGMENT.intensity/16 + 1;
if (SEGENV.call == 0) {
for (int i = 0; i < maxNumBalls; i++) {
balls[i].lastBounceUpdate = strip.now;
balls[i].velocity = 20.0f * float(random16(1000, 10000))/10000.0f; // number from 1 to 10
if (random8()<128) balls[i].velocity = -balls[i].velocity; // 50% chance of reverse direction
balls[i].height = (float(random16(0, 10000)) / 10000.0f); // from 0. to 1.
balls[i].mass = (float(random16(1000, 10000)) / 10000.0f); // from .1 to 1.
}
}
float cfac = float(scale8(8, 255-SEGMENT.speed) +1)*20000.0f; // this uses the Aircoookie conversion factor for scaling time using speed slider
bool hasCol2 = SEGCOLOR(2);
if (!SEGMENT.check2) SEGMENT.fill(hasCol2 ? BLACK : SEGCOLOR(1));
for (int i = 0; i < numBalls; i++) {
float timeSinceLastUpdate = float((strip.now - balls[i].lastBounceUpdate))/cfac;
float thisHeight = balls[i].height + balls[i].velocity * timeSinceLastUpdate; // this method keeps higher resolution
// test if intensity level was increased and some balls are way off the track then put them back
if (thisHeight < -0.5f || thisHeight > 1.5f){
thisHeight = balls[i].height = (float(random16(0, 10000)) / 10000.0f); // from 0. to 1.
balls[i].lastBounceUpdate = strip.now;
}
// check if reached ends of the strip
if ((thisHeight <= 0.0f && balls[i].velocity < 0.0f) || (thisHeight >= 1.0f && balls[i].velocity > 0.0f)) {
balls[i].velocity = -balls[i].velocity; // reverse velocity
balls[i].lastBounceUpdate = strip.now;
balls[i].height = thisHeight;
}
// check for collisions
if (SEGMENT.check1) {
for (int j = i+1; j < numBalls; j++) {
if (balls[j].velocity != balls[i].velocity) {
// tcollided + balls[j].lastBounceUpdate is acutal time of collision (this keeps precision with long to float conversions)
float tcollided = (cfac*(balls[i].height - balls[j].height) +
balls[i].velocity*float(balls[j].lastBounceUpdate - balls[i].lastBounceUpdate))/(balls[j].velocity - balls[i].velocity);
if ((tcollided > 2.0f) && (tcollided < float(strip.now - balls[j].lastBounceUpdate))) { // 2ms minimum to avoid duplicate bounces
balls[i].height = balls[i].height + balls[i].velocity*(tcollided + float(balls[j].lastBounceUpdate - balls[i].lastBounceUpdate))/cfac;
balls[j].height = balls[i].height;
balls[i].lastBounceUpdate = (unsigned long)(tcollided + 0.5f) + balls[j].lastBounceUpdate;
balls[j].lastBounceUpdate = balls[i].lastBounceUpdate;
float vtmp = balls[i].velocity;
balls[i].velocity = ((balls[i].mass - balls[j].mass)*vtmp + 2.0f*balls[j].mass*balls[j].velocity)/(balls[i].mass + balls[j].mass);
balls[j].velocity = ((balls[j].mass - balls[i].mass)*balls[j].velocity + 2.0f*balls[i].mass*vtmp) /(balls[i].mass + balls[j].mass);
thisHeight = balls[i].height + balls[i].velocity*(strip.now - balls[i].lastBounceUpdate)/cfac;
}
}
}
}
uint32_t color = SEGCOLOR(0);
if (SEGMENT.palette) {
//color = SEGMENT.color_wheel(i*(256/MAX(numBalls, 8)));
color = SEGMENT.color_from_palette(i*255/numBalls, false, PALETTE_SOLID_WRAP, 0);
} else if (hasCol2) {
color = SEGCOLOR(i % NUM_COLORS);
}
if (thisHeight < 0.0f) thisHeight = 0.0f;
if (thisHeight > 1.0f) thisHeight = 1.0f;
uint16_t pos = round(thisHeight * (SEGLEN - 1));
SEGMENT.setPixelColor(pos, color);
balls[i].lastBounceUpdate = strip.now;
balls[i].height = thisHeight;
}
return FRAMETIME;
}
static const char _data_FX_MODE_ROLLINGBALLS[] PROGMEM = "Rolling Balls@!,# of balls,,,,Collisions,Overlay;!,!,!;!;1;m12=1"; //bar
/*
* Sinelon stolen from FASTLED examples
*/
@ -7607,6 +7704,7 @@ void WS2812FX::setupEffectData() {
addEffect(FX_MODE_FIRE_FLICKER, &mode_fire_flicker, _data_FX_MODE_FIRE_FLICKER);
addEffect(FX_MODE_GRADIENT, &mode_gradient, _data_FX_MODE_GRADIENT);
addEffect(FX_MODE_LOADING, &mode_loading, _data_FX_MODE_LOADING);
addEffect(FX_MODE_ROLLINGBALLS, &rolling_balls, _data_FX_MODE_ROLLINGBALLS);
addEffect(FX_MODE_FAIRY, &mode_fairy, _data_FX_MODE_FAIRY);
addEffect(FX_MODE_TWO_DOTS, &mode_two_dots, _data_FX_MODE_TWO_DOTS);

View File

@ -176,7 +176,7 @@
#define FX_MODE_FIRE_FLICKER 45
#define FX_MODE_GRADIENT 46
#define FX_MODE_LOADING 47
// #define FX_MODE_POLICE 48 // removed in 0.14!
#define FX_MODE_ROLLINGBALLS 48 //was Police before 0.14
#define FX_MODE_FAIRY 49 //was Police All prior to 0.13.0-b6 (use "Two Dots" with Red/Blue and full intensity)
#define FX_MODE_TWO_DOTS 50
#define FX_MODE_FAIRYTWINKLE 51 //was Two Areas prior to 0.13.0-b6 (use "Two Dots" with full intensity)