Fix Tetris 2P preview block synchronization issue
- Prevent duplicate piece shapes when generating next pieces - Enhanced randomTetromino() with excludeShape parameter - Update piece placement logic to avoid visual duplicates - Improve initial state generation for both players - Add P1 and P2 next piece previews in 2P mode
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import { useRef, useCallback } from 'react';
|
||||
|
||||
interface PerformanceMetrics {
|
||||
frameRate: number;
|
||||
memoryUsage?: number;
|
||||
renderTime: number;
|
||||
dropCount: number;
|
||||
}
|
||||
|
||||
export function usePerformanceMonitor() {
|
||||
const frameCount = useRef(0);
|
||||
const lastTime = useRef(performance.now());
|
||||
const dropCount = useRef(0);
|
||||
const renderTimes = useRef<number[]>([]);
|
||||
const maxRenderTimeSamples = 60; // Keep last 60 frames
|
||||
|
||||
const recordFrame = useCallback(() => {
|
||||
const now = performance.now();
|
||||
const deltaTime = now - lastTime.current;
|
||||
|
||||
frameCount.current++;
|
||||
|
||||
// Track render time
|
||||
renderTimes.current.push(deltaTime);
|
||||
if (renderTimes.current.length > maxRenderTimeSamples) {
|
||||
renderTimes.current.shift();
|
||||
}
|
||||
|
||||
// Detect frame drops (should be ~16.67ms for 60fps)
|
||||
if (deltaTime > 20) { // Allow some tolerance
|
||||
dropCount.current++;
|
||||
}
|
||||
|
||||
lastTime.current = now;
|
||||
|
||||
// Calculate metrics every second
|
||||
if (frameCount.current % 60 === 0) {
|
||||
const avgRenderTime = renderTimes.current.reduce((a, b) => a + b, 0) / renderTimes.current.length;
|
||||
const fps = 1000 / avgRenderTime;
|
||||
|
||||
const metrics: PerformanceMetrics = {
|
||||
frameRate: fps,
|
||||
memoryUsage: (performance as any).memory ?
|
||||
Math.round((performance as any).memory.usedJSHeapSize / (1024 * 1024)) : undefined,
|
||||
renderTime: avgRenderTime,
|
||||
dropCount: dropCount.current
|
||||
};
|
||||
|
||||
// Log performance warnings
|
||||
if (fps < 30) {
|
||||
console.warn(`⚠️ Low FPS: ${fps.toFixed(1)}, Drops: ${dropCount.current}, Memory: ${metrics.memoryUsage}MB`);
|
||||
}
|
||||
|
||||
if (metrics.memoryUsage && metrics.memoryUsage > 2000) { // > 2GB
|
||||
console.warn(`⚠️ High memory usage: ${metrics.memoryUsage}MB, FPS: ${fps.toFixed(1)}`);
|
||||
}
|
||||
|
||||
return metrics;
|
||||
}
|
||||
|
||||
return null;
|
||||
}, []);
|
||||
|
||||
const reset = useCallback(() => {
|
||||
frameCount.current = 0;
|
||||
lastTime.current = performance.now();
|
||||
dropCount.current = 0;
|
||||
renderTimes.current = [];
|
||||
}, []);
|
||||
|
||||
const getCurrentMetrics = useCallback((): PerformanceMetrics => {
|
||||
const avgRenderTime = renderTimes.current.length > 0
|
||||
? renderTimes.current.reduce((a, b) => a + b, 0) / renderTimes.current.length
|
||||
: 16.67; // Default for 60fps
|
||||
|
||||
return {
|
||||
frameRate: 1000 / avgRenderTime,
|
||||
memoryUsage: (performance as any).memory ?
|
||||
Math.round((performance as any).memory.usedJSHeapSize / (1024 * 1024)) : undefined,
|
||||
renderTime: avgRenderTime,
|
||||
dropCount: dropCount.current
|
||||
};
|
||||
}, []);
|
||||
|
||||
return {
|
||||
recordFrame,
|
||||
reset,
|
||||
getCurrentMetrics
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user