Skip to content

Instantly share code, notes, and snippets.

@mattstermiller
Last active May 28, 2019 01:18
Show Gist options
  • Save mattstermiller/affb97a4ecd00b76e3e86abe58dbfcb7 to your computer and use it in GitHub Desktop.
Save mattstermiller/affb97a4ecd00b76e3e86abe58dbfcb7 to your computer and use it in GitHub Desktop.
doom fire animation
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>doom fire</title>
<style>
#bod {
background-color: black;
color: white;
font-size: 20px;
text-align: center;
}
canvas {
border: 1px gray solid;
}
.panel {
display: inline-block;
margin: 0 10px;
}
</style>
</head>
<body id="bod">
<div>
<div class="panel">
<canvas id="fireGrad"
width="37"
height="20">
</canvas>
</div>
<div class="panel">
<label><input id="anim" type="checkbox" onclick="toggleAnim()">anim</label>
<label><input id="fire" type="checkbox" onclick="toggleFire()" checked>fire</label>
</div>
<div class="panel">
Size:
<label><input type="radio" name="size" onclick="setSize(100)" checked>100</label>
<label><input type="radio" name="size" onclick="setSize(400)">400</label>
<label><input type="radio" name="size" onclick="setSize(800)">800</label>
</div>
<div class="panel">
FPS:
<label><input type="radio" name="fps" onclick="setFPS(15)" checked>15</label>
<label><input type="radio" name="fps" onclick="setFPS(30)">30</label>
<label><input type="radio" name="fps" onclick="setFPS(60)">60</label>
</div>
</div>
<canvas id="canvas"
width="100"
height="250">
</canvas>
<script>
let canvas = document.getElementById("canvas");
let gradCanvas = document.getElementById("fireGrad");
var W = canvas.width;
const H = canvas.height;
const MAX_HEAT = gradCanvas.width-1;
var FPS = 15;
function setSize(size) {
canvas.width = size;
W = size;
init();
}
function setFPS(fps) {
FPS = fps;
toggleAnim();
toggleAnim();
}
function getCtx(canv) {
return canv.getContext("2d", { alpha: false });
}
let gradCtx = getCtx(gradCanvas);
let grad = gradCtx.createLinearGradient(0, 0, gradCanvas.width, 0);
grad.addColorStop(0, "black");
grad.addColorStop(0.5, "red");
grad.addColorStop(0.9, "yellow");
grad.addColorStop(1, "#22f");
gradCtx.fillStyle = grad;
gradCtx.fillRect(0, 0, gradCanvas.width, gradCanvas.height);
let gradImg = gradCtx.getImageData(0, 0, gradCanvas.width, 1);
let heat = Array.from(Array(gradCanvas.width), (x, p) =>
Array.from(Array(3), (x, d) => gradImg.data[p*4+d]));
var fire;
var ctx;
var img;
function toggleFire() {
let start = W*(H-1);
let val = fire[start] ? 0 : MAX_HEAT;
fire.fill(val, start);
}
function init() {
fire = Array(W*H);
fire.fill(0);
ctx = getCtx(canvas);
img = ctx.createImageData(W, H);
if (document.getElementById("fire").checked) {
toggleFire();
}
tick();
}
function spread(src) {
let rand = (Math.random() * 3) & 3;
let dst = src - W - rand + 1;
let decay = rand & 1;
fire[dst] = Math.max(0, fire[src] - decay);
}
function update() {
for (let x=1; x<W; x++) {
for (let y=1; y<H; y++) {
spread(y*W + x);
}
}
}
function render() {
for (let p=0; p < W*H; p++) {
let pix = heat[fire[p]];
for (let d=0; d < 3; d++) {
img.data[p*4+d] = pix[d];
}
}
ctx.putImageData(img, 0, 0);
}
function tick() {
update();
render();
}
var loop;
function toggleAnim() {
if (loop) {
clearInterval(loop);
loop = null;
} else {
loop = setInterval(tick, 1000/FPS);
}
}
init();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment