Discusión

Crea un juego completo de Breakout Arcade en HTML

De Wikiprompt, la enciclopedia libre de prompts

Eyisha Zyer
Contribuido porEyisha ZyerXFuente

11 jul 2026

Crea un juego completo de Breakout Arcade en HTML Un prompt completo para generar un juego Breakout totalmente funcional en un solo archivo HTML, que cubra la jugabilidad, los controles, los visuales, el audio y los detalles técnicos.

Contenido del PromptGuardar

🌐
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <title>NEON BREAKOUT</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; user-select: none; } body { background: #0b0e1a; min-height: 100vh; display: flex; justify-content: center; align-items: center; font-family: 'Segoe UI', 'Poppins', system-ui, sans-serif; touch-action: none; } .game-container { background: #0f1322; border-radius: 2rem; padding: 1.2rem; box-shadow: 0 20px 40px rgba(0, 0, 0, 0.8), 0 0 0 2px #2a2f45 inset; } canvas { display: block; width: 100%; max-width: 900px; height: auto; aspect-ratio: 16 / 10; border-radius: 16px; background: #0a0d18; box-shadow: 0 0 30px #1e2a4a, 0 0 0 1px #3b4468; cursor: none; } .info-bar { display: flex; justify-content: space-between; align-items: center; padding: 0.6rem 0.3rem 0.2rem 0.3rem; color: #b9c8ff; font-weight: 600; letter-spacing: 0.5px; text-shadow: 0 0 8px #3d5afe; } .score, .lives, .level { background: #1a1f33; padding: 0.3rem 1rem; border-radius: 40px; box-shadow: inset 0 2px 5px #00000055, 0 0 10px #2b3b8f; font-size: 1.1rem; } .lives span { color: #ff5e7c; margin-left: 6px; font-size: 1.2rem; text-shadow: 0 0 12px #ff3b5c; } .level-badge { background: #1b2140; padding: 0.3rem 1.2rem; border-radius: 30px; font-size: 1rem; border: 1px solid #4c5aa0; } .controls-hint { color: #6f7db0; font-size: 0.8rem; margin-top: 0.3rem; display: flex; gap: 1.5rem; justify-content: center; background: #0c0f1c; padding: 0.4rem; border-radius: 30px; } .controls-hint kbd { background: #1d233b; padding: 0.1rem 0.7rem; border-radius: 20px; color: #b0c2ff; border: 1px solid #3f4b7a; } </style> </head> <body> <div style="display: flex; flex-direction: column; width: 95%; max-width: 950px;"> <div class="game-container"> <div class="info-bar"> <div class="score">🏆 <span id="scoreDisplay">0</span></div> <div class="level-badge">🌊 LEVEL <span id="levelDisplay">1</span></div> <div class="lives">❤️ <span id="livesDisplay">3</span></div> </div> <canvas id="gameCanvas" width="960" height="600"></canvas> <div class="footer-hint" style="display: flex; justify-content: space-between; padding: 0.4rem 0.2rem 0; color: #7c8bc0;"> <span>← → / mouse</span> <span>space: launch · P: pause</span> </div> </div> </div> <script> (function() { // ---------- canvas & context ---------- const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const scoreSpan = document.getElementById('scoreDisplay'); const livesSpan = document.getElementById('livesDisplay'); const levelSpan = document.getElementById('levelDisplay'); // ---------- dimensions ---------- const W = 960, H = 600; canvas.width = W; canvas.height = H; // ---------- game state ---------- let state = 'start'; // 'start', 'playing', 'paused', 'gameover', 'win' let score = 0; let lives = 3; let level = 1; let ball = { x: W/2, y: H-80, vx: 3.2, vy: -4.2, r: 8, speed: 5.2 }; let paddle = { x: W/2 - 55, y: H-30, w: 110, h: 14 }; let bricks = []; let particles = []; let keys = { left: false, right: false }; let ballLaunched = false; let gameOverFlag = false; let winFlag = false; let animationId = null; // ---------- audio (synthetic) ---------- function playTone(freq, duration = 0.1, type = 'square', volume = 0.08) { try { const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); const osc = audioCtx.createOscillator(); const gain = audioCtx.createGain(); osc.type = type; osc.frequency.value = freq; gain.gain.value = volume; osc.connect(gain); gain.connect(audioCtx.destination); osc.start(); setTimeout(() => { osc.stop(); audioCtx.close(); }, duration * 1000); } catch(e) { /* audio not critical */ } } const sfxBounce = () => playTone(180, 0.06, 'triangle', 0.05); const sfxBrick = () => playTone(520, 0.12, 'sawtooth', 0.06); const sfxGameOver = () => { playTone(120, 0.5, 'sawtooth', 0.07); setTimeout(()=>playTone(80,0.4,'square',0.05), 150); }; const sfxWin = () => { [440, 550, 660].forEach((f,i)=>setTimeout(()=>playTone(f,0.2,'sine',0.06), i*120)); }; // ---------- brick grid ---------- const BRICK_ROWS = 6; const BRICK_COLS = 12; const BRICK_WIDTH = 64; const BRICK_HEIGHT = 22; const BRICK_GAP = 6; const BRICK_OFFSET_TOP = 70; const BRICK_OFFSET_LEFT = 40; // neon palette const brickColors = [ '#ff5e7a', '#ff9f5a', '#ffd966', '#6bffb8', '#5ad1ff', '#b28dff' ]; function createBricks(levelMultiplier = 1) { const newBricks = []; for (let r = 0; r < BRICK_ROWS; r++) { for (let c = 0; c < BRICK_COLS; c++) { const x = BRICK_OFFSET_LEFT + c * (BRICK_WIDTH + BRICK_GAP); const y = BRICK_OFFSET_TOP + r * (BRICK_HEIGHT + BRICK_GAP); const color = brickColors[r % brickColors.length]; newBricks.push({ x, y, w: BRICK_WIDTH, h: BRICK_HEIGHT, color: color, alive: true, glow: 0.5 + Math.random() * 0.3 }); } } return newBricks; } const BRICK_GAP = 6; // ---------- reset / init ---------- function resetGame() { score = 0; lives = 3; level = 1; ballLaunched = false; gameOverFlag = false; winFlag = false; bricks = createBricks(); resetBall(); updateHUD(); state = 'playing'; } function resetBall() { ballLaunched = false; ball.x = paddle.x + paddle.w / 2; ball.y = paddle.y - 12; ball.vx = 3.2; ball.vy = -4.2; ball.speed = 5.2 + (level - 1) * 0.3; } function resetPaddle() { paddle.w = 110; paddle.x = W/2 - paddle.w/2; } function nextLevel() { level++; if (level > 3) { // win condition after level 3 winGame(); return; } bricks = createBricks(); resetPaddle(); resetBall(); ball.speed = 5.2 + (level - 1) * 0.5; updateHUD(); } function winGame() { winFlag = true; state = 'win'; sfxWin(); } function loseLife() { lives--; updateHUD(); if (lives <= 0) { state = 'gameover'; sfxGameOver(); } else { resetBall(); resetPaddle(); } } // ---------- HUD ---------- function updateHUD() { scoreSpan.textContent = score; livesSpan.textContent = lives; levelSpan.textContent = level; } // ---------- collision helpers ---------- function circleRectCollision(cx, cy, r, rect) { const closestX = Math.max(rect.x, Math.min(cx, rect.x + rect.w)); const closestY = Math.max(rect.y, Math.min(cy, rect.y + rect.h)); const dx = cx - closestX; const dy = cy - closestY; return (dx * dx + dy * dy) < (r * r); } // ---------- particles ---------- function spawnBrickParticles(brick) { for (let i = 0; i < 8; i++) { particles.push({ x: brick.x + brick.w/2, y: brick.y + brick.h/2, vx: (Math.random() - 0.5) * 8, vy: (Math.random() - 0.8) * 7, size: 3 + Math.random() * 5, color: brick.color, life: 0.7 + Math.random() * 0.5, maxLife: 1 }); } } // ---------- update ---------- function update() { if (state !== 'playing') return; // paddle movement if (keys.left) paddle.x -= 7.5; if (keys.right) paddle.x += 7.5; paddle.x = Math.max(0, Math.min(W - paddle.w, paddle.x)); // ball launch / follow paddle if (!ballLaunched) { ball.x = paddle.x + paddle.w / 2; ball.y = paddle.y - 12; return; } // move ball ball.x += ball.vx; ball.y += ball.vy; // wall collisions (left/right/top) if (ball.x - ball.radius < 0) { ball.x = ball.radius; ball.vx = -ball.vx; sfxBounce(); } else if (ball.x + ball.radius > W) { ball.x = W - ball.radius; ball.vx = -ball.vx; sfxBounce(); } if (ball.y - ball.radius < 0) { ball.y = ball.radius; ball.vy = -ball.vy; sfxBounce(); } // bottom (lose life) if (ball.y - ball.radius > H) { lives--; updateHUD(); if (lives <= 0) { state = 'gameover'; sfxGameOver(); return; } else { resetBall(); resetPaddle(); return; } } // paddle collision if (ball.vy > 0 && ball.y + ball.radius >= paddle.y && ball.y + ball.radius <= paddle.y + paddle.h + 8 && ball.x >= paddle.x - ball.radius && ball.x <= paddle.x + paddle.w + ball.radius) { // angle based on hit position const hitPos = (ball.x - (paddle.x + paddle.w/2)) / (paddle.w/2); const angle = hitPos * 0.9; const speed = Math.hypot(ball.vx, ball.vy); ball.vx = speed * Math.sin(angle); ball.vy = -Math.abs(speed * Math.cos(angle)); ball.y = paddle.y - ball.radius - 1; sfxBounce(); } // bricks collision for (let i = 0; i < bricks.length; i++) { const b = bricks[i]; if (!b.alive) continue; if (circleRectCollision(ball.x, ball.y, ball.radius, b)) { b.alive = false; score += 10; updateHUD(); sfxBrick(); spawnBrickParticles(b); // reflect ball const overlapLeft = ball.x + ball.radius - b.x; const overlapRight = b.x + b.w - (ball.x - ball.radius); const overlapTop = ball.y + ball.radius - b.y; const overlapBottom = b.y + b.h - (ball.y - ball.radius); const minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom); if (minOverlap === overlapLeft || minOverlap === overlapRight) { ball.vx = -ball.vx; } else { ball.vy = -ball.vy; } break; } } // check win (all bricks dead) const aliveCount = bricks.filter(b => b.alive).length; if (aliveCount === 0) { nextLevel(); return; } // particles update for (let i = particles.length - 1; i >= 0; i--) { const p = particles[i]; p.x += p.vx; p.y += p.vy; p.vy += 0.15; p.life -= 0.02; if (p.life <= 0) particles.splice(i, 1); } } function spawnBrickParticles(brick) { for (let i = 0; i < 10; i++) { particles.push({ x: brick.x + brick.w/2, y: brick.y + brick.h/2, vx: (Math.random() - 0.5) * 9, vy: (Math.random() - 0.8) * 7, size: 2 + Math.random() * 5, color: brick.color, life: 0.8 + Math.random() * 0.6, maxLife: 1 }); } } // ---------- draw ---------- function draw() { ctx.clearRect(0, 0, W, H); // background gradient const grad = ctx.createLinearGradient(0, 0, 0, H); grad.addColorStop(0, '#0b0e1e'); grad.addColorStop(1, '#131a2f'); ctx.fillStyle = grad; ctx.fillRect(0, 0, W, H); // draw bricks for (const b of bricks) { if (!b.alive) continue; ctx.shadowColor = b.color; ctx.shadowBlur = 12; ctx.fillStyle = b.color; ctx.beginPath(); ctx.roundRect(b.x, b.y, b.w, b.h, 6); ctx.fill(); // inner glow ctx.shadowBlur = 4; ctx.fillStyle = 'rgba(255,255,255,0.15)'; ctx.beginPath(); ctx.roundRect(b.x+2, b.y+2, b.w-4, b.h-4, 4); ctx.fill(); } ctx.shadowBlur = 0; // paddle ctx.shadowColor = '#4de1ff'; ctx.shadowBlur = 18; ctx.fillStyle = '#e0f2ff'; ctx.beginPath(); ctx.roundRect(paddle.x, paddle.y, paddle.w, paddle.h, 12); ctx.fill(); ctx.shadowBlur = 0; // ball ctx.shadowColor = '#ffd966'; ctx.shadowBlur = 20; ctx.fillStyle = '#fff8e0'; ctx.beginPath(); ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2); ctx.fill(); ctx.shadowBlur = 0; // particles for (const p of particles) { ctx.globalAlpha = Math.max(0, p.life); ctx.fillStyle = p.color; ctx.shadowColor = p.color; ctx.shadowBlur = 10; ctx.beginPath(); ctx.arc(p.x, p.y, p.size * p.life, 0, Math.PI * 2); ctx.fill(); } ctx.globalAlpha = 1; ctx.shadowBlur = 0; // overlays if (state === 'start') { ctx.fillStyle = 'rgba(0,0,0,0.6)'; ctx.fillRect(0, 0, W, H); ctx.font = 'bold 36px "Segoe UI", sans-serif'; ctx.fillStyle = '#c9e2ff'; ctx.shadowColor = '#3d6afe'; ctx.shadowBlur = 20; ctx.textAlign = 'center'; ctx.fillText('⚡ BREAKOUT ⚡', W/2, H/2 - 40); ctx.font = '20px "Segoe UI"'; ctx.fillStyle = '#b0c8ff'; ctx.fillText('press SPACE to launch', W/2, H/2 + 20); ctx.shadowBlur = 0; } else if (state === 'paused') { ctx.fillStyle = 'rgba(0,0,0,0.5)'; ctx.fillRect(0, 0, W, H); ctx.font = 'bold 42px "Segoe UI"'; ctx.fillStyle = '#ffffff'; ctx.shadowColor = '#3d6afe'; ctx.shadowBlur = 20; ctx.textAlign = 'center'; ctx.fillText('⏸ PAUSED', W/2, H/2); ctx.font = '18px "Segoe UI"'; ctx.fillText('press P to resume', W/2, H/2 + 40); ctx.shadowBlur = 0; } else if (state === 'gameover') { ctx.fillStyle = 'rgba(20,0,20,0.7)'; ctx.fillRect(0, 0, W, H); ctx.font = 'bold 46px "Segoe UI"'; ctx.fillStyle = '#ff7b7b'; ctx.shadowColor = '#ff0000'; ctx.shadowBlur = 30; ctx.textAlign = 'center'; ctx.fillText('GAME OVER', W/2, H/2 - 20); ctx.font = '24px "Segoe UI"'; ctx.fillStyle = '#ffd0d0'; ctx.fillText('score: ' + score, W/2, H/2 + 30); ctx.fillText('press SPACE to restart', W/2, H/2 + 70); ctx.shadowBlur = 0; } else if (state === 'win') { ctx.fillStyle = 'rgba(0,20,20,0.7)'; ctx.fillRect(0, 0, W, H); ctx.font = 'bold 48px "Segoe UI"'; ctx.fillStyle = '#7dffb0'; ctx.shadowColor = '#00ffaa'; ctx.shadowBlur = 40; ctx.textAlign = 'center'; ctx.fillText('🏆 YOU WIN!', W/2, H/2 - 20); ctx.font = '24px "Segoe UI"'; ctx.fillStyle = '#c0ffe0'; ctx.fillText('final score: ' + score, W/2, H/2 + 30); ctx.fillText('press SPACE to play again', W/2, H/2 + 70); ctx.shadowBlur = 0; } } // roundRect helper CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) { if (w < 2 * r) r = w / 2; if (h < 2 * r) r = h / 2; this.moveTo(x + r, y); this.lineTo(x + w - r, y); this.quadraticCurveTo(x + w, y, x + w, y + r); this.lineTo(x + w, y + h - r); this.quadraticCurveTo(x + w, y + h, x + w - r, y + h); this.lineTo(x + r, y + h); this.quadraticCurveTo(x, y + h, x, y + h - r); this.lineTo(x, y + r); this.quadraticCurveTo(x, y, x + r, y); return this; }; // ---------- game loop ---------- function gameLoop() { update(); draw(); animationId = requestAnimationFrame(gameLoop); } // ---------- event listeners ---------- function handleKeyDown(e) { const key = e.key; if (key === 'ArrowLeft') { keys.left = true; e.preventDefault(); } if (key === 'ArrowRight') { keys.right = true; e.preventDefault(); } if (key === ' ' || key === 'Space') { e.preventDefault(); if (state === 'start') { state = 'playing'; resetGame(); ballLaunched = true; } else if (state === 'playing' && !ballLaunched) { ballLaunched = true; ball.vy = -ball.speed; } else if (state === 'gameover' || state === 'win') { resetGame(); state = 'playing'; ballLaunched = true; } } if (key === 'p' || key === 'P') { if (state === 'playing') { state = 'paused'; } else if (state === 'paused') { state = 'playing'; } } } function handleKeyUp(e) { if (e.key === 'ArrowLeft') keys.left = false; if (e.key === 'ArrowRight') keys.right = false; } function handleMouseMove(e) { const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; const mouseX = (e.clientX - rect.left) * scaleX; paddle.x = mouseX - paddle.w / 2; paddle.x = Math.max(0, Math.min(W - paddle.w, paddle.x)); if (!ballLaunched && state === 'playing') { ball.x = paddle.x + paddle.w / 2; ball.y = paddle.y - 12; } } // ---------- init ---------- function init() { bricks = createBricks(); resetPaddle(); resetBall(); state = 'start'; updateHUD(); window.addEventListener('keydown', handleKeyDown); window.addEventListener('keyup', handleKeyUp); canvas.addEventListener('mousemove', handleMouseMove); canvas.addEventListener('mouseleave', () => { /* keep paddle */ }); gameLoop(); } init(); })(); </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| twitter| breakout-game| html5-canvas

Discusión