0% found this document useful (0 votes)
72 views6 pages

Racing HTML

Uploaded by

ks159603
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
72 views6 pages

Racing HTML

Uploaded by

ks159603
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 6

<!

DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Canvas Racing Game</title>
<style>
:root { --road:#1c1f26; --line:#e8e8e8; --accent:#19f; --danger:#ff5a5f; --
good:#35c759; }
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; font-family: system-ui, -apple-system,
Segoe UI, Roboto, sans-serif; background: radial-gradient(1000px 600px at 50% -
200px, #10131a 0%, #0a0c10 60%); color: #e8e8e8; }
.wrap { display:flex; align-items:center; justify-content:center; height:100%;
padding:16px; }
.frame { position:relative; width:min(92vw, 520px); aspect-ratio: 9/16; border-
radius: 24px; box-shadow: 0 20px 60px rgba(0,0,0,.6), inset 0 0 0 1px
rgba(255,255,255,.06); overflow:hidden; background:#0b0f14; }
canvas { width:100%; height:100%; display:block; background: linear-
gradient(#0c1016, #0a0d12); }
.hud { position:absolute; inset:12px; display:flex; justify-content:space-
between; align-items:flex-start; pointer-events:none; }
.badge { background:rgba(0,0,0,.35); padding:6px 10px; border-radius:12px;
font-weight:600; letter-spacing:.2px; box-shadow: 0 0 0 1px rgba(255,255,255,.06)
inset; }
.center-top { position:absolute; top:12px; left:50%; transform:translateX(-
50%); pointer-events:none; font-weight:700; opacity:.8; }

.controls { position:absolute; bottom:12px; left:50%; transform:translateX(-


50%); display:flex; gap:10px; }
.btn { -webkit-tap-highlight-color:transparent; border:0;
background:rgba(255,255,255,.08); color:#e8e8e8; width:64px; height:64px; border-
radius:16px; font-size:22px; font-weight:800; box-shadow: 0 0 0 1px
rgba(255,255,255,.08) inset, 0 8px 20px rgba(0,0,0,.45); cursor:pointer; }
.btn:active { transform: translateY(1px) scale(.98); }
.btn--wide { width:140px; }

.overlay { position:absolute; inset:0; display:grid; place-items:center;


background:linear-gradient(180deg, rgba(0,0,0,.55), rgba(0,0,0,.45)); backdrop-
filter: blur(2px); }
.card { text-align:center; padding:22px 20px; background:rgba(15,18,24,.86);
border-radius:16px; box-shadow: 0 20px 40px rgba(0,0,0,.5), inset 0 0 0 1px
rgba(255,255,255,.06); max-width: 90%; }
.title { font-size:22px; margin:0 0 6px; }
.muted { opacity:.85; font-size:14px; line-height:1.4; }
.chip { display:inline-block; margin-top:10px; padding:6px 10px; border-
radius:999px; background:rgba(255,255,255,.08); font-size:12px; letter-
spacing:.3px; }
.row { display:flex; gap:10px; justify-content:center; margin-top:14px; }

.tag { position:absolute; right:12px; bottom:92px; font-size:12px;


opacity:.7; }
</style>
</head>
<body>
<div class="wrap">
<div class="frame" id="frame">
<canvas id="game" width="540" height="960"></canvas>
<!-- HUD -->
<div class="hud">
<div class="badge" id="score">Score: 0</div>
<div class="badge" id="hi">Best: 0</div>
</div>
<div class="center-top badge">Canvas Racing</div>

<!-- Touch Controls -->


<div class="controls" aria-label="Touch controls">
<button class="btn" id="left" title="Left">⟵</button>
<button class="btn btn--wide" id="start">Start</button>
<button class="btn" id="right" title="Right">⟶</button>
</div>
<div class="tag">Keys: ← → to steer · P to pause · R to restart</div>

<!-- Overlays -->


<div class="overlay" id="intro">
<div class="card">
<h2 class="title">Mini Racing</h2>
<p class="muted">Dodge traffic and drive as far as you can. The car snaps
to 3 lanes. Speed rises over time.</p>
<p class="chip">Controls: ← → / Tap arrows</p>
<div class="row">
<button class="btn btn--wide" id="playBtn">Play</button>
</div>
</div>
</div>

<div class="overlay" id="gameOver" style="display:none">


<div class="card">
<h2 class="title">Crash!</h2>
<p class="muted" id="final">Your score: 0</p>
<div class="row">
<button class="btn btn--wide" id="retry">Retry</button>
</div>
</div>
</div>

<div class="overlay" id="paused" style="display:none">


<div class="card">
<h2 class="title">Paused</h2>
<div class="row">
<button class="btn btn--wide" id="resume">Resume</button>
</div>
</div>
</div>
</div>
</div>

<script>
// ====== Utility helpers ======
const rnd = (min, max) => Math.random() * (max - min) + min;

// ====== Game constants ======


const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');

const LANES = 3;
const ROAD_W = canvas.width * 0.76; // road width
const LANE_W = ROAD_W / LANES;
const ROAD_X = (canvas.width - ROAD_W) / 2;

// Car model
const CAR_W = LANE_W * 0.6;
const CAR_H = CAR_W * 1.6;
const CAR_Y = canvas.height - CAR_H - 40;

// Gameplay
const SPAWN_MIN = 500; // ms
const SPAWN_MAX = 1100; // ms

// State
let running = false, paused = false, over = false;
let score = 0, hi = Number(localStorage.getItem('racing_hi')||0);
let speed = 6; // pixels per frame base
let lastSpawn = 0, spawnRate = SPAWN_MAX;
let last = 0; // last raf time

// Objects
const car = { lane: 1, x: 0, y: CAR_Y, w: CAR_W, h: CAR_H };
const traffic = []; // array of o {lane, y, speed}
const particles = []; // for lane dash motion

// HUD
const scoreEl = document.getElementById('score');
const hiEl = document.getElementById('hi');
hiEl.textContent = 'Best: ' + hi;

// ====== Setup functions ======


function laneX(lane) { return ROAD_X + lane * LANE_W + (LANE_W - CAR_W)/2; }
function reset() {
score = 0; speed = 6; spawnRate = SPAWN_MAX; lastSpawn = 0; last = 0;
car.lane = 1; car.x = laneX(car.lane);
traffic.length = 0; particles.length = 0; over = false; paused = false;
spawnDashes();
}

function spawnDashes(){
// create dashed lane markers as particles
particles.length = 0;
for (let lane = 1; lane < LANES; lane++) {
for (let y = -200; y < canvas.height + 200; y += 80) {
particles.push({ x: ROAD_X + lane*LANE_W, y, w: 6, h: 32 });
}
}
}

function spawnTraffic() {
const lane = Math.floor(rnd(0, LANES));
const y = -CAR_H - 20;
const s = speed * rnd(0.9, 1.25);
// avoid spawning directly over another in same lane too close
const tooClose = traffic.some(t => t.lane === lane && Math.abs(t.y - y) <
CAR_H * 2.2);
if (!tooClose) traffic.push({ lane, x: laneX(lane), y, w: CAR_W, h: CAR_H,
s });
}
// ====== Drawing ======
function drawRoad(){
// road background
ctx.fillStyle =
getComputedStyle(document.documentElement).getPropertyValue('--road');
ctx.fillRect(ROAD_X, 0, ROAD_W, canvas.height);

// side gradients (shoulders)


const grdL = ctx.createLinearGradient(ROAD_X-20,0,ROAD_X,0);
grdL.addColorStop(0,'rgba(0,0,0,.0)'); grdL.addColorStop(1,'#0d1016');
ctx.fillStyle = grdL; ctx.fillRect(ROAD_X-20,0,20,canvas.height);

const grdR = ctx.createLinearGradient(ROAD_X+ROAD_W,0,ROAD_X+ROAD_W+20,0);


grdR.addColorStop(0,'#0d1016'); grdR.addColorStop(1,'rgba(0,0,0,.0)');
ctx.fillStyle = grdR; ctx.fillRect(ROAD_X+ROAD_W,0,20,canvas.height);

// moving dashes
ctx.fillStyle =
getComputedStyle(document.documentElement).getPropertyValue('--line');
particles.forEach(p => { ctx.fillRect(p.x-3, p.y, p.w, p.h); });
}

function drawCar(x, y, baseColor){


const r = 10;
ctx.fillStyle = baseColor;
roundRect(ctx, x, y, CAR_W, CAR_H, r, true);
// windshield
ctx.fillStyle = 'rgba(255,255,255,.2)';
roundRect(ctx, x+CAR_W*0.14, y+CAR_H*0.14, CAR_W*0.72, CAR_H*0.26, 8, true);
// cockpit
ctx.fillStyle = 'rgba(0,0,0,.25)';
roundRect(ctx, x+CAR_W*0.2, y+CAR_H*0.44, CAR_W*0.6, CAR_H*0.18, 8, true);
// lights
ctx.fillStyle = '#ffd15c';
ctx.fillRect(x+CAR_W*0.1, y+CAR_H*0.9, 10, 8);
ctx.fillRect(x+CAR_W*0.8-10, y+CAR_H*0.9, 10, 8);
}

function roundRect(ctx, x, y, w, h, r, fill){


ctx.beginPath();
ctx.moveTo(x+r, y);
ctx.arcTo(x+w, y, x+w, y+h, r);
ctx.arcTo(x+w, y+h, x, y+h, r);
ctx.arcTo(x, y+h, x, y, r);
ctx.arcTo(x, y, x+w, y, r);
ctx.closePath();
if (fill) ctx.fill();
}

// ====== Loop ======


function step(t){
if (!running) return;
const dt = t - last; last = t;
if (paused || over) { requestAnimationFrame(step); return; }

// clear
ctx.clearRect(0,0,canvas.width, canvas.height);

// update background dashes


particles.forEach(p => { p.y += speed * 1.4; if (p.y > canvas.height + 40)
p.y = -80; });

drawRoad();

// move traffic
for (let i=traffic.length-1; i>=0; i--){
const o = traffic[i];
o.y += o.s;
if (o.y > canvas.height + 60) traffic.splice(i,1);
}

// draw traffic cars


traffic.forEach((o, idx) => drawCar(o.x, o.y, idx%2? '#19f' : '#35c759'));

// player car
car.x = laneX(car.lane);
drawCar(car.x, car.y, '#ff5a5f');

// collisions
const hit = traffic.some(o =>
Math.abs(o.lane - car.lane) < 0.1 &&
o.y + o.h*0.8 > car.y &&
o.y < car.y + car.h*0.8
);
if (hit) return gameOver();

// scoring & difficulty


score += (speed * dt) / 100; // distance-based
speed += 0.0009 * dt; // slowly accelerate
spawnRate = Math.max(SPAWN_MIN, SPAWN_MAX - score * 0.6);

// spawn timing
lastSpawn += dt;
if (lastSpawn > spawnRate){
spawnTraffic();
lastSpawn = 0;
}

// hud
scoreEl.textContent = 'Score: ' + Math.floor(score);

requestAnimationFrame(step);
}

function gameOver(){
over = true; running = false;
const s = Math.floor(score);
if (s > hi){ hi = s; localStorage.setItem('racing_hi', hi); }
hiEl.textContent = 'Best: ' + hi;
document.getElementById('final').textContent = `Your score: ${s} · Best: $
{hi}`;
show('gameOver');
}

// ====== Controls ======


function steer(dir){
if (over || paused) return;
car.lane = Math.min(LANES-1, Math.max(0, car.lane + dir));
}

window.addEventListener('keydown', e => {
if (e.key === 'ArrowLeft') steer(-1);
else if (e.key === 'ArrowRight') steer(1);
else if (e.key.toLowerCase() === 'p') togglePause();
else if (e.key.toLowerCase() === 'r') restart();
});

document.getElementById('left').addEventListener('pointerdown', () => steer(-


1));
document.getElementById('right').addEventListener('pointerdown', () =>
steer(1));

// Buttons
function hide(id){ document.getElementById(id).style.display='none'; }
function show(id){ document.getElementById(id).style.display='grid'; }

document.getElementById('playBtn').onclick = start;
document.getElementById('start').onclick = start;
document.getElementById('retry').onclick = restart;
document.getElementById('resume').onclick = () => { paused=false;
hide('paused'); running=true; requestAnimationFrame(step); };

function start(){ hide('intro'); hide('gameOver'); reset(); running = true;


requestAnimationFrame(step); }
function restart(){ hide('gameOver'); reset(); running = true;
requestAnimationFrame(step); }

function togglePause(){
if (over || !running) return; paused = !paused;
if (paused) { show('paused'); running = false; } else { hide('paused');
running = true; requestAnimationFrame(step); }
}

// Fit canvas to container size while preserving internal resolution


const frame = document.getElementById('frame');
const resize = () => {
// Canvas displayed size handled by CSS; we keep internal resolution fixed
for physics
spawnDashes();
};
window.addEventListener('resize', resize);
resize();

// Initialize car placement


car.x = laneX(car.lane);
</script>
</body>
</html>

You might also like