Super Runner
by RapidGecko49261 lines5.2 KB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Super Runner</title>
<style>
body {
margin: 0;
background: #15152e;
color: white;
text-align: center;
font-family: Arial, sans-serif;
}
h2 { color: #ffe45c; }
canvas {
background: #70d6ff;
width: 95%;
max-width: 400px;
height: 520px;
border: 3px solid white;
border-radius: 12px;
touch-action: none;
}
button {
padding: 13px 20px;
margin: 5px;
font-size: 18px;
border: none;
border-radius: 10px;
background: #ffcc00;
font-weight: bold;
}
</style>
</head>
<body>
<h2>🏃 SUPER RUNNER 🏃</h2>
<p>Coins: <span id="score">0</span></p>
<canvas id="game" width="400" height="520"></canvas>
<div>
<button onclick="move(-1)">⬅️ Left</button>
<button onclick="jump()">⬆️ Jump</button>
<button onclick="move(1)">Right ➡️</button>
</div>
<button onclick="restart()">🔄 Restart</button>
<p>Collect coins and dodge the obstacles!</p>
<script>
const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
let lane = 1;
let playerY = 420;
let jumping = false;
let jumpHeight = 0;
let objects = [];
let score = 0;
let speed = 4;
let gameOver = false;
let frame = 0;
function move(dir) {
if (!gameOver) lane = Math.max(0, Math.min(2, lane + dir));
}
function jump() {
if (!jumping && !gameOver) {
jumping = true;
jumpHeight = 105;
}
}
function restart() {
lane = 1;
playerY = 420;
jumping = false;
jumpHeight = 0;
objects = [];
score = 0;
speed = 4;
gameOver = false;
frame = 0;
document.getElementById("score").textContent = score;
}
document.addEventListener("keydown", e => {
if (e.key === "ArrowLeft") move(-1);
if (e.key === "ArrowRight") move(1);
if (e.key === "ArrowUp" || e.key === " ") jump();
if (e.key.toLowerCase() === "r") restart();
});
function drawPlayer() {
const x = 80 + lane * 120;
const y = playerY - jumpHeight;
ctx.fillStyle = "#ff8c42";
ctx.fillRect(x - 15, y + 35, 30, 32);
ctx.fillStyle = "#ffd6a5";
ctx.beginPath();
ctx.arc(x, y + 20, 17, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = "#2878ff";
ctx.fillRect(x - 19, y + 48, 13, 25);
ctx.fillRect(x + 6, y + 48, 13, 25);
ctx.fillStyle = "#222";
ctx.fillRect(x - 21, y + 70, 17, 7);
ctx.fillRect(x + 5, y + 70, 17, 7);
}
function drawRoad() {
ctx.fillStyle = "#39a96b";
ctx.fillRect(0, 0, 400, 520);
ctx.fillStyle = "#555";
ctx.beginPath();
ctx.moveTo(100, 0);
ctx.lineTo(300, 0);
ctx.lineTo(390, 520);
ctx.lineTo(10, 520);
ctx.closePath();
ctx.fill();
ctx.strokeStyle = "#fff";
ctx.lineWidth = 4;
ctx.setLineDash([22, 18]);
ctx.beginPath();
ctx.moveTo(166, 0);
ctx.lineTo(135, 520);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(234, 0);
ctx.lineTo(265, 520);
ctx.stroke();
ctx.setLineDash([]);
}
function spawnObject() {
const laneIndex = Math.floor(Math.random() * 3);
const isCoin = Math.random() < 0.55;
objects.push({
lane: laneIndex,
y: -20,
coin: isCoin,
hit: false
});
}
function drawObjects() {
for (let i = objects.length - 1; i >= 0; i--) {
const o = objects[i];
const x = 80 + o.lane * 120;
o.y += speed;
if (o.coin) {
ctx.fillStyle = "#ffe600";
ctx.beginPath();
ctx.arc(x, o.y, 13, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = "#b87500";
ctx.font = "bold 16px Arial";
ctx.fillText("$", x - 5, o.y + 6);
} else {
ctx.fillStyle = "#e63946";
ctx.fillRect(x - 24, o.y - 18, 48, 36);
ctx.fillStyle = "#fff";
ctx.fillRect(x - 18, o.y - 10, 36, 7);
}
const sameLane = o.lane === lane;
const nearPlayer = o.y > 385 && o.y < 465;
if (sameLane && nearPlayer && !o.hit) {
if (o.coin) {
score++;
document.getElementById("score").textContent = score;
o.hit = true;
} else if (jumpHeight < 45) {
gameOver = true;
}
}
if (o.y > 550) objects.splice(i, 1);
}
}
function loop() {
drawRoad();
if (!gameOver) {
frame++;
if (frame % 42 === 0) spawnObject();
if (frame % 500 === 0) speed += 0.5;
if (jumping) {
jumpHeight -= 7;
if (jumpHeight <= 0) {
jumpHeight = 0;
jumping = false;
}
}
drawObjects();
drawPlayer();
} else {
drawObjects();
drawPlayer();
ctx.fillStyle = "rgba(0,0,0,0.75)";
ctx.fillRect(25, 190, 350, 130);
ctx.fillStyle = "#ffe45c";
ctx.font = "bold 32px Arial";
ctx.fillText("GAME OVER!", 78, 240);
ctx.fillStyle = "#fff";
ctx.font = "20px Arial";
ctx.fillText("Coins: " + score, 145, 275);
ctx.fillText("Press Restart", 128, 302);
}
requestAnimationFrame(loop);
}
let touchStartX = 0;
let touchStartY = 0;
canvas.addEventListener("touchstart", e => {
touchStartX = e.changedTouches[0].clientX;
touchStartY = e.changedTouches[0].clientY;
}, {passive: true});
canvas.addEventListener("touchend", e => {
const dx = e.changedTouches[0].clientX - touchStartX;
const dy = e.changedTouches[0].clientY - touchStartY;
if (Math.abs(dx) > Math.abs(dy)) {
if (dx > 25) move(1);
if (dx < -25) move(-1);
} else if (dy < -25) {
jump();
}
}, {passive: true});
loop();
</script>
</body>
</html>Game Source: Super Runner
Creator: RapidGecko49
Libraries: none
Complexity: complex (261 lines, 5.2 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: super-runner-rapidgecko49" to link back to the original. Then publish at arcadelab.ai/publish.