A grid of simple rules, not a physics engine
Sand, smoke, fire and water in this simulation are not modelled with real fluid equations — they are a cellular automaton: a grid of cells, each holding a material type, updated every frame by a small set of local rules that look only at each cell's immediate neighbours. This is the same family of technique as Conway's Game of Life, just with more than two states and rules tuned to look like physical materials. It is the same trick used in classic "falling-sand" games — cheap to compute, easy to make interactive, and visually convincing without solving a single differential equation.
Sand: gravity plus a coin flip
Each sand cell asks, every frame: is the cell directly below empty? If yes, fall into it. If the cell directly below is occupied but one of the two diagonal cells below is empty, move there instead — this is what lets sand form the realistic sloped piles you see when it lands, called the angle of repose, instead of a single unnatural vertical column. When both diagonals are free the automaton typically picks one at random, which is what gives sand piles their slightly irregular, natural-looking edges rather than perfect symmetric triangles.
Smoke and fire: diffusion and buoyancy
Smoke does the opposite of sand — it tends to rise and spread. Each smoke cell has a chance to move upward or sideways into an empty neighbour, and its density or life value slowly decays each frame until it disappears, which is what makes a smoke plume thin out and fade the higher it climbs. Fire cells behave like smoke but also carry a rule for combustion: a fire cell next to a flammable cell (like sand standing in for fuel) has a chance to convert its neighbour into fire too, and burning cells convert themselves into smoke once their fuel value runs out. This local infection-and-decay pattern is enough to produce flame that flickers, spreads across a fuel source and leaves a smoke trail — all from rules that only ever look one cell away.
SAND: if below empty → fall down
elif diag empty (either) → fall diagonally (random pick)
else → stay
FIRE: each frame: chance to ignite a flammable neighbour
fuel -= decay_rate; fuel <= 0 → convert to SMOKE
SMOKE: chance to move up/sideways into empty cell
life -= decay_rate; life <= 0 → cell becomes empty
Water: the slow-flowing case
Water cells add one more rule on top of sand's falling behaviour: if a water cell cannot fall down or diagonally, it tries to move sideways into an empty neighbour, in either direction. That single extra option — spreading horizontally when blocked from below — is what turns a falling-sand rule into something that pools, finds its own level and spreads out into puddles instead of piling into a heap.
None of this is a Navier-Stokes solver; there is no pressure field, no viscosity term, no velocity vector per particle. What it captures is the qualitative behaviour of each material — sand piles, water spreads, smoke rises and thins, fire eats fuel and produces smoke — which is exactly the level of realism a click-and-draw sandbox needs to feel alive and responsive at 60 frames per second on a grid of tens of thousands of cells.
Frequently asked questions
Is this a real fluid simulation like the water in a game engine?
No — it is a cellular automaton, the same family of technique as Conway's Game of Life. Each cell just checks its handful of neighbours and follows a short list of movement and conversion rules; there is no pressure or velocity field being solved, which is exactly what makes it fast enough to run on a large grid in real time.
Why does sand form neat triangular piles?
Because a grain that cannot fall straight down checks the two diagonal cells below it before giving up, so it slides sideways as it falls, similar to real sand's angle of repose. The random choice between the two diagonals when both are open is what keeps the pile's surface looking natural instead of a perfect cone.
How does fire spread and eventually burn out?
Each fire cell has a chance every frame to ignite a flammable neighbour, so a fire front creeps outward one cell at a time; each burning cell also carries a shrinking fuel value, and once that reaches zero the cell converts itself into smoke, which is why flames flicker, spread and eventually give way to a drifting smoke trail.
Try it live
Everything above runs in your browser — open Magic Sand & Smoke and change the parameters while it is running. Nothing is installed, nothing is uploaded, the whole model lives in one tab.
▶ Open Magic Sand & Smoke simulation