Discussion

Cyber Grid Link : Jeu de Serpent sur Canvas HTML5

De Wikiprompt, l’encyclopédie libre de prompts

loshu2000
Contribué parloshu2000Source

17 mai 2026

Cyber Grid Link : Jeu de Serpent sur Canvas HTML5 Invite détaillée pour générer un jeu HTML5 complet sur canvas à fichier unique avec une mécanique de serpent cyberpunk, incluant les spécifications de rendu, de contrôles et de style visuel.

Contenu du PromptEnregistrer

🌐
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Cyber Grid Link</title> <style> body { margin: 0; padding: 0; background: #0a0a0f; display: flex; justify-content: center; align-items: center; height: 100vh; font-family: 'Courier New', monospace; overflow: hidden; } canvas { border: 2px solid #00ffcc; box-shadow: 0 0 30px rgba(0, 255, 204, 0.3); background: #0a0a0f; } #ui { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); color: #00ffcc; font-size: 18px; text-shadow: 0 0 10px #00ffcc; z-index: 10; text-align: center; } #gameOver { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #ff0044; font-size: 32px; text-shadow: 0 0 20px #ff0044; z-index: 10; display: none; text-align: center; } #gameOver button { background: #0a0a0f; border: 2px solid #ff0044; color: #ff0044; font-family: 'Courier New', monospace; font-size: 18px; padding: 10px 20px; margin-top: 20px; cursor: pointer; text-shadow: 0 0 10px #ff0044; } #gameOver button:hover { background: #ff0044; color: #0a0a0f; } </style> </head> <body> <div id="ui"> <span>SCORE: <span id="score">0</span></span> <span style="margin-left: 30px;">LINK: <span id="length">3</span></span> </div> <div id="gameOver"> <div>LINK BROKEN</div> <button onclick="restartGame()">REINITIALIZE</button> </div> <canvas id="gameCanvas"></canvas> <script> // ========== CONFIG ========== const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const scoreEl = document.getElementById('score'); const lengthEl = document.getElementById('length'); const gameOverEl = document.getElementById('gameOver'); const GRID_SIZE = 40; const CELL_SIZE = 20; const VIEW_WIDTH = GRID_SIZE * CELL_SIZE; const VIEW_HEIGHT = GRID_SIZE * CELL_SIZE; canvas.width = VIEW_WIDTH; canvas.height = VIEW_HEIGHT; // ========== GAME STATE ========== let snake = []; let direction = { x: 1, y: 0 }; let nextDirection = { x: 1, y: 0 }; let crystals = []; let firewalls = []; let score = 0; let gameRunning = true; let lastTime = 0; let moveTimer = 0; const MOVE_INTERVAL = 150; // ms per grid step // ========== INITIALIZE ========== function initGame() { snake = []; // Start with 3 segments in the middle const startX = Math.floor(GRID_SIZE / 2); const startY = Math.floor(GRID_SIZE / 2); for (let i = 0; i < 3; i++) { snake.push({ x: startX - i, y: startY, px: startX - i, py: startY }); } direction = { x: 1, y: 0 }; nextDirection = { x: 1, y: 0 }; crystals = []; firewalls = []; score = 0; gameRunning = true; gameOverEl.style.display = 'none'; updateUI(); spawnCrystal(); spawnFirewalls(); } // ========== SPAWNING ========== function spawnCrystal() { let pos; do { pos = { x: Math.floor(Math.random() * GRID_SIZE), y: Math.floor(Math.random() * GRID_SIZE) }; } while (snake.some(s => s.x === pos.x && s.y === pos.y) || crystals.some(c => c.x === pos.x && c.y === pos.y)); crystals.push({ x: pos.x, y: pos.y, pulse: 0 }); } function spawnFirewalls() { // Spawn 3-5 firewalls at random positions, moving in random directions const count = 3 + Math.floor(Math.random() * 3); for (let i = 0; i < count; i++) { let pos; do { pos = { x: Math.floor(Math.random() * GRID_SIZE), y: Math.floor(Math.random() * GRID_SIZE) }; } while (snake.some(s => s.x === pos.x && s.y === pos.y) || crystals.some(c => c.x === pos.x && c.y === pos.y) || firewalls.some(f => f.x === pos.x && f.y === pos.y)); const dirs = [ { x: 1, y: 0 }, { x: -1, y: 0 }, { x: 0, y: 1 }, { x: 0, y: -1 } ]; firewalls.push({ x: pos.x, y: pos.y, dir: dirs[Math.floor(Math.random() * 4)], speed: 0.5 + Math.random() * 0.5 }); } } // ========== INPUT ========== document.addEventListener('keydown', (e) => { if (!gameRunning) return; switch(e.key) { case 'ArrowUp': case 'w': if (direction.y !== 1) nextDirection = { x: 0, y: -1 }; break; case 'ArrowDown': case 's': if (direction.y !== -1) nextDirection = { x: 0, y: 1 }; break; case 'ArrowLeft': case 'a': if (direction.x !== 1) nextDirection = { x: -1, y: 0 }; break; case 'ArrowRight': case 'd': if (direction.x !== -1) nextDirection = { x: 1, y: 0 }; break; } }); // ========== GAME LOGIC ========== function update(deltaTime) { if (!gameRunning) return; // Move firewalls firewalls.forEach(fw => { fw.x += fw.dir.x * fw.speed * (deltaTime / 1000) * 5; fw.y += fw.dir.y * fw.speed * (deltaTime / 1000) * 5; // Wrap around edges if (fw.x < 0) fw.x = GRID_SIZE - 1; if (fw.x >= GRID_SIZE) fw.x = 0; if (fw.y < 0) fw.y = GRID_SIZE - 1; if (fw.y >= GRID_SIZE) fw.y = 0; }); // Move snake on timer moveTimer += deltaTime; if (moveTimer >= MOVE_INTERVAL) { moveTimer -= MOVE_INTERVAL; direction = { ...nextDirection }; // Save previous positions for interpolation snake.forEach(seg => { seg.px = seg.x; seg.py = seg.y; }); // Move head const head = { ...snake[0] }; head.x += direction.x; head.y += direction.y; // Wrap around if (head.x < 0) head.x = GRID_SIZE - 1; if (head.x >= GRID_SIZE) head.x = 0; if (head.y < 0) head.y = GRID_SIZE - 1; if (head.y >= GRID_SIZE) head.y = 0; // Check collision with self if (snake.some(s => s.x === head.x && s.y === head.y)) { gameOver(); return; } // Check collision with firewalls if (firewalls.some(fw => Math.floor(fw.x) === head.x && Math.floor(fw.y) === head.y)) { gameOver(); return; } snake.unshift(head); // Check crystal collection const crystalIdx = crystals.findIndex(c => c.x === head.x && c.y === head.y); if (crystalIdx !== -1) { crystals.splice(crystalIdx, 1); score += 10; updateUI(); spawnCrystal(); // Don't remove tail - snake grows } else { snake.pop(); } updateUI(); } } function gameOver() { gameRunning = false; gameOverEl.style.display = 'block'; } function restartGame() { initGame(); } function updateUI() { scoreEl.textContent = score; lengthEl.textContent = snake.length; } // ========== RENDERING ========== function drawGrid(time) { ctx.strokeStyle = 'rgba(0, 255, 204, 0.15)'; ctx.lineWidth = 1; // Warp effect near head const head = snake[0]; const warpRadius = 3; for (let i = 0; i <= GRID_SIZE; i++) { ctx.beginPath(); for (let j = 0; j <= GRID_SIZE; j++) { let x = i * CELL_SIZE; let y = j * CELL_SIZE; // Apply warp displacement const dx = (i - head.x) / warpRadius; const dy = (j - head.y) / warpRadius; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < 1) { const warp = (1 - dist) * 8; x += dx * warp; y += dy * warp; } if (j === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.stroke(); } for (let j = 0; j <= GRID_SIZE; j++) { ctx.beginPath(); for (let i = 0; i <= GRID_SIZE; i++) { let x = i * CELL_SIZE; let y = j * CELL_SIZE; const dx = (i - head.x) / warpRadius; const dy = (j - head.y) / warpRadius; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < 1) { const warp = (1 - dist) * 8; x += dx * warp; y += dy * warp; } if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.stroke(); } } function drawSnake(time) { if (snake.length === 0) return; // Draw chain with pulsing gradient for (let i = snake.length - 1; i >= 0; i--) { const seg = snake[i]; // Interpolate position const alpha = Math.min(1, moveTimer / MOVE_INTERVAL); const x = seg.px + (seg.x - seg.px) * alpha; const y = seg.py + (seg.y - seg.py) * alpha; const screenX = x * CELL_SIZE + CELL_SIZE / 2; const screenY = y * CELL_SIZE + CELL_SIZE / 2; // Pulsing gradient based on position in chain const pulse = Math.sin(time / 200 + i * 0.5) * 0.5 + 0.5; const size = CELL_SIZE * 0.7 * (1 - (i / snake.length) * 0.3); const hue = 160 + (i / snake.length) * 40; const gradient = ctx.createRadialGradient(screenX, screenY, 0, screenX, screenY, size); gradient.addColorStop(0, `hsla(${hue}, 100%, 70%, ${0.9 - (i / snake.length) * 0.5})`); gradient.addColorStop(1, `hsla(${hue}, 100%, 30%, ${0.3 - (i / snake.length) * 0.2})`); ctx.beginPath(); ctx.arc(screenX, screenY, size, 0, Math.PI * 2); ctx.fillStyle = gradient; ctx.fill(); // Glow effect ctx.shadowColor = `hsla(${hue}, 100%, 50%, ${0.5 * pulse})`; ctx.shadowBlur = 15; ctx.beginPath(); ctx.arc(screenX, screenY, size * 0.5, 0, Math.PI * 2); ctx.fillStyle = `hsla(${hue}, 100%, 80%, ${0.3 * pulse})`; ctx.fill(); ctx.shadowBlur = 0; } // Head glow const head = snake[0]; const headX = head.px + (head.x - head.px) * Math.min(1, moveTimer / MOVE_INTERVAL); const headY = head.py + (head.y - head.py) * Math.min(1, moveTimer / MOVE_INTERVAL); ctx.shadowColor = '#00ffcc'; ctx.shadowBlur = 25; ctx.beginPath(); ctx.arc(headX * CELL_SIZE + CELL_SIZE / 2, headY * CELL_SIZE + CELL_SIZE / 2, CELL_SIZE * 0.8, 0, Math.PI * 2); ctx.fillStyle = 'rgba(0, 255, 204, 0.3)'; ctx.fill(); ctx.shadowBlur = 0; } function drawCrystals(time) { crystals.forEach(c => { c.pulse += 0.05; const pulse = Math.sin(c.pulse) * 0.5 + 0.5; const x = c.x * CELL_SIZE + CELL_SIZE / 2; const y = c.y * CELL_SIZE + CELL_SIZE / 2; // Diamond shape ctx.save(); ctx.translate(x, y); ctx.rotate(time / 1000); ctx.shadowColor = '#ff00ff'; ctx.shadowBlur = 20 * pulse; ctx.beginPath(); ctx.moveTo(0, -CELL_SIZE * 0.6); ctx.lineTo(CELL_SIZE * 0.4, 0); ctx.lineTo(0, CELL_SIZE * 0.6); ctx.lineTo(-CELL_SIZE * 0.4, 0); ctx.closePath(); const gradient = ctx.createLinearGradient(-CELL_SIZE * 0.4, 0, CELL_SIZE * 0.4, 0); gradient.addColorStop(0, '#ff00ff'); gradient.addColorStop(0.5, '#00ffff'); gradient.addColorStop(1, '#ff00ff'); ctx.fillStyle = gradient; ctx.fill(); ctx.strokeStyle = '#ffffff'; ctx.lineWidth = 1; ctx.stroke(); ctx.restore(); }); } function drawFirewalls(time) { firewalls.forEach(fw => { const x = fw.x * CELL_SIZE + CELL_SIZE / 2; const y = fw.y * CELL_SIZE + CELL_SIZE / 2; ctx.shadowColor = '#ff0044'; ctx.shadowBlur = 15; // Animated flame-like shape const flameHeight = CELL_SIZE * (0.8 + Math.sin(time / 100 + fw.x) * 0.2); ctx.beginPath(); ctx.moveTo(x - CELL_SIZE * 0.3, y + CELL_SIZE * 0.4); ctx.quadraticCurveTo(x - CELL_SIZE * 0.4, y - flameHeight * 0.3, x, y - flameHeight); ctx.quadraticCurveTo(x + CELL_SIZE * 0.4, y - flameHeight * 0.3, x + CELL_SIZE * 0.3, y + CELL_SIZE * 0.4); ctx.closePath(); const gradient = ctx.createLinearGradient(x, y + CELL_SIZE * 0.4, x, y - flameHeight); gradient.addColorStop(0, 'rgba(255, 0, 68, 0.8)'); gradient.addColorStop(1, 'rgba(255, 100, 0, 0.2)'); ctx.fillStyle = gradient; ctx.fill(); ctx.shadowBlur = 0; }); } // ========== MAIN LOOP ========== function gameLoop(time) { const deltaTime = Math.min(50, time - lastTime); lastTime = time; update(deltaTime); // Clear ctx.fillStyle = '#0a0a0f'; ctx.fillRect(0, 0, VIEW_WIDTH, VIEW_HEIGHT); // Draw everything drawGrid(time); drawCrystals(time); drawFirewalls(time); drawSnake(time); requestAnimationFrame(gameLoop); } // ========== START ========== initGame(); requestAnimationFrame(gameLoop); </script> </body> </html>

Connectez-vous pour voir le prompt complet

Continuer avec:

En vous connectant, vous acceptez nos Conditions et Confidentialité

Utilisation

Ce prompt est conçu pour être utilisé avec coding. Copiez le contenu ci-dessus et collez-le dans votre outil d’IA préféré.

Pour de meilleurs résultats, personnalisez les espaces réservés (indiqués par des crochets ou des majuscules) selon vos besoins.

Références

Catégories :coding| prompts.chat| html5-canvas| game-development

Discussion