import { useGameStore } from '@/stores/gameStore' import { useWorldStore } from '@/stores/worldStore' import { usePlayerStore } from '@/stores/playerStore' import { TICK_DURATION_MS, MAX_TICKS } from '@/engine/constants' let lastTime = 0 let accumulatedTime = 0 let frameTime = 0 let tickTime = 0 let tickCount = 0 let frameCount = 0 let lastSecondTime = 0 /** * Main game loop that handles fixed timestep updates and rendering * @param timestamp Current timestamp from requestAnimationFrame */ function gameLoop(timestamp: number) { // Initialize time on first frame if (!lastTime) { lastTime = timestamp } // Calculate time differences const delta = timestamp - lastTime lastTime = timestamp accumulatedTime += delta // Update frame counter for FPS calculation frameCount++ frameTime += delta // Process game ticks at fixed intervals while (accumulatedTime >= TICK_DURATION_MS) { // Update game state updateGame() // Update tick counter for TPS calculation tickCount++ tickTime += TICK_DURATION_MS accumulatedTime -= TICK_DURATION_MS } // Calculate and update performance metrics updatePerformanceMetrics(timestamp) // Render the game renderGame() // Schedule next frame requestAnimationFrame(gameLoop) } /** * Update game state (fixed timestep) */ function updateGame() { const gameStore = useGameStore.getState() const worldStore = useWorldStore.getState() const playerStore = usePlayerStore.getState() // Skip updates if game is paused if (gameStore.paused) return // Update game tick counter gameStore.actions.incrementTick() // Update world time worldStore.actions.updateWorldTime() // Update player position and physics updatePlayerPhysics() // Update entities updateEntities() // Update scheduled block ticks updateScheduledTicks() // Update random block ticks updateRandomTicks() } /** * Update player physics and movement */ function updatePlayerPhysics() { const playerStore = usePlayerStore.getState() const player = playerStore.player if (!player) return // Apply gravity player.velocity[1] += -32 * (TICK_DURATION_MS / 1000) // Apply movement // This is a simplified version - actual implementation would handle input and collision detection player.position[0] += player.velocity[0] * (TICK_DURATION_MS / 1000) player.position[1] += player.velocity[1] * (TICK_DURATION_MS / 1000) player.position[2] += player.velocity[2] * (TICK_DURATION_MS / 1000) // Update player state playerStore.actions.updatePosition(player.position) } /** * Update all entities in the world */ function updateEntities() { // Implementation would iterate through all entities and update their state // including AI, physics, and animations } /** * Process scheduled block ticks */ function updateScheduledTicks() { // Implementation would handle scheduled block updates like redstone ticks } /** * Process random block ticks (like plant growth) */ function updateRandomTicks() { // Implementation would handle random block updates based on world's randomTickSpeed } /** * Render the game scene */ function renderGame() { // Implementation would handle rendering with Three.js // including camera updates, chunk rendering, and UI } /** * Update performance metrics (FPS, TPS) * @param timestamp Current timestamp */ function updatePerformanceMetrics(timestamp: number) { // Calculate FPS and TPS if (timestamp - lastSecondTime >= 1000) { const fps = frameCount / (frameTime / 1000) const tps = tickCount / (tickTime / 1000) useGameStore.getState().actions.updatePerformance({ averageFPS: fps, averageTPS: tps, }) // Update debug UI useUIStore.getState().actions.updateDebugInfo({ fps: Math.round(fps), tps: Math.round(tps), }) // Reset counters frameCount = 0 frameTime = 0 tickCount = 0 tickTime = 0 lastSecondTime = timestamp } } /** * Start the game loop */ export function startGameLoop() { requestAnimationFrame(gameLoop) }