<!DOCTYPE html>
<html>
<head>
<title>Making a game with Functional Programming</title>
</head>
<body>
<canvas id="game" width="480" height="320">
We can add some fallback code here!
</canvas>
<script src="game.js"></script>
</body>
</html>
let canvas = document.getElementById('game');
let ctx = canvas.getContext('2d');
const CANVAS_WIDTH = canvas.width;
let state = {};
window.requestAnimationFrame(gameLoop);
function gameLoop() {
state = update(state, Date.now());
render(state, ctx, canvas);
window.requestAnimationFrame(gameLoop);
}
function update(state, now) {
let { squares, nextSquareAt } = state;
nextSquareAt = nextSquareAt || 0;
squares = squares || [];
if (now >= nextSquareAt) {
// Math.random() is not quite a pure function, but let's ignore that for now
let newSquare = { x: 0, y: Math.random() * 200, size: Math.random() * 50 };
squares = squares.concat([newSquare]);
// Schedules the next square for a random value between 0 and 1000 milliseconds
nextSquareAt = now + Math.random() * 1000;
}
squares = squares.map(square => {
return { x: square.x + 1, y: square.y, size: square.size }
}).filter(square => square.x <= CANVAS_WIDTH);
console.log(squares.length)
return Object.assign(state, { squares, nextSquareAt });
}
function render(state, ctx, canvas) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgb(0, 0, 200)';
state.squares.forEach(square => {
ctx.fillRect(square.x, square.y, square.size, square.size);
});
}
# Moving square