Meta Description" name="description" />

Share this result

Previews are deleted daily. Get a permanent share link sent to your inbox:
Script
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Dirt Rally Arcade</title> <style> * { box-sizing: border-box; margin: 0; padding: 0; } body { background-color: #111; color: #fff; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; overflow: hidden; } #game-container { position: relative; width: 800px; height: 600px; box-shadow: 0 0 20px rgba(255, 120, 0, 0.4); border: 3px solid #ff6600; } canvas { display: block; width: 100%; height: 100%; background: #000; } #ui-overlay { position: absolute; top: 20px; left: 20px; right: 20px; display: flex; justify-content: space-between; pointer-events: none; } .hud-box { background: rgba(0, 0, 0, 0.7); border-left: 4px solid #ff6600; padding: 10px 18px; font-size: 20px; font-weight: bold; text-transform: uppercase; letter-spacing: 1px; } .hud-box span { color: #ff6600; } #controls-hint { position: absolute; bottom: 15px; left: 50%; transform: translateX(-50%); background: rgba(0, 0, 0, 0.6); padding: 6px 15px; border-radius: 20px; font-size: 13px; color: #aaa; pointer-events: none; } </style> </head> <body> <div id="game-container"> <canvas id="canvas" width="800" height="600"></canvas> <div id="ui-overlay"> <div class="hud-box">SPEED: <span id="speed-val">0</span> KM/H</div> <div class="hud-box">SCORE: <span id="score-val">0</span></div> </div> <div id="controls-hint">Controls: [UP / W] Accelerate | [DOWN / S] Brake | [LEFT/RIGHT / A/D] Steer | [SPACE] Handbrake Drift</div> </div> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const speedEl = document.getElementById('speed-val'); const scoreEl = document.getElementById('score-val'); // Game Config & Constants const CANVAS_WIDTH = 800; const CANVAS_HEIGHT = 600; const ROAD_WIDTH = 2000; const SEGMENT_LENGTH = 200; const CAM_DEPTH = 0.8; const DRAW_DISTANCE = 300; // Inputs const keys = { Up: false, Down: false, Left: false, Right: false, Space: false }; // Player Physics State let playerX = 0; // Normalized position (-1 left, 1 right relative to road center) let playerZ = 0; // Distance along track let speed = 0; // Current speed const maxSpeed = 12000; // Max units/sec const accel = 4800; const braking = 8000; const decel = 3000; const offroadDecel = 9000; const offroadMaxSpeed = 4000; let driftFactor = 0; let score = 0; // Track Generation let segments = []; const TRACK_LENGTH = 1200; function buildTrack() { segments = []; for (let i = 0; i < TRACK_LENGTH; i++) { let curve = 0; // Add curves at specific segments to simulate rally stages if (i > 100 && i < 300) curve = 2.5; if (i > 400 && i < 600) curve = -3.5; if (i > 700 && i < 900) curve = 4; if (i > 1000 && i < 1150) curve = -2; segments.push({ index: i, p1: { world: { z: i * SEGMENT_LENGTH }, camera: {}, screen: {} }, p2: { world: { z: (i + 1) * SEGMENT_LENGTH }, camera: {}, screen: {} }, curve: curve, color: (Math.floor(i / 3) % 2) ? { grass: '#4e3b2b', road: '#6e5a44', lane: '#8a735a', border: '#ff6600' } : { grass: '#3a2b1f', road: '#5c4a37', lane: '#6e5a44', border: '#ffffff' } }); } } // Projection Geometry function project(p, cameraX, cameraY, cameraZ) { p.camera.x = p.world.x - cameraX; p.camera.y = p.world.y - cameraY; p.camera.z = p.world.z - cameraZ; let scale = CAM_DEPTH / (p.camera.z / 1000); p.screen.scale = scale; p.screen.x = Math.round((CANVAS_WIDTH / 2) + (scale * p.camera.x * CANVAS_WIDTH / 2)); p.screen.y = Math.round((CANVAS_HEIGHT / 2) - (scale * p.camera.y * CANVAS_HEIGHT / 2)); p.screen.w = Math.round(scale * ROAD_WIDTH * CANVAS_WIDTH / 2); } // Input Handlers window.addEventListener('keydown', (e) => { if (e.code === 'ArrowUp' || e.code === 'KeyW') keys.Up = true; if (e.code === 'ArrowDown' || e.code === 'KeyS') keys.Down = true; if (e.code === 'ArrowLeft' || e.code === 'KeyA') keys.Left = true; if (e.code === 'ArrowRight' || e.code === 'KeyD') keys.Right = true; if (e.code === 'Space') keys.Space = true; }); window.addEventListener('keyup', (e) => { if (e.code === 'ArrowUp' || e.code === 'KeyW') keys.Up = false; if (e.code === 'ArrowDown' || e.code === 'KeyS') keys.Down = false; if (e.code === 'ArrowLeft' || e.code === 'KeyA') keys.Left = false; if (e.code === 'ArrowRight' || e.code === 'KeyD') keys.Right = false; if (e.code === 'Space') keys.Space = false; }); // Segment Finder Helper function findSegment(z) { return segments[Math.floor(z / SEGMENT_LENGTH) % segments.length]; } // Render Trapezoid Road Segment function renderSegment(ctx, width, lanes, x1, y1, w1, x2, y2, w2, color) { // Grass background ctx.fillStyle = color.grass; ctx.fillRect(0, y2, width, y1 - y2); // Road Base ctx.fillStyle = color.road; ctx.beginPath(); ctx.moveTo(x1 - w1, y1); ctx.lineTo(x2 - w2, y2); ctx.lineTo(x2 + w2, y2); ctx.lineTo(x1 + w1, y1); ctx.closePath(); ctx.fill(); // Red/White Dirt Borders let bw1 = w1 * 0.1; let bw2 = w2 * 0.1; ctx.fillStyle = color.border; ctx.beginPath(); ctx.moveTo(x1 - w1 - bw1, y1); ctx.lineTo(x2 - w2 - bw2, y2); ctx.lineTo(x2 - w2, y2); ctx.lineTo(x1 - w1, y1); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.moveTo(x1 + w1, y1); ctx.lineTo(x2 + w2, y2); ctx.lineTo(x2 + w2 + bw2, y2); ctx.lineTo(x1 + w1 + bw1, y1); ctx.closePath(); ctx.fill(); } // Render Player Car Sprite function renderPlayer(ctx, speedRatio, turnSign, isDrifting) { let cx = CANVAS_WIDTH / 2; let cy = CANVAS_HEIGHT - 70; ctx.save(); ctx.translate(cx, cy); // Dynamic tilt angle let angle = turnSign * 0.08; if (isDrifting) angle = turnSign * 0.22; ctx.rotate(angle); // Car Body Base ctx.fillStyle = '#cc2200'; // Rally Red Body ctx.fillRect(-40, -25, 80, 40); // Roof / Windshield ctx.fillStyle = '#111'; ctx.fillRect(-30, -20, 60, 20); // Headlights / Taillights ctx.fillStyle = '#ff2200'; // Red Taillights ctx.fillRect(-38, 10, 15, 6); ctx.fillRect(23, 10, 15, 6); // Rear Bumper Details ctx.fillStyle = '#333'; ctx.fillRect(-40, 12, 80, 5); // Tires ctx.fillStyle = '#000'; ctx.fillRect(-45, -5, 10, 20); // Rear Left ctx.fillRect(35, -5, 10, 20); // Rear Right // Dust particles when drifting/turning if (speedRatio > 0.2 && (isDrifting || Math.abs(turnSign) > 0.5)) { ctx.fillStyle = 'rgba(160, 130, 90, 0.6)'; for (let i = 0; i < 6; i++) { let px = (Math.random() - 0.5) * 60 + (turnSign * -30); let py = 15 + Math.random() * 20; let pSize = Math.random() * 10 + 4; ctx.beginPath(); ctx.arc(px, py, pSize, 0, Math.PI * 2); ctx.fill(); } } ctx.restore(); } // Game Loop Processing let lastTime = performance.now(); function update(dt) { let currentSegment = findSegment(playerZ); let speedRatio = speed / maxSpeed; // Steering & Drifting let steerPower = 1.4; let isDrifting = keys.Space && speed > 2000; if (isDrifting) { steerPower = 2.8; // Enhanced response during drift driftFactor = Math.min(driftFactor + dt * 2, 1); if (speed > 1000) score += Math.floor(dt * 500); } else { driftFactor = Math.max(driftFactor - dt * 2, 0); } let turnSign = 0; if (keys.Left) { playerX -= steerPower * speedRatio * dt; turnSign = -1; } if (keys.Right) { playerX += steerPower * speedRatio * dt; turnSign = 1; } // Apply curve centrifugal force playerX -= (currentSegment.curve * speedRatio * speedRatio * 0.8 * dt); // Acceleration / Braking if (keys.Up) { speed += accel * dt; } else if (keys.Down) { speed -= braking * dt; } else { speed -= decel * dt; } // Off-road Penalty if ((playerX < -1.1 || playerX > 1.1)) { if (speed > offroadMaxSpeed) { speed -= offroadDecel * dt; } } // Clamp speed and bounds speed = Math.max(0, Math.min(speed, maxSpeed)); playerX = Math.max(-2.5, Math.min(2.5, playerX)); // Move Player Forward playerZ += speed * dt; while (playerZ >= TRACK_LENGTH * SEGMENT_LENGTH) { playerZ -= TRACK_LENGTH * SEGMENT_LENGTH; } // Accumulate Distance Score if (speed > 0) { score += Math.floor((speed * dt) / 100); } // UI Updates speedEl.innerText = Math.floor((speed / maxSpeed) * 210); // Display simulated km/h scoreEl.innerText = score; } function render() { ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); // Render Sky / Background Horizon let skyGradient = ctx.createLinearGradient(0, 0, 0, CANVAS_HEIGHT / 2); skyGradient.addColorStop(0, '#1a0d00'); skyGradient.addColorStop(1, '#663300'); ctx.fillStyle = skyGradient; ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT / 2); // Draw Distance Segments let baseSegment = findSegment(playerZ); let cameraX = playerX * ROAD_WIDTH; let cameraY = 1000; // Camera height above ground let cameraZ = playerZ; let dx = 0; let x = 0; let maxy = CANVAS_HEIGHT; for (let n = 0; n < DRAW_DISTANCE; n++) { let segment = segments[(baseSegment.index + n) % segments.length]; // Loop track logic for projection calculations let loopOffset = (segment.index < baseSegment.index) ? TRACK_LENGTH * SEGMENT_LENGTH : 0; segment.p1.world.x = -x; segment.p1.world.y = 0; segment.p1.world.z = (segment.index * SEGMENT_LENGTH) + loopOffset; segment.p2.world.x = -x - dx; segment.p2.world.y = 0; segment.p2.world.z = ((segment.index + 1) * SEGMENT_LENGTH) + loopOffset; dx += segment.curve; x += dx; project(segment.p1, cameraX, cameraY, cameraZ); project(segment.p2, cameraX, cameraY, cameraZ); // Cull segments behind camera or occluded if (segment.p1.camera.z <= CAM_DEPTH || segment.p2.screen.y >= maxy) { continue; } renderSegment( ctx, CANVAS_WIDTH, 3, segment.p1.screen.x, segment.p1.screen.y, segment.p1.screen.w, segment.p2.screen.x, segment.p2.screen.y, segment.p2.screen.w, segment.color ); maxy = segment.p1.screen.y; } // Draw Player let turnSign = keys.Left ? -1 : (keys.Right ? 1 : 0); renderPlayer(ctx, speed / maxSpeed, turnSign, keys.Space); } function gameLoop(now) { let dt = Math.min(0.1, (now - lastTime) / 1000); lastTime = now; update(dt); render(); requestAnimationFrame(gameLoop); } // Initialization buildTrack(); requestAnimationFrame(gameLoop); </script> </body> </html>
Landing Page
This ad does not have a landing page available
Network Timeline
Performance Summary

1

Requests

1

Domains

12KB

Transfer Size

12KB

Content Size

95.0ms

Dom Content Loaded

212.0ms

First Paint

96.0ms

Load Time
Domain Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...
Timings (ms)
Loading...
Total Time
Loading...
Content Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...