您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Kour.io (canvas/WebGL) için basit motion blur / frame trail overlay. press M for open, wirh +/- change the power
// ==UserScript== // @name Kour.io Motion Blur (Trail) // @namespace http://tampermonkey.net/ // @version 1.0 // @description Kour.io (canvas/WebGL) için basit motion blur / frame trail overlay. press M for open, wirh +/- change the power // @author ChatGPT // @match https://kour.io/* // @grant GM_registerMenuCommand // @run-at document-idle // ==/UserScript== (function () { 'use strict'; // ---------------------------- // Ayarlar (istediğiniz gibi değiştirin) // ---------------------------- let enabled = true; // başlangıçta açık mu? let decay = 0.12; // fade miktarı; küçük => daha uzun iz (0.02..0.3 arası uygun) let maxCanvasSearchAttempts = 20; // sayfa yüklenince canvas bulunana kadar deneme sayısı let searchIntervalMs = 500; // ---------------------------- let targetCanvas = null; let overlay = null; let accCanvas = null; let rafId = null; let lastWidth = 0, lastHeight = 0; function findLargestCanvas() { const canvases = Array.from(document.querySelectorAll('canvas')); if (canvases.length === 0) return null; // alanına göre en büyüğü seç canvases.sort((a, b) => (b.width * b.height) - (a.width * a.height)); return canvases[0]; } function createOverlayFor(canvas) { const rect = canvas.getBoundingClientRect(); const w = canvas.width || Math.max(1, Math.round(rect.width)); const h = canvas.height || Math.max(1, Math.round(rect.height)); // accumulation canvas (offscreen) accCanvas = document.createElement('canvas'); accCanvas.width = w; accCanvas.height = h; const accCtx = accCanvas.getContext('2d', { alpha: true }); // visible overlay overlay = document.createElement('canvas'); overlay.width = w; overlay.height = h; overlay.style.position = 'absolute'; overlay.style.left = rect.left + 'px'; overlay.style.top = rect.top + 'px'; overlay.style.pointerEvents = 'none'; overlay.style.zIndex = 999999; // üstte görünsün overlay.style.mixBlendMode = 'normal'; // isterseniz 'screen' veya 'lighter' deneyin overlay.style.imageRendering = 'auto'; document.body.appendChild(overlay); // handle resizing / repositioning function syncSizePos() { const r = canvas.getBoundingClientRect(); const newW = canvas.width || Math.max(1, Math.round(r.width)); const newH = canvas.height || Math.max(1, Math.round(r.height)); if (overlay.width !== newW || overlay.height !== newH) { overlay.width = newW; accCanvas.width = newW; } if (overlay.height !== newH || overlay.width !== newW) { overlay.height = newH; accCanvas.height = newH; } overlay.style.left = r.left + 'px'; overlay.style.top = r.top + 'px'; overlay.style.width = r.width + 'px'; overlay.style.height = r.height + 'px'; } window.addEventListener('resize', syncSizePos); // MutationObserver to keep position synced if canvas moves in DOM const mo = new MutationObserver(syncSizePos); mo.observe(document.body, { attributes: true, childList: true, subtree: true }); return { accCanvas, overlay, accCtx, syncSizePos, mo }; } function startLoop() { if (!targetCanvas || !overlay || !accCanvas) return; const accCtx = accCanvas.getContext('2d', { alpha: true }); const overCtx = overlay.getContext('2d', { alpha: true }); function frame() { if (!enabled) { rafId = requestAnimationFrame(frame); return; } // fade accumulation slightly (draw a semi-opaque rect to dim previous content) accCtx.fillStyle = `rgba(0,0,0,${decay})`; accCtx.fillRect(0, 0, accCanvas.width, accCanvas.height); // draw current game frame onto accumulation canvas try { // drawImage from target canvas (same-origin expected) accCtx.drawImage(targetCanvas, 0, 0, accCanvas.width, accCanvas.height); } catch (e) { // drawImage hata veriyorsa (ör. cross-origin), dur ve temizle console.warn('MotionBlur: drawImage failed (cross-origin?). Disabling effect.', e); stop(); return; } // copy accumulation to overlay (clear then draw) overCtx.clearRect(0, 0, overlay.width, overlay.height); overCtx.drawImage(accCanvas, 0, 0, overlay.width, overlay.height); rafId = requestAnimationFrame(frame); } if (!rafId) frame(); } function stop() { if (rafId) cancelAnimationFrame(rafId); rafId = null; if (overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay); if (accCanvas) accCanvas = null; overlay = null; } function enableEffect() { if (!targetCanvas) return; if (!overlay || !accCanvas) { const created = createOverlayFor(targetCanvas); accCanvas = created.accCanvas; overlay = created.overlay; } startLoop(); } function disableEffect() { stop(); } // keyboard controls: M toggle, +/- adjust decay (motion strength) function keyHandler(e) { if (e.key === 'm' || e.key === 'M') { enabled = !enabled; if (enabled) enableEffect(); else disableEffect(); showToast(`Motion blur ${enabled ? 'Açıldı' : 'Kapandı'}. decay=${decay.toFixed(3)}`); } else if (e.key === '+') { // daha güçlü iz = daha küçük decay decay = Math.max(0.01, decay - 0.02); showToast(`Decay: ${decay.toFixed(3)}`); } else if (e.key === '-') { decay = Math.min(0.6, decay + 0.02); showToast(`Decay: ${decay.toFixed(3)}`); } } function showToast(msg, duration = 1500) { let el = document.getElementById('tm-mblur-toast'); if (!el) { el = document.createElement('div'); el.id = 'tm-mblur-toast'; Object.assign(el.style, { position: 'fixed', right: '12px', bottom: '12px', padding: '8px 12px', background: 'rgba(0,0,0,0.7)', color: 'white', fontSize: '13px', borderRadius: '6px', zIndex: 9999999, pointerEvents: 'none' }); document.body.appendChild(el); } el.textContent = msg; el.style.opacity = '1'; clearTimeout(el._hideT); el._hideT = setTimeout(() => { el.style.transition = 'opacity 400ms'; el.style.opacity = '0'; }, duration); } // Tampermonkey menu commands try { GM_registerMenuCommand && GM_registerMenuCommand('Toggle Motion Blur (M)', () => { enabled = !enabled; enabled ? enableEffect() : disableEffect(); }); GM_registerMenuCommand && GM_registerMenuCommand('Increase Blur (+)', () => { decay = Math.max(0.01, decay - 0.02); }); GM_registerMenuCommand && GM_registerMenuCommand('Decrease Blur (-)', () => { decay = Math.min(0.6, decay + 0.02); }); } catch (e) { /* ignore if not available */ } // Başlangıç: sayfadaki en büyük canvas'ı bulana kadar dene let attempts = 0; const finder = setInterval(() => { if (attempts++ > maxCanvasSearchAttempts) { clearInterval(finder); console.warn('MotionBlur: canvas bulunamadı.'); return; } const c = findLargestCanvas(); if (c) { clearInterval(finder); targetCanvas = c; // bazen oyun canvas boyutunu daha sonra ayarlıyor; overlay'i yaratmadan önce biraz bekleyebiliriz setTimeout(() => { enableEffect(); window.addEventListener('keydown', keyHandler); showToast('Motion Blur hazır. M ile aç/kapa, +/- ile güç ayarla.'); }, 300); } }, searchIntervalMs); })();