讨论

赛博网格链接:HTML5画布贪吃蛇游戏提示

来自 Wikiprompt,自由的提示词百科全书

loshu2000

2026年5月17日

赛博网格链接:HTML5画布贪吃蛇游戏提示 一个用于生成完整单文件HTML5画布游戏的详细提示,包含赛博朋克贪吃蛇机制,涵盖渲染、控制和视觉风格规格。

提示词内容收藏

🌐
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <title>Cyber Grid Link</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { background: #0b0e1a; min-height: 100vh; display: flex; justify-content: center; align-items: center; font-family: 'Courier New', monospace; } .game-wrapper { background: #101624; padding: 20px; border-radius: 24px; box-shadow: 0 0 40px rgba(0, 255, 255, 0.2); border: 1px solid #2a3a6a; } canvas { display: block; margin: 0 auto; width: 800px; height: 800px; border-radius: 16px; box-shadow: inset 0 0 30px rgba(0, 180, 255, 0.3); background: #0d1225; cursor: default; } .status-bar { display: flex; justify-content: space-between; align-items: center; margin-top: 16px; color: #b0e0ff; text-shadow: 0 0 8px #2f9fff; font-size: 1.3rem; letter-spacing: 2px; padding: 0 10px; } .status-bar span { background: #1a2240; padding: 6px 18px; border-radius: 40px; border: 1px solid #3f6bb0; backdrop-filter: blur(2px); } .restart-btn { background: #1f2b4a; border: 1px solid #5f8ad0; color: #b0e0ff; padding: 6px 20px; border-radius: 40px; font-size: 1.1rem; font-weight: bold; letter-spacing: 1px; transition: 0.2s; box-shadow: 0 0 12px #2f6faf; cursor: pointer; } .restart-btn:hover { background: #2f4080; box-shadow: 0 0 20px #4f9fff; color: white; transform: scale(1.02); } .restart-btn:active { transform: scale(0.96); } @media (max-width: 840px) { canvas { width: 100%; height: auto; aspect-ratio: 1/1; } .game-wrapper { padding: 12px; } } </style> </head> <body> <div class="game-wrapper"> <canvas id="gameCanvas" width="800" height="800"></canvas> <div class="status-bar"> <span>⚡ 链长 <span id="scoreDisplay">3</span></span> <button class="restart-btn" id="restartButton">⟳ 重启</button> </div> </div> <script> (function() { const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const scoreSpan = document.getElementById('scoreDisplay'); // ---------- 尺寸常量 ---------- const GRID_SIZE = 20; // 20x20 逻辑网格 const CELL_SIZE = 800 / GRID_SIZE; // 40px const HALF_CELL = CELL_SIZE / 2; // ---------- 游戏状态 ---------- let snake = []; // 坐标数组 {x, y} (逻辑网格) let food = { x: 8, y: 10 }; let barriers = []; // 防火墙 {x, y} let direction = { dx: 1, dy: 0 }; // 当前移动方向 let nextDirection = { dx: 1, dy: 0 }; let gameOver = false; let winFlag = false; let score = 3; // 初始长度3 // 插值相关 (平滑移动) let moveProgress = 0; // 0..1 每帧累加 const MOVE_SPEED = 0.035; // 每帧增量 (约30帧完成一格) // 网格扭曲参数 (靠近蛇头) let warpOffset = { x: 0, y: 0 }; // 帧率节流 (防止delta爆炸) let lastTimestamp = 0; // ---------- 初始化 ---------- function initGame() { // 蛇: 初始3节水平 snake = [ { x: 9, y: 10 }, { x: 8, y: 10 }, { x: 7, y: 10 } ]; direction = { dx: 1, dy: 0 }; nextDirection = { dx: 1, dy: 0 }; gameOver = false; winFlag = false; score = 3; moveProgress = 0; barriers = []; // 生成食物 & 初始屏障 generateFood(); generateBarriers(4); // 4个移动防火墙 updateScore(); } // ---------- 生成食物 (避开蛇身和屏障) ---------- function generateFood() { const occupied = new Set(); snake.forEach(seg => occupied.add(`${seg.x},${seg.y}`)); barriers.forEach(b => occupied.add(`${b.x},${b.y}`)); const freeCells = []; for (let i = 0; i < GRID_SIZE; i++) { for (let j = 0; j < GRID_SIZE; j++) { if (!occupied.has(`${i},${j}`)) { freeCells.push({ x: i, y: j }); } } } if (freeCells.length === 0) { // 胜利: 所有格子占满 winFlag = true; gameOver = true; return; } const rand = Math.floor(Math.random() * freeCells.length); food = freeCells[rand]; } // ---------- 生成屏障 (移动防火墙) ---------- function generateBarriers(count) { barriers = []; const occupied = new Set(); snake.forEach(seg => occupied.add(`${seg.x},${seg.y}`)); occupied.add(`${food.x},${food.y}`); for (let i = 0; i < count; i++) { let attempts = 0; let pos; while (attempts < 200) { const x = Math.floor(Math.random() * GRID_SIZE); const y = Math.floor(Math.random() * GRID_SIZE); if (!occupied.has(`${x},${y}`) && !(x === food.x && y === food.y)) { // 避免与蛇头太近 (至少距离2) const head = snake[0]; if (Math.abs(x - head.x) + Math.abs(y - head.y) > 2) { pos = { x, y }; break; } } attempts++; } if (pos) { barriers.push(pos); occupied.add(`${pos.x},${pos.y}`); } } } // ---------- 移动屏障 (每帧更新) ---------- function moveBarriers() { if (gameOver) return; const head = snake[0]; // 每个屏障尝试向蛇头方向移动一步 (曼哈顿距离) for (let i = 0; i < barriers.length; i++) { const b = barriers[i]; const dx = Math.sign(head.x - b.x); const dy = Math.sign(head.y - b.y); // 随机选择优先轴 (增加变化) let newX = b.x; let newY = b.y; if (Math.random() < 0.5) { if (dx !== 0) newX = b.x + dx; else if (dy !== 0) newY = b.y + dy; } else { if (dy !== 0) newY = b.y + dy; else if (dx !== 0) newX = b.x + dx; } // 边界约束 newX = Math.min(GRID_SIZE-1, Math.max(0, newX)); newY = Math.min(GRID_SIZE-1, Math.max(0, newY)); // 不能与蛇身重叠 (除了蛇头? 但防火墙碰到蛇头即游戏结束) const collideSnake = snake.some(seg => seg.x === newX && seg.y === newY); const collideOtherBarrier = barriers.some((other, idx) => idx !== i && other.x === newX && other.y === newY); if (!collideSnake && !collideOtherBarrier && !(newX === food.x && newY === food.y)) { barriers[i] = { x: newX, y: newY }; } else { // 尝试另一轴 let altX = b.x; let altY = b.y; if (dx !== 0 && dy !== 0) { if (Math.random() < 0.5) { altX = b.x + dx; } else { altY = b.y + dy; } } else if (dx !== 0) { altX = b.x + dx; } else if (dy !== 0) { altY = b.y + dy; } altX = Math.min(GRID_SIZE-1, Math.max(0, altX)); altY = Math.min(GRID_SIZE-1, Math.max(0, altY)); const collideSnake2 = snake.some(seg => seg.x === altX && seg.y === altY); const collideOtherBarrier2 = barriers.some((other, idx) => idx !== i && other.x === altX && other.y === altY); if (!collideSnake2 && !collideOtherBarrier2 && !(altX === food.x && altY === food.y)) { barriers[i] = { x: altX, y: altY }; } // 否则保持不动 } } } // ---------- 碰撞检测 (蛇头 vs 屏障/自身/边界) ---------- function checkCollisions(headPos) { const { x, y } = headPos; // 边界 if (x < 0 || x >= GRID_SIZE || y < 0 || y >= GRID_SIZE) { return true; } // 自身 (除头部) for (let i = 1; i < snake.length; i++) { if (snake[i].x === x && snake[i].y === y) { return true; } } // 防火墙 for (let b of barriers) { if (b.x === x && b.y === y) { return true; } } return false; } // ---------- 核心更新 (逻辑步进) ---------- function stepGame() { if (gameOver) return; // 1. 应用方向 direction = { dx: nextDirection.dx, dy: nextDirection.dy }; // 2. 计算新蛇头 const head = snake[0]; const newHead = { x: head.x + direction.dx, y: head.y + direction.dy }; // 3. 检测是否吃到食物 const ate = (newHead.x === food.x && newHead.y === food.y); // 4. 执行移动 (先加头) snake.unshift(newHead); if (!ate) { snake.pop(); // 没吃到移除尾 } else { score++; updateScore(); // 生成新食物 & 屏障 generateFood(); if (gameOver) return; // 胜利时gameOver置true // 增加一个屏障 (动态) if (barriers.length < 8) { const occupied = new Set(); snake.forEach(seg => occupied.add(`${seg.x},${seg.y}`)); barriers.forEach(b => occupied.add(`${b.x},${b.y}`)); occupied.add(`${food.x},${food.y}`); let freeCells = []; for (let i = 0; i < GRID_SIZE; i++) { for (let j = 0; j < GRID_SIZE; j++) { if (!occupied.has(`${i},${j}`)) freeCells.push({x:i, y:j}); } } if (freeCells.length > 0) { const rand = Math.floor(Math.random() * freeCells.length); barriers.push(freeCells[rand]); } } } // 5. 碰撞检测 (蛇头) if (checkCollisions(snake[0])) { gameOver = true; return; } // 6. 移动屏障 (在蛇移动后) moveBarriers(); // 额外碰撞: 蛇头与移动后的屏障 for (let b of barriers) { if (b.x === snake[0].x && b.y === snake[0].y) { gameOver = true; break; } } } // ---------- 更新分数显示 ---------- function updateScore() { scoreSpan.textContent = score; } // ---------- 重置游戏 ---------- function resetGame() { initGame(); } // ---------- 键盘控制 ---------- function handleKey(e) { if (gameOver) return; const key = e.key; e.preventDefault(); if (key === 'ArrowUp' || key === 'w' || key === 'W') { if (direction.dy !== 1) nextDirection = { dx: 0, dy: -1 }; } else if (key === 'ArrowDown' || key === 's' || key === 'S') { if (direction.dy !== -1) nextDirection = { dx: 0, dy: 1 }; } else if (key === 'ArrowLeft' || key === 'a' || key === 'A') { if (direction.dx !== 1) nextDirection = { dx: -1, dy: 0 }; } else if (key === 'ArrowRight' || key === 'd' || key === 'D') { if (direction.dx !== -1) nextDirection = { dx: 1, dy: 0 }; } } // ---------- 渲染 (带插值 + 扭曲) ---------- function draw() { ctx.clearRect(0, 0, 800, 800); // 背景网格 (暗) ctx.strokeStyle = '#1f2f5a'; ctx.lineWidth = 1.2; for (let i = 0; i <= GRID_SIZE; i++) { ctx.beginPath(); ctx.moveTo(i * CELL_SIZE, 0); ctx.lineTo(i * CELL_SIZE, 800); ctx.strokeStyle = '#1f2f5a'; ctx.stroke(); ctx.beginPath(); ctx.moveTo(0, i * CELL_SIZE); ctx.lineTo(800, i * CELL_SIZE); ctx.stroke(); } // 扭曲偏移 (基于蛇头) const head = snake[0]; if (head) { const headPx = head.x * CELL_SIZE + HALF_CELL; const headPy = head.y * CELL_SIZE + HALF_CELL; warpOffset.x = Math.sin(Date.now() / 600) * 3; warpOffset.y = Math.cos(Date.now() / 700) * 3; } // 绘制食物 (能量晶体) if (food && !winFlag) { const fx = food.x * CELL_SIZE + HALF_CELL + warpOffset.x * 0.3; const fy = food.y * CELL_SIZE + HALF_CELL + warpOffset.y * 0.3; const gradient = ctx.createRadialGradient(fx-4, fy-4, 2, fx, fy, 16); gradient.addColorStop(0, '#b0ffff'); gradient.addColorStop(0.5, '#2fc0ff'); gradient.addColorStop(1, '#004488'); ctx.shadowColor = '#2fc0ff'; ctx.shadowBlur = 24; ctx.beginPath(); ctx.arc(fx, fy, 12, 0, Math.PI*2); ctx.fillStyle = gradient; ctx.fill(); ctx.shadowBlur = 0; // 内部菱形 ctx.fillStyle = '#e0f0ff'; ctx.shadowBlur = 12; ctx.beginPath(); ctx.moveTo(fx, fy-6); ctx.lineTo(fx+6, fy); ctx.lineTo(fx, fy+6); ctx.lineTo(fx-6, fy); ctx.closePath(); ctx.fill(); ctx.shadowBlur = 0; } // 绘制防火墙 (移动屏障) ctx.shadowBlur = 18; ctx.shadowColor = '#ff4a6a'; for (let b of barriers) { const bx = b.x * CELL_SIZE + HALF_CELL + warpOffset.x * 0.2; const by = b.y * CELL_SIZE + HALF_CELL + warpOffset.y * 0.2; ctx.fillStyle = '#ff3a5a'; ctx.beginPath(); ctx.arc(bx, by, 14, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = '#ff8a9a'; ctx.beginPath(); ctx.arc(bx-2, by-2, 6, 0, Math.PI*2); ctx.fill(); } ctx.shadowBlur = 0; // 绘制蛇 (链式粒子 + 插值) if (snake.length === 0) return; const headPos = snake[0]; // 计算插值偏移 (基于moveProgress) let lerpX = 0, lerpY = 0; if (direction.dx !== 0 || direction.dy !== 0) { lerpX = direction.dx * CELL_SIZE * moveProgress; lerpY = direction.dy * CELL_SIZE * moveProgress; } // 绘制每个segment (从尾到头) for (let i = snake.length - 1; i >= 0; i--) { const seg = snake[i]; let segX = seg.x * CELL_SIZE + HALF_CELL; let segY = seg.y * CELL_SIZE + HALF_CELL; // 头部应用插值 if (i === 0) { segX += lerpX + warpOffset.x * 0.5; segY += lerpY + warpOffset.y * 0.5; } else { segX += warpOffset.x * 0.2; segY += warpOffset.y * 0.2; } // 脉冲渐变 (根据时间) const pulse = Math.sin(Date.now() / 200 + i * 0.8) * 0.3 + 0.7; const gradient = ctx.createRadialGradient(segX-4, segY-4, 2, segX, segY, 18); gradient.addColorStop(0, `rgba(100, 220, 255, ${pulse})`); gradient.addColorStop(0.6, `rgba(20, 120, 255, ${pulse*0.8})`); gradient.addColorStop(1, `rgba(10, 40, 120, 0.2)`); ctx.shadowColor = '#2fc0ff'; ctx.shadowBlur = 22; ctx.beginPath(); ctx.arc(segX, segY, 14, 0, Math.PI*2); ctx.fillStyle = gradient; ctx.fill(); // 内圈高光 ctx.shadowBlur = 10; ctx.beginPath(); ctx.arc(segX-2, segY-2, 6, 0, Math.PI*2); ctx.fillStyle = `rgba(180, 240, 255, ${pulse*0.7})`; ctx.fill(); } ctx.shadowBlur = 0; // 游戏结束/胜利信息 if (gameOver) { ctx.font = 'bold 44px "Courier New", monospace'; ctx.fillStyle = winFlag ? '#aaffaa' : '#ff6a7a'; ctx.shadowColor = winFlag ? '#2fcf2f' : '#ff2f4f'; ctx.shadowBlur = 30; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(winFlag ? '⚡ 矩阵链接 ⚡' : '⛔ 链接断裂', 400, 400); ctx.shadowBlur = 0; } } // ---------- 游戏循环 (requestAnimationFrame) ---------- function gameLoop(timestamp) { const delta = Math.min((timestamp - lastTimestamp) / 16.667, 4); // 限制最大delta lastTimestamp = timestamp; if (!gameOver) { // 累积移动进度 moveProgress += MOVE_SPEED * delta; if (moveProgress >= 1.0) { moveProgress -= 1.0; stepGame(); // 逻辑步进 } } draw(); requestAnimationFrame(gameLoop); } // ---------- 事件绑定 ---------- window.addEventListener('keydown', (e) => { const arrows = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'w', 'W', 's', 'S', 'a', 'A', 'd', 'D']; if (arrows.includes(e.key)) { handleKey(e); } }); document.getElementById('restartButton').addEventListener('click', resetGame); // 启动 initGame(); requestAnimationFrame(gameLoop); })(); </script> </body> </html>

登录以查看完整提示词

继续使用:

登录即表示你同意我们的 使用条款 和 隐私政策

用法

此提示词专为 coding 设计。复制上方内容并粘贴到你常用的 AI 工具中。

为获得最佳效果,可将占位符(方括号或大写字母标示)替换为你的具体需求。

参考资料

分类:coding| prompts.chat| html5-canvas| game-development

讨论