From 0a13dfc0a371d2a55d00882961d70702b1c16b59 Mon Sep 17 00:00:00 2001 From: "Kacper Kostka (aider)" Date: Sat, 5 Apr 2025 18:15:32 +0200 Subject: [PATCH] refactor: Optimize camera movement with chunk-aware smooth tracking --- js/entities/player.js | 49 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/js/entities/player.js b/js/entities/player.js index 09bea27..c1ee7ed 100644 --- a/js/entities/player.js +++ b/js/entities/player.js @@ -173,15 +173,48 @@ class Player extends Entity { } centerCamera() { - // Calculate the target world offset to center on player - const targetOffsetX = this.x - (canvas.width / PIXEL_SIZE / 2); - const targetOffsetY = this.y - (canvas.height / PIXEL_SIZE / 2); + // Get current camera center in world coordinates + const cameraWidth = canvas.width / PIXEL_SIZE; + const cameraHeight = canvas.height / PIXEL_SIZE; + const cameraCenterX = worldOffsetX + cameraWidth / 2; + const cameraCenterY = worldOffsetY + cameraHeight / 2; - // Smoothly move the camera to the target position (reduced smoothing factor) - worldOffsetX += (targetOffsetX - worldOffsetX) * 0.05; - worldOffsetY += (targetOffsetY - worldOffsetY) * 0.05; + // Calculate distance from player to camera center + const distanceX = Math.abs(this.x - cameraCenterX); + const distanceY = Math.abs(this.y - cameraCenterY); - // Mark that the world has moved for rendering - worldMoved = true; + // Define thresholds for camera movement (percentage of screen size) + const thresholdX = cameraWidth * 0.3; // Move when player is 30% away from center + const thresholdY = cameraHeight * 0.3; + + // Only move camera when player gets close to the edge of current view + let needsUpdate = false; + + if (distanceX > thresholdX) { + // Calculate target position with chunk-based snapping + const chunkSize = CHUNK_SIZE; + const playerChunkX = Math.floor(this.x / chunkSize); + const targetX = this.x - (canvas.width / PIXEL_SIZE / 2); + + // Smooth transition to the target position + worldOffsetX += (targetX - worldOffsetX) * 0.1; + needsUpdate = true; + } + + if (distanceY > thresholdY) { + // Calculate target position with chunk-based snapping + const chunkSize = CHUNK_SIZE; + const playerChunkY = Math.floor(this.y / chunkSize); + const targetY = this.y - (canvas.height / PIXEL_SIZE / 2); + + // Smooth transition to the target position + worldOffsetY += (targetY - worldOffsetY) * 0.1; + needsUpdate = true; + } + + // Only mark world as moved if we actually updated the camera + if (needsUpdate) { + worldMoved = true; + } } }