Reputation: 8998
Well, after looking this problem up three times and finding nothing really relevant to my question, I will now ask.
I got curious and decided to experiment to see if I could make a very basic falling sand toy in canvas.
I did successfully do it, as the "sand" builds up on the ground like it should, but it slows down very quickly because of the hit detection between airborne particles and ground particles.
See for yourself Edit: Possibly dead link, here's a JsFiddle instead.
Particles are spawned by clicking and holding the mouse button. And after you've spawned approximately 200 particles, it gets brought to its knees.
for(i in P){
if(P[i].Y<canvas.height-1){
P[i].Y++
for(j in G){//This loop seems to cause the lag
if(P[i].X==G[j].X&&P[i].Y==G[j].Y-1){
G[G.length]={X:P[i].X,Y:P[i].Y}
}
}
}else{
G[G.length]={X:P[i].X,Y:P[i].Y}
}
}
I'm just wondering if there's something I'm doing horribly wrong; I'm pretty sure it's not supposed to lag that badly. I'm also wondering if there's a way to do it without nested loops, but it seems the only way I've been able to make this work is by checking every individual airborne particle against every individual ground particle, which makes it lag.
If the link is broken, say the word and I'll post the entire code here.
Thanks
Upvotes: 2
Views: 1038
Reputation: 37905
It is easier to remember the height of each pile of sand (eg for each column or x-coordinate in the canvas) and check against that. You can directly use the index (should be the same as the x-coordinate), so you do not require to loop through all ground positions to find the correct one.
You need only one check for each airborne sand piece, namely the check with the height of the pile of the corresponding column.
Additionally when the sand has hit the pile, remove it from the 'active particle' list, so you do not need to check it each time, keeping the outer for
-loop as small/short as possible.
Redraw each pile using the height of the pile (does not work well when the sand grains have separate colors...) or put the sand that is not falling anymore in a separate memory structure to redraw the piles properly.
Upvotes: 2