4 ms·
Nice I see the final result here has a left bias, just press and hold to see it stacking towards left before right. So the next fix could be a random choice.
by kzrdude 5y ago
Nice
I see the final result here has a left bias, just press and hold to see it stacking towards left before right. So the next fix could be a random choice.
- techbio 5y agoI also observe this bias, I imagine it is an artifact of > versus >= on the pixel boundary.
- tpxl 5y agoIt's because the left pixel is checked before the right pixel (the settling behaviour section). This is common in games where you handle movement input (left, right arrow keys) - if you press both of them you'll always go one way, because that way is checked first for movement.
- jasonjmcghee 5y agoIt does indeed! It's a great note. As you say, randomly choosing between left and right if they both exist would fix the bias. Another issue is that it forms a perfect diagonal, which isn't the most pleasing to look at. It can be addressed by randomly allowing for stacks of two granules and allowing spreading further than just one position to the left or right. I figured where I left it was appropriate for this post, but I'm happy to write follow-ups for other particle types and the kind of improvement you mentioned!
- UncleEntity 5y agoAlso wraps around if the pile gets too big to fit in the frame.
- jasonjmcghee 5y agoIt's true! This has to do with how I wrote the "belowLeft" and "belowRight" variables. I don't ensure they are in the same row. You can do this by taking a pair of indices, dividing by width and flooring and checking for equality.
- jakear 5y agoChoosing 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); }
- 4y ago