// FPS Monitor - Performance Tracking class FPSMonitor { constructor(scene) { this.scene = scene; this.fps = 60; this.avgFps = 60; this.minFps = 60; this.maxFps = 60; this.frameCount = 0; this.lastTime = performance.now(); this.fpsHistory = []; this.createDisplay(); } createDisplay() { const x = 10; const y = 10; // Background this.bg = this.scene.add.rectangle(x, y, 200, 120, 0x000000, 0.7); this.bg.setOrigin(0, 0); this.bg.setScrollFactor(0); this.bg.setDepth(10000); // Title this.titleText = this.scene.add.text(x + 100, y + 10, 'PERFORMANCE', { fontSize: '14px', fontFamily: 'Courier New', color: '#00ff41', fontStyle: 'bold' }); this.titleText.setOrigin(0.5, 0); this.titleText.setScrollFactor(0); this.titleText.setDepth(10001); // FPS Display this.fpsText = this.scene.add.text(x + 10, y + 35, 'FPS: 60', { fontSize: '16px', fontFamily: 'Courier New', color: '#00ff00' }); this.fpsText.setOrigin(0, 0); this.fpsText.setScrollFactor(0); this.fpsText.setDepth(10001); // Avg FPS this.avgText = this.scene.add.text(x + 10, y + 55, 'AVG: 60', { fontSize: '12px', fontFamily: 'Courier New', color: '#ffff00' }); this.avgText.setOrigin(0, 0); this.avgText.setScrollFactor(0); this.avgText.setDepth(10001); // Min/Max this.rangeText = this.scene.add.text(x + 10, y + 75, 'MIN: 60 | MAX: 60', { fontSize: '12px', fontFamily: 'Courier New', color: '#888888' }); this.rangeText.setOrigin(0, 0); this.rangeText.setScrollFactor(0); this.rangeText.setDepth(10001); // Memory (if available) this.memoryText = this.scene.add.text(x + 10, y + 95, 'MEM: --', { fontSize: '12px', fontFamily: 'Courier New', color: '#8888ff' }); this.memoryText.setOrigin(0, 0); this.memoryText.setScrollFactor(0); this.memoryText.setDepth(10001); console.log('📊 FPS Monitor initialized'); } update() { this.frameCount++; const currentTime = performance.now(); const deltaTime = currentTime - this.lastTime; // Update every 250ms if (deltaTime >= 250) { this.fps = Math.round((this.frameCount * 1000) / deltaTime); this.frameCount = 0; this.lastTime = currentTime; // Track history this.fpsHistory.push(this.fps); if (this.fpsHistory.length > 60) { this.fpsHistory.shift(); } // Calculate stats this.avgFps = Math.round( this.fpsHistory.reduce((a, b) => a + b, 0) / this.fpsHistory.length ); this.minFps = Math.min(...this.fpsHistory); this.maxFps = Math.max(...this.fpsHistory); // Update display this.updateDisplay(); } } updateDisplay() { // Color based on FPS let fpsColor = '#00ff00'; // Green if (this.fps < 60) fpsColor = '#ffff00'; // Yellow if (this.fps < 30) fpsColor = '#ff8800'; // Orange if (this.fps < 20) fpsColor = '#ff0000'; // Red this.fpsText.setText(`FPS: ${this.fps}`); this.fpsText.setColor(fpsColor); this.avgText.setText(`AVG: ${this.avgFps}`); this.rangeText.setText(`MIN: ${this.minFps} | MAX: ${this.maxFps}`); // Memory (Chrome only) if (performance.memory) { const usedMB = (performance.memory.usedJSHeapSize / 1048576).toFixed(1); const totalMB = (performance.memory.jsHeapSizeLimit / 1048576).toFixed(1); this.memoryText.setText(`MEM: ${usedMB}/${totalMB} MB`); } else { this.memoryText.setText('MEM: N/A'); } } toggle() { const visible = !this.bg.visible; this.bg.setVisible(visible); this.titleText.setVisible(visible); this.fpsText.setVisible(visible); this.avgText.setVisible(visible); this.rangeText.setVisible(visible); this.memoryText.setVisible(visible); } destroy() { this.bg.destroy(); this.titleText.destroy(); this.fpsText.destroy(); this.avgText.destroy(); this.rangeText.destroy(); this.memoryText.destroy(); } } // Export for use if (typeof module !== 'undefined') { module.exports = FPSMonitor; }