HTML BALL GAME - FEEDBACK?

Please give me feedback on the following project -

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Avoid the Balls Game</title>
    <style>
        body {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
            margin: 0;
            background-color: #282c34;
            color: white;
            font-family: Arial, sans-serif;
        }

        #game-container {
            position: relative;
            width: 600px;
            height: 600px;
            border: 2px solid white;
            overflow: hidden;
        }

        .ball {
            position: absolute;
            width: 20px;
            height: 20px;
            border-radius: 50%;
        }

        #player {
            background-color: white;
        }

        .enemy {
            background-color: red;
        }

        .green {
            background-color: green;
        }

        #lives {
            margin-top: 20px;
            font-size: 24px;
        }

        #level {
            margin-top: 10px;
            font-size: 18px;
        }
    </style>
</head>
<body>
    <div id="game-container">
        <div id="player" class="ball"></div>
    </div>
    <div id="lives">Lives: 3</div>
    <div id="level">Level: 1</div>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const gameContainer = document.getElementById('game-container');
            const player = document.getElementById('player');
            const livesDisplay = document.getElementById('lives');
            const levelDisplay = document.getElementById('level');

            let lives = 3;
            let level = 1;
            const playerSpeed = 5;
            let enemySpeed = 2;
            let greenSpeed = 3;
            const gameSize = 600;
            const initialEnemies = 1; // Initial number of red balls
            const greenCount = 3; // Number of green balls (constant)
            let enemies = [];
            let greens = [];

            let keys = {};

            function setRandomPosition(element) {
                element.style.left = `${Math.floor(Math.random() * (gameSize - 20))}px`;
                element.style.top = `${Math.floor(Math.random() * (gameSize - 20))}px`;
            }

            function calculateDistance(element1, element2) {
                const dx = element1.offsetLeft - element2.offsetLeft;
                const dy = element1.offsetTop - element2.offsetTop;
                return Math.sqrt(dx * dx + dy * dy);
            }

            function createEnemies() {
                // Clear existing enemies
                enemies.forEach(enemy => gameContainer.removeChild(enemy));
                enemies = [];

                // Create new enemies based on level
                for (let i = 0; i < initialEnemies + level - 1; i++) {
                    const enemy = document.createElement('div');
                    enemy.className = 'ball enemy';
                    setRandomPosition(enemy);
                    gameContainer.appendChild(enemy);
                    enemies.push(enemy);
                }
            }

            function createGreens() {
                // Clear existing greens
                greens.forEach(green => gameContainer.removeChild(green.element));
                greens = [];

                // Create fixed number of green balls
                for (let i = 0; i < greenCount; i++) {
                    const green = document.createElement('div');
                    green.className = 'ball green';
                    setRandomPosition(green);
                    gameContainer.appendChild(green);
                    greens.push({
                        element: green,
                        dx: Math.random() * greenSpeed * 2 - greenSpeed,
                        dy: Math.random() * greenSpeed * 2 - greenSpeed
                    });
                }
            }

            function movePlayer() {
                if (keys['ArrowUp'] && player.offsetTop > 0) {
                    player.style.top = `${player.offsetTop - playerSpeed}px`;
                }
                if (keys['ArrowDown'] && player.offsetTop < gameSize - player.offsetHeight) {
                    player.style.top = `${player.offsetTop + playerSpeed}px`;
                }
                if (keys['ArrowLeft'] && player.offsetLeft > 0) {
                    player.style.left = `${player.offsetLeft - playerSpeed}px`;
                }
                if (keys['ArrowRight'] && player.offsetLeft < gameSize - player.offsetWidth) {
                    player.style.left = `${player.offsetLeft + playerSpeed}px`;
                }
            }

            function moveEnemies() {
                enemies.forEach(enemy => {
                    // Calculate distance between enemy and player
                    const distance = calculateDistance(enemy, player);

                    // Move enemy towards the player
                    if (distance > 0) {
                        const dx = (player.offsetLeft - enemy.offsetLeft) / distance;
                        const dy = (player.offsetTop - enemy.offsetTop) / distance;
                        enemy.style.left = `${enemy.offsetLeft + dx * enemySpeed}px`;
                        enemy.style.top = `${enemy.offsetTop + dy * enemySpeed}px`;
                    }
                });
            }

            function moveGreens() {
                greens.forEach(green => {
                    let newX = green.element.offsetLeft + green.dx;
                    let newY = green.element.offsetTop + green.dy;

                    // Keep greens within game container bounds
                    if (newX < 0 || newX > gameSize - green.element.offsetWidth) {
                        green.dx *= -1;
                    }
                    if (newY < 0 || newY > gameSize - green.element.offsetHeight) {
                        green.dy *= -1;
                    }

                    green.element.style.left = `${newX}px`;
                    green.element.style.top = `${newY}px`;
                });
            }

            function detectCollision() {
                enemies.forEach((enemy, index) => {
                    if (player.offsetLeft < enemy.offsetLeft + enemy.offsetWidth &&
                        player.offsetLeft + player.offsetWidth > enemy.offsetLeft &&
                        player.offsetTop < enemy.offsetTop + enemy.offsetHeight &&
                        player.offsetTop + player.offsetHeight > enemy.offsetTop) {
                        lives -= 1;
                        livesDisplay.textContent = `Lives: ${lives}`;
                        if (lives === 0) {
                            alert('Game Over');
                            window.location.reload();
                        }
                        setRandomPosition(player);
                    }
                });

                greens.forEach((green, index) => {
                    if (player.offsetLeft < green.element.offsetLeft + green.element.offsetWidth &&
                        player.offsetLeft + player.offsetWidth > green.element.offsetLeft &&
                        player.offsetTop < green.element.offsetTop + green.element.offsetHeight &&
                        player.offsetTop + player.offsetHeight > green.element.offsetTop) {
                        lives -= 1;
                        livesDisplay.textContent = `Lives: ${lives}`;
                        if (lives === 0) {
                            alert('Game Over');
                            window.location.reload();
                        }
                        setRandomPosition(player);
                    }
                });
            }

            document.addEventListener('keydown', (event) => {
                keys[event.key] = true;
            });

            document.addEventListener('keyup', (event) => {
                keys[event.key] = false;
            });

            function increaseLevel() {
                level += 1;
                levelDisplay.textContent = `Level: ${level}`;
                enemySpeed += 0.1; // Increase enemy speed slightly each level
                greenSpeed += 0.5; // Increase green balls speed slightly each level

                // Add a new enemy (red ball) for this level
                const enemy = document.createElement('div');
                enemy.className = 'ball enemy';
                setRandomPosition(enemy);
                gameContainer.appendChild(enemy);
                enemies.push(enemy);

                // Reset player position
                setRandomPosition(player);
            }

            setInterval(increaseLevel, 10000); // 1 minute per level

            createEnemies(); // Initial creation of enemies
            createGreens(); // Initial creation of greens

            function gameLoop() {
                movePlayer();
                moveEnemies();
                moveGreens();
                detectCollision();
                requestAnimationFrame(gameLoop);
            }

            gameLoop();
        });
    </script>
</body>
</html>

I’ve edited your code for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (').

Hey there, it would be nice if you shared a codepen link or something so we can access your game directly. I did run it to try it out though, and i have a few details for you to consider:

  • Are greens also enemies? At first sight I thought I was meant to catch them (since there are green x red colors)
  • Greens seem to get stuck and never move again
  • Since all reds are going in the exact same direction (player) they end up alligning at some point, and no matter how many of them you create, they just seem like one or two.
  • We are able to go beyond the bottom limits of the game container, probably beacuse you didnt consider the size of the player/enemy elements

Overall your code is very well organized and easy to understand! And the game is fun :slight_smile:

2 Likes

Thanks for the tips… Will definitely consider this!!

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.