about summary refs log tree commit diff stats
path: root/html/rogue/js
diff options
context:
space:
mode:
Diffstat (limited to 'html/rogue/js')
-rw-r--r--html/rogue/js/camera.js56
-rw-r--r--html/rogue/js/player.js64
-rw-r--r--html/rogue/js/rogue.js108
-rw-r--r--html/rogue/js/world.js236
4 files changed, 464 insertions, 0 deletions
diff --git a/html/rogue/js/camera.js b/html/rogue/js/camera.js
new file mode 100644
index 0000000..e5d5d14
--- /dev/null
+++ b/html/rogue/js/camera.js
@@ -0,0 +1,56 @@
+const createCamera = (x, y) => ({
+    x,
+    y,
+    width: window.innerWidth,
+    height: window.innerHeight,
+    // Define the dead zone (the area where camera won't move)
+    deadZone: {
+        x: window.innerWidth * 0.3, // 30% of screen width
+        y: window.innerHeight * 0.3, // 30% of screen height
+    }
+});
+
+const updateCamera = (camera, target) => {
+    // Calculate the center point of the screen
+    const screenCenterX = camera.x + camera.width / 2;
+    const screenCenterY = camera.y + camera.height / 2;
+
+    // Calculate the distance from the target to the screen center
+    const distanceX = target.x - screenCenterX;
+    const distanceY = target.y - screenCenterY;
+
+    // Calculate the dead zone boundaries
+    const deadZoneLeft = -camera.deadZone.x / 2;
+    const deadZoneRight = camera.deadZone.x / 2;
+    const deadZoneTop = -camera.deadZone.y / 2;
+    const deadZoneBottom = camera.deadZone.y / 2;
+
+    // Calculate new camera position with smooth following
+    let newX = camera.x;
+    let newY = camera.y;
+
+    // Horizontal camera movement
+    if (distanceX < deadZoneLeft) {
+        newX += distanceX - deadZoneLeft;
+    } else if (distanceX > deadZoneRight) {
+        newX += distanceX - deadZoneRight;
+    }
+
+    // Vertical camera movement
+    if (distanceY < deadZoneTop) {
+        newY += distanceY - deadZoneTop;
+    } else if (distanceY > deadZoneBottom) {
+        newY += distanceY - deadZoneBottom;
+    }
+
+    // Add subtle smoothing to camera movement
+    const smoothing = 0.1;
+    newX = camera.x + (newX - camera.x) * smoothing;
+    newY = camera.y + (newY - camera.y) * smoothing;
+
+    return {
+        ...camera,
+        x: newX,
+        y: newY
+    };
+};
diff --git a/html/rogue/js/player.js b/html/rogue/js/player.js
index e69de29..270b26f 100644
--- a/html/rogue/js/player.js
+++ b/html/rogue/js/player.js
@@ -0,0 +1,64 @@
+const createPlayer = (x, y) => ({
+    x,
+    y,
+    width: 32,
+    height: 32,
+    velocityX: 0,
+    velocityY: 0,
+    speed: 300,
+    jumping: false
+});
+
+const updatePlayer = (player, deltaTime) => {
+    const keys = getKeys();
+    const seconds = deltaTime / 1000;
+
+    let velocityX = 0;
+    let velocityY = player.velocityY;
+
+    // Horizontal movement
+    if (keys.ArrowLeft) velocityX -= player.speed;
+    if (keys.ArrowRight) velocityX += player.speed;
+
+    // Simple jumping (can be improved)
+    if (keys.ArrowUp && !player.jumping) {
+        velocityY = -500;
+    }
+
+    // Apply gravity
+    velocityY += 980 * seconds; // 980 pixels/secondĀ²
+
+    // Update position
+    const x = player.x + velocityX * seconds;
+    const y = player.y + velocityY * seconds;
+
+    // Create updated player state
+    let updatedPlayer = {
+        ...player,
+        x,
+        y,
+        velocityX,
+        velocityY
+    };
+
+    // Handle collisions with the world
+    return handleWorldCollisions(updatedPlayer, window.gameState.world);
+};
+
+const renderPlayer = (ctx, player) => {
+    ctx.fillStyle = '#f00';
+    ctx.fillRect(player.x, player.y, player.width, player.height);
+};
+
+// Key handling
+const keys = {};
+
+window.addEventListener('keydown', (e) => {
+    keys[e.key] = true;
+});
+
+window.addEventListener('keyup', (e) => {
+    keys[e.key] = false;
+});
+
+const getKeys = () => ({...keys});
diff --git a/html/rogue/js/rogue.js b/html/rogue/js/rogue.js
index e69de29..8276d8d 100644
--- a/html/rogue/js/rogue.js
+++ b/html/rogue/js/rogue.js
@@ -0,0 +1,108 @@
+window.gameState = null;
+
+const initGame = () => {
+    const canvas = document.getElementById('gameCanvas');
+    const ctx = canvas.getContext('2d');
+
+    // Set canvas to full viewport size
+    const resizeCanvas = () => {
+        canvas.width = window.innerWidth;
+        canvas.height = window.innerHeight;
+    };
+
+    window.addEventListener('resize', resizeCanvas);
+    resizeCanvas();
+
+    // Game state
+    let gameState = {
+        time: 0,
+        player: createPlayer(100, 100), // Starting position
+        camera: createCamera(0, 0),
+        world: createWorld()
+    };
+    
+    // Make gameState globally accessible
+    window.gameState = gameState;
+
+    // Game loop
+    const gameLoop = (timestamp) => {
+        // Calculate delta time
+        const deltaTime = timestamp - gameState.time;
+        gameState.time = timestamp;
+
+        // Update
+        gameState = updateGame(gameState, deltaTime);
+
+        // Render
+        render(ctx, gameState);
+
+        // Next frame
+        requestAnimationFrame(gameLoop);
+    };
+
+    // Start the game loop
+    requestAnimationFrame(gameLoop);
+};
+
+const updateGame = (state, deltaTime) => {
+    const updatedPlayer = updatePlayer(state.player, deltaTime);
+    const updatedCamera = updateCamera(state.camera, updatedPlayer);
+
+    return {
+        ...state,
+        player: updatedPlayer,
+        camera: updatedCamera
+    };
+};
+
+const render = (ctx, state) => {
+    // Clear the canvas
+    ctx.fillStyle = '#000';
+    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
+
+    // Apply camera transform
+    ctx.save();
+    ctx.translate(-state.camera.x, -state.camera.y);
+
+    // 1. Render background objects
+    state.world.backgroundTrees.forEach(tree => {
+        renderTree(ctx, tree, ctx.canvas.height - state.world.groundHeight);
+    });
+    
+    state.world.backgroundRocks.forEach(rock => {
+        renderRock(ctx, rock, ctx.canvas.height - state.world.groundHeight);
+    });
+    
+    // 2. 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);
+
+    // 4. Render foreground objects
+    state.world.foregroundTrees.forEach(tree => {
+        renderTree(ctx, tree, ctx.canvas.height - state.world.groundHeight);
+    });
+    
+    state.world.foregroundRocks.forEach(rock => {
+        renderRock(ctx, rock, ctx.canvas.height - state.world.groundHeight);
+    });
+
+    // 5. Render ground
+    const groundY = ctx.canvas.height - state.world.groundHeight;
+    ctx.fillStyle = '#4a4';
+    ctx.fillRect(
+        state.camera.x - 1000,
+        groundY,
+        ctx.canvas.width + 2000,
+        state.world.groundHeight
+    );
+
+    ctx.restore();
+};
+
+// Initialize the game when the window loads
+window.addEventListener('load', initGame);
diff --git a/html/rogue/js/world.js b/html/rogue/js/world.js
index e69de29..b20aa54 100644
--- a/html/rogue/js/world.js
+++ b/html/rogue/js/world.js
@@ -0,0 +1,236 @@
+// Define world object types
+const WORLD_OBJECTS = {
+    PLATFORM: 'platform',
+    TREE_BACKGROUND: 'tree_background',
+    TREE_FOREGROUND: 'tree_foreground',
+    ROCK_BACKGROUND: 'rock_background',
+    ROCK_FOREGROUND: 'rock_foreground'
+};
+
+// Tree configurations
+const TREE_TYPES = {
+    SMALL: {
+        width: 80,
+        height: 120,
+        canopyOffset: 40,  // Distance from bottom where canopy starts
+        canopyColor: '#2a4',
+        trunkColor: '#531'
+    },
+    LARGE: {
+        width: 120,
+        height: 200,
+        canopyOffset: 60,
+        canopyColor: '#1a4',
+        trunkColor: '#420'
+    }
+};
+
+// Rock configurations
+const ROCK_TYPES = {
+    SMALL: {
+        width: 40,
+        height: 30,
+        color: '#666',
+        highlights: '#888'
+    },
+    MEDIUM: {
+        width: 70,
+        height: 45,
+        color: '#555',
+        highlights: '#777'
+    },
+    LARGE: {
+        width: 100,
+        height: 60,
+        color: '#444',
+        highlights: '#666'
+    }
+};
+
+// Create a world with platforms, trees, and rocks
+const createWorld = () => ({
+    groundHeight: 12,
+    // Separate arrays for different layers
+    backgroundTrees: [
+        {
+            type: WORLD_OBJECTS.TREE_BACKGROUND,
+            x: 50,
+            config: TREE_TYPES.LARGE
+        },
+        {
+            type: WORLD_OBJECTS.TREE_BACKGROUND,
+            x: 500,
+            config: TREE_TYPES.SMALL
+        }
+    ],
+    backgroundRocks: [
+        {
+            type: WORLD_OBJECTS.ROCK_BACKGROUND,
+            x: 150,
+            config: ROCK_TYPES.LARGE
+        },
+        {
+            type: WORLD_OBJECTS.ROCK_BACKGROUND,
+            x: 400,
+            config: ROCK_TYPES.SMALL
+        }
+    ],
+    platforms: [
+        {
+            type: WORLD_OBJECTS.PLATFORM,
+            x: 300,
+            y: 300,
+            width: 200,
+            height: 20,
+            color: '#484'
+        },
+        {
+            type: WORLD_OBJECTS.PLATFORM,
+            x: 600,
+            y: 200,
+            width: 200,
+            height: 20,
+            color: '#484'
+        },
+        {
+            type: WORLD_OBJECTS.PLATFORM,
+            x: -200,
+            y: 250,
+            width: 200,
+            height: 20,
+            color: '#484'
+        }
+    ],
+    foregroundTrees: [
+        {
+            type: WORLD_OBJECTS.TREE_FOREGROUND,
+            x: 200,
+            config: TREE_TYPES.SMALL
+        },
+        {
+            type: WORLD_OBJECTS.TREE_FOREGROUND,
+            x: 800,
+            config: TREE_TYPES.LARGE
+        }
+    ],
+    foregroundRocks: [
+        {
+            type: WORLD_OBJECTS.ROCK_FOREGROUND,
+            x: 300,
+            config: ROCK_TYPES.MEDIUM
+        },
+        {
+            type: WORLD_OBJECTS.ROCK_FOREGROUND,
+            x: 700,
+            config: ROCK_TYPES.SMALL
+        }
+    ]
+});
+
+const renderTree = (ctx, tree, groundY) => {
+    const { x, config } = tree;
+    const { width, height, canopyOffset, trunkColor, canopyColor } = config;
+    
+    // Draw trunk
+    ctx.fillStyle = trunkColor;
+    ctx.fillRect(
+        x - width/6,
+        groundY - height,
+        width/3,
+        height
+    );
+    
+    // Draw canopy (triangular shape)
+    ctx.fillStyle = canopyColor;
+    ctx.beginPath();
+    ctx.moveTo(x - width/2, groundY - canopyOffset);
+    ctx.lineTo(x + width/2, groundY - canopyOffset);
+    ctx.lineTo(x, groundY - height);
+    ctx.closePath();
+    ctx.fill();
+};
+
+const renderRock = (ctx, rock, groundY) => {
+    const { x, config } = rock;
+    const { width, height, color, highlights } = config;
+    
+    // Draw main rock shape (slightly irregular pentagon)
+    ctx.fillStyle = color;
+    ctx.beginPath();
+    ctx.moveTo(x - width/2, groundY);
+    ctx.lineTo(x - width/2 + width/6, groundY - height);
+    ctx.lineTo(x + width/3, groundY - height);
+    ctx.lineTo(x + width/2, groundY - height/2);
+    ctx.lineTo(x + width/2, groundY);
+    ctx.closePath();
+    ctx.fill();
+
+    // Add highlights
+    ctx.fillStyle = highlights;
+    ctx.beginPath();
+    ctx.moveTo(x - width/4, groundY - height);
+    ctx.lineTo(x, groundY - height);
+    ctx.lineTo(x + width/6, groundY - height/2);
+    ctx.lineTo(x - width/6, groundY - height/2);
+    ctx.closePath();
+    ctx.fill();
+};
+
+// Collision detection helper
+const checkCollision = (player, platform) => {
+    return player.x < platform.x + platform.width &&
+           player.x + player.width > platform.x &&
+           player.y < platform.y + platform.height &&
+           player.y + player.height > platform.y;
+};
+
+// World physics helper
+const handleWorldCollisions = (player, world) => {
+    let onGround = false;
+    
+    // Check ground collision first
+    const groundY = window.innerHeight - world.groundHeight;
+    if (player.y + player.height > groundY) {
+        player.y = groundY - player.height;
+        player.velocityY = 0;
+        onGround = true;
+    }
+    
+    // Then check platform collisions
+    for (const platform of world.platforms) {
+        if (checkCollision(player, platform)) {
+            // Calculate overlap on each axis
+            const overlapX = Math.min(
+                player.x + player.width - platform.x,
+                platform.x + platform.width - player.x
+            );
+            const overlapY = Math.min(
+                player.y + player.height - platform.y,
+                platform.y + platform.height - player.y
+            );
+
+            // Resolve collision on the axis with smallest overlap
+            if (overlapX < overlapY) {
+                // Horizontal collision
+                if (player.x < platform.x) {
+                    player.x = platform.x - player.width;
+                } else {
+                    player.x = platform.x + platform.width;
+                }
+                player.velocityX = 0;
+            } else {
+                // Vertical collision
+                if (player.y < platform.y) {
+                    player.y = platform.y - player.height;
+                    player.velocityY = 0;
+                    onGround = true;
+                } else {
+                    player.y = platform.y + platform.height;
+                    player.velocityY = 0;
+                }
+            }
+        }
+    }
+    
+    return { ...player, jumping: !onGround };
+};