您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Juego clásico Space Invaders en Drawaria.online con gráficos pixel-art personalizados, panel arrastrable y optimización de rastros mejorada.
// ==UserScript== // @name Drawaria Space Invaders Game // @namespace http://tampermonkey.net/ // @version 1.7 // @description Juego clásico Space Invaders en Drawaria.online con gráficos pixel-art personalizados, panel arrastrable y optimización de rastros mejorada. // @author YouTubeDrawaria // @match https://drawaria.online/* // @grant none // @license MIT // @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online // ==/UserScript== (function() { 'use strict'; let drawariaSocket = null; let drawariaCanvas = null; let drawariaCtx = null; const commandQueue = []; let batchProcessor = null; const BATCH_SIZE = 8; const BATCH_INTERVAL = 60; // ms const originalWebSocketSend = WebSocket.prototype.send; WebSocket.prototype.send = function(...args) { if (!drawariaSocket && this.url && this.url.includes('drawaria')) { drawariaSocket = this; console.log('🔗 Drawaria WebSocket capturado para Space Invaders.'); startBatchProcessor(); } return originalWebSocketSend.apply(this, args); }; function startBatchProcessor() { if (batchProcessor) return; batchProcessor = setInterval(() => { if (!drawariaSocket || drawariaSocket.readyState !== WebSocket.OPEN || commandQueue.length === 0) { return; } const batch = commandQueue.splice(0, BATCH_SIZE); batch.forEach(cmd => { try { drawariaSocket.send(cmd); } catch (e) { console.warn('⚠️ Fallo al enviar comando:', e); } }); }, BATCH_INTERVAL); } // Color de fondo para "borrar" rastros y el escenario espacial const BACKGROUND_COLOR = '#000000'; // Negro /** * Función unificada para encolar comandos de dibujo. * Utiliza una línea muy corta con grosor negativo para dibujar formas rellenas (puntos/círculos) * o líneas con grosor negativo para "simular" líneas gruesas o rellenos rectangulares. * @param {number} x1 - Coordenada X inicial * @param {number} y1 - Coordenada Y inicial * @param {number} x2 - Coordenada X final * @param {number} y2 - Coordenada Y final * @param {string} color - Color del objeto (ej. '#FFFFFF') * @param {number} thickness - Grosor efectivo (positivo para círculo, negativo para línea gruesa/relleno) * @param {boolean} isArc - Si es true, dibuja un círculo con x1,y1 como centro y thickness como diámetro. Si es false, dibuja una línea o un rectángulo relleno (si es una línea corta con grosor negativo). * @param {number} startAngle - Ángulo inicial para arcos (usado solo localmente si isArc es true) * @param {number} endAngle - Ángulo final para arcos (usado solo localmente si isArc es true) */ function enqueueDrawCommand(x1, y1, x2, y2, color, thickness, isArc = false, startAngle = 0, endAngle = 0) { if (!drawariaCanvas || !drawariaSocket) return; // Renderizado local para retroalimentación visual inmediata (útil para depuración) if (drawariaCtx) { drawariaCtx.fillStyle = color; // Para formas rellenas drawariaCtx.strokeStyle = color; // Para líneas drawariaCtx.lineWidth = Math.abs(thickness); // Usa el valor absoluto para el grosor local drawariaCtx.lineCap = 'butt'; // Para líneas cuadradas, no redondas drawariaCtx.lineJoin = 'miter'; // Para esquinas cuadradas if (isArc) { // Para dibujar círculos/píxeles rellenos localmente drawariaCtx.beginPath(); drawariaCtx.arc(x1, y1, Math.abs(thickness) / 2, startAngle, endAngle); drawariaCtx.fill(); // Rellenar el círculo } else { // Para líneas o rectángulos rellenos (interpretando thickness como alto/ancho) // Si x1 == x2 y y1 == y2 (o muy cercanos), Drawaria puede interpretar como punto/círculo. // Para garantizar un rectángulo localmente, podemos usar fillRect para el feedback. // Sin embargo, para Drawaria, una línea muy gruesa (grosor negativo) actuará como un relleno rectangular. // Si la "línea" es horizontal (y1=y2), actuará como un rect.width = x2-x1, rect.height = thickness // Si la "línea" es vertical (x1=x2), actuará como un rect.width = thickness, rect.height = y2-y1 // Dado que estamos enviando una línea de un punto a otro con un grosor, // localmente esto dibujará una línea de ese grosor. drawariaCtx.beginPath(); drawariaCtx.moveTo(x1, y1); drawariaCtx.lineTo(x2, y2); drawariaCtx.stroke(); // Dibuja la línea gruesa/rectángulo } } const normX1 = (x1 / drawariaCanvas.width).toFixed(4); const normY1 = (y1 / drawariaCanvas.height).toFixed(4); const normX2 = (x2 / drawariaCanvas.width).toFixed(4); const normY2 = (y2 / drawariaCanvas.height).toFixed(4); let cmd; // Para el servidor, los círculos/píxeles se envían como puntos con grosor negativo (si isArc es true). // Las líneas o rectángulos rellenos se envían con grosor negativo (si isArc es false). // El cliente de Drawaria interpreta un comando de línea con grosor negativo como un rectángulo relleno. cmd = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${-Math.abs(thickness)},"${color}",0,0,{}]]`; commandQueue.push(cmd); } // --- CONSTANTES Y FUNCIÓN AUXILIAR PARA PIXEL ART --- // ✅ Cambio para mayor GROSOR: Aumentar el valor de PIXEL_SCALE para píxeles más gruesos y cuadrados. const PIXEL_SCALE = 8; // Cada "píxel" en nuestras matrices y el grosor de los elementos será de 8x8 en el canvas // Forma del invasor (11x8 píxeles) const INVADER_PIXELS = [ [0,1,1,0,0,0,0,0,1,1,0], [1,1,1,1,1,1,1,1,1,1,1], [1,1,0,0,1,1,1,0,0,1,1], [1,1,0,0,1,1,1,0,0,1,1], [0,1,1,1,1,1,1,1,1,1,0], [0,0,1,1,1,1,1,1,1,0,0], [0,1,0,0,0,0,0,0,0,1,0], [0,0,1,0,0,0,0,0,1,0,0] ]; const INVADER_WIDTH_PX = 11; const INVADER_HEIGHT_PX = 8; const INVADER_COLOR = '#00FF00'; // Verde // Forma del jugador (13x8 píxeles) const PLAYER_PIXELS = [ [0,0,0,0,0,1,1,1,0,0,0,0,0], [0,0,0,0,1,1,1,1,1,0,0,0,0], [0,0,0,1,1,1,1,1,1,1,0,0,0], [0,0,1,1,1,1,1,1,1,1,1,0,0], [0,1,1,1,1,1,1,1,1,1,1,1,0], [1,1,1,1,1,1,1,1,1,1,1,1,1], [1,1,1,1,1,1,1,1,1,1,1,1,1], [1,1,1,1,1,1,1,1,1,1,1,1,1] ]; const PLAYER_WIDTH_PX = 13; const PLAYER_HEIGHT_PX = 8; const PLAYER_COLOR = '#00FFFF'; // Azul vibrante / Cian // Función auxiliar para dibujar formas de pixel art function drawPixelShape(originX, originY, pixelMap, color, pixelSize) { for (let y = 0; y < pixelMap.length; y++) { for (let x = 0; x < pixelMap[y].length; x++) { if (pixelMap[y][x] === 1) { const px = originX + x * pixelSize; const py = originY + y * pixelSize; // ✅ CAMBIO CLAVE: Dibuja cada "píxel" como un rectángulo relleno // Envía una línea horizontal de longitud `pixelSize` con grosor `pixelSize`. // Esto crea un cuadrado relleno. isArc es false. enqueueDrawCommand(px, py + pixelSize / 2, px + pixelSize, py + pixelSize / 2, color, pixelSize, false); } } } } // --- FIN DE LAS NUEVAS CONSTANTES Y FUNCIÓN AUXILIAR --- class SpaceInvadersGame { constructor() { this.isActive = false; // Ajustar tamaños de jugador basados en el pixel art y la escala this.playerWidth = PLAYER_WIDTH_PX * PIXEL_SCALE; this.playerHeight = PLAYER_HEIGHT_PX * PIXEL_SCALE; this.playerSpeed = 6 * (PIXEL_SCALE / 6); // Ajustar velocidad para la nueva escala this.bullets = []; // Velocidad de bala ajustada para intervalo de 5 segundos y "más arriba" this.bulletSpeed = 50; this.canShoot = true; this.shootCooldown = 300; // ms this.invaders = []; this.invaderRows = 1; // Solo una fila de invasores this.invaderCols = 5; // Un total de 5 invasores // Ajustar tamaños de invasores basados en el pixel art y la escala this.invaderWidth = INVADER_WIDTH_PX * PIXEL_SCALE; this.invaderHeight = INVADER_HEIGHT_PX * PIXEL_SCALE; this.invaderGapX = 20; // Espacio entre invasores para distribuirlos mejor this.invaderGapY = 15; // Menos relevante con una sola fila, pero se mantiene // Reintroducir velocidad del invader y ajustar para intervalo de 5 segundos this.invaderSpeed = 7.5; this.invaderDirection = 1; // 1 derecha, -1 izquierda this.invaderStepDown = 20; // Bajada más pronunciada al cambiar de dirección this.score = 0; this.gameInterval = null; // Limitar la velocidad de fotogramas del juego a 5 segundos (0.2 FPS) this.gameSpeed = 5000; // ms por frame (antes 1000) this.isGameOver = false; // --- NUEVAS PROPIEDADES PARA ELIMINAR RASTROS (estado del frame anterior) --- this.prevPlayerX = 0; this.prevPlayerY = 0; this.prevInvaders = []; this.prevBullets = []; // --- FIN NUEVAS PROPIEDADES --- this.init(); } init() { const checkCanvasReady = () => { const canvas = document.getElementById('canvas'); if (canvas) { drawariaCanvas = canvas; drawariaCtx = canvas.getContext('2d'); // Posicionar jugador al centro abajo this.playerX = (drawariaCanvas.width - this.playerWidth) / 2; this.playerY = drawariaCanvas.height - this.playerHeight - 10; // Inicializar prevPlayerX/Y con la posición inicial del jugador this.prevPlayerX = this.playerX; this.prevPlayerY = this.playerY; this.createGamePanel(); this.resetGame(); console.log('✅ Space Invaders inicializado.'); } else { setTimeout(checkCanvasReady, 100); } }; checkCanvasReady(); } createGamePanel() { const existing = document.getElementById('spaceinvaders-game-panel'); if (existing) existing.remove(); const panel = document.createElement('div'); panel.id = 'spaceinvaders-game-panel'; panel.style.cssText = ` position: fixed !important; top: 20px !important; right: 20px !important; width: 250px !important; z-index: 2147483647 !important; background: linear-gradient(135deg, #000011, #000006) !important; border: 2px solid #00FF00 !important; border-radius: 12px !important; color: #00FF00 !important; font-family: 'Press Start 2P', 'Segoe UI', Arial, sans-serif !important; box-shadow: 0 0 20px rgba(0, 255, 0, 0.3) !important; padding: 15px !important; text-align: center !important; `; panel.innerHTML = ` <h3 style="margin-top: 0; color: #00FF00;">🚀 Space Invaders</h3> <div style="margin-bottom: 10px;"> Score: <span id="si-score">0</span> </div> <button id="si-create-space-btn" style=" width: 100%; padding: 10px; background: #34495e; /* Un tono oscuro de azul/gris */ color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: bold; margin-bottom: 10px; transition: background 0.3s ease; ">🌌 Create Space</button> <button id="si-start-pause" style=" width: 100%; padding: 10px; background: #00FF00; color: black; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: bold; margin-bottom: 10px; transition: background 0.3s ease; ">▶️ Iniciar Juego</button> <div id="si-game-message" style=" margin-top: 10px; color: #FF4444; font-weight: bold; display: none; "></div> <div style=" margin-top: 15px; font-size: 10px; color: rgba(0,255,0,0.6); "> Usa ← → para mover.<br> Barra espaciadora para disparar. <br><br> *Nota: Animación de juego cada 5 segundos para reducir comandos al servidor.* </div> `; document.body.appendChild(panel); this.makePanelDraggable(panel); document.getElementById('si-create-space-btn').addEventListener('click', () => this.createSpaceScenario()); document.getElementById('si-start-pause').addEventListener('click', () => this.toggleGame()); document.addEventListener('keydown', e => this.handleKeyInput(e)); document.addEventListener('keyup', e => this.handleKeyUp(e)); } makePanelDraggable(panel) { let isDragging = false; let currentX, currentY, initialX, initialY; let xOffset = 0, yOffset = 0; const dragStart = e => { e.preventDefault(); initialX = e.clientX - xOffset; initialY = e.clientY - yOffset; isDragging = true; panel.style.cursor = 'grabbing'; document.addEventListener("mousemove", drag); document.addEventListener("mouseup", dragEnd); }; const dragEnd = () => { isDragging = false; panel.style.cursor = 'grab'; document.removeEventListener("mousemove", drag); document.removeEventListener("mouseup", dragEnd); }; const drag = e => { if (isDragging) { e.preventDefault(); currentX = e.clientX - initialX; currentY = e.clientY - initialY; xOffset = currentX; yOffset = currentY; panel.style.transform = `translate3d(${currentX}px, ${currentY}px, 0)`; } }; const header = panel.querySelector('h3'); if (header) { header.style.cursor = 'grab'; header.addEventListener("mousedown", dragStart); } } resetGame() { this.isActive = false; this.isGameOver = false; this.score = 0; this.updateScore(); this.bullets = []; this.invaderDirection = 1; this.createInvaders(); this.playerX = (drawariaCanvas.width - this.playerWidth) / 2; this.playerY = drawariaCanvas.height - this.playerHeight - 10; this.prevPlayerX = this.playerX; this.prevPlayerY = this.playerY; this.prevInvaders = this.invaders.map(inv => ({ ...inv })); this.prevBullets = []; this.lastShotTime = 0; this.keysPressed = {}; this.clearCanvas(); // Borrado completo this.drawAll(); // Dibuja el estado inicial } // Modificado para crear solo 5 invasores centrados createInvaders() { this.invaders = []; const numInvaders = 5; const totalInvadersContentWidth = numInvaders * this.invaderWidth + (numInvaders - 1) * this.invaderGapX; const startX = (drawariaCanvas.width - totalInvadersContentWidth) / 2; const startY = 40; for (let i = 0; i < numInvaders; i++) { this.invaders.push({ x: startX + i * (this.invaderWidth + this.invaderGapX), y: startY, width: this.invaderWidth, height: this.invaderHeight, alive: true }); } } toggleGame() { if (!this.isActive) { this.startGame(); document.getElementById('si-start-pause').textContent = '⏸️ Pausar Juego'; } else { this.pauseGame(); document.getElementById('si-start-pause').textContent = '▶️ Reanudar Juego'; } } startGame() { if (this.isActive) return; this.isActive = true; this.isGameOver = false; this.gameLoop(); document.getElementById('si-game-message').style.display = 'none'; document.getElementById('si-start-pause').style.background = '#00FF00'; } pauseGame() { this.isActive = false; if (this.gameInterval) clearTimeout(this.gameInterval); this.gameInterval = null; } endGame(message) { this.isGameOver = true; this.pauseGame(); const msgEl = document.getElementById('si-game-message'); msgEl.textContent = message; msgEl.style.display = 'block'; document.getElementById('si-start-pause').textContent = '🔄 Reiniciar Juego'; document.getElementById('si-start-pause').style.background = '#cc0000'; console.log(`💀 Juego terminado: ${message}. Puntuación: ${this.score}`); } gameLoop() { if (!this.isActive) return; this.updateGame(); this.drawAll(); if (!this.isGameOver) { this.gameInterval = setTimeout(() => this.gameLoop(), this.gameSpeed); } } updateGame() { // --- ALMACENAR ESTADO ANTERIOR PARA ELIMINACIÓN DE RASTROS --- this.prevPlayerX = this.playerX; this.prevPlayerY = this.playerY; this.prevInvaders = this.invaders.map(inv => ({ ...inv })); this.prevBullets = this.bullets.map(b => ({ ...b })); // --- FIN ALMACENAR ESTADO ANTERIOR --- // Mover jugador según teclas (efecto visual cada 5 segundos) if (this.keysPressed['ArrowLeft']) { this.playerX = Math.max(this.playerX - this.playerSpeed, 0); } if (this.keysPressed['ArrowRight']) { this.playerX = Math.min(this.playerX + this.playerSpeed, drawariaCanvas.width - this.playerWidth); } // Actualizar balas (efecto visual cada 5 segundos, con velocidad ajustada) this.bullets.forEach(bullet => { bullet.y -= this.bulletSpeed; }); this.bullets = this.bullets.filter(bullet => bullet.y + bullet.height > 0); // Verificar colisiones bala-invader for (let b = this.bullets.length -1; b >= 0; b--) { const bullet = this.bullets[b]; for (let i = 0; i < this.invaders.length; i++) { const invader = this.invaders[i]; if (invader.alive && this.rectOverlap(bullet, invader)) { invader.alive = false; this.bullets.splice(b,1); this.score += 100; this.updateScore(); break; } } } // Reintroducir lógica de movimiento para invasores ("mueva de un lado a otro solo") let invaderHitWall = false; for (const invader of this.invaders) { if (!invader.alive) continue; invader.x += this.invaderSpeed * this.invaderDirection; if (invader.x + invader.width > drawariaCanvas.width || invader.x < 0) { invaderHitWall = true; } // Condición de derrota: si un invader llega al jugador if (invader.y + invader.height > this.playerY) { this.endGame('¡Los invasores te alcanzaron!'); return; } } if (invaderHitWall) { this.invaderDirection *= -1; // Cambia de dirección for (const invader of this.invaders) { invader.y += this.invaderStepDown; // Baja un paso // Ajustar posición si se salió por el otro lado debido al cambio de dirección if (invader.x + invader.width > drawariaCanvas.width) { invader.x = drawariaCanvas.width - invader.width; } else if (invader.x < 0) { invader.x = 0; } } } // Condición de victoria if (this.invaders.every(i => !i.alive)) { this.endGame('¡Ganaste!'); } } rectOverlap(a, b) { return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y; } /** * Borra los dibujos del frame anterior dibujando sobre ellos con el color de fondo. * El área de borrado es ligeramente más grande para asegurar una limpieza completa. */ erasePreviousDrawings() { // Borrar jugador de su posición anterior const playerErasePadding = PIXEL_SCALE * 2; // Añadir margen para borrar bien const playerEraseWidth = this.playerWidth + playerErasePadding; const playerEraseHeight = this.playerHeight + playerErasePadding; const playerEraseX = this.prevPlayerX - (playerErasePadding / 2); const playerEraseY = this.prevPlayerY - (playerErasePadding / 2); enqueueDrawCommand(playerEraseX, playerEraseY + playerEraseHeight / 2, playerEraseX + playerEraseWidth, playerEraseY + playerEraseHeight / 2, BACKGROUND_COLOR, playerEraseHeight, false); // Borrar invasores de sus posiciones anteriores for (const invader of this.prevInvaders) { // Borrar siempre, incluso si ya no está vivo, para limpiar su último rastro const invaderErasePadding = PIXEL_SCALE * 2; const invaderEraseWidth = invader.width + invaderErasePadding; const invaderEraseHeight = invader.height + invaderErasePadding; const invaderEraseX = invader.x - (invaderErasePadding / 2); const invaderEraseY = invader.y - (invaderErasePadding / 2); enqueueDrawCommand(invaderEraseX, invaderEraseY + invaderEraseHeight / 2, invaderEraseX + invaderEraseWidth, invaderEraseY + invaderEraseHeight / 2, BACKGROUND_COLOR, invaderEraseHeight, false); } // Borrar balas de sus posiciones anteriores this.prevBullets.forEach(bullet => { // Para balas, que son rectángulos, dibujamos un rectángulo un poco más grande de color de fondo const bulletEraseWidth = bullet.width + PIXEL_SCALE; const bulletEraseHeight = bullet.height + PIXEL_SCALE; const bulletEraseX = bullet.x - (PIXEL_SCALE / 2); const bulletEraseY = bullet.y - (PIXEL_SCALE / 2); enqueueDrawCommand(bulletEraseX, bulletEraseY + bulletEraseHeight / 2, bulletEraseX + bulletEraseWidth, bulletEraseY + bulletEraseHeight / 2, BACKGROUND_COLOR, bulletEraseHeight, false); }); } /** * Dibuja todos los elementos del juego en sus posiciones actuales. */ drawAll() { // Primero, borrar los dibujos del frame anterior // Esto se asegura de que los elementos "desaparezcan" de su posición anterior // y luego se "redibujen" en la nueva, cada 5 segundos. this.erasePreviousDrawings(); // Dibujar jugador con la nueva forma pixel-art en su posición actual (ahora con píxeles cuadrados) drawPixelShape(this.playerX, this.playerY, PLAYER_PIXELS, PLAYER_COLOR, PIXEL_SCALE); // Dibujar invasores con la nueva forma pixel-art en sus posiciones actuales (ahora con píxeles cuadrados) for (const invader of this.invaders) { if (!invader.alive) continue; // Solo dibujar invasores vivos drawPixelShape(invader.x, invader.y, INVADER_PIXELS, INVADER_COLOR, PIXEL_SCALE); } // Dibujar balas (rectángulos blancos) en sus posiciones actuales this.bullets.forEach(bullet => { // ✅ CAMBIO CLAVE: Balas dibujadas como rectángulos rellenos // Dibuja una línea horizontal de la longitud de la bala y con el grosor de la altura de la bala. enqueueDrawCommand(bullet.x, bullet.y + bullet.height / 2, bullet.x + bullet.width, bullet.y + bullet.height / 2, '#FFFFFF', bullet.height, false); }); } /** * Realiza un borrado completo de todo el canvas. * Se usa principalmente al inicio o reinicio del juego y para el escenario espacial. */ clearCanvas() { enqueueDrawCommand(0, 0, drawariaCanvas.width, drawariaCanvas.height, BACKGROUND_COLOR, Math.max(1500, 1500), false); // Usar false para borrar con rectángulo grueso } handleKeyInput(e) { // Permitir que las pulsaciones de teclas se registren incluso si el juego no está activo, // pero el movimiento visual solo se aplicará en el gameLoop cada 5 segundos. if (e.code === 'Space') { e.preventDefault(); // El disparo ocurre inmediatamente, pero la bala solo se mueve cada 5 segundos. // Esto podría sentirse un poco raro, pero es la consecuencia de la restricción de 5 segundos. this.shoot(); } else if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') { this.keysPressed[e.key] = true; e.preventDefault(); } } handleKeyUp(e) { if(e.key === 'ArrowLeft' || e.key === 'ArrowRight') { this.keysPressed[e.key] = false; } } // Modificado para que las balas se ajusten al nuevo tamaño del jugador pixel art y empiecen más arriba shoot() { if(!this.canShoot || this.isGameOver) return; const now = Date.now(); if (this.lastShotTime && now - this.lastShotTime < this.shootCooldown) { return; } this.lastShotTime = now; // Agrega una bala en la parte superior del jugador // Bala inicia aún más arriba, ajustado al nuevo PIXEL_SCALE this.bullets.push({ x: this.playerX + this.playerWidth / 2 - (PIXEL_SCALE / 2), // Centrar la bala con respecto al jugador (ajuste fino) y: this.playerY - (PIXEL_SCALE * 7), // La bala comienza significativamente más arriba width: PIXEL_SCALE, // Ancho base de la bala (será un cuadrado) height: PIXEL_SCALE * 3 // Alto base de la bala (para una forma rectangular si se desea) }); } updateScore() { const scoreEl = document.getElementById('si-score'); if(scoreEl) scoreEl.textContent = this.score; } // --- FUNCIÓN PARA EL ESCENARIO ESPACIAL --- createSpaceScenario() { if (!drawariaCanvas || !drawariaSocket) { console.log('Canvas or WebSocket not available.'); return; } this.pauseGame(); // Pausa el juego para dibujar el escenario // Borra todo el canvas con negro this.clearCanvas(); // Dibuja puntos blancos para simular estrellas // Se usa un setTimeout para dar tiempo a que el borrado completo se procese setTimeout(() => { const numStars = 200; // Número de estrellas const starSize = PIXEL_SCALE / 2; // Tamaño de los puntos (más pequeño que el PIXEL_SCALE general) for (let i = 0; i < numStars; i++) { const x = Math.random() * drawariaCanvas.width; const y = Math.random() * drawariaCanvas.height; // Dibuja una pequeña estrella como un pequeño cuadrado (pixel) enqueueDrawCommand(x, y + starSize / 2, x + starSize, y + starSize / 2, '#FFFFFF', starSize, false); } console.log('✅ Escenario espacial dibujado con éxito.'); }, 200); // Pequeño retraso para asegurar que el borrado se complete primero } // --- FIN FUNCIÓN --- } // Inicialización del juego const initSpaceInvaders = () => { new SpaceInvadersGame(); }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initSpaceInvaders); } else { setTimeout(initSpaceInvaders, 500); } })();