4 ms·
Choosing between left and right if they're both open fixes the bias when there is only a single pixel falling, but not when a circle is used. This is because th
by jakear 4y ago
Choosing between left and right if they're both open fixes the bias when there is only a single pixel falling, but not when a circle is used. This is because the update function runs from right to left across the screen, so the falling pillar of sand behaves like a solid wall as the update has not had the chance to move the other side of the circle yet. The best example of this is dropping a pillar on the right slope of an existing cone, a solid line will form on the right side of the falling segment, but a slope will form against the left side of the pillar. When you try this with the left side of a cone, the behavior is correct.
One fix I found is relatively straightforward:
class FallingGrid2 extends FallingGrid {
// Draw from the end of the list to the beginning
update() {
+ const direction = Math.random() > 0.5 ? 'ltr' : 'rtl';
for (let i = this.grid.length - this.width - 1; i > 0; i--) {
- this.updatePixel(i);
+ if (direction === 'rtl') {
+ this.updatePixel(i);
+ } else {
+ const offset = i % this.width;
+ const flipped = this.width - offset;
+ this.updatePixel(i - offset + flipped);
+ }
}
}
}
Cheers for making the source so easily hackable :)
- jdthedisciple 4y agoInteresting, I solved it differently, by just randomly selecting the order in which belowLeft and belowRight are checked, inside the updatePixel function: updatePixel(i) { const below = i + this.width; const belowLeft = below - 1; const belowRight = below + 1; // flag to indicate if we checked the left side already let checkedLeft = false; if (this.isEmpty(below)) { swap(i, below); // check the left side first with 50 % prob (ltr) } else if (Math.random() <= 0.5 && this.isEmpty(belowLeft)) { swap(i, belowLeft); // indicate we checked the left side already checkedLeft = true; // check the right side first with 50 % prob } else if (this.isEmpty(belowRight)) { swap(i, belowRight); // if we haven't checked the left side earlier, check it now (rtl) } else if (!checkedLeft && window.sandgrid[belowLeft] == 1) swap(i, belowLeft); }
- jakear 4y agoI may be testing wrong, but I believe that approach causes dropping a steady stream of sand on the right side of a cone to produce very strange falling behaviour as compared to the left, because the stream is more than one pixel wide. Looks like you changed some other bits around so you may have addressed this some other way.
- jdthedisciple 4y agoWhoops I just noticed a copy-paste error I did, which might be the reason for what you describe in case you copied my code above 3rd last line the "window.sandgrid[belowLeft] == 1" needs to be "this.isEmpty(belowLeft)" instead Other than that I'm not sure what would be causing the weird behaviour. I use this and it seems to work just fine.
- jasonjmcghee 4y agoAh! I see now! Yes, we should alternate the direction of the rowwise pass, or pick randomly, as you demonstrate. This would be a great step to start a next post with.