<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flying Car Race</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="game-container">
        <div id="sky">
            <div id="player-car"></div>
        </div>
        <div id="ui">
            <div id="score-display">Score: <span id="score">0</span></div>
            <div id="start-screen">
                <h1>Flying Car Race</h1>
                <p>Press SPACE or TAP to Fly Up!</p>
                <button id="start-button">Start Game</button>
            </div>
            <div id="game-over-screen" class="hidden">
                <h2>Game Over!</h2>
                <p>Your Score: <span id="final-score">0</span></p>
                <button id="restart-button">Restart</button>
            </div>
        </div>
    </div>

    <script src="script.js"></script>
</body>
</html>
body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #add8e6; /* Light blue background */
    font-family: 'Arial', sans-serif;
    overflow: hidden; /* Prevent scrollbars if game container is slightly off */
}

#game-container {
    width: 800px;
    height: 500px;
    border: 5px solid #333;
    position: relative; /* Crucial for absolute positioning inside */
    background-color: #87ceeb; /* Sky blue */
    overflow: hidden; /* Keep elements inside */
}

#sky {
    width: 100%;
    height: 100%;
    position: relative;
    /* Add a subtle gradient or background image later if desired */
    /* background: linear-gradient(to bottom, #87ceeb, #add8e6); */
     background-image: url('https://www.transparenttextures.com/patterns/subtle-clouds.png'); /* Example cloud texture */
     animation: scroll-sky 20s linear infinite; /* Animate background */
}

/* Simple scrolling animation for the background */
@keyframes scroll-sky {
    0% { background-position: 0 0; }
    100% { background-position: -800px 0; } /* Scroll width of container */
}


#player-car {
    width: 60px;
    height: 30px;
    background-color: #ff4500; /* Orangey-red car */
    border-radius: 5px 5px 0 0; /* Simple car shape */
    position: absolute;
    bottom: 50px; /* Initial position */
    left: 50px;
    z-index: 10;
    box-shadow: 0 4px 8px rgba(0,0,0,0.2);
    transition: bottom 0.1s ease-out; /* Smooth vertical movement */
}

/* Style for obstacles */
.obstacle {
    width: 50px; /* Width of the obstacle */
    background-color: #666; /* Dark grey obstacles */
    border: 2px solid #444;
    position: absolute;
    right: -60px; /* Start off-screen */
    z-index: 5;
    box-shadow: 2px 2px 5px rgba(0,0,0,0.3);
}

/* UI Elements Styling */
#ui {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    z-index: 20; /* Above game elements */
}

#score-display {
    position: absolute;
    top: 10px;
    left: 10px;
    font-size: 1.5em;
    color: white;
    text-shadow: 1px 1px 2px black;
}

#start-screen, #game-over-screen {
    margin-top: 100px;
    background-color: rgba(0, 0, 0, 0.7);
    color: white;
    padding: 30px;
    border-radius: 10px;
    text-align: center;
    display: flex; /* Use flexbox for content alignment */
    flex-direction: column;
    align-items: center;
}

#start-screen h1, #game-over-screen h2 {
    margin-top: 0;
}

#start-screen p, #game-over-screen p {
    font-size: 1.1em;
    margin-bottom: 20px;
}

button {
    padding: 10px 20px;
    font-size: 1.2em;
    cursor: pointer;
    background-color: #4CAF50; /* Green */
    color: white;
    border: none;
    border-radius: 5px;
    transition: background-color 0.2s;
}

button:hover {
    background-color: #45a049;
}

/* Utility class to hide elements */
.hidden {
    display: none !important; /* Use important to override other display styles */
}
document.addEventListener('DOMContentLoaded', () => {
    // Game elements
    const sky = document.getElementById('sky');
    const playerCar = document.getElementById('player-car');
    const gameContainer = document.getElementById('game-container');
    const scoreDisplay = document.getElementById('score');
    const finalScoreDisplay = document.getElementById('final-score');
    const startScreen = document.getElementById('start-screen');
    const gameOverScreen = document.getElementById('game-over-screen');
    const startButton = document.getElementById('start-button');
    const restartButton = document.getElementById('restart-button');

    // Game variables
    let isGameOver = true; // Start in game over state (show start screen)
    let score = 0;
    let gameLoopInterval;
    let obstacleInterval;
    let playerBottom = 50; // Initial vertical position matches CSS
    const gravity = 0.9;
    const jumpAmount = 25; // How much the car moves up per jump
    const gameSpeed = 5; // How fast obstacles move left
    const obstacleFrequency = 1500; // Milliseconds between new obstacles
    let obstacles = []; // Array to track obstacle elements

    // --- Controls ---
    function jump(event) {
        if (!isGameOver) {
            // Only allow jump if Spacebar (32) or ArrowUp (38) is pressed
            if (event.keyCode === 32 || event.keyCode === 38 || event.type === 'touchstart') {
                 event.preventDefault(); // Prevent spacebar scrolling or default touch behavior
                 if (playerBottom < gameContainer.offsetHeight - playerCar.offsetHeight - jumpAmount/3) { // Prevent going off top
                     playerBottom += jumpAmount;
                     playerCar.style.bottom = playerBottom + 'px';
                 }
            }
        }
    }

    // --- Game Loop ---
    function gameLoop() {
        if (isGameOver) return;

        // Apply Gravity
        playerBottom -= gravity;
        playerCar.style.bottom = playerBottom + 'px';

        // Check Floor Collision
        if (playerBottom <= 0) {
            endGame();
            return; // Stop loop execution for this frame
        }

        // Move & Check Obstacles
        moveObstacles();

        // Update Score (simple time-based scoring)
        score++;
        scoreDisplay.textContent = score;

        // Optional: Increase difficulty over time
        // if (score % 500 === 0) { /* Increase speed */ }
    }

    // --- Obstacles ---
    function generateObstacle() {
        if (isGameOver) return;

        const obstacleHeight = Math.random() * (gameContainer.offsetHeight / 2.5) + 50; // Random height, min 50px
        const positionChoice = Math.random(); // Determine if top or bottom obstacle

        const obstacle = document.createElement('div');
        obstacle.classList.add('obstacle');
        obstacle.style.width = '50px'; // Match CSS if needed, ensures consistency
        obstacle.style.height = obstacleHeight + 'px';

        if (positionChoice > 0.5) {
            // Bottom obstacle
            obstacle.style.bottom = '0px';
        } else {
            // Top obstacle
            obstacle.style.bottom = gameContainer.offsetHeight - obstacleHeight + 'px';
        }

        obstacle.style.right = '-60px'; // Start off-screen right
        sky.appendChild(obstacle);
        obstacles.push(obstacle); // Add to our tracking array
    }

    function moveObstacles() {
        obstacles.forEach((obstacle, index) => {
            let obstacleRight = parseFloat(obstacle.style.right);
            obstacleRight += gameSpeed;
            obstacle.style.right = obstacleRight + 'px';

            // Collision Detection
            const carRect = playerCar.getBoundingClientRect();
            const obsRect = obstacle.getBoundingClientRect();

            // Basic AABB collision check
            if (
                carRect.left < obsRect.right &&
                carRect.right > obsRect.left &&
                carRect.top < obsRect.bottom &&
                carRect.bottom > obsRect.top
            ) {
                endGame();
                return; // Stop checking other obstacles once collision detected
            }

            // Remove obstacle if it's off-screen left
            if (obstacleRight > gameContainer.offsetWidth + parseFloat(obstacle.style.width)) {
                obstacle.remove(); // Remove from DOM
                obstacles.splice(index, 1); // Remove from array
            }
        });
    }

    // --- Game State ---
    function startGame() {
        if (!isGameOver) return; // Prevent starting if already running

        isGameOver = false;
        score = 0;
        playerBottom = 150; // Reset position slightly higher
        playerCar.style.bottom = playerBottom + 'px';
        scoreDisplay.textContent = score;
        obstacles.forEach(obstacle => obstacle.remove()); // Clear old obstacles
        obstacles = []; // Reset array

        // Hide screens, show score
        startScreen.classList.add('hidden');
        gameOverScreen.classList.add('hidden');
        scoreDisplay.parentElement.classList.remove('hidden'); // Show score container if hidden

        // Add controls
        document.addEventListener('keydown', jump);
        document.addEventListener('touchstart', jump); // Basic touch support

        // Start loops
        gameLoopInterval = setInterval(gameLoop, 20); // Run game loop ~50fps
        obstacleInterval = setInterval(generateObstacle, obstacleFrequency);

         // Start background animation
         sky.style.animationPlayState = 'running';
    }

    function endGame() {
        if (isGameOver) return; // Prevent ending multiple times

        isGameOver = true;
        clearInterval(gameLoopInterval);
        clearInterval(obstacleInterval);

        // Remove controls
        document.removeEventListener('keydown', jump);
        document.removeEventListener('touchstart', jump);

        // Show game over screen
        finalScoreDisplay.textContent = score;
        gameOverScreen.classList.remove('hidden');

        // Pause background animation
        sky.style.animationPlayState = 'paused';

    }

    // --- Event Listeners ---
    startButton.addEventListener('click', startGame);
    restartButton.addEventListener('click', startGame);

    // Initial setup: Pause background animation
     sky.style.animationPlayState = 'paused';

}); // End DOMContentLoaded

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.