The original game’s trees are still images. There is no wind in the data, no animation frames for it, and I am not about to redraw a few hundred trees. So the wind is applied to the sprites that already exist: each one is bent as it is drawn.
Bending a sprite
The renderer gained one call, drawTextureLeaning, which takes the sprite, how
far its top edge should shift sideways, and how firm it is. Instead of one quad,
the sprite is drawn as a stack of horizontal strips — one every four rows — each
offset a little further than the one below it. The bottom row never moves, so a
trunk stays planted while the canopy leans.
firmness shapes how that offset is distributed up the sprite. A firm plant
keeps most of its bend near the top; a soft one curves from lower down.
This also forced a change I did not expect: textures are now uploaded with premultiplied alpha. Drawing through geometry interpolates the texture coordinates, and with straight alpha the semi-transparent edges of every leaf picked up a halo.
Making it look like wind and not a metronome
The horizontal shift comes from a wind field, which is two things multiplied together.
A gust travels across the map: a long wave, 2600 px from crest to crest, moving diagonally at 340 px/s. It never fully dies — it dips to 30% and comes back — so the whole treeline breathes together and you can watch a gust arrive.
A per-sprite swing, a sine plus a second harmonic at 2.31x the rate, so a tree does not simply tick left and right. Amplitude scales with the sprite’s height, so a tall tree travels further than a shrub for the same wind.
The part that matters most is the phase. Every foliage instance gets its own, hashed from its world position and sprite name — so two identical trees planted next to each other never sway in lockstep, and each tree keeps the same phase across restarts.
Which sprites are foliage
None of this is hardcoded per sprite. The catalog carries foliage rules — name
patterns to match and exclude, plus travel, period and firmness — and a
template file is written out if one is not there yet. Strength and speed of the
wind itself are ini settings, and it can be turned off entirely.
What it costs
This is not free. A still sprite is one quad and sits happily in the texture batching from devlog #2. A swaying one is a strip of quads — one every four rows, so a tall tree becomes dozens of them — pushed through geometry rather than a plain blit. Vertex count multiplies, and those draws break the run of same-texture calls that the batching works to build up.
So the frame rate drops. I am taking that trade knowingly, and right now it is not a problem: at the 200% setting the game will actually be played at, there were over 2000 FPS of headroom before any of this, and a scene worth looking at is worth more than a number that was already far past what a monitor can show.
It is also measurable and reversible rather than baked in. The debug overlay counts how many scenery pieces are actually swaying, not just how many exist, so the cost is visible as it grows. If it ever does start to matter, the foliage rules decide which sprites qualify, and the wind has a switch.