Discusión

Enlace Cyber Grid: Prompt de Juego de Serpiente en HTML5 Canvas

De Wikiprompt, la enciclopedia libre de prompts

loshu2000
Contribuido porloshu2000Fuente

17 may 2026

Enlace Cyber Grid: Prompt de Juego de Serpiente en HTML5 Canvas Un prompt detallado para generar un juego completo de canvas HTML5 en un solo archivo con mecánica de serpiente cyberpunk, incluyendo especificaciones de renderizado, controles y estilo visual.

Contenido del PromptGuardar

🌐
<!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: #0a0a12; 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: #0d0d1a; } #ui { position: absolute; top: 10px; left: 50%; transform: translateX(-50%); color: #00ffcc; font-size: 18px; text-shadow: 0 0 10px #00ffcc; z-index: 10; letter-spacing: 2px; } #gameOver { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #ff0044; font-size: 32px; text-shadow: 0 0 20px #ff0044; display: none; z-index: 20; text-align: center; background: rgba(0, 0, 0, 0.8); padding: 20px; border: 1px solid #ff0044; } #gameOver button { margin-top: 15px; padding: 10px 20px; background: #ff0044; color: white; border: none; font-size: 16px; cursor: pointer; font-family: 'Courier New', monospace; } </style> </head> <body> <div id="ui">SCORE: 0 | LENGTH: 5</div> <div id="gameOver"> <div>GAME OVER</div> <button onclick="restartGame()">RESTART</button> </div> <canvas id="gameCanvas"></canvas> <script> (function() { const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const ui = document.getElementById('ui'); const gameOverDiv = document.getElementById('gameOver'); // Grid settings const GRID_SIZE = 20; const CELL_SIZE = 30; const COLS = 30; const ROWS = 20; canvas.width = COLS * CELL_SIZE; canvas.height = ROWS * CELL_SIZE; // 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 // Particle system for snake segments class Particle { constructor(x, y) { this.x = x; this.y = y; this.targetX = x; this.targetY = y; this.prevX = x; this.prevY = y; } update(deltaTime) { // LERP interpolation for smooth movement const lerpSpeed = 0.15; this.x += (this.targetX - this.x) * lerpSpeed; this.y += (this.targetY - this.y) * lerpSpeed; } setTarget(x, y) { this.prevX = this.targetX; this.prevY = this.targetY; this.targetX = x; this.targetY = y; } } // Initialize snake function initSnake() { snake = []; const startX = Math.floor(COLS / 2); const startY = Math.floor(ROWS / 2); for (let i = 0; i < 5; i++) { const particle = new Particle( (startX - i) * CELL_SIZE + CELL_SIZE / 2, startY * CELL_SIZE + CELL_SIZE / 2 ); particle.setTarget( (startX - i) * CELL_SIZE + CELL_SIZE / 2, startY * CELL_SIZE + CELL_SIZE / 2 ); snake.push(particle); } } // Spawn crystal function spawnCrystal() { let x, y; do { x = Math.floor(Math.random() * COLS); y = Math.floor(Math.random() * ROWS); } while (isSnakeCell(x, y) || isFirewallCell(x, y)); crystals.push({ x, y }); } // Spawn firewall function spawnFirewall() { let x, y; do { x = Math.floor(Math.random() * COLS); y = Math.floor(Math.random() * ROWS); } while (isSnakeCell(x, y) || isCrystalCell(x, y)); firewalls.push({ x, y, dx: Math.random() > 0.5 ? 1 : -1, dy: Math.random() > 0.5 ? 1 : -1 }); } function isSnakeCell(x, y) { return snake.some(seg => { const segX = Math.floor(seg.targetX / CELL_SIZE); const segY = Math.floor(seg.targetY / CELL_SIZE); return segX === x && segY === y; }); } function isCrystalCell(x, y) { return crystals.some(c => c.x === x && c.y === y); } function isFirewallCell(x, y) { return firewalls.some(f => f.x === x && f.y === y); } // Grid warping effect near snake head function warpGrid(x, y) { const head = snake[0]; if (!head) return { x, y }; const headX = head.x; const headY = head.y; const dx = x - headX; const dy = y - headY; const dist = Math.sqrt(dx * dx + dy * dy); const warpRadius = 100; if (dist < warpRadius) { const warpFactor = (1 - dist / warpRadius) * 0.3; return { x: x + dx * warpFactor, y: y + dy * warpFactor }; } return { x, y }; } // Move snake function moveSnake() { // Update direction direction = { ...nextDirection }; // Get head position const head = snake[0]; const headGridX = Math.floor(head.targetX / CELL_SIZE); const headGridY = Math.floor(head.targetY / CELL_SIZE); // New head position const newHeadX = headGridX + direction.x; const newHeadY = headGridY + direction.y; // Check wall collision if (newHeadX < 0 || newHeadX >= COLS || newHeadY < 0 || newHeadY >= ROWS) { gameOver(); return; } // Check self collision if (isSnakeCell(newHeadX, newHeadY)) { gameOver(); return; } // Check firewall collision if (isFirewallCell(newHeadX, newHeadY)) { gameOver(); return; } // Create new head particle const newHead = new Particle( newHeadX * CELL_SIZE + CELL_SIZE / 2, newHeadY * CELL_SIZE + CELL_SIZE / 2 ); newHead.setTarget( newHeadX * CELL_SIZE + CELL_SIZE / 2, newHeadY * CELL_SIZE + CELL_SIZE / 2 ); // Shift snake snake.unshift(newHead); // Check crystal collection const crystalIndex = crystals.findIndex(c => c.x === newHeadX && c.y === newHeadY); if (crystalIndex !== -1) { crystals.splice(crystalIndex, 1); score += 10; spawnCrystal(); // Don't remove tail (grow) } else { snake.pop(); } // Update targets for smooth movement for (let i = 1; i < snake.length; i++) { snake[i].setTarget(snake[i - 1].prevX, snake[i - 1].prevY); } updateUI(); } // Update firewalls function updateFirewalls() { firewalls.forEach(fw => { fw.x += fw.dx; fw.y += fw.dy; // Bounce off walls if (fw.x < 0 || fw.x >= COLS) fw.dx *= -1; if (fw.y < 0 || fw.y >= ROWS) fw.dy *= -1; // Clamp fw.x = Math.max(0, Math.min(COLS - 1, fw.x)); fw.y = Math.max(0, Math.min(ROWS - 1, fw.y)); }); } function gameOver() { gameRunning = false; gameOverDiv.style.display = 'block'; } function restartGame() { gameOverDiv.style.display = 'none'; score = 0; direction = { x: 1, y: 0 }; nextDirection = { x: 1, y: 0 }; crystals = []; firewalls = []; initSnake(); spawnCrystal(); for (let i = 0; i < 3; i++) spawnFirewall(); gameRunning = true; updateUI(); } function updateUI() { ui.textContent = `SCORE: ${score} | LENGTH: ${snake.length}`; } // Drawing functions function drawGrid() { ctx.strokeStyle = 'rgba(0, 255, 204, 0.2)'; ctx.lineWidth = 1; for (let i = 0; i <= COLS; i++) { const x = i * CELL_SIZE; ctx.beginPath(); for (let j = 0; j <= ROWS; j++) { const y = j * CELL_SIZE; const warped = warpGrid(x, y); if (j === 0) ctx.moveTo(warped.x, warped.y); else ctx.lineTo(warped.x, warped.y); } ctx.stroke(); } for (let j = 0; j <= ROWS; j++) { const y = j * CELL_SIZE; ctx.beginPath(); for (let i = 0; i <= COLS; i++) { const x = i * CELL_SIZE; const warped = warpGrid(x, y); if (i === 0) ctx.moveTo(warped.x, warped.y); else ctx.lineTo(warped.x, warped.y); } ctx.stroke(); } } function drawSnake() { // Draw glow effect ctx.shadowBlur = 20; ctx.shadowColor = '#00ffcc'; // Draw snake segments with gradient for (let i = snake.length - 1; i >= 0; i--) { const seg = snake[i]; const hue = 160 + (i / snake.length) * 40; const lightness = 50 + (i / snake.length) * 20; ctx.fillStyle = `hsl(${hue}, 100%, ${lightness}%)`; ctx.beginPath(); ctx.arc(seg.x, seg.y, CELL_SIZE * 0.35, 0, Math.PI * 2); ctx.fill(); } // Draw head with special effect if (snake.length > 0) { const head = snake[0]; ctx.fillStyle = '#00ffcc'; ctx.beginPath(); ctx.arc(head.x, head.y, CELL_SIZE * 0.45, 0, Math.PI * 2); ctx.fill(); // Eyes ctx.fillStyle = '#ffffff'; const eyeOffset = CELL_SIZE * 0.15; ctx.beginPath(); ctx.arc(head.x + direction.x * eyeOffset, head.y + direction.y * eyeOffset, 4, 0, Math.PI * 2); ctx.fill(); } ctx.shadowBlur = 0; } function drawCrystals() { crystals.forEach(crystal => { const x = crystal.x * CELL_SIZE + CELL_SIZE / 2; const y = crystal.y * CELL_SIZE + CELL_SIZE / 2; ctx.shadowBlur = 15; ctx.shadowColor = '#ff00ff'; ctx.fillStyle = '#ff00ff'; ctx.beginPath(); ctx.moveTo(x, y - 10); ctx.lineTo(x + 8, y); ctx.lineTo(x, y + 10); ctx.lineTo(x - 8, y); ctx.closePath(); ctx.fill(); ctx.fillStyle = 'rgba(255, 255, 255, 0.5)'; ctx.beginPath(); ctx.arc(x, y, 3, 0, Math.PI * 2); ctx.fill(); }); ctx.shadowBlur = 0; } function drawFirewalls() { firewalls.forEach(fw => { const x = fw.x * CELL_SIZE + CELL_SIZE / 2; const y = fw.y * CELL_SIZE + CELL_SIZE / 2; ctx.shadowBlur = 10; ctx.shadowColor = '#ff4400'; ctx.fillStyle = 'rgba(255, 68, 0, 0.8)'; ctx.fillRect(x - CELL_SIZE * 0.4, y - CELL_SIZE * 0.4, CELL_SIZE * 0.8, CELL_SIZE * 0.8); ctx.strokeStyle = '#ff4400'; ctx.lineWidth = 2; ctx.strokeRect(x - CELL_SIZE * 0.4, y - CELL_SIZE * 0.4, CELL_SIZE * 0.8, CELL_SIZE * 0.8); }); ctx.shadowBlur = 0; } // Main game loop function gameLoop(timestamp) { const deltaTime = timestamp - lastTime; lastTime = timestamp; if (gameRunning) { // Move timer moveTimer += deltaTime; if (moveTimer >= MOVE_INTERVAL) { moveTimer -= MOVE_INTERVAL; moveSnake(); updateFirewalls(); } // Update particle positions snake.forEach(seg => seg.update(deltaTime)); // Clear canvas ctx.fillStyle = '#0d0d1a'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Draw everything drawGrid(); drawCrystals(); drawFirewalls(); drawSnake(); } requestAnimationFrame(gameLoop); } // Input handling 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; } e.preventDefault(); }); // Initialize game initSnake(); spawnCrystal(); for (let i = 0; i < 3; i++) spawnFirewall(); updateUI(); // Start game loop requestAnimationFrame(gameLoop); })(); </script> </body> </html>

Iniciá sesión para ver el prompt completo

Continuar con:

Al iniciar sesión, aceptás nuestros Términos de uso y Política de privacidad

Uso

Este prompt está diseñado para usarse con coding. Copiá el contenido de arriba y pegalo en tu herramienta de IA preferida.

Para mejores resultados, personalizá los marcadores (indicados con corchetes o mayúsculas) con tus requisitos específicos.

Referencias

Categorías:coding| prompts.chat| html5-canvas| game-development

Discusión