opal-racing

bysumanth krishna

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>F1 Micro Racing</title> <style> body { margin: 0; background: #222; overflow: hidden; font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; } #gameCanvas { background: #444; box-shadow: 0 0 20px rgba(0,0,0,0.5); } #ui { position: absolute; top: 20px; color: white; font-size: 20px; font-weight: bold; text-shadow: 2px 2px black; pointer-events: none; } </style> </head> <body> <div id="ui">Score: <span id="score">0</span></div> <canvas id="gameCanvas" width="400" height="600"></canvas> <script> const canvas = document.getElementById("gameCanvas"); const ctx = canvas.getContext("2d"); const scoreEl = document.getElementById("score"); // Game Variables let score = 0; let gameOver = false; let speed = 5; // Player F1 Car (Red) const player = { x: 180, y: 480, width: 40, height: 70, color: "#E10600" // F1 Red }; // Enemy F1 Cars const enemies = []; const enemyColors = ["#00A294", "#00D2FF", "#FFF500", "#FFFFFF"]; function spawnEnemy() { if (enemies.length < 3 && Math.random() < 0.02) { let lane = Math.floor(Math.random() * 3); // 3 lanes let xPos = 50 + lane * 110; // Prevent overlapping on spawn if (!enemies.some(e => Math.abs(e.y) < 150 && e.x === xPos)) { enemies.push({ x: xPos + 15, y: -100, width: 40, height: 70, color: enemyColors[Math.floor(Math.random() * enemyColors.length)] }); } } } // Controls (Keyboard for PC, Clicks/Touches for Mobile) window.addEventListener("keydown", (e) => { if (e.key === "ArrowLeft" && player.x > 50) player.x -= 110; if (e.key === "ArrowRight" && player.x < 270) player.x += 110; }); canvas.addEventListener("touchstart", (e) => { const touchX = e.touches[0].clientX - canvas.getBoundingClientRect().left; if (touchX < canvas.width / 2 && player.x > 50) player.x -= 110; if (touchX >= canvas.width / 2 && player.x < 270) player.x += 110; }); // Collision Detection function checkCollision(rect1, rect2) { return rect1.x < rect2.x + rect2.width && rect1.x + rect1.width > rect2.x && rect1.y < rect2.y + rect2.height && rect1.y + rect1.height > rect2.y; } // Game Loop function update() { if (gameOver) { ctx.fillStyle = "rgba(0,0,0,0.7)"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "white"; ctx.font = "30px Arial"; ctx.fillText("GAME OVER", 110, 280); ctx.font = "20px Arial"; ctx.fillText("Tap screen to restart", 110, 320); return; } // Clear Canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // Draw Track Borders & Lanes ctx.fillStyle = "#555"; // Track ctx.fillRect(40, 0, 320, canvas.height); ctx.fillStyle = "#FFF"; // Left line ctx.fillRect(40, 0, 5, canvas.height); ctx.fillRect(355, 0, 5, canvas.height); // Move & Draw Enemies spawnEnemy(); for (let i = enemies.length - 1; i >= 0; i--) { enemies[i].y += speed; // Draw Enemy Car ctx.fillStyle = enemies[i].color; ctx.fillRect(enemies[i].x, enemies[i].y, enemies[i].width, enemies[i].height); // Spoiler & Wheels details ctx.fillStyle = "#111"; ctx.fillRect(enemies[i].x - 5, enemies[i].y + 10, 5, 15); // Front Left wheel ctx.fillRect(enemies[i].x + enemies[i].width, enemies[i].y + 10, 5, 15); ctx.fillRect(enemies[i].x - 5, enemies[i].y + 50, 5, 15); // Rear wheels ctx.fillRect(enemies[i].x + enemies[i].width, enemies[i].y + 50, 5, 15); // Check Collision if (checkCollision(player, enemies[i])) { gameOver = true; } // Score point if passed if (enemies[i].y > canvas.height) { enemies.splice(i, 1); score++; scoreEl.innerText = score; if (score % 5 === 0) speed += 0.5; // Speed up } } // Draw Player Car ctx.fillStyle = player.color; ctx.fillRect(player.x, player.y, player.width, player.height); // Player wheels ctx.fillStyle = "#111"; ctx.fillRect(player.x - 5, player.y + 10, 5, 15); ctx.fillRect(player.x + player.width, player.y + 10, 5, 15); ctx.fillRect(player.x - 5, player.y + 50, 5, 15); ctx.fillRect(player.x + player.width, player.y + 50, 5, 15); requestAnimationFrame(update); } // Restart game on click after game over canvas.addEventListener("click", () => { if (gameOver) { enemies.length = 0; score = 0; scoreEl.innerText = score; speed = 5; player.x = 180; gameOver = false; update(); } }); update(); </script> </body> </html>

No preview

Comments (0)

No comments yet. Be the first!

System Requirements

System Requirement Document
📝

Requirements Not Generated Yet

The SRD will be automatically generated as you discuss your project with the Tech Lead Agent.

No completed page designs yet.

Completed design pages will appear here when they are ready to preview.

No user flows yet.

The User Flow Agent will generate per-persona navigation diagrams after SRD updates.

No completed page designs yet.

Completed design pages will appear here when they are ready to preview.

No user flows yet.

The User Flow Agent will generate per-persona navigation diagrams after SRD updates.