Would you mind if both sides are symmetrical? If you wouldn't mind then this might work (I have not been able to test this);
void loop() {
byte colors[3][3] = { {0xff, 0,0},
{0xff, 0xff, 0xff},
{0 , 0 , 0xff} };
BouncingColoredBalls(3, colors);
}
void BouncingColoredBalls(int BallCount, byte colors[][3]) {
float Gravity = -9.81;
int StartHeight = 1;
int Halfway = NUM_LEDS/2; // determine number of leds per side
float Height[BallCount];
float ImpactVelocityStart = sqrt( -2 * Gravity * StartHeight );
float ImpactVelocity[BallCount];
float TimeSinceLastBounce[BallCount];
int Position[BallCount];
long ClockTimeSinceLastBounce[BallCount];
float Dampening[BallCount];
for (int i = 0 ; i < BallCount ; i++) {
ClockTimeSinceLastBounce = millis();
Height = StartHeight;
Position = 0;
ImpactVelocity = ImpactVelocityStart;
TimeSinceLastBounce = 0;
Dampening = 0.90 - float(i)/pow(BallCount,2);
}
while (true) {
for (int i = 0 ; i < BallCount ; i++) {
TimeSinceLastBounce = millis() - ClockTimeSinceLastBounce;
Height = 0.5 * Gravity * pow( TimeSinceLastBounce/1000 , 2.0 ) + ImpactVelocity * TimeSinceLastBounce/1000;
if ( Height < 0 ) {
Height = 0;
ImpactVelocity = Dampening * ImpactVelocity;
ClockTimeSinceLastBounce = millis();
if ( ImpactVelocity < 0.01 ) {
ImpactVelocity = ImpactVelocityStart;
}
}
Position = round( Height * (Halfway - 1) / StartHeight); // One side
}
for (int i = 0 ; i < BallCount ; i++) {
setPixel(Position,colors[0],colors[1],colors[2]);
setPixel(NUM_LEDS-Position,colors[0],colors[1],colors[2]); // mirror to other side
}
showStrip();
setAll(0,0,0);
}
}
The idea is to split the entire strip in two virtual strips. One strip counts from 0 to the middle (Halfway variable). The second strip counts from the last LED up to the middle, say we have 10 LEDs, then this would look like this:
1,2,3,4,5 (middle) 6,7,8,9,10
now becomes:
1,2,3,4,5 (middle) 5,4,3,2,1
So the position of any ball can only exist (initially) in the left half, so we bounce between 0 and Halfway.
The right side will bounce identical, so we just copy the position of the ball on the left side and just make sure that we start counting from the last LED back to the middle (NUM_LEDS-Position).
Not sure if this is an acceptable answer ...
However, when we'd make a function to make both side work individually/independent, then we'd need to repeat a lot of the code and I'd probably need to start experimenting to see how well this would work. But I do like the idea ...