// loadingdecoding pod stream
12.0 KB · main
neon-drift-duel/index.html
1<!doctype html>2<html lang="en">3<head>4 <meta charset="UTF-8" />5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />6 <title>Neon Drift Duel</title>7 <style>8 :root {9 --bg1: #0a0f1f;10 --bg2: #111b38;11 --cyan: #54f7ff;12 --pink: #ff4fd8;13 --gold: #ffe66d;14 --white: #eef6ff;15 --red: #ff6b6b;16 --green: #7dffb3;17 }18 * { box-sizing: border-box; }19 body {20 margin: 0;21 font-family: Inter, system-ui, sans-serif;22 color: var(--white);23 min-height: 100vh;24 display: grid;25 place-items: center;26 background:27 radial-gradient(circle at top, rgba(84,247,255,.18), transparent 28%),28 radial-gradient(circle at bottom, rgba(255,79,216,.14), transparent 30%),29 linear-gradient(160deg, var(--bg1), var(--bg2));30 overflow: hidden;31 }32 .wrap {33 width: min(94vw, 860px);34 display: grid;35 gap: 14px;36 justify-items: center;37 }38 .hud {39 width: 100%;40 display: flex;41 gap: 12px;42 justify-content: space-between;43 align-items: center;44 flex-wrap: wrap;45 padding: 10px 14px;46 border: 1px solid rgba(255,255,255,.16);47 background: rgba(255,255,255,.06);48 backdrop-filter: blur(10px);49 border-radius: 16px;50 box-shadow: 0 0 24px rgba(0,0,0,.25);51 }52 .stats { display: flex; gap: 16px; flex-wrap: wrap; }53 .pill {54 padding: 8px 12px;55 border-radius: 999px;56 background: rgba(255,255,255,.08);57 border: 1px solid rgba(255,255,255,.1);58 font-weight: 700;59 letter-spacing: .02em;60 }61 .pill strong { color: var(--gold); }62 button {63 border: 0;64 cursor: pointer;65 color: #06101f;66 background: linear-gradient(135deg, var(--cyan), #9efff1);67 padding: 10px 16px;68 border-radius: 999px;69 font-weight: 900;70 box-shadow: 0 8px 24px rgba(84,247,255,.25);71 }72 canvas {73 width: min(94vw, 860px);74 height: min(70vh, 620px);75 border-radius: 22px;76 border: 1px solid rgba(255,255,255,.14);77 background: linear-gradient(180deg, rgba(9,18,43,.96), rgba(4,9,23,.96));78 box-shadow: 0 30px 80px rgba(0,0,0,.45), inset 0 0 70px rgba(84,247,255,.05);79 }80 .help {81 text-align: center;82 color: rgba(238,246,255,.86);83 font-size: 14px;84 line-height: 1.5;85 max-width: 700px;86 }87 .accent { color: var(--cyan); font-weight: 700; }88 .accent2 { color: var(--pink); font-weight: 700; }89 </style>90</head>91<body>92 <div class="wrap">93 <div class="hud">94 <div class="stats">95 <div class="pill">Score <strong id="score">0</strong></div>96 <div class="pill">Best <strong id="best">0</strong></div>97 <div class="pill">Lives <strong id="lives">3</strong></div>98 <div class="pill">Level <strong id="level">1</strong></div>99 </div>100 <button id="restart">Restart</button>101 </div>102 <canvas id="game" width="860" height="620" aria-label="Neon Drift Duel game canvas"></canvas>103 <div class="help">104 Move with <span class="accent">WASD</span> or <span class="accent">Arrow Keys</span>. Collect glowing <span class="accent">energy orbs</span>, dodge <span class="accent2">hunter drones</span>, and survive long enough to reach higher levels.105 </div>106 </div>107108 <script>109 const canvas = document.getElementById('game');110 const ctx = canvas.getContext('2d');111 const scoreEl = document.getElementById('score');112 const bestEl = document.getElementById('best');113 const livesEl = document.getElementById('lives');114 const levelEl = document.getElementById('level');115 const restartBtn = document.getElementById('restart');116117 const W = canvas.width;118 const H = canvas.height;119 const keys = new Set();120 const bestKey = 'neon-drift-duel-best';121122 let stars = Array.from({ length: 120 }, () => ({123 x: Math.random() * W,124 y: Math.random() * H,125 r: Math.random() * 1.6 + 0.4,126 a: Math.random() * 0.8 + 0.2,127 s: Math.random() * 0.3 + 0.05128 }));129130 let player, drones, orbs, score, best, lives, level, spawnTimer, hitFlash, gameOver, frame;131132 function rand(min, max) { return Math.random() * (max - min) + min; }133 function clamp(v, min, max) { return Math.max(min, Math.min(max, v)); }134 function dist(a, b) { return Math.hypot(a.x - b.x, a.y - b.y); }135136 function reset() {137 player = { x: W / 2, y: H / 2, r: 16, speed: 4.2, vx: 0, vy: 0, trail: [] };138 drones = [];139 orbs = [];140 score = 0;141 lives = 3;142 level = 1;143 spawnTimer = 0;144 hitFlash = 0;145 gameOver = false;146 frame = 0;147 best = Number(localStorage.getItem(bestKey) || 0);148 for (let i = 0; i < 4; i++) spawnOrb();149 updateHud();150 }151152 function updateHud() {153 scoreEl.textContent = score;154 bestEl.textContent = best;155 livesEl.textContent = lives;156 levelEl.textContent = level;157 }158159 function spawnOrb() {160 orbs.push({161 x: rand(40, W - 40),162 y: rand(40, H - 40),163 r: rand(8, 12),164 pulse: rand(0, Math.PI * 2)165 });166 }167168 function spawnDrone() {169 const edge = Math.floor(Math.random() * 4);170 let x = 0, y = 0;171 if (edge === 0) { x = rand(0, W); y = -30; }172 if (edge === 1) { x = W + 30; y = rand(0, H); }173 if (edge === 2) { x = rand(0, W); y = H + 30; }174 if (edge === 3) { x = -30; y = rand(0, H); }175 const speed = rand(1.4, 2.4) + level * 0.18;176 drones.push({ x, y, r: rand(14, 22), speed, hue: rand(320, 360), wobble: rand(0, Math.PI * 2) });177 }178179 function hitPlayer() {180 lives -= 1;181 hitFlash = 18;182 player.x = W / 2;183 player.y = H / 2;184 player.trail = [];185 drones = drones.slice(Math.max(0, drones.length - 2));186 if (lives <= 0) {187 gameOver = true;188 if (score > best) {189 best = score;190 localStorage.setItem(bestKey, String(best));191 }192 }193 updateHud();194 }195196 function controlPlayer() {197 let dx = 0;198 let dy = 0;199 if (keys.has('arrowleft') || keys.has('a')) dx -= 1;200 if (keys.has('arrowright') || keys.has('d')) dx += 1;201 if (keys.has('arrowup') || keys.has('w')) dy -= 1;202 if (keys.has('arrowdown') || keys.has('s')) dy += 1;203 const len = Math.hypot(dx, dy) || 1;204 player.vx = (dx / len) * player.speed;205 player.vy = (dy / len) * player.speed;206 player.x = clamp(player.x + player.vx, player.r, W - player.r);207 player.y = clamp(player.y + player.vy, player.r, H - player.r);208 player.trail.push({ x: player.x, y: player.y });209 if (player.trail.length > 16) player.trail.shift();210 }211212 function update() {213 frame += 1;214 if (!gameOver) {215 controlPlayer();216217 const desiredLevel = 1 + Math.floor(score / 8);218 if (desiredLevel !== level) {219 level = desiredLevel;220 updateHud();221 }222223 spawnTimer -= 1;224 if (spawnTimer <= 0) {225 spawnDrone();226 spawnTimer = Math.max(26, 92 - level * 6);227 }228229 drones.forEach((d, i) => {230 d.wobble += 0.05;231 const dx = player.x - d.x;232 const dy = player.y - d.y;233 const len = Math.hypot(dx, dy) || 1;234 d.x += (dx / len) * d.speed + Math.cos(d.wobble) * 0.45;235 d.y += (dy / len) * d.speed + Math.sin(d.wobble) * 0.45;236 if (dist(player, d) < player.r + d.r - 2) hitPlayer();237 });238239 orbs.forEach((o, idx) => {240 o.pulse += 0.08;241 if (dist(player, o) < player.r + o.r + 2) {242 orbs.splice(idx, 1);243 score += 1;244 if (score > best) {245 best = score;246 localStorage.setItem(bestKey, String(best));247 }248 updateHud();249 spawnOrb();250 if (score % 5 === 0) spawnOrb();251 }252 });253 }254255 if (hitFlash > 0) hitFlash -= 1;256 }257258 function drawGrid() {259 ctx.save();260 ctx.strokeStyle = 'rgba(84,247,255,0.08)';261 ctx.lineWidth = 1;262 const gap = 40;263 for (let x = 0; x <= W; x += gap) {264 ctx.beginPath();265 ctx.moveTo(x, 0);266 ctx.lineTo(x, H);267 ctx.stroke();268 }269 for (let y = 0; y <= H; y += gap) {270 ctx.beginPath();271 ctx.moveTo(0, y);272 ctx.lineTo(W, y);273 ctx.stroke();274 }275 ctx.restore();276 }277278 function drawStars() {279 stars.forEach(s => {280 s.y += s.s;281 if (s.y > H) { s.y = -4; s.x = Math.random() * W; }282 ctx.fillStyle = `rgba(255,255,255,${s.a})`;283 ctx.beginPath();284 ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);285 ctx.fill();286 });287 }288289 function drawPlayer() {290 player.trail.forEach((p, i) => {291 ctx.fillStyle = `rgba(84,247,255,${i / player.trail.length * 0.35})`;292 ctx.beginPath();293 ctx.arc(p.x, p.y, 6 + i * 0.1, 0, Math.PI * 2);294 ctx.fill();295 });296297 ctx.save();298 ctx.translate(player.x, player.y);299 ctx.rotate(Math.atan2(player.vy || -1, player.vx || 0) + Math.PI / 2);300 ctx.shadowBlur = 24;301 ctx.shadowColor = '#54f7ff';302 ctx.fillStyle = '#54f7ff';303 ctx.beginPath();304 ctx.moveTo(0, -18);305 ctx.lineTo(12, 14);306 ctx.lineTo(0, 8);307 ctx.lineTo(-12, 14);308 ctx.closePath();309 ctx.fill();310 ctx.restore();311 }312313 function drawOrbs() {314 orbs.forEach(o => {315 const pulse = 1 + Math.sin(o.pulse) * 0.18;316 const grd = ctx.createRadialGradient(o.x, o.y, 0, o.x, o.y, o.r * 2.2);317 grd.addColorStop(0, 'rgba(255,230,109,1)');318 grd.addColorStop(0.4, 'rgba(255,170,51,.8)');319 grd.addColorStop(1, 'rgba(255,170,51,0)');320 ctx.fillStyle = grd;321 ctx.beginPath();322 ctx.arc(o.x, o.y, o.r * 2.2 * pulse, 0, Math.PI * 2);323 ctx.fill();324 ctx.fillStyle = '#ffe66d';325 ctx.beginPath();326 ctx.arc(o.x, o.y, o.r * pulse, 0, Math.PI * 2);327 ctx.fill();328 });329 }330331 function drawDrones() {332 drones.forEach(d => {333 ctx.save();334 ctx.translate(d.x, d.y);335 ctx.shadowBlur = 24;336 ctx.shadowColor = 'rgba(255,79,216,.8)';337 ctx.strokeStyle = '#ff4fd8';338 ctx.lineWidth = 3;339 ctx.beginPath();340 ctx.arc(0, 0, d.r, 0, Math.PI * 2);341 ctx.stroke();342 ctx.beginPath();343 ctx.moveTo(-d.r * 0.9, 0);344 ctx.lineTo(d.r * 0.9, 0);345 ctx.moveTo(0, -d.r * 0.9);346 ctx.lineTo(0, d.r * 0.9);347 ctx.stroke();348 ctx.fillStyle = '#ff7cf0';349 ctx.beginPath();350 ctx.arc(0, 0, d.r * 0.28, 0, Math.PI * 2);351 ctx.fill();352 ctx.restore();353 });354 }355356 function drawGameOver() {357 if (!gameOver) return;358 ctx.save();359 ctx.fillStyle = 'rgba(4,10,22,.72)';360 ctx.fillRect(0, 0, W, H);361 ctx.textAlign = 'center';362 ctx.fillStyle = '#eef6ff';363 ctx.font = '900 54px Inter, system-ui, sans-serif';364 ctx.fillText('Game Over', W / 2, H / 2 - 30);365 ctx.font = '700 26px Inter, system-ui, sans-serif';366 ctx.fillStyle = '#ffe66d';367 ctx.fillText(`Final Score: ${score}`, W / 2, H / 2 + 18);368 ctx.font = '500 20px Inter, system-ui, sans-serif';369 ctx.fillStyle = '#b9d3ff';370 ctx.fillText('Press Restart to jump back in.', W / 2, H / 2 + 58);371 ctx.restore();372 }373374 function render() {375 ctx.clearRect(0, 0, W, H);376 drawStars();377 drawGrid();378 drawOrbs();379 drawDrones();380 drawPlayer();381382 if (hitFlash > 0) {383 ctx.fillStyle = `rgba(255,107,107,${hitFlash / 30})`;384 ctx.fillRect(0, 0, W, H);385 }386387 drawGameOver();388 }389390 function loop() {391 update();392 render();393 requestAnimationFrame(loop);394 }395396 window.addEventListener('keydown', (e) => {397 keys.add(e.key.toLowerCase());398 if (["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"," "].includes(e.key)) e.preventDefault();399 }, { passive: false });400401 window.addEventListener('keyup', (e) => keys.delete(e.key.toLowerCase()));402 restartBtn.addEventListener('click', reset);403404 reset();405 loop();406 </script>407</body>408</html>