ノート

サイバーグリッドリンク:HTML5キャンバススネークゲームプロンプト

フリーのプロンプト百科事典 Wikiprompt より

loshu2000

2026年5月17日

サイバーグリッドリンク:HTML5キャンバススネークゲームプロンプト サイバーパンク風のスネークメカニクスを備えた完全な単一ファイルHTML5キャンバスゲームを生成するための詳細なプロンプト。レンダリング、コントロール、ビジュアルスタイルの仕様を含む。

プロンプト内容保存

🌐
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Cyber Grid Link</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { background: #0a0a12; display: flex; justify-content: center; align-items: center; height: 100vh; overflow: hidden; font-family: 'Courier New', monospace; } canvas { border: 2px solid #00ffcc; box-shadow: 0 0 30px #00ffcc33; } #ui { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); color: #00ffcc; font-size: 20px; text-shadow: 0 0 10px #00ffcc; z-index: 10; } #gameOver { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #ff0044; font-size: 40px; text-shadow: 0 0 20px #ff0044; display: none; z-index: 20; background: #0a0a12cc; padding: 20px; border: 2px solid #ff0044; } </style> </head> <body> <div id="ui">SCORE: 0</div> <div id="gameOver">GAME OVER<br><span style="font-size:20px">PRESS SPACE TO RESTART</span></div> <canvas id="gameCanvas"></canvas> <script> const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const ui = document.getElementById('ui'); const gameOverDiv = document.getElementById('gameOver'); canvas.width = 800; canvas.height = 600; const GRID_SIZE = 40; const COLS = canvas.width / GRID_SIZE; const ROWS = canvas.height / GRID_SIZE; // Snake state let snake = []; let snakeLength = 5; let direction = { x: 1, y: 0 }; let nextDirection = { x: 1, y: 0 }; let speed = 0.15; // interpolation speed let score = 0; let gameRunning = true; // Crystals let crystals = []; const CRYSTAL_COUNT = 5; // Firewalls let firewalls = []; const FIREWALL_COUNT = 3; // Grid warp const warpRadius = 150; const warpStrength = 15; // Initialize snake function initSnake() { snake = []; const startX = Math.floor(COLS / 2) * GRID_SIZE; const startY = Math.floor(ROWS / 2) * GRID_SIZE; for (let i = 0; i < snakeLength; i++) { snake.push({ x: startX - i * GRID_SIZE, y: startY, targetX: startX - i * GRID_SIZE, targetY: startY }); } } // Spawn crystals function spawnCrystals() { crystals = []; for (let i = 0; i < CRYSTAL_COUNT; i++) { let pos = getRandomFreeCell(); crystals.push({ x: pos.x * GRID_SIZE + GRID_SIZE/2, y: pos.y * GRID_SIZE + GRID_SIZE/2, pulse: Math.random() * Math.PI * 2 }); } } // Spawn firewalls function spawnFirewalls() { firewalls = []; for (let i = 0; i < FIREWALL_COUNT; i++) { let dir = Math.random() < 0.5 ? 'vertical' : 'horizontal'; let pos = Math.floor(Math.random() * (dir === 'vertical' ? COLS : ROWS)); let speed = 0.5 + Math.random() * 1.5; firewalls.push({ dir, pos, speed, offset: Math.random() * 100 }); } } // Get random free cell (not on snake) function getRandomFreeCell() { let x, y; do { x = Math.floor(Math.random() * COLS); y = Math.floor(Math.random() * ROWS); } while (snake.some(s => Math.floor(s.targetX / GRID_SIZE) === x && Math.floor(s.targetY / GRID_SIZE) === y)); return { x, y }; } // Input handling document.addEventListener('keydown', (e) => { if (e.key === 'ArrowUp' || e.key === 'w' || e.key === 'W') { if (direction.y !== 1) nextDirection = { x: 0, y: -1 }; } else if (e.key === 'ArrowDown' || e.key === 's' || e.key === 'S') { if (direction.y !== -1) nextDirection = { x: 0, y: 1 }; } else if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'A') { if (direction.x !== 1) nextDirection = { x: -1, y: 0 }; } else if (e.key === 'ArrowRight' || e.key === 'd' || e.key === 'D') { if (direction.x !== -1) nextDirection = { x: 1, y: 0 }; } else if (e.key === ' ' && !gameRunning) { restartGame(); } }); // Update snake movement function updateSnake() { // Apply direction change direction = { ...nextDirection }; // Move head target let head = snake[0]; let newTargetX = head.targetX + direction.x * GRID_SIZE; let newTargetY = head.targetY + direction.y * GRID_SIZE; // Wrap around edges if (newTargetX >= canvas.width) newTargetX = 0; if (newTargetX < 0) newTargetX = canvas.width - GRID_SIZE; if (newTargetY >= canvas.height) newTargetY = 0; if (newTargetY < 0) newTargetY = canvas.height - GRID_SIZE; // Check self collision for (let i = 1; i < snake.length; i++) { if (Math.abs(snake[i].targetX - newTargetX) < GRID_SIZE/2 && Math.abs(snake[i].targetY - newTargetY) < GRID_SIZE/2) { gameOver(); return; } } // Move body (each segment follows the one before) for (let i = snake.length - 1; i > 0; i--) { snake[i].targetX = snake[i-1].targetX; snake[i].targetY = snake[i-1].targetY; } // Move head snake[0].targetX = newTargetX; snake[0].targetY = newTargetY; // Check crystal collection for (let i = crystals.length - 1; i >= 0; i--) { let c = crystals[i]; if (Math.abs(snake[0].targetX + GRID_SIZE/2 - c.x) < GRID_SIZE && Math.abs(snake[0].targetY + GRID_SIZE/2 - c.y) < GRID_SIZE) { // Grow snake let tail = snake[snake.length - 1]; snake.push({ x: tail.x, y: tail.y, targetX: tail.targetX, targetY: tail.targetY }); crystals.splice(i, 1); score += 10; ui.textContent = 'SCORE: ' + score; // Spawn new crystal let pos = getRandomFreeCell(); crystals.push({ x: pos.x * GRID_SIZE + GRID_SIZE/2, y: pos.y * GRID_SIZE + GRID_SIZE/2, pulse: 0 }); } } // Check firewall collision for (let fw of firewalls) { let fwX, fwY, fwW, fwH; if (fw.dir === 'vertical') { fwX = fw.pos * GRID_SIZE; fwY = (Math.sin(Date.now() * 0.001 * fw.speed + fw.offset) * 0.5 + 0.5) * (canvas.height - GRID_SIZE); fwW = GRID_SIZE; fwH = GRID_SIZE * 2; } else { fwX = (Math.sin(Date.now() * 0.001 * fw.speed + fw.offset) * 0.5 + 0.5) * (canvas.width - GRID_SIZE); fwY = fw.pos * GRID_SIZE; fwW = GRID_SIZE * 2; fwH = GRID_SIZE; } // Check head collision let headX = snake[0].targetX + GRID_SIZE/2; let headY = snake[0].targetY + GRID_SIZE/2; if (headX > fwX && headX < fwX + fwW && headY > fwY && headY < fwY + fwH) { gameOver(); return; } } } // Interpolate snake positions for smooth movement function interpolateSnake() { for (let seg of snake) { seg.x += (seg.targetX - seg.x) * speed; seg.y += (seg.targetY - seg.y) * speed; } } // Grid warp function function warpGrid(x, y) { let head = snake[0]; let dx = x - (head.x + GRID_SIZE/2); let dy = y - (head.y + GRID_SIZE/2); let dist = Math.sqrt(dx*dx + dy*dy); if (dist < warpRadius) { let factor = (1 - dist / warpRadius) * warpStrength; return { x: x + dx * factor, y: y + dy * factor }; } return { x, y }; } // Draw grid with warp function drawGrid() { ctx.strokeStyle = '#1a1a3a'; ctx.lineWidth = 1; for (let i = 0; i <= COLS; i++) { let x = i * GRID_SIZE; ctx.beginPath(); for (let j = 0; j <= ROWS; j++) { let y = j * GRID_SIZE; let p = warpGrid(x, y); if (j === 0) ctx.moveTo(p.x, p.y); else ctx.lineTo(p.x, p.y); } ctx.stroke(); } for (let j = 0; j <= ROWS; j++) { let y = j * GRID_SIZE; ctx.beginPath(); for (let i = 0; i <= COLS; i++) { let x = i * GRID_SIZE; let p = warpGrid(x, y); if (i === 0) ctx.moveTo(p.x, p.y); else ctx.lineTo(p.x, p.y); } ctx.stroke(); } } // Draw snake with pulsing gradient function drawSnake() { for (let i = snake.length - 1; i >= 0; i--) { let seg = snake[i]; let pulse = Math.sin(Date.now() * 0.01 + i * 0.5) * 0.5 + 0.5; let size = GRID_SIZE * 0.7 * (1 - i * 0.01); let hue = 180 + i * 2; let lightness = 50 + pulse * 20; ctx.fillStyle = `hsl(${hue}, 100%, ${lightness}%)`; ctx.shadowColor = `hsl(${hue}, 100%, 70%)`; ctx.shadowBlur = 20; ctx.beginPath(); ctx.arc(seg.x + GRID_SIZE/2, seg.y + GRID_SIZE/2, size/2, 0, Math.PI * 2); ctx.fill(); } ctx.shadowBlur = 0; } // Draw crystals function drawCrystals() { for (let c of crystals) { c.pulse += 0.05; let size = GRID_SIZE * 0.5 + Math.sin(c.pulse) * 5; ctx.fillStyle = '#00ff88'; ctx.shadowColor = '#00ff88'; ctx.shadowBlur = 30; ctx.beginPath(); ctx.moveTo(c.x, c.y - size); ctx.lineTo(c.x + size * 0.7, c.y); ctx.lineTo(c.x, c.y + size); ctx.lineTo(c.x - size * 0.7, c.y); ctx.closePath(); ctx.fill(); } ctx.shadowBlur = 0; } // Draw firewalls function drawFirewalls() { ctx.fillStyle = '#ff0044'; ctx.shadowColor = '#ff0044'; ctx.shadowBlur = 20; for (let fw of firewalls) { let fwX, fwY, fwW, fwH; if (fw.dir === 'vertical') { fwX = fw.pos * GRID_SIZE; fwY = (Math.sin(Date.now() * 0.001 * fw.speed + fw.offset) * 0.5 + 0.5) * (canvas.height - GRID_SIZE); fwW = GRID_SIZE; fwH = GRID_SIZE * 2; } else { fwX = (Math.sin(Date.now() * 0.001 * fw.speed + fw.offset) * 0.5 + 0.5) * (canvas.width - GRID_SIZE); fwY = fw.pos * GRID_SIZE; fwW = GRID_SIZE * 2; fwH = GRID_SIZE; } ctx.fillRect(fwX, fwY, fwW, fwH); } ctx.shadowBlur = 0; } // Game over function gameOver() { gameRunning = false; gameOverDiv.style.display = 'block'; } // Restart function restartGame() { gameRunning = true; gameOverDiv.style.display = 'none'; score = 0; ui.textContent = 'SCORE: 0'; snakeLength = 5; direction = { x: 1, y: 0 }; nextDirection = { x: 1, y: 0 }; initSnake(); spawnCrystals(); spawnFirewalls(); } // Main game loop let lastTime = 0; function gameLoop(timestamp) { let deltaTime = timestamp - lastTime; lastTime = timestamp; if (gameRunning) { updateSnake(); interpolateSnake(); } // Clear canvas ctx.fillStyle = '#0a0a12'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Draw everything drawGrid(); drawCrystals(); drawFirewalls(); drawSnake(); requestAnimationFrame(gameLoop); } // Initialize initSnake(); spawnCrystals(); spawnFirewalls(); requestAnimationFrame(gameLoop); </script> </body> </html>

ログインして完全なプロンプトを表示

次で続行:

ログインすると、次に同意したことになります: 利用規約 と プライバシーポリシー

使い方

このプロンプトは coding 向けに設計されています。上の内容をコピーして、お好みの AI ツールに貼り付けてください。

最良の結果を得るには、プレースホルダー(角括弧や大文字で示された部分)を具体的な要件に置き換えてください。

参考資料

カテゴリ:coding| prompts.chat| html5-canvas| game-development

ノート