<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cartoon Racer</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>Simple Cartoon Race!</h1>
    <div id="game-container">
        <div id="track">
            <div id="start-line"></div>
            <div id="finish-line"></div>

            <div id="player-car" class="car">
                <div class="windshield"></div>
                <div class="roof">P1</div>
            </div>
            <div id="ai-car" class="car">
                <div class="windshield"></div>
                 <div class="roof">AI</div>
            </div>
        </div>
         <div id="controls-info">Press and Hold [Right Arrow] Key to Accelerate!</div>
         <div id="message-area">
            <p id="message">Click to Start Race!</p>
         </div>
    </div>

    <script src="script.js"></script>
</body>
</html>
body {
    display: flex;
    flex-direction: column; /* Stack title above game */
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    background-color: #87CEEB; /* Sky blue background */
    font-family: 'Comic Sans MS', cursive, sans-serif; /* Cartoonish font */
    margin: 0;
    overflow: hidden;
}

h1 {
    color: #FFD700; /* Gold */
    text-shadow: 2px 2px 4px #555;
    margin-bottom: 20px;
}

#game-container {
    background-color: #90EE90; /* Light green grass */
    padding: 20px;
    border-radius: 15px;
    box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.3);
    position: relative; /* For message positioning */
    text-align: center;
}

#track {
    width: 800px;
    height: 200px;
    background-color: #A9A9A9; /* Grey track */
    border: 5px dashed #FFFF00; /* Yellow dashed border */
    position: relative; /* For positioning cars and lines */
    margin: 0 auto; /* Center track if container is wider */
    overflow: hidden; /* Keep cars visually inside */
}

#start-line, #finish-line {
    position: absolute;
    top: 0;
    height: 100%;
    width: 10px;
    background: repeating-linear-gradient(
        white,
        white 10px,
        black 10px,
        black 20px
    );
}

#start-line {
    left: 40px; /* Position start line slightly in */
}

#finish-line {
    right: 40px; /* Position finish line slightly before edge */
}

.car {
    position: absolute;
    width: 60px;
    height: 35px;
    border-radius: 15px 15px 5px 5px; /* Rounded top, flatter bottom */
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
    left: 10px; /* Starting position */
    transition: left 0.1s linear; /* Smooth movement */
    border: 2px solid black;
}

#player-car {
    background-color: #FF4500; /* OrangeRed */
    top: 40px; /* Position player car */
}

#ai-car {
    background-color: #1E90FF; /* DodgerBlue */
    top: 120px; /* Position AI car */
}

.car .windshield {
    position: absolute;
    top: 5px;
    left: 10px;
    width: 25px;
    height: 20px;
    background-color: #ADD8E6; /* Light blue */
    border: 1px solid black;
    border-radius: 5px 5px 0 0;
    clip-path: polygon(0 0, 100% 0, 80% 100%, 20% 100%); /* Tapered shape */
}
.car .roof {
    position: absolute;
    top: 0px;
    left: 32px;
    right: 3px;
    height: 27px;
    background: inherit; /* Match car color */
    border-left: 2px solid black;
     border-radius: 0 10px 0 0;
    font-size: 10px;
    font-weight: bold;
    color: white;
    text-shadow: 1px 1px 1px black;
    line-height: 27px; /* Center text vertically */
    text-align: center;
}


#controls-info {
    margin-top: 15px;
    font-size: 0.9em;
    color: #333;
}

#message-area {
    margin-top: 10px;
    font-size: 1.5em;
    font-weight: bold;
    color: #DC143C; /* Crimson */
    cursor: pointer;
}

#message.winner {
    color: #32CD32; /* LimeGreen */
}

#message.loser {
    color: #8B0000; /* DarkRed */
}
document.addEventListener('DOMContentLoaded', () => {
    const track = document.getElementById('track');
    const playerCar = document.getElementById('player-car');
    const aiCar = document.getElementById('ai-car');
    const finishLine = document.getElementById('finish-line');
    const messageArea = document.getElementById('message-area');
    const message = document.getElementById('message');

    const TRACK_WIDTH = track.clientWidth;
    const CAR_WIDTH = playerCar.offsetWidth;
    // Calculate finish based on finish line's left position relative to track
    const FINISH_POSITION = finishLine.offsetLeft - CAR_WIDTH;
    const START_POSITION = 10; // Match initial CSS 'left'

    // --- Game Parameters ---
    const PLAYER_ACCELERATION = 0.15;
    const MAX_PLAYER_SPEED = 6;
    const FRICTION = 0.05; // Slowdown when not accelerating
    const AI_BASE_SPEED = 2.5;
    const AI_SPEED_VARIATION = 1.5; // How much AI speed can fluctuate

    let gameActive = false;
    let playerPosition = START_POSITION;
    let aiPosition = START_POSITION;
    let playerSpeed = 0;
    let aiSpeed = 0;
    let isAccelerating = false;
    let animationFrameId;

    // --- Initialization ---

    function resetGame() {
        cancelAnimationFrame(animationFrameId); // Stop previous loop if any
        gameActive = false;
        playerPosition = START_POSITION;
        aiPosition = START_POSITION;
        playerSpeed = 0;
        aiSpeed = 0;
        isAccelerating = false;

        playerCar.style.left = `${playerPosition}px`;
        aiCar.style.left = `${aiPosition}px`;

        message.textContent = "Click to Start Race!";
        message.className = ''; // Reset win/loss styling
        messageArea.style.cursor = 'pointer';

        document.removeEventListener('keydown', handleKeyDown);
        document.removeEventListener('keyup', handleKeyUp);
    }

    // --- Game Start ---

    messageArea.addEventListener('click', startGame);

    function startGame() {
        if (gameActive) return;

        resetGame(); // Ensure clean state
        gameActive = true;
        message.textContent = "GO GO GO!";
        messageArea.style.cursor = 'default';

        // Start listening for controls
        document.addEventListener('keydown', handleKeyDown);
        document.addEventListener('keyup', handleKeyUp);

        // Start the game loop
        animationFrameId = requestAnimationFrame(gameLoop);
    }

    // --- Player Controls ---

    function handleKeyDown(e) {
        if (e.key === 'ArrowRight') {
            isAccelerating = true;
        }
    }

    function handleKeyUp(e) {
        if (e.key === 'ArrowRight') {
            isAccelerating = false;
        }
    }

    // --- Game Loop ---

    function gameLoop() {
        if (!gameActive) return;

        // 1. Update Player Speed & Position
        if (isAccelerating) {
            playerSpeed += PLAYER_ACCELERATION;
        } else {
            playerSpeed -= FRICTION;
        }
        // Clamp speed (prevent negative speed from friction and limit max speed)
        playerSpeed = Math.max(0, Math.min(playerSpeed, MAX_PLAYER_SPEED));
        playerPosition += playerSpeed;

        // 2. Update AI Speed & Position
        // Simple AI: Varies speed slightly around a base value
        let aiTargetSpeed = AI_BASE_SPEED + (Math.random() - 0.5) * AI_SPEED_VARIATION * 2;
        aiSpeed = aiTargetSpeed; // AI instantly adjusts for simplicity
        aiSpeed = Math.max(0, aiSpeed); // Ensure non-negative speed
        aiPosition += aiSpeed;

        // Clamp positions to track boundaries (just before finish mostly)
        playerPosition = Math.min(playerPosition, TRACK_WIDTH - CAR_WIDTH);
        aiPosition = Math.min(aiPosition, TRACK_WIDTH - CAR_WIDTH);

        // 3. Render Car Positions
        playerCar.style.left = `${playerPosition}px`;
        aiCar.style.left = `${aiPosition}px`;

        // 4. Check Win Condition
        let winner = null;
        if (playerPosition >= FINISH_POSITION) {
            winner = 'Player 1';
        } else if (aiPosition >= FINISH_POSITION) {
            winner = 'AI';
        }

        if (winner) {
            endGame(winner);
        } else {
            // Request next frame
            animationFrameId = requestAnimationFrame(gameLoop);
        }
    }

    // --- End Game ---

    function endGame(winner) {
        gameActive = false;
        document.removeEventListener('keydown', handleKeyDown);
        document.removeEventListener('keyup', handleKeyUp);

        if (winner === 'Player 1') {
            message.textContent = "YOU WIN! Click to Race Again!";
            message.className = 'winner';
        } else {
            message.textContent = "AI Wins! Click to Race Again!";
            message.className = 'loser';
        }
        messageArea.style.cursor = 'pointer';
    }

    // --- Initial Setup ---
    resetGame(); // Set initial state when the page loads

});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.