Fire

Temerature of fire from coldest to hottest would be:

[ 0x852A40, 0xFF4229, 0xFFC948, 0xe6ff63, 0x78ffb4, 0x7FFFFC, 0xffffff ].forEach((color, x) => point(x, 0, color));

Fire is going up, so I would just look for the color in the next row (in 3 nearest cells) and sometimes decrease the temperature by one. This principle of creating fire was used in the demoscene code from 80 years when commodores were the best computers.

const flameTemperature = [ alpha, 0x852A40, 0xFF4229, 0xFFC948, 0xe6ff63, 0x78ffb4, 0x7FFFFC, 0xffffff ]; px.frameRate = 2; update = () => { rect(0,0,w,h,0x000000); const arr = [1, 2, 3, 4, 5]; arr .map((id)=>flameTemperature[id]) .forEach((color, i)=>{ rect(1+i*8,h/2+1, 7, 7, color) }); [1, 2, 3].forEach( n => { let colorID = rand(3) - 1, direction = colorID, decreased = false; let bottomColor = flameTemperature[colorID+arr[n]]; if(rand(4) === 0){ colorID--; decreased = true; } let color = flameTemperature[colorID+arr[n]]; rect(1+n*8, 1, 7, 3, color); rect(1+n*8, 4, 7, 4, bottomColor); if(decreased) rect(2+n*8, 2, 5, 1, 0xffffff); arrow( (n+direction)*8+4, h/2+3, // from (n)*8+4, h/2-5, // to 0xffffff ); }) };

Testing this solution in full size

px.frameRate = 44; const flameTemperature = [ alpha, 0x852A40, 0xFF4229, 0xFFC948, 0xe6ff63, 0x78ffb4, 0x7FFFFC, 0xffffff ], temperatureCount = flameTemperature.length, colors = {}; flameTemperature.forEach( (color, i) => colors[color] = i ); rect(0, 0, w, h, 0x000000); for(let x = 0; x < w; x++){ point( x, h-1, flameTemperature[ floor( // distance from center (1 - abs(w / 2 - x) / (w/2)) * temperatureCount * 0.99 ) ] ); } update = function(dt, t){ let x, y, color; for(y = 0; y < h - 1; y++){ for(x = 1; x < w - 1; x++){ color = flameTemperature[ round(( colors[getPoint(round(sin(t*y*x*13))+x, y+1)] )+sin(t*y*x*22)*0.3-0.22) ]; point( x, y, color ); } } }; point(10, 10, 0xff00ff);