Pixel Paw Productions home

Devlog · · Wyatt · 7 min read

Simulating Wind for Rain, Snow and Trees in a Pixel Art Game

Street trees in a breeze: each crown leans with the wind where it stands, and its clumps flutter on their own.

Philadelphia Fiefdom has one wind, and everything that moves in it reads the same one. It blows in bands of gust that roll downwind across the city, its heading wanders, and buildings calm it in their lee. Every raindrop and snowflake rides the wind at its own spot, so you can watch a gust bend the rain and then reach the plants a moment later. Shaders and scripts ask for it the same way and get the same numbers.

Last time was rain: wet that builds up, gutters, drips and splashes. The wind was all through it, slanting the streaks and carrying the splashes. This is how it works.

Why one wind for everything?

When the weather first went in, there was a single wind value and each thing used it its own way. Plants swayed and the rain leaned, but nothing tied a gust in the plants to a gust in the rain beside them.

Now there's one function, wind_at(position). It gives the push at that spot right now (a direction and a strength) and how much of a gust is passing there. Plants, vines and laundry lean and flutter by it. Every raindrop and snowflake is carried by it. Smoke, litter, the water's surface and the wind's sound read it too. The rule in the code is simple: anything new that moves with the wind reads this, never its own idea of the wind.

How do gusts travel?

A gust isn't the whole screen getting windier for a second. It's a band of stronger air, about ten meters deep along the wind and three times that across it, rolling downwind:

  • Bands from noise. Two layers of smooth noise, stretched long across the wind, slide downwind over time. Where they peak, the wind is up to about one and a half times its average. Between bands it drops to about half.
  • They travel by how far the wind has blown. The bands move 1.5 m a second in still weather and 7.5 at full strength. That distance is added up frame by frame instead of worked out from the strength, so when the wind picks up, the bands speed up without jumping.
  • A little swirl across. A small sideways wobble, so nothing ever leans in perfect unison.
  • A wandering heading. The direction drifts up to about 30° either side of the weather's own heading, over a few minutes, so it's never one fixed direction.
  • Gusts and lulls. On top of the bands, the whole wind pulses, and the rain pulses with it.

All of it runs on the game's clock, so pausing freezes the gusts mid-roll.

This demo needs JavaScript.

Try it: every snowflake here reads the same wind where it is. Watch the gust bands roll across the street and the flakes speed up as one passes, then drag the building and watch the flakes in its lee drop straight down.

How do rain and snow ride the wind?

Each drop and flake reads the wind where it is at that moment of its fall. A gust band bends the rain as it passes through, and each streak lies along its own drop's flight. A gale drives the rain in at about 45°.

That broke two things. Snowflakes drifted 30 to 45 meters in a seven-second fall, and they were released upwind by a guess from the gust of the moment. When the gust changed mid-fall they missed the view and the screen emptied. Now every flake and drop is kept in a box round the view: blown out of one side, it comes back in at the other, off screen.

The second was rain coming down through buildings. With the slant, a drop landing in the street could have fallen through the tower beside it. So each drop's path is checked against the cover map, and one that runs into a building stops there: no streak below, no splash. The first version checked at five fixed heights, and in a gale that left gaps meters wide where rain came straight through. Now it's checked at least every half meter sideways, up to 16 times. A few drops still get through (7%), because gusts do scatter rain into a lee.

The same slant decides which walls get wet. Walls turned into the wind take the rain and darken, and walls turned away stay dry from foot to roof. When the wind swings round, the newly struck ground soaks and the newly sheltered ground slowly dries.

How does snow drift?

Snow drifts much harder than rain. A flake is light and slow, so the wind takes it at once. It also eddies: the flakes are stirred by turbulence that itself moves downwind. My first pass had too much of it, and the snow floated instead of falling. Calmer turbulence fixed it.

On the ground, the drifts are drawn out along the wind the snow fell in, and they keep that shape while any snow lies. The wind keeps wandering, but the drifts don't redraw themselves every time it does.

What else moves in the wind?

  • Drips. A drop letting go of an awning falls nearly straight, then bends downwind as the air brings its sideways speed up to the wind's over 0.4 seconds. At first they slanted from the first frame, which read as wrong. Awning drips are heavy, so the wind carries them less than the rain (7.5 against 17) and takes a full second to do it.
  • Plants, vines and laundry lean with the wind and flutter in the gusts.
  • Street trees. A crown sways a few pixels in a gale, each clump fluttering on its own. The sway was four times smaller at first and didn't show.
  • Smoke and steam. Each puff rises on its own warmth and takes up the wind where it is. Before, the wind was written into one shared particle setting, so every smoke emitter got whichever one's wind was written last.
  • Water. Cat's paws ruffle the water where a gust crosses it. The harbor swell follows the sustained wind instead, building over minutes, and the boats ride it.
  • The sky. Clouds are carried across it by the wind.

What does the wind sound like?

The wind sound reads the same wind, so it swells as a gust reaches you. Indoors it drops to under a third, and in a building's lee it calms down, just like everything else there.

How do buildings shelter you from the wind?

Stand in the lee of a building in a storm and it's calmer. The game knows that from the cover map, the overhead height map that already keeps rain and snow out from under roofs. For any point, it looks upwind at 0.5, 1.5, 3.5 and 7.5 meters. A wall standing over the point (rising more than 0.6 m above it, so a curb or a step doesn't count) stills the air for about three times its height downwind, by up to 85%. Air also slows just in front of a wall it's blowing into.

The shelter calms what's near the ground: drips off awnings, splash spray, plants and cloth, snow near the ground, blown litter, the wind's sound. An awning's drips beside a wall fall straight instead of blowing off. The rain's own flight doesn't use it, because rain comes in over the roofs in open air. That's what leaves a narrow dry strip along a building's lee foot.

How does code know what the shader's wind is doing?

Most of the wind lives in shaders, because that's where the plants and the rain are drawn. Scripts need it too: the sound, the smoke, anything new like a flag. So there's a script twin, Wind.at(), written line for line from the shader, down to the same noise and the same integer hash. Ask both about the same spot at the same moment and they agree.

One detail matters. The distance the gusts have travelled grows forever, and a shader's 32-bit floats lose precision on big numbers long before a script's 64-bit ones do. So both wrap it every 4,096 meters, and the hash under the noise is one that gives the same answer at either precision.

Quick answers

Is the wind random? Each weather has its own wind and heading. The gusts and the wandering are smooth noise on the game clock, so they never jump.

Does the wind change how the game plays? Not yet. It changes where rain lands, which walls get wet, how snow drifts and what you hear.

Does a building really block it? Yes, near the ground, for about three times its height downwind.

Follow along

Philadelphia Fiefdom is a single-player sandbox I'm building in Godot, in a city laid out after Philadelphia. If you missed it, the last post was about rain that soaks in. Next up: vehicles you can drive, from the truck to a boat and a motorbike. Join the playtest list to play it early, or come say hi on Discord (opens in a new tab).

Get updates by email

One email when there's something worth seeing: new footage, playtest invites, the day the Steam page goes up and launch day.

No spam. Unsubscribe any time. Privacy

Want to play early? Join the playtest list. Rather chat? Hang out on Discord (opens in a new tab).