🎮ArcadeLab

Coin Runner

by SuperCobra92
471 lines8.7 KB
▶ Play
<!DOCTYPE html>
<html lang="hi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Coin Runner</title>

<style>
* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    background: #111;
    overflow: hidden;
    font-family: Arial, sans-serif;
    touch-action: none;
}

#game {
    position: relative;
    width: 100vw;
    height: 100vh;
    max-width: 500px;
    margin: auto;
    overflow: hidden;
    background: linear-gradient(#55c9ff, #d8f7ff);
}

#road {
    position: absolute;
    left: 10%;
    width: 80%;
    height: 100%;
    background: #333;
    border-left: 7px solid white;
    border-right: 7px solid white;
}

.lane {
    position: absolute;
    width: 6px;
    height: 80px;
    background: white;
    left: 50%;
    transform: translateX(-50%);
    opacity: .8;
}

#player {
    position: absolute;
    width: 55px;
    height: 75px;
    bottom: 110px;
    left: calc(50% - 27px);
    background: #1976ff;
    border-radius: 14px 14px 8px 8px;
    box-shadow: 0 5px 10px #0008;
}

#player::before {
    content: "";
    position: absolute;
    width: 34px;
    height: 22px;
    left: 10px;
    top: 9px;
    background: #bdeaff;
    border-radius: 8px;
}

#player::after {
    content: "🏎️";
    position: absolute;
    font-size: 42px;
    left: 5px;
    top: 25px;
}

.obstacle {
    position: absolute;
    width: 55px;
    height: 55px;
    background: #e53935;
    border-radius: 10px;
    box-shadow: 0 4px 8px #0008;
}

.obstacle::after {
    content: "🚧";
    font-size: 38px;
    position: absolute;
    left: 7px;
    top: 5px;
}

.coin {
    position: absolute;
    width: 35px;
    height: 35px;
    background: gold;
    border: 4px solid #ff9800;
    border-radius: 50%;
    box-shadow: 0 0 15px gold;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
}

#score {
    position: absolute;
    top: 15px;
    left: 15px;
    color: white;
    font-size: 22px;
    font-weight: bold;
    z-index: 20;
    text-shadow: 2px 2px 4px #000;
}

#highScore {
    position: absolute;
    top: 45px;
    left: 15px;
    color: white;
    font-size: 16px;
    z-index: 20;
    text-shadow: 2px 2px 4px #000;
}

#gameOver {
    display: none;
    position: absolute;
    inset: 0;
    background: #000b;
    color: white;
    z-index: 50;
    text-align: center;
    padding-top: 35vh;
}

#gameOver h1 {
    font-size: 42px;
    margin-bottom: 15px;
}

#gameOver p {
    font-size: 22px;
    margin-bottom: 25px;
}

button {
    border: none;
    padding: 15px 28px;
    margin: 8px;
    border-radius: 12px;
    background: #00c853;
    color: white;
    font-size: 18px;
    font-weight: bold;
}

.controls {
    position: absolute;
    bottom: 20px;
    left: 0;
    width: 100%;
    z-index: 30;
    text-align: center;
}

.controls button {
    width: 90px;
    height: 55px;
    background: #ffffffcc;
    color: #111;
    font-size: 25px;
}
</style>
</head>

<body>

<div id="game">

    <div id="road"></div>

    <div id="score">Score: 0</div>
    <div id="highScore">High Score: 0</div>

    <div id="player"></div>

    <div class="controls">
        <button id="left">⬅️</button>
        <button id="right">➡️</button>
    </div>

    <div id="gameOver">
        <h1>GAME OVER</h1>
        <p id="finalScore">Score: 0</p>
        <button onclick="restartGame()">🔄 Restart</button>
    </div>

</div>

<script>
const game = document.getElementById("game");
const player = document.getElementById("player");
const scoreText = document.getElementById("score");
const highScoreText = document.getElementById("highScore");
const gameOverScreen = document.getElementById("gameOver");
const finalScore = document.getElementById("finalScore");

let playerX;
let score = 0;
let speed = 5;
let gameRunning = true;
let objects = [];
let keys = {
    left: false,
    right: false
};

let highScore = Number(localStorage.getItem("coinRunnerHighScore")) || 0;
highScoreText.textContent = "High Score: " + highScore;

function setPlayerStart() {
    playerX = game.clientWidth / 2 - 27;
    player.style.left = playerX + "px";
}

setPlayerStart();

window.addEventListener("resize", setPlayerStart);

document.addEventListener("keydown", function(e) {
    if (e.key === "ArrowLeft" || e.key === "a") {
        keys.left = true;
    }

    if (e.key === "ArrowRight" || e.key === "d") {
        keys.right = true;
    }
});

document.addEventListener("keyup", function(e) {
    if (e.key === "ArrowLeft" || e.key === "a") {
        keys.left = false;
    }

    if (e.key === "ArrowRight" || e.key === "d") {
        keys.right = false;
    }
});

function controlButton(button, direction) {

    button.addEventListener("touchstart", function(e) {
        e.preventDefault();
        keys[direction] = true;
    });

    button.addEventListener("touchend", function(e) {
        e.preventDefault();
        keys[direction] = false;
    });

    button.addEventListener("mousedown", function() {
        keys[direction] = true;
    });

    button.addEventListener("mouseup", function() {
        keys[direction] = false;
    });
}

controlButton(document.getElementById("left"), "left");
controlButton(document.getElementById("right"), "right");

function createObstacle() {

    const obstacle = document.createElement("div");
    obstacle.className = "obstacle";

    const roadLeft = game.clientWidth * 0.10;
    const roadWidth = game.clientWidth * 0.80;

    let x = roadLeft + Math.random() * (roadWidth - 55);

    obstacle.style.left = x + "px";
    obstacle.style.top = "-70px";

    game.appendChild(obstacle);

    objects.push({
        element: obstacle,
        type: "obstacle",
        x: x,
        y: -70
    });
}

function createCoin() {

    const coin = document.createElement("div");
    coin.className = "coin";
    coin.textContent = "★";

    const roadLeft = game.clientWidth * 0.10;
    const roadWidth = game.clientWidth * 0.80;

    let x = roadLeft + Math.random() * (roadWidth - 35);

    coin.style.left = x + "px";
    coin.style.top = "-50px";

    game.appendChild(coin);

    objects.push({
        element: coin,
        type: "coin",
        x: x,
        y: -50
    });
}

let spawnTimer = 0;

function gameLoop() {

    if (!gameRunning) return;

    // Player movement
    if (keys.left) {
        playerX -= 7;
    }

    if (keys.right) {
        playerX += 7;
    }

    const roadLeft = game.clientWidth * 0.10;
    const roadRight = game.clientWidth * 0.90 - 55;

    if (playerX < roadLeft) {
        playerX = roadLeft;
    }

    if (playerX > roadRight) {
        playerX = roadRight;
    }

    player.style.left = playerX + "px";

    // Move objects
    for (let i = objects.length - 1; i >= 0; i--) {

        const obj = objects[i];

        obj.y += speed;
        obj.element.style.top = obj.y + "px";

        if (checkCollision(player, obj.element)) {

            if (obj.type === "coin") {

                score += 10;

                obj.element.remove();
                objects.splice(i, 1);

                scoreText.textContent = "Score: " + score;

                if (score > highScore) {
                    highScore = score;
                    highScoreText.textContent =
                        "High Score: " + highScore;
                    localStorage.setItem(
                        "coinRunnerHighScore",
                        highScore
                    );
                }

                continue;
            }

            if (obj.type === "obstacle") {
                endGame();
                return;
            }
        }

        if (obj.y > game.clientHeight + 100) {
            obj.element.remove();
            objects.splice(i, 1);
        }
    }

    spawnTimer++;

    if (spawnTimer > 45) {

        if (Math.random() < 0.6) {
            createObstacle();
        } else {
            createCoin();
        }

        spawnTimer = 0;
    }

    // Difficulty increases
    if (score > 0 && score % 100 === 0) {
        speed = Math.min(12, 5 + score / 500);
    }

    requestAnimationFrame(gameLoop);
}

function checkCollision(a, b) {

    const A = a.getBoundingClientRect();
    const B = b.getBoundingClientRect();

    return !(
        A.right < B.left ||
        A.left > B.right ||
        A.bottom < B.top ||
        A.top > B.bottom
    );
}

function endGame() {

    gameRunning = false;

    finalScore.textContent = "Your Score: " + score;

    gameOverScreen.style.display = "block";
}

function restartGame() {

    objects.forEach(obj => {
        obj.element.remove();
    });

    objects = [];

    score = 0;
    speed = 5;
    spawnTimer = 0;
    gameRunning = true;

    scoreText.textContent = "Score: 0";

    gameOverScreen.style.display = "none";

    setPlayerStart();

    requestAnimationFrame(gameLoop);
}

gameLoop();
</script>

</body>
</html>

Game Source: Coin Runner

Creator: SuperCobra92

Libraries: none

Complexity: complex (471 lines, 8.7 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: coin-runner-supercobra92" to link back to the original. Then publish at arcadelab.ai/publish.