Loading…
a327ex.com

Oh hell yeah! A new a327ex prototype, babe wake up! Good to see you're still creating things! :3 Looking good! I love the fire particles! How do you create them? Any resources on that? Wanted to creating fire particles like that for a little while now. owo

Here's the full recipe, then. The high-level answer: there is no texture and no particle system — every flame is just circles (plus one tiny outline shader the whole game already uses). Each burning tile spawns a couple of small circles about thirty times per second; each circle launches upward along a fake height axis with accelerating rise, holds its size for the first third of its short life and then shrinks to nothing, and tweens its color from yellow to red as it "cools". Two kinds of circle are layered — tall rising tongues and a tight, low base core — and the whole thing is grounded by a black outline pass and little ground shadows that shrink as each ember climbs. That's it. Everything below is the details, with live toys you can poke — they run the game's actual numbers, on the game's board, through the game's actual outline shader.

One ember

An ember is a table with a position, a fake height z, velocities, a radius and a lifetime. Three curves run over that lifetime and each one carries a specific job:

function ember:update(dt)
  self.t = self.t + dt
  if self.t >= self.life then self:kill(); return end
  self.vz = self.vz + self.rise*dt        -- 1. RISE: accelerate upward
  self.z  = self.z + self.vz*dt           --    (z subtracts from screen y)
  self.x, self.y = self.x + self.vx*dt, self.y + self.vy*dt
  self.vx, self.vy = self.vx - self.vx*3*dt, self.vy - self.vy*3*dt
  self.rs = (self.t < self.hold) and self.rs0            -- 2. SHRINK: hold,
            or self.rs0*(1 - (self.t - self.hold)/(self.life - self.hold))
  local u = self.t/self.life              -- 3. COOL: yellow -> red
  self.col.r = yellow.r + (red.r - yellow.r)*u
  self.col.g = yellow.g + (red.g - yellow.g)*u
  self.col.b = yellow.b + (red.b - yellow.b)*u
end

Rise is an acceleration, not a constant speed — embers leave the ground lazily and whip away at the end, which is what makes them read as heat instead of confetti. Shrink has a hold phase: a circle that shrinks from birth reads as a fizzle; one that holds and then collapses reads as a flame tip pinching off. Cool is the classic yellow-to-red tween — the single cheapest thing you can do to make circles read as fire. One thing to keep in mind: the game is top-down, so z is a made-up third axis and "up the screen" doubles as "toward the camera" — each ember stays pinned to the board by a shadow at its true (x, y), and the gap that opens between circle and shadow is what turns vertical screen movement into height. The demo below runs single embers in slow motion on the game's board; watch a circle lift away from its shadow, click anywhere to launch one at your cursor, and turn the three ingredients off one at a time to see what each contributes:

The emitter

A burning tile doesn't emit one kind of ember — it emits two, on a ~28 Hz clock:

if emit then
  if burning then                          -- rising tongues, full height
    spawn_ember(cx + random_float(-SQUARE*0.28, SQUARE*0.28),
                cy + random_float(-SQUARE*0.2, SQUARE*0.22))
  end
  if random_float(0, 1) < inten then       -- the glowing base core
    spawn_base_ember(cx + random_float(-SQUARE*0.12, SQUARE*0.12),
                     cy + random_float(-SQUARE*0.04, SQUARE*0.16), inten)
  end
end

The tongues are the visible flames: full rise, wide jitter, launched from anywhere on the tile. The base core is the trick most people miss: small circles with almost no rise and a tighter spawn area, so the bottom of the fire stays a dense pulsing glow that the tongues appear to climb out of. Without the core the effect looks like sparks leaving a surface; with it, the surface itself looks like it's on fire. Spawn positions are random inside a box covering most of the tile — an area, seen from above, never a single point, or the fire becomes a fountain. Rate matters more than anything: fire is a stream, and below ~15 embers a second the illusion collapses into individual dots. Play with both here:

Composition — what sells it

Three finishing touches, all visible in the last demo. First, the outline — and this is the part hand-rolled versions usually get wrong. The embers are not outlined one by one: they all render into their own layer as plain colored circles, and a small shader pass then reads that layer's alpha — any transparent pixel within two pixels of an opaque one turns black — and the result is stamped underneath the layer. That outlines the silhouette of the whole mass: where embers overlap they weld into one outlined flame, the way a pixel artist would ink it, instead of every circle dragging its own black ring through its neighbors. The demos on this page run the game's actual fragment shader for this. If your engine has no layer shaders, you can get an identical result by hand: draw all the embers as slightly fatter black discs first, then all of them in color on top — the black survives only outside the colored union, which is exactly the union's outline. Second, ground shadows: a small dark ellipse stays pinned to the board under each ember and shrinks as the ember climbs — that's the entire reason the flat z trick reads as height rather than as a circle sliding up the screen. Third, the recipe doesn't know it's fire: swap the two palette endpoints and the same skeleton is magic, or poison, or anything else that glows and rises. Click any tile to set it alight:

One more thing to watch in that demo: endings. When a tile's fuel runs out the fire doesn't cut off — the tongues stop instantly, but the base core keeps emitting for half a second at falling intensity and shrinking size, so it visibly dies down instead of switching off. Ignition gets the same care in reverse: a tile lights with a one-shot burst of ten embers, so the fire arrives with a pop instead of fading in. Endings and beginnings are where cheap effects usually give themselves away.

As for resources: this isn't really a technique with a name, just the standard juice ideas — accelerate, hold-then-shrink, color-tween, layer, outline, shadow — pointed at circles until they look hot. But the demos above can be the resource now. Their complete source — board, embers, emitter, lifecycle, outline shader, even the UI chips, exactly as it runs on this page — is in one readable file: fire-demos.txt. The fire itself is maybe eighty lines of it; the rest is board and buttons. Steal freely.