about summary refs log tree commit diff stats
path: root/html/rogue/js/rogue.js
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2024-12-24 15:53:19 -0500
committerelioat <elioat@tilde.institute>2024-12-24 15:53:19 -0500
commit8d4ebce0ef9eb7495e2b27a9a4df5f6001f7e65f (patch)
treed5a394ab15985715a70c1fb4ed8c4c09dcb65da4 /html/rogue/js/rogue.js
parentbb977cc4e502e3d35f3c82e1fca1a3535fda5e19 (diff)
downloadtour-8d4ebce0ef9eb7495e2b27a9a4df5f6001f7e65f.tar.gz
*
Diffstat (limited to 'html/rogue/js/rogue.js')
-rw-r--r--html/rogue/js/rogue.js134
1 files changed, 42 insertions, 92 deletions
diff --git a/html/rogue/js/rogue.js b/html/rogue/js/rogue.js
index b4379ea..75a4c86 100644
--- a/html/rogue/js/rogue.js
+++ b/html/rogue/js/rogue.js
@@ -3,11 +3,20 @@ window.gameState = null;
 const initGame = () => {
     const canvas = document.getElementById('gameCanvas');
     const ctx = canvas.getContext('2d');
+    
+    // Target frame rate
+    const FPS = 60;
+    const FRAME_TIME = 1000 / FPS;
+    let lastFrameTime = 0;
 
     // Set canvas to full viewport size
     const resizeCanvas = () => {
         canvas.width = window.innerWidth;
         canvas.height = window.innerHeight;
+        // Clear any cached gradients when resizing
+        if (window.gameState) {
+            window.gameState.cachedGradient = null;
+        }
     };
 
     window.addEventListener('resize', resizeCanvas);
@@ -16,7 +25,7 @@ const initGame = () => {
     // Game state
     let gameState = {
         time: 0,
-        player: createPlayer(100, 100), // Starting position
+        player: createPlayer(100, 100),
         camera: createCamera(0, 0),
         world: createWorld(),
         debug: {
@@ -29,42 +38,37 @@ const initGame = () => {
     // Make gameState globally accessible
     window.gameState = gameState;
 
-    // Throttle mouse move updates
-    let mouseMoveThrottle;
-    canvas.addEventListener('mousemove', (e) => {
-        if (!mouseMoveThrottle) {
-            mouseMoveThrottle = setTimeout(() => {
-                gameState.debug.mouseX = e.clientX + gameState.camera.x;
-                gameState.debug.mouseY = e.clientY + gameState.camera.y;
-                mouseMoveThrottle = null;
-            }, 16); // ~60fps
-        }
-    });
-
-    // Add debug toggle listener
-    window.addEventListener('keydown', (e) => {
-        if (e.key === 'd') {
-            gameState.debug.enabled = !gameState.debug.enabled;
-        }
-    });
+    // Set up input handlers
+    setupInputHandlers(canvas, gameState);
 
     // Game loop
     const gameLoop = (timestamp) => {
-        // Calculate delta time
-        const deltaTime = timestamp - gameState.time;
+        // Check if enough time has passed since last frame
+        if (timestamp - lastFrameTime < FRAME_TIME) {
+            requestAnimationFrame(gameLoop);
+            return;
+        }
+
+        // Calculate delta time (capped at 1 second to prevent huge jumps)
+        const deltaTime = Math.min(timestamp - lastFrameTime, 1000);
+        lastFrameTime = timestamp;
         gameState.time = timestamp;
 
+        // Clear the entire canvas
+        ctx.clearRect(0, 0, canvas.width, canvas.height);
+
         // Update
         gameState = updateGame(gameState, deltaTime);
 
         // Render
         render(ctx, gameState);
 
-        // Next frame
+        // Schedule next frame
         requestAnimationFrame(gameLoop);
     };
 
     // Start the game loop
+    lastFrameTime = performance.now();
     requestAnimationFrame(gameLoop);
 };
 
@@ -80,107 +84,53 @@ const updateGame = (state, deltaTime) => {
 };
 
 const render = (ctx, state) => {
-    // Calculate groundY once at the start
     const groundY = ctx.canvas.height - state.world.groundHeight;
 
-    // Create gradient for sky - cache this instead of recreating every frame
+    // Cache sky gradient
     if (!state.cachedGradient) {
-        const gradient = ctx.createLinearGradient(0, 0, 0, groundY);
-        gradient.addColorStop(0, '#1a1a2e');
-        gradient.addColorStop(0.4, '#2d1b3d');
-        gradient.addColorStop(0.7, '#462639');
-        gradient.addColorStop(1, '#1f1f2f');
-        state.cachedGradient = gradient;
+        state.cachedGradient = createSkyGradient(ctx, groundY);
     }
 
-    // Fill sky using cached gradient
-    ctx.fillStyle = state.cachedGradient;
-    ctx.fillRect(0, 0, ctx.canvas.width, groundY);
-    
-    // Implement view frustum culling - only render visible objects
-    const viewBounds = {
-        left: state.camera.x - 100, // Add small buffer
-        right: state.camera.x + state.camera.width + 100,
-        top: state.camera.y - 100,
-        bottom: state.camera.y + state.camera.height + 100
-    };
+    const viewBounds = getViewBounds(state.camera);
 
     // Apply camera transform
     ctx.save();
     ctx.translate(-state.camera.x, -state.camera.y);
 
-    // Fill black background
-    ctx.fillStyle = '#000000';
-    ctx.fillRect(
+    // Clear the transformed canvas area
+    ctx.clearRect(
         viewBounds.left,
-        groundY,
+        0,
         viewBounds.right - viewBounds.left,
         ctx.canvas.height
     );
 
-    // 1. Render only visible background objects
-    state.world.backgroundTrees.forEach(tree => {
-        if (tree.x > viewBounds.left && tree.x < viewBounds.right) {
-            renderTree(ctx, tree, groundY);
-        }
-    });
+    // Render layers
+    renderBackground(ctx, state, groundY, viewBounds);
+    renderBackgroundObjects(ctx, state, groundY, viewBounds);
     
-    state.world.backgroundRocks.forEach(rock => {
-        if (rock.x > viewBounds.left && rock.x < viewBounds.right) {
-            renderRock(ctx, rock, groundY);
-        }
-    });
-
-    state.world.backgroundGrass.forEach(grass => {
-        if (grass.x > viewBounds.left && grass.x < viewBounds.right) {
-            renderGrass(ctx, grass, groundY, state.time);
-        }
-    });
-    
-    // 2. Render platforms
+    // Render platforms
     state.world.platforms.forEach(platform => {
         ctx.fillStyle = platform.color;
         ctx.fillRect(platform.x, platform.y, platform.width, platform.height);
     });
 
-    // 3. Render player
     renderPlayer(ctx, state.player);
+    renderForegroundObjects(ctx, state, groundY, viewBounds);
 
-    // 4. Render foreground objects
-    state.world.foregroundTrees.forEach(tree => {
-        if (tree.x > viewBounds.left && tree.x < viewBounds.right) {
-            renderTree(ctx, tree, groundY);
-        }
-    });
-    
-    state.world.foregroundRocks.forEach(rock => {
-        if (rock.x > viewBounds.left && rock.x < viewBounds.right) {
-            renderRock(ctx, rock, groundY);
-        }
-    });
-
-    state.world.foregroundGrass.forEach(grass => {
-        if (grass.x > viewBounds.left && grass.x < viewBounds.right) {
-            renderGrass(ctx, grass, groundY, state.time);
-        }
-    });
-
-    // 5. Render ground (just the grass top)
-    ctx.fillStyle = '#4a4';
+    // Render ground line
+    ctx.fillStyle = RENDER_CONSTANTS.GROUND_COLOR;
     ctx.fillRect(
         state.camera.x - 1000,
         groundY,
         ctx.canvas.width + 2000,
-        1  // Only render the grass line
+        1
     );
 
-    // Render debug information if enabled
+    // Handle debug rendering
     if (state.debug.enabled) {
         ctx.restore();
-        ctx.fillStyle = '#ffffff';
-        ctx.font = '14px monospace';
-        const text = `x: ${Math.round(state.debug.mouseX)}, y: ${Math.round(state.debug.mouseY)}`;
-        ctx.fillText(text, 10, ctx.canvas.height - 20);
+        renderDebugInfo(ctx, state);
     } else {
         ctx.restore();
     }