robertlipe / NightDriverStrip

NightDriver client for ESP32
https://plummerssoftwarellc.github.io/NightDriverStrip/
GNU General Public License v3.0
0 stars 0 forks source link

SMFlocking is broken #11

Closed robertlipe closed 1 year ago

robertlipe commented 1 year ago

Bug report

Problem

Steps

Example

Notes

robertlipe commented 1 year ago

Flocking was indeed broken in several ways. The bad news is that even once fixed, I'm not sure it meeds the cutoff for default on. I do think it's worth including because it's actually a good demonstration of Boids. These served as my own introduction to the concept.

All boids were created with a y of zero and a speed of zero. This meant that none could escape that line to rescue the others. Normally if one gets "stuck" on an edge, the gravity of nearby passing flock will quickly absorb them. Everyone starting in a line with a speed of zero meant that there were only dead boids on the ground.

DrawPixelXYF() actually draws four pixels, Fixed by changing callers to not draw too close to the edge where the need to blend with a nearby neighbor might cause a bounds violation.

getPixColorXY and DrawPixelXYF were inconsistent in the way they handled the flipped Y axis relative to the original code base.

The default speed was too fast. The original had an integrated version of Boids.h and changed the default in Boids class instead of in this code via changing the accessor. When we changed to use our "Boids.h", we didn't notice the difference. The result was Tesla-style acceleration inside a garage and we spent most of our time backing up and then bouncing off the opposing wall. To visually compensate for that, I changed the fade time to give them a longer 'tail' like a comet or a tadpole.

This was the killer, though. boid.update() Uses current acceleration, speed to update x and y so we fly in a flock with the same orientation to the same goal. boid.bounceOffBorders changes the direction and reduces acceleration of anything at the borders boid.avoidBorders grabs anything 8px from the edges and nudges them back toward the center

Should work great. No way are you flying out of bounds now! Well, despite TWO method invocations to prevent it, no.

The problem is that we aren't moving this just boid. boid.update on element 4 can actually change the x and y (amongst other members) on elements 5 and 3, for example. The larger your flock, the more update() has to change and if you're at the back of the pack and still accelerating toward a wall, the bounce and avoid might save you, but those methods don't get a chance to walk the entire array; they service only this element. The result is they can push or pull other pixels over the edge and escape teh clamp by those two.

Solution? After doing all the updates, walk Boids[] again after bounceOffBorders and avoidBorders have had a chance to gracefully guide you away from the border and this time just harsly clamp it into the outer edges of the display.. (Oh, and it's 2 px from the edge to avoid the blending problem inherent to the 4x4p Boid itself.)

Now, with all of that said, I think it's still a decent example - maybe even more so now that I've documented the heck out of that code and writen these words.

robertlipe commented 1 year ago

Fixed in balls c2aed95