// loadingdecoding pod stream
15.9 KB · main
neon-dodge/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 Dodge</title>7 <style>8 :root {9 color-scheme: dark;10 --bg1: #050816;11 --bg2: #0a1636;12 --cyan: #60f5ff;13 --pink: #ff5fd2;14 --gold: #ffd166;15 --white: #f6fbff;16 --danger: #ff6b6b;17 }18 * { box-sizing: border-box; }19 body {20 margin: 0;21 min-height: 100vh;22 display: grid;23 place-items: center;24 overflow: hidden;25 font-family: Inter, ui-sans-serif, system-ui, sans-serif;26 color: var(--white);27 background:28 radial-gradient(circle at 20% 20%, rgba(96,245,255,0.18), transparent 35%),29 radial-gradient(circle at 80% 10%, rgba(255,95,210,0.2), transparent 30%),30 radial-gradient(circle at 50% 90%, rgba(255,209,102,0.14), transparent 30%),31 linear-gradient(180deg, var(--bg2), var(--bg1));32 }33 .wrap {34 width: min(94vw, 960px);35 display: grid;36 gap: 14px;37 }38 .hud {39 display: flex;40 justify-content: space-between;41 gap: 12px;42 align-items: center;43 padding: 10px 14px;44 border: 1px solid rgba(255,255,255,0.14);45 border-radius: 18px;46 background: rgba(7, 12, 28, 0.66);47 backdrop-filter: blur(12px);48 box-shadow: 0 16px 50px rgba(0,0,0,0.35);49 flex-wrap: wrap;50 }51 .brand {52 display: flex;53 flex-direction: column;54 gap: 2px;55 }56 .brand h1 {57 margin: 0;58 font-size: clamp(1.25rem, 2vw, 1.8rem);59 letter-spacing: 0.08em;60 text-transform: uppercase;61 color: var(--cyan);62 text-shadow: 0 0 18px rgba(96,245,255,0.45);63 }64 .brand p, .meta {65 margin: 0;66 color: rgba(246,251,255,0.8);67 font-size: 0.95rem;68 }69 .stats {70 display: flex;71 gap: 10px;72 flex-wrap: wrap;73 }74 .pill {75 min-width: 105px;76 padding: 10px 12px;77 border-radius: 14px;78 background: rgba(255,255,255,0.06);79 border: 1px solid rgba(255,255,255,0.1);80 }81 .pill span {82 display: block;83 font-size: 0.75rem;84 letter-spacing: 0.08em;85 text-transform: uppercase;86 color: rgba(246,251,255,0.68);87 }88 .pill strong {89 font-size: 1.15rem;90 color: var(--white);91 }92 .stage {93 position: relative;94 border-radius: 24px;95 overflow: hidden;96 border: 1px solid rgba(255,255,255,0.14);97 box-shadow: 0 18px 80px rgba(0,0,0,0.48);98 background: rgba(5, 8, 22, 0.9);99 }100 canvas {101 display: block;102 width: 100%;103 height: auto;104 aspect-ratio: 16 / 10;105 background: transparent;106 }107 .overlay {108 position: absolute;109 inset: 0;110 display: grid;111 place-items: center;112 pointer-events: none;113 padding: 24px;114 }115 .panel {116 max-width: 520px;117 text-align: center;118 background: rgba(4, 8, 20, 0.72);119 border: 1px solid rgba(255,255,255,0.14);120 border-radius: 24px;121 padding: 24px;122 backdrop-filter: blur(10px);123 box-shadow: 0 12px 40px rgba(0,0,0,0.4);124 }125 .panel.hidden { display: none; }126 .panel h2 {127 margin: 0 0 8px;128 font-size: clamp(1.8rem, 4vw, 2.8rem);129 color: var(--pink);130 text-shadow: 0 0 18px rgba(255,95,210,0.35);131 }132 .panel p { margin: 8px 0; line-height: 1.5; }133 .panel .hint { color: rgba(246,251,255,0.72); }134 .flash {135 color: var(--gold);136 font-weight: 700;137 }138 @media (max-width: 640px) {139 .pill { min-width: 92px; }140 .hud { padding: 12px; }141 .panel { padding: 18px; }142 }143 </style>144</head>145<body>146 <div class="wrap">147 <div class="hud">148 <div class="brand">149 <h1>Neon Dodge</h1>150 <p>Dash, weave, survive the pulse.</p>151 </div>152 <div class="stats">153 <div class="pill"><span>Score</span><strong id="score">0</strong></div>154 <div class="pill"><span>Best</span><strong id="best">0</strong></div>155 <div class="pill"><span>Level</span><strong id="level">1</strong></div>156 </div>157 <p class="meta">Move with arrow keys or WASD. Press space to start or restart.</p>158 </div>159160 <div class="stage">161 <canvas id="game" width="960" height="600" aria-label="Neon Dodge game"></canvas>162 <div class="overlay">163 <div class="panel" id="panel">164 <h2 id="panelTitle">Neon Dodge</h2>165 <p id="panelText">Slip through the glowing shards, collect gold sparks, and hold out as the arena speeds up.</p>166 <p class="hint">Arrow keys / WASD to move • Space to play</p>167 <p class="flash" id="panelFlash">Ready when you are.</p>168 </div>169 </div>170 </div>171 </div>172173 <script>174 const canvas = document.getElementById('game');175 const ctx = canvas.getContext('2d');176 const scoreEl = document.getElementById('score');177 const bestEl = document.getElementById('best');178 const levelEl = document.getElementById('level');179 const panel = document.getElementById('panel');180 const panelTitle = document.getElementById('panelTitle');181 const panelText = document.getElementById('panelText');182 const panelFlash = document.getElementById('panelFlash');183184 const W = canvas.width;185 const H = canvas.height;186 const keys = new Set();187 const stars = Array.from({ length: 90 }, () => ({188 x: Math.random() * W,189 y: Math.random() * H,190 r: Math.random() * 2 + 0.4,191 s: Math.random() * 0.5 + 0.2,192 }));193194 const state = {195 running: false,196 gameOver: false,197 score: 0,198 best: Number(localStorage.getItem('neon-dodge-best') || 0),199 level: 1,200 tick: 0,201 difficulty: 1,202 pulse: 0,203 pickupTimer: 0,204 message: 'Ready when you are.',205 };206207 const player = {208 x: W / 2,209 y: H - 90,210 r: 16,211 speed: 5,212 glow: 0,213 };214215 let obstacles = [];216 let pickups = [];217 let particles = [];218219 bestEl.textContent = state.best;220221 function resetGame() {222 state.running = true;223 state.gameOver = false;224 state.score = 0;225 state.level = 1;226 state.tick = 0;227 state.difficulty = 1;228 state.pulse = 0;229 state.pickupTimer = 0;230 state.message = 'Collect sparks for bonus points.';231 player.x = W / 2;232 player.y = H - 90;233 player.glow = 0;234 obstacles = [];235 pickups = [];236 particles = [];237 hidePanel();238 updateHud();239 }240241 function showPanel(title, text, flash) {242 panelTitle.textContent = title;243 panelText.textContent = text;244 panelFlash.textContent = flash;245 panel.classList.remove('hidden');246 }247248 function hidePanel() {249 panel.classList.add('hidden');250 }251252 function updateHud() {253 scoreEl.textContent = Math.floor(state.score);254 bestEl.textContent = state.best;255 levelEl.textContent = state.level;256 }257258 function spawnObstacle() {259 const side = Math.random() < 0.55 ? 'top' : (Math.random() < 0.5 ? 'left' : 'right');260 const speed = 2 + Math.random() * 1.8 + state.difficulty * 0.8;261 const radius = 12 + Math.random() * 18;262 let x, y, vx, vy;263 if (side === 'top') {264 x = 50 + Math.random() * (W - 100);265 y = -30;266 vx = (Math.random() - 0.5) * 1.6;267 vy = speed;268 } else if (side === 'left') {269 x = -30;270 y = 60 + Math.random() * (H - 220);271 vx = speed;272 vy = (Math.random() - 0.5) * 1.2 + 0.4;273 } else {274 x = W + 30;275 y = 60 + Math.random() * (H - 220);276 vx = -speed;277 vy = (Math.random() - 0.5) * 1.2 + 0.4;278 }279 obstacles.push({ x, y, vx, vy, r: radius, hue: 330 + Math.random() * 50 });280 }281282 function spawnPickup() {283 pickups.push({284 x: 70 + Math.random() * (W - 140),285 y: 80 + Math.random() * (H - 220),286 r: 10,287 life: 420,288 phase: Math.random() * Math.PI * 2,289 });290 }291292 function burst(x, y, hue, count) {293 for (let i = 0; i < count; i++) {294 const a = Math.random() * Math.PI * 2;295 const s = 0.8 + Math.random() * 3.4;296 particles.push({297 x, y,298 vx: Math.cos(a) * s,299 vy: Math.sin(a) * s,300 life: 24 + Math.random() * 28,301 hue,302 size: 2 + Math.random() * 3,303 });304 }305 }306307 function endGame() {308 state.running = false;309 state.gameOver = true;310 state.best = Math.max(state.best, Math.floor(state.score));311 localStorage.setItem('neon-dodge-best', String(state.best));312 updateHud();313 showPanel(314 'Crashed Out',315 `You scored ${Math.floor(state.score)} and reached level ${state.level}.`,316 'Press space to jump back in.'317 );318 burst(player.x, player.y, 0, 38);319 }320321 function handleInput() {322 let dx = 0;323 let dy = 0;324 if (keys.has('ArrowLeft') || keys.has('a') || keys.has('A')) dx -= 1;325 if (keys.has('ArrowRight') || keys.has('d') || keys.has('D')) dx += 1;326 if (keys.has('ArrowUp') || keys.has('w') || keys.has('W')) dy -= 1;327 if (keys.has('ArrowDown') || keys.has('s') || keys.has('S')) dy += 1;328 if (dx !== 0 || dy !== 0) {329 const len = Math.hypot(dx, dy) || 1;330 player.x += (dx / len) * player.speed;331 player.y += (dy / len) * player.speed;332 player.glow = Math.min(1, player.glow + 0.08);333 } else {334 player.glow = Math.max(0, player.glow - 0.05);335 }336 player.x = Math.max(player.r + 12, Math.min(W - player.r - 12, player.x));337 player.y = Math.max(player.r + 12, Math.min(H - player.r - 12, player.y));338 }339340 function updateGame() {341 state.tick += 1;342 state.pulse += 0.025;343 state.score += 0.12 + state.level * 0.015;344 state.level = 1 + Math.floor(state.score / 18);345 state.difficulty = 1 + state.level * 0.16;346 state.pickupTimer += 1;347348 handleInput();349350 if (state.tick % Math.max(16, 42 - state.level * 2) === 0) spawnObstacle();351 if (state.pickupTimer > 260) {352 state.pickupTimer = 0;353 if (pickups.length < 2) spawnPickup();354 }355356 obstacles.forEach((o) => {357 o.x += o.vx;358 o.y += o.vy;359 });360 obstacles = obstacles.filter((o) => o.x > -120 && o.x < W + 120 && o.y > -120 && o.y < H + 120);361362 pickups.forEach((p) => {363 p.life -= 1;364 p.phase += 0.08;365 });366 pickups = pickups.filter((p) => p.life > 0);367368 particles.forEach((p) => {369 p.x += p.vx;370 p.y += p.vy;371 p.vx *= 0.985;372 p.vy *= 0.985;373 p.life -= 1;374 });375 particles = particles.filter((p) => p.life > 0);376377 for (const o of obstacles) {378 const dx = o.x - player.x;379 const dy = o.y - player.y;380 if (dx * dx + dy * dy < (o.r + player.r - 2) ** 2) {381 endGame();382 return;383 }384 }385386 for (let i = pickups.length - 1; i >= 0; i--) {387 const p = pickups[i];388 const dx = p.x - player.x;389 const dy = p.y - player.y;390 if (dx * dx + dy * dy < (p.r + player.r + 4) ** 2) {391 pickups.splice(i, 1);392 state.score += 8;393 state.message = 'Spark snagged!';394 burst(p.x, p.y, 48, 18);395 }396 }397398 if (state.tick % 10 === 0) updateHud();399 }400401 function drawBackground() {402 const gradient = ctx.createLinearGradient(0, 0, 0, H);403 gradient.addColorStop(0, '#091225');404 gradient.addColorStop(1, '#050816');405 ctx.fillStyle = gradient;406 ctx.fillRect(0, 0, W, H);407408 ctx.save();409 ctx.globalAlpha = 0.18;410 for (const star of stars) {411 star.y += star.s + state.level * 0.02;412 if (star.y > H + 2) {413 star.y = -4;414 star.x = Math.random() * W;415 }416 ctx.fillStyle = '#d6f7ff';417 ctx.beginPath();418 ctx.arc(star.x, star.y, star.r, 0, Math.PI * 2);419 ctx.fill();420 }421 ctx.restore();422423 ctx.save();424 ctx.strokeStyle = 'rgba(96,245,255,0.08)';425 ctx.lineWidth = 1;426 for (let x = 0; x <= W; x += 48) {427 ctx.beginPath();428 ctx.moveTo(x, 0);429 ctx.lineTo(x, H);430 ctx.stroke();431 }432 for (let y = 0; y <= H; y += 48) {433 ctx.beginPath();434 ctx.moveTo(0, y);435 ctx.lineTo(W, y);436 ctx.stroke();437 }438 ctx.restore();439440 ctx.save();441 ctx.globalAlpha = 0.4;442 const pulseRadius = 180 + Math.sin(state.pulse) * 35;443 const g = ctx.createRadialGradient(W * 0.5, H * 0.38, 0, W * 0.5, H * 0.38, pulseRadius * 2.6);444 g.addColorStop(0, 'rgba(255,95,210,0.18)');445 g.addColorStop(0.45, 'rgba(96,245,255,0.10)');446 g.addColorStop(1, 'rgba(0,0,0,0)');447 ctx.fillStyle = g;448 ctx.fillRect(0, 0, W, H);449 ctx.restore();450 }451452 function drawPlayer() {453 ctx.save();454 const glow = 18 + player.glow * 18;455 ctx.shadowBlur = glow;456 ctx.shadowColor = '#60f5ff';457 ctx.translate(player.x, player.y);458 ctx.fillStyle = '#60f5ff';459 ctx.beginPath();460 ctx.moveTo(0, -18);461 ctx.lineTo(14, 18);462 ctx.lineTo(0, 10);463 ctx.lineTo(-14, 18);464 ctx.closePath();465 ctx.fill();466 ctx.fillStyle = '#f6fbff';467 ctx.beginPath();468 ctx.arc(0, 3, 4, 0, Math.PI * 2);469 ctx.fill();470 ctx.restore();471 }472473 function drawObstacles() {474 obstacles.forEach((o) => {475 ctx.save();476 ctx.translate(o.x, o.y);477 ctx.rotate((state.tick * 0.02) + o.r);478 ctx.shadowBlur = 22;479 ctx.shadowColor = `hsla(${o.hue}, 95%, 62%, 0.9)`;480 ctx.fillStyle = `hsla(${o.hue}, 95%, 62%, 0.95)`;481 ctx.beginPath();482 for (let i = 0; i < 6; i++) {483 const angle = (Math.PI * 2 * i) / 6;484 const radius = i % 2 === 0 ? o.r : o.r * 0.52;485 const x = Math.cos(angle) * radius;486 const y = Math.sin(angle) * radius;487 if (i === 0) ctx.moveTo(x, y);488 else ctx.lineTo(x, y);489 }490 ctx.closePath();491 ctx.fill();492 ctx.restore();493 });494 }495496 function drawPickups() {497 pickups.forEach((p) => {498 const bob = Math.sin(p.phase) * 5;499 ctx.save();500 ctx.translate(p.x, p.y + bob);501 ctx.shadowBlur = 24;502 ctx.shadowColor = '#ffd166';503 ctx.fillStyle = '#ffd166';504 ctx.beginPath();505 for (let i = 0; i < 8; i++) {506 const angle = (Math.PI * 2 * i) / 8;507 const radius = i % 2 === 0 ? p.r + 3 : p.r - 2;508 const x = Math.cos(angle) * radius;509 const y = Math.sin(angle) * radius;510 if (i === 0) ctx.moveTo(x, y);511 else ctx.lineTo(x, y);512 }513 ctx.closePath();514 ctx.fill();515 ctx.restore();516 });517 }518519 function drawParticles() {520 particles.forEach((p) => {521 ctx.save();522 ctx.globalAlpha = Math.max(0, p.life / 50);523 ctx.fillStyle = `hsla(${p.hue}, 100%, 70%, 1)`;524 ctx.beginPath();525 ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);526 ctx.fill();527 ctx.restore();528 });529 }530531 function drawMessage() {532 ctx.save();533 ctx.fillStyle = 'rgba(246,251,255,0.84)';534 ctx.font = '600 18px Inter, system-ui, sans-serif';535 ctx.fillText(state.message, 22, H - 20);536 ctx.restore();537 }538539 function loop() {540 drawBackground();541 if (state.running) updateGame();542 drawPickups();543 drawObstacles();544 drawParticles();545 drawPlayer();546 drawMessage();547 requestAnimationFrame(loop);548 }549550 window.addEventListener('keydown', (e) => {551 if (["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"," "].includes(e.key)) e.preventDefault();552 keys.add(e.key);553 if (e.key === ' ') {554 if (!state.running) {555 resetGame();556 }557 }558 }, { passive: false });559560 window.addEventListener('keyup', (e) => {561 keys.delete(e.key);562 });563564 showPanel(565 'Neon Dodge',566 'Slip through the glowing shards, collect gold sparks, and hold out as the arena speeds up.',567 'Press space to start.'568 );569 updateHud();570 loop();571 </script>572</body>573</html>