// modules/core/frameloop.js import {Logger} from "./logger"; /** * @typedef {Object} FrameTaskOptions * @property {boolean} [autoStart=false] - Automatically start the frame loop */ /** @type {Map} */ const tasks = new Map(); /** @type {boolean} */ let running = false; /** @type {boolean} */ let showDebug = false; let lastTime = performance.now(); let frameCount = 0; let fps = 0; // Create debug overlay const debugOverlay = document.createElement('div'); debugOverlay.style.position = 'fixed'; debugOverlay.style.bottom = '0'; debugOverlay.style.left = '0'; debugOverlay.style.font = '12px monospace'; debugOverlay.style.color = '#0f0'; debugOverlay.style.background = 'rgba(0,0,0,0.75)'; debugOverlay.style.padding = '0.25rem 0.5rem'; debugOverlay.style.zIndex = '9999'; debugOverlay.style.pointerEvents = 'none'; debugOverlay.style.display = 'none'; const barWidth = Math.min(fps * 2, 100); const bar = `
`; debugOverlay.innerHTML += bar; debugOverlay.style.lineHeight = '1.4'; document.body.appendChild(debugOverlay); import { PerformanceMonitor } from './PerformanceMonitor.js'; /** @type {PerformanceMonitor} */ export const monitor = new PerformanceMonitor(); // Debug toggle with § key window.addEventListener('keydown', (e) => { if (e.key === '§') { showDebug = !showDebug; debugOverlay.style.display = showDebug ? 'block' : 'none'; } }); /** * Register a task to run on every frame * @param {string} id - Unique identifier for the task * @param {Function} callback - Function to execute each frame * @param {FrameTaskOptions} [options={}] - Task options */ export function registerFrameTask(id, callback, options = {}) { tasks.set(id, callback); if (options.autoStart && !running) startFrameLoop(); } /** * Unregister a frame task * @param {string} id - Task identifier to remove */ export function unregisterFrameTask(id) { tasks.delete(id); } /** * Clear all registered frame tasks */ export function clearFrameTasks() { tasks.clear(); } /** * Start the main frame loop */ export function startFrameLoop() { if (running) return; running = true; function loop() { for (const [id, task] of tasks) { try { if (showDebug) { monitor.trackTask(id, task); } else { task(); } } catch (err) { Logger.warn(`[Frameloop] Fehler in Task:`, err); } } if (showDebug) { monitor.update(tasks); } requestAnimationFrame(loop); } requestAnimationFrame(loop); } /** * Stop the frame loop * Note: Loop continues until next frame, this just sets the flag */ export function stopFrameLoop() { running = false; // Achtung: Loop läuft weiter, solange nicht aktiv gestoppt }