Я написал код игры, но она не работает. В чём дело?

<!DOCTYPE html>
<html lang="ru">
<head>
    <title>Шутер с зомби</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
        #gameCanvas {
            display: block;
            background-color: black;
        }
        #gameOverScreen {
            display: none;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            font-size: 30px;
            text-align: center;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }
    </style>
</head>
<body>
    <canvas id="gameCanvas"></canvas>
    <div id="gameOverScreen">
        <div id="finalScore"></div>
        <button onclick="startGame()">Начать заново</button>
    </div>
    <script>
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const gameOverScreen = document.getElementById('gameOverScreen');
        const finalScore = document.getElementById('finalScore');

        window.addEventListener('resize', resizeCanvas, false);

        function resizeCanvas() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        }
        resizeCanvas();

        const player = {
            x: canvas.width / 2,
            y: canvas.height / 2,
            angle: 0,
            size: 20
        };

        const bullets = [];
        const zombies = [];
        let scores = 0;
        let lastShotTime = 0;
        const shotCooldown = 2000;
        let gameOver = false;

        function startGame() {
            player.x = canvas.width / 2;
            player.y = canvas.height / 2;
            bullets.length = 0;
            zombies.length = 0;
            scores = 0;
            lastShotTime = 0;
            gameOver = false;
            gameOverScreen.style.display = 'none';
            requestAnimationFrame(gameLoop);
        }

        function spawnZombie() {
            const angle = Math.random() * Math.PI * 2;
            const distance = Math.min(canvas.width, canvas.height) / 2 + 100;
            zombies.push({
                x: player.x + Math.cos(angle) * distance,
                y: player.y + Math.sin(angle) * distance,
                size: 15
            });
        }

        function handleInput() {
            const speed = 2;
            if (keyState['W']) {
                player.x += Math.cos(player.angle) * speed;
                player.y += Math.sin(player.angle) * speed;
            }
            if (keyState['S']) {
                player.x -= Math.cos(player.angle) * speed;
                player.y -= Math.sin(player.angle) * speed;
            }
            if (keyState['A']) {
                player.angle -= 0.05;
            }
            if (keyState['D']) {
                player.angle += 0.05;
            }
            if (keyState['K'] && Date.now() - lastShotTime > shotCooldown) {
                bullets.push({
                    x: player.x,
                    y: player.y,
                    angle: player.angle,
                    size: 5
                });
                lastShotTime = Date.now();
            }
        }
        
        function updateBullets() {
            bullets.forEach((bullet, index) => {
                bullet.x += Math.cos(bullet.angle) * 5;
                bullet.y += Math.sin(bullet.angle) * 5;

                if (
                    bullet.x < 0 || bullet.x > canvas.width ||
                    bullet.y < 0 || bullet.y > canvas.height
                ) {
                    bullets.splice(index, 1);
                }
            });
        }

        function updateZombies() {
            zombies.forEach((zombie, index) => {
                const angleToPlayer = Math.atan2(player.y - zombie.y, player.x - zombie.x);
                zombie.x += Math.cos(angleToPlayer) * 1;
                zombie.y += Math.sin(angleToPlayer) * 1;

                // Check collision with player
                if (Math.hypot(zombie.x - player.x, zombie.y - player.y) < player.size) {
                    gameOver = true;
                }

                // Check collision with bullets
                bullets.forEach((bullet, bulletIdx) => {
                    if (Math.hypot(zombie.x - bullet.x, zombie.y - bullet.y) < zombie.size) {
                        zombies.splice(index, 1);
                        bullets.splice(bulletIdx, 1);
                        scores++;
                    }
                });
            });

            // Spawn zombies over time
            if (zombies.length < 10 && Math.random() < 0.02) {
                spawnZombie();
            }
        }

        function gameLoop() {
            if (gameOver) {
                finalScore.innerHTML = Score: ${scores};
                gameOverScreen.style.display = 'flex';
                return;
            }

            ctx.clearRect(0, 0, canvas.width, canvas.height);
            handleInput();
            updateBullets();
            updateZombies();
            drawPlayer();
            drawBullets();
            drawZombies();
            
            ctx.fillStyle = 'white';
            ctx.font = '20px Arial';
            ctx.fillText(Score: ${scores}, 10, 30);
            requestAnimationFrame(gameLoop);
        }

        function drawPlayer() {
            ctx.save();
            ctx.translate(player.x, player.y);
            ctx.rotate(player.angle);
            ctx.beginPath();
            ctx.moveTo(0, -player.size);
            ctx.lineTo(player.size, player.size);
            ctx.lineTo(-player.size, player.size);
            ctx.closePath();
            ctx.fillStyle = 'white';
            ctx.fill();
            ctx.restore();
        }

        function drawBullets() {
            bullets.forEach((bullet) => {
                ctx.beginPath();
                ctx.arc(bullet.x, bullet.y, bullet.size, 0, Math.PI * 2);
                ctx.fillStyle = 'red';
                ctx.fill();
            });
        }

        function drawZombies() {
            zombies.forEach((zombie) => {
                ctx.beginPath();
                ctx.arc(zombie.x, zombie.y, zombie.size, 0, Math.PI * 2);
                ctx.fillStyle = 'green';
                ctx.fill();
            });
        }

        const keyState = {};
        window.addEventListener('keydown', (e) => {
            keyState[e.key.toUpperCase()] = true;
        });

        window.addEventListener('keyup', (e) => {
            keyState[e.key.toUpperCase()] = false;
        });

        startGame();
    </script>
</body>
</html>