您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Capture drawn pixels from canvas and DESTROY them with epic laser beams!
// ==UserScript== // @name Epic Pixel Laser Destroyer for Drawaria // @namespace http://tampermonkey.net/ // @version 4.0 // @description Capture drawn pixels from canvas and DESTROY them with epic laser beams! // @author YouTubeDrawaria // @match https://drawaria.online/* // @match https://*.drawaria.online/* // @grant GM_xmlhttpRequest // @license MIT // @icon https://www.google.com/s2/favicons?sz=64&domain=drawaria.online // ==/UserScript== (function () { 'use strict'; /* ---------- CONFIGURACIÓN DEL SISTEMA LÁSER ---------- */ const LASER_MODES = { 'Láser Rojo Clásico': { color: '#ff0000', name: '🔴 Classic Red Laser', particles: 'fire', speed: 'fast' }, 'Láser Azul Industrial': { color: '#00ffff', name: '🔵 Industrial Blue Laser', particles: 'electric', speed: 'medium' }, 'Láser Verde Militar': { color: '#00ff00', name: '🟢 Military Green Laser', particles: 'smoke', speed: 'precise' }, 'Plasma Púrpura': { color: '#ff00ff', name: '🟣 Purple Plasma Beam', particles: 'energy', speed: 'slow' }, 'Láser Dorado Épico': { color: '#ffd700', name: '🟡 Epic Golden Laser', particles: 'golden', speed: 'instant' } }; /* ---------- VARIABLES GLOBALES ---------- */ let canvas, ctx, socket; let currentLaserMode = 'Láser Rojo Clásico'; let laserIntensity = 3; let isDestroying = false; let drawingPixels = []; // Almacena píxeles dibujados capturados let sampleRate = 4; // Rate de muestreo para reducir píxeles por rendimiento let originalWebSocketSend; /* ---------- SISTEMA DE CAPTURA DE PÍXELES ---------- */ function captureDrawingPixels() { if (!canvas || !ctx) { console.warn("Canvas no encontrado o no inicializado"); return false; } const cw = canvas.width; const ch = canvas.height; const imageData = ctx.getImageData(0, 0, cw, ch); const data = imageData.data; drawingPixels = []; // Usar la misma lógica que GenerativeAnimatorTool for (let y = 0; y < ch; y += sampleRate) { for (let x = 0; x < cw; x += sampleRate) { const i = (y * cw + x) * 4; // Un píxel se considera "dibujado" si no es totalmente transparente (alpha > 100) // Y si no es un blanco casi puro (R, G, B < 250) if (data[i + 3] > 100 && (data[i] < 250 || data[i + 1] < 250 || data[i + 2] < 250)) { drawingPixels.push({ x: x, y: y, normalizedX: x / cw, normalizedY: y / ch, color: `rgb(${data[i]},${data[i + 1]},${data[i + 2]})`, r: data[i], g: data[i + 1], b: data[i + 2], a: data[i + 3] }); } } } console.log(`🎨 Píxeles capturados: ${drawingPixels.length} puntos detectados`); return drawingPixels.length > 0; } /* ---------- FUNCIONES AUXILIARES DE WEBSOCKET ---------- */ function initializeWebSocketInterceptor() { originalWebSocketSend = WebSocket.prototype.send; WebSocket.prototype.send = function (data) { if (!socket) socket = this; return originalWebSocketSend.call(this, data); }; } function getGameSocket() { return socket; } function sendLaserToServer(x1, y1, x2, y2, color, thickness) { if (!socket || !canvas) return; const normX1 = (x1 / canvas.width).toFixed(4); const normY1 = (y1 / canvas.height).toFixed(4); const normX2 = (x2 / canvas.width).toFixed(4); const normY2 = (y2 / canvas.height).toFixed(4); const cmd = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${thickness},"${color}",0,0,{}]]`; originalWebSocketSend.call(socket, cmd); } function sendEraseCommand(x, y, size) { if (!socket || !canvas) return; const normX1 = ((x - size) / canvas.width).toFixed(4); const normY1 = ((y - size) / canvas.height).toFixed(4); const normX2 = ((x + size) / canvas.width).toFixed(4); const normY2 = ((y + size) / canvas.height).toFixed(4); const eraseCmd = `42["drawcmd",0,[${normX1},${normY1},${normX2},${normY2},false,${-(size * 2)},"#000000",0,0,{}]]`; originalWebSocketSend.call(socket, eraseCmd); } /* ---------- EFECTOS VISUALES DEL LÁSER ---------- */ function drawLaserBeam(startX, startY, endX, endY, laserColor, intensity = 3) { if (!ctx) return; // Núcleo brillante del láser ctx.strokeStyle = '#ffffff'; ctx.lineWidth = 3 + intensity; ctx.lineCap = 'round'; ctx.shadowBlur = 15; ctx.shadowColor = laserColor; ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(endX, endY); ctx.stroke(); // Halo exterior ctx.strokeStyle = laserColor; ctx.lineWidth = 8 + intensity * 2; ctx.shadowBlur = 25; ctx.globalAlpha = 0.8; ctx.beginPath(); ctx.moveTo(startX, startY); ctx.lineTo(endX, endY); ctx.stroke(); // Limpiar efectos ctx.shadowBlur = 0; ctx.globalAlpha = 1.0; // Enviar al servidor sendLaserToServer(startX, startY, endX, endY, laserColor, 8 + intensity * 2); } function createVaporizationParticles(x, y, originalPixel, particleType) { if (!ctx) return; const particleCount = 8 + laserIntensity * 2; let particleColors; switch (particleType) { case 'fire': particleColors = ['#ff4500', '#ff6600', '#ffa500', '#ff0000']; break; case 'electric': particleColors = ['#00ffff', '#87ceeb', '#ffffff', '#add8e6']; break; case 'smoke': particleColors = ['#696969', '#808080', '#a0a0a0', '#778899']; break; case 'energy': particleColors = ['#ff00ff', '#ff69b4', '#da70d6', '#dda0dd']; break; case 'golden': particleColors = ['#ffd700', '#ffdf00', '#fff700', '#f0e68c']; break; default: particleColors = [originalPixel.color, '#ffffff', '#f0f0f0']; } for (let i = 0; i < particleCount; i++) { setTimeout(() => { const angle = (Math.PI * 2 * i) / particleCount + Math.random() * 0.5; const distance = 15 + Math.random() * 25; const particleX = x + distance * Math.cos(angle); const particleY = y + distance * Math.sin(angle); const color = particleColors[Math.floor(Math.random() * particleColors.length)]; // Dibujar partícula local ctx.fillStyle = color; ctx.shadowBlur = 8; ctx.shadowColor = color; ctx.globalAlpha = 0.8; ctx.fillRect(particleX - 2, particleY - 2, 4, 4); ctx.globalAlpha = 1.0; ctx.shadowBlur = 0; // Enviar partícula al servidor sendLaserToServer(x, y, particleX, particleY, color, 3); }, i * 30); } } function createPixelShockwave(x, y, intensity) { if (!ctx) return; const maxRadius = 30 + intensity * 8; let currentRadius = 0; const shockwaveInterval = setInterval(() => { currentRadius += 4; if (currentRadius > maxRadius) { clearInterval(shockwaveInterval); return; } const alpha = 1 - (currentRadius / maxRadius); const color = LASER_MODES[currentLaserMode].color; ctx.strokeStyle = color; ctx.lineWidth = 2; ctx.globalAlpha = alpha * 0.6; ctx.shadowBlur = 8; ctx.shadowColor = color; ctx.beginPath(); ctx.arc(x, y, currentRadius, 0, Math.PI * 2); ctx.stroke(); ctx.globalAlpha = 1.0; ctx.shadowBlur = 0; }, 50); } /* ---------- SISTEMA DE DESTRUCCIÓN LÁSER POR PÍXELES ---------- */ async function laserDestroyPixels() { if (isDestroying) { console.log('🚫 Ya hay una destrucción en curso'); return; } // Capturar píxeles actuales const captured = captureDrawingPixels(); if (!captured || drawingPixels.length === 0) { alert('🚫 No hay píxeles dibujados para destruir. ¡Dibuja algo primero!'); return; } if (!getGameSocket()) { alert('🚫 No hay conexión WebSocket. Conéctate a una sala primero.'); return; } isDestroying = true; console.log(`🔫 Iniciando destrucción láser de ${drawingPixels.length} píxeles`); const laserMode = LASER_MODES[currentLaserMode]; const pixelsCopy = [...drawingPixels]; // Agrupar píxeles cercanos para mayor eficiencia const pixelGroups = groupNearbyPixels(pixelsCopy, 20); console.log(`📊 ${pixelsCopy.length} píxeles agrupados en ${pixelGroups.length} grupos`); // Configurar velocidad según el modo let destroySpeed; switch (laserMode.speed) { case 'instant': destroySpeed = 30; break; case 'fast': destroySpeed = 80; break; case 'medium': destroySpeed = 150; break; case 'precise': destroySpeed = 300; break; case 'slow': destroySpeed = 500; break; default: destroySpeed = 150; } for (let i = 0; i < pixelGroups.length; i++) { if (!isDestroying) break; const group = pixelGroups[i]; const centerPixel = group[Math.floor(group.length / 2)]; // Pixel central del grupo const targetX = centerPixel.x; const targetY = centerPixel.y; // Puntos de origen del láser (variados) const laserOrigins = [ { x: targetX + (Math.random() - 0.5) * 100, y: -30 }, // Desde arriba { x: -30, y: targetY + (Math.random() - 0.5) * 50 }, // Desde la izquierda { x: canvas.width + 30, y: targetY + (Math.random() - 0.5) * 50 }, // Desde la derecha { x: targetX + (Math.random() - 0.5) * 100, y: canvas.height + 30 } // Desde abajo ]; const origin = laserOrigins[i % laserOrigins.length]; // Efectos de pre-carga setTimeout(() => { if (!isDestroying) return; // Punto de carga del láser ctx.fillStyle = laserMode.color; ctx.shadowBlur = 15; ctx.shadowColor = laserMode.color; ctx.globalAlpha = 0.8; ctx.fillRect(origin.x - 2, origin.y - 2, 4, 4); ctx.globalAlpha = 1.0; ctx.shadowBlur = 0; }, i * destroySpeed); // Disparo del láser setTimeout(() => { if (!isDestroying) return; // Rayo láser principal drawLaserBeam(origin.x, origin.y, targetX, targetY, laserMode.color, laserIntensity); // Efectos de impacto createPixelShockwave(targetX, targetY, laserIntensity); createVaporizationParticles(targetX, targetY, centerPixel, laserMode.particles); }, i * destroySpeed + 100); // Borrado de píxeles del grupo setTimeout(() => { if (!isDestroying) return; // Borrar cada píxel del grupo group.forEach(pixel => { // Borrar localmente ctx.globalCompositeOperation = 'destination-out'; ctx.fillStyle = '#000000'; ctx.fillRect(pixel.x - 2, pixel.y - 2, 4, 4); ctx.globalCompositeOperation = 'source-over'; }); // Enviar comando de borrado al servidor para el grupo const eraseSize = Math.max(4, group.length / 3); sendEraseCommand(targetX, targetY, eraseSize); }, i * destroySpeed + 250); } // Finalizar destrucción setTimeout(() => { drawingPixels = []; isDestroying = false; console.log('🔥 ¡Destrucción por píxeles completada!'); }, pixelGroups.length * destroySpeed + 1000); } function groupNearbyPixels(pixels, maxDistance) { const groups = []; const used = new Set(); pixels.forEach((pixel, index) => { if (used.has(index)) return; const group = [pixel]; used.add(index); // Buscar píxeles cercanos for (let i = index + 1; i < pixels.length; i++) { if (used.has(i)) continue; const otherPixel = pixels[i]; const distance = Math.sqrt( Math.pow(pixel.x - otherPixel.x, 2) + Math.pow(pixel.y - otherPixel.y, 2) ); if (distance <= maxDistance) { group.push(otherPixel); used.add(i); } } groups.push(group); }); return groups; } function stopDestruction() { isDestroying = false; console.log('🛑 Destrucción láser detenida por el usuario'); } /* ---------- INTERFAZ DE USUARIO ---------- */ function createLaserUI() { const container = document.createElement('div'); container.style.cssText = ` position: fixed; top: 10px; right: 10px; z-index: 9999; background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460); color: #fff; padding: 20px; border-radius: 15px; font-family: 'Orbitron', 'Segoe UI', Arial, sans-serif; font-size: 13px; display: flex; flex-direction: column; gap: 15px; box-shadow: 0 8px 25px rgba(0,0,0,0.8), inset 0 1px 0 rgba(255,255,255,0.1); border: 2px solid #ff6b35; min-width: 320px; backdrop-filter: blur(10px); `; // Título const title = document.createElement('div'); title.innerHTML = '🎨 PIXEL LASER DESTROYER 🔫'; title.style.cssText = ` font-weight: bold; font-size: 16px; text-align: center; cursor: grab; background: linear-gradient(45deg, #ff6b35, #f7931e, #ffcc02); -webkit-background-clip: text; -webkit-text-fill-color: transparent; text-shadow: 0 0 10px rgba(255, 107, 53, 0.5); margin: -20px -20px 10px -20px; padding: 20px; border-bottom: 2px solid rgba(255, 107, 53, 0.3); border-radius: 15px 15px 0 0; `; container.appendChild(title); // Estado de conexión const connectionStatus = document.createElement('div'); connectionStatus.style.cssText = ` background: rgba(255, 107, 53, 0.2); padding: 10px; border-radius: 8px; text-align: center; font-size: 12px; display: flex; align-items: center; gap: 8px; `; container.appendChild(connectionStatus); // Información de píxeles capturados const pixelInfo = document.createElement('div'); pixelInfo.style.cssText = ` background: rgba(0, 255, 255, 0.1); padding: 10px; border-radius: 8px; text-align: center; font-size: 14px; font-weight: bold; `; container.appendChild(pixelInfo); // Botón de captura manual const captureBtn = document.createElement('button'); captureBtn.textContent = '📷 Scan Drawing Pixels'; captureBtn.style.cssText = ` padding: 12px 15px; border-radius: 8px; border: none; font-size: 14px; background: linear-gradient(145deg, #00ffff, #0080ff); color: #000; font-weight: bold; cursor: pointer; transition: all 0.3s ease; `; captureBtn.addEventListener('click', () => { const captured = captureDrawingPixels(); if (captured) { console.log(`📷 Captura manual: ${drawingPixels.length} píxeles detectados`); } }); container.appendChild(captureBtn); // Selector de modo láser const modeRow = createControlRow('🎯 Laser Mode:'); const modeSelect = document.createElement('select'); modeSelect.style.cssText = getSelectStyle(); Object.keys(LASER_MODES).forEach(modeName => { const option = document.createElement('option'); option.value = modeName; option.textContent = LASER_MODES[modeName].name; modeSelect.appendChild(option); }); modeSelect.value = currentLaserMode; modeSelect.addEventListener('change', (e) => { currentLaserMode = e.target.value; console.log(`🔫 Modo láser: ${currentLaserMode}`); }); modeRow.appendChild(modeSelect); container.appendChild(modeRow); // Control de intensidad const intensityRow = createControlRow('⚡ Power:'); const intensitySlider = document.createElement('input'); intensitySlider.type = 'range'; intensitySlider.min = '1'; intensitySlider.max = '5'; intensitySlider.value = laserIntensity.toString(); intensitySlider.style.cssText = getSliderStyle(); intensitySlider.addEventListener('input', (e) => { laserIntensity = parseInt(e.target.value); }); intensityRow.appendChild(intensitySlider); container.appendChild(intensityRow); // Control de sample rate const sampleRow = createControlRow('🔍 Quality:'); const sampleSlider = document.createElement('input'); sampleSlider.type = 'range'; sampleSlider.min = '1'; sampleSlider.max = '8'; sampleSlider.value = sampleRate.toString(); sampleSlider.style.cssText = getSliderStyle(); sampleSlider.addEventListener('input', (e) => { sampleRate = parseInt(e.target.value); console.log(`🔍 Sample rate: ${sampleRate} (menor = más píxeles)`); }); sampleRow.appendChild(sampleSlider); container.appendChild(sampleRow); // Botón principal de destrucción const destroyBtn = document.createElement('button'); destroyBtn.textContent = '🔥 VAPORIZE ALL PIXELS 🔥'; destroyBtn.style.cssText = ` padding: 15px 20px; border-radius: 10px; border: none; font-size: 16px; background: linear-gradient(145deg, #ff6b35, #f7931e); color: white; font-weight: bold; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 6px 20px rgba(255, 107, 53, 0.4); text-transform: uppercase; `; destroyBtn.addEventListener('click', laserDestroyPixels); container.appendChild(destroyBtn); // Botón de parada const stopBtn = document.createElement('button'); stopBtn.textContent = '🛑 STOP VAPORIZATION'; stopBtn.style.cssText = ` padding: 12px 18px; border-radius: 8px; border: none; font-size: 14px; background: linear-gradient(145deg, #ff1744, #d50000); color: white; font-weight: bold; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(255, 23, 68, 0.4); `; stopBtn.addEventListener('click', stopDestruction); container.appendChild(stopBtn); // Botón para limpiar píxeles const clearBtn = document.createElement('button'); clearBtn.textContent = '🗑️ Clear Pixel Memory'; clearBtn.style.cssText = ` padding: 10px 15px; border-radius: 8px; border: none; font-size: 12px; background: linear-gradient(145deg, #666, #444); color: white; cursor: pointer; transition: all 0.3s ease; `; clearBtn.addEventListener('click', () => { drawingPixels = []; console.log('🗑️ Memoria de píxeles limpiada'); }); container.appendChild(clearBtn); document.body.appendChild(container); makeDraggable(container, title); // Actualizar información periódicamente setInterval(() => { const isConnected = getGameSocket() !== null; connectionStatus.innerHTML = ` <span style="width: 12px; height: 12px; border-radius: 50%; background: ${isConnected ? '#00ff00' : '#ff0000'}; display: inline-block;"></span> <span>WebSocket: ${isConnected ? 'Connected' : 'Disconnected'}</span> `; pixelInfo.innerHTML = ` 📊 Detected Pixels: <span style="color: #ff6b35;">${drawingPixels.length}</span><br> 🔍 Sample Rate: ${sampleRate} | ⚡ Power: ${laserIntensity}<br> 💡 Draw something, then VAPORIZE! `; }, 1000); } function createControlRow(label) { const row = document.createElement('div'); row.style.cssText = 'display: flex; align-items: center; gap: 12px;'; const labelEl = document.createElement('span'); labelEl.textContent = label; labelEl.style.cssText = 'color: #ff6b35; font-weight: bold; min-width: 110px;'; row.appendChild(labelEl); return row; } function getSelectStyle() { return ` flex-grow: 1; padding: 8px 12px; border-radius: 8px; border: 2px solid #ff6b35; background: rgba(20, 20, 40, 0.8); color: #ff6b35; font-size: 13px; cursor: pointer; `; } function getSliderStyle() { return ` flex-grow: 1; -webkit-appearance: none; height: 6px; border-radius: 5px; background: linear-gradient(to right, #ff6b35 0%, #f7931e 100%); `; } function makeDraggable(container, handle) { let isDragging = false; let dragOffsetX = 0; let dragOffsetY = 0; handle.addEventListener('mousedown', (e) => { isDragging = true; dragOffsetX = e.clientX - container.offsetLeft; dragOffsetY = e.clientY - container.offsetTop; handle.style.cursor = 'grabbing'; }); document.addEventListener('mousemove', (e) => { if (isDragging) { container.style.left = (e.clientX - dragOffsetX) + 'px'; container.style.top = (e.clientY - dragOffsetY) + 'px'; container.style.right = 'auto'; } }); document.addEventListener('mouseup', () => { isDragging = false; handle.style.cursor = 'grab'; }); } /* ---------- INICIALIZACIÓN ---------- */ function initialize() { console.log('🎨 Iniciando Pixel Laser Destroyer...'); const checkCanvas = setInterval(() => { canvas = document.getElementById('canvas'); ctx = canvas ? canvas.getContext('2d') : null; if (canvas && ctx) { clearInterval(checkCanvas); initializeWebSocketInterceptor(); createLaserUI(); console.log('🔫 Pixel Laser Destroyer listo!'); console.log('🎨 Dibuja algo, luego usa VAPORIZE ALL PIXELS'); console.log('📷 El script detecta píxeles automáticamente usando getImageData()'); } }, 500); } // Inicializar cuando la página esté lista if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize); } else { initialize(); } })();