diff options
author | elioat <elioat@tilde.institute> | 2024-12-27 07:25:05 -0500 |
---|---|---|
committer | elioat <elioat@tilde.institute> | 2024-12-27 07:25:05 -0500 |
commit | 1ae1729728f0907ddb17e9303edad19aa2ff143c (patch) | |
tree | b7bb5082e9099890156d9e9c36866a9dc2b8ee99 /html | |
parent | f1268ab00394de6f751c58f825efbc905680b161 (diff) | |
download | tour-1ae1729728f0907ddb17e9303edad19aa2ff143c.tar.gz |
*
Diffstat (limited to 'html')
-rw-r--r-- | html/rogue/index.html | 19 | ||||
-rw-r--r-- | html/rogue/js/game.js | 169 | ||||
-rw-r--r-- | html/rogue/js/player.js | 188 | ||||
-rw-r--r-- | html/side-scrolling-rogue-thing/index.html | 26 | ||||
-rw-r--r-- | html/side-scrolling-rogue-thing/js/camera.js (renamed from html/rogue/js/camera.js) | 0 | ||||
-rw-r--r-- | html/side-scrolling-rogue-thing/js/config.js (renamed from html/rogue/js/config.js) | 0 | ||||
-rw-r--r-- | html/side-scrolling-rogue-thing/js/input.js (renamed from html/rogue/js/input.js) | 0 | ||||
-rw-r--r-- | html/side-scrolling-rogue-thing/js/player.js | 64 | ||||
-rw-r--r-- | html/side-scrolling-rogue-thing/js/renderer.js (renamed from html/rogue/js/renderer.js) | 0 | ||||
-rw-r--r-- | html/side-scrolling-rogue-thing/js/rogue.js (renamed from html/rogue/js/rogue.js) | 0 | ||||
-rw-r--r-- | html/side-scrolling-rogue-thing/js/world.js (renamed from html/rogue/js/world.js) | 0 |
11 files changed, 400 insertions, 66 deletions
diff --git a/html/rogue/index.html b/html/rogue/index.html index ef37885..79aac67 100644 --- a/html/rogue/index.html +++ b/html/rogue/index.html @@ -1,10 +1,15 @@ <!DOCTYPE html> -<html> +<html lang="en"> <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Rogue</title> <style> - body { + body, html { margin: 0; + padding: 0; + width: 100%; + height: 100%; overflow: hidden; } canvas { @@ -14,13 +19,7 @@ </head> <body> <canvas id="gameCanvas"></canvas> - <!-- Load config first since other files depend on it --> - <script src="js/config.js"></script> - <script src="js/renderer.js"></script> - <script src="js/input.js"></script> - <script src="js/world.js"></script> <script src="js/player.js"></script> - <script src="js/camera.js"></script> - <script src="js/rogue.js"></script> + <script src="js/game.js"></script> </body> -</html> +</html> \ No newline at end of file diff --git a/html/rogue/js/game.js b/html/rogue/js/game.js new file mode 100644 index 0000000..29b5037 --- /dev/null +++ b/html/rogue/js/game.js @@ -0,0 +1,169 @@ +// Constants for hex grid +const HEX_SIZE = 20; // Fixed hex size +const HEX_WIDTH = HEX_SIZE * 2; +const HEX_HEIGHT = Math.sqrt(3) * HEX_SIZE; +const GRID_SIZE = 100; // Number of hexes in each dimension + +// Game state +const state = { + canvas: null, + ctx: null, + camera: { x: 0, y: 0 }, // Camera position in pixel coordinates + hexGrid: [], // Will store hex grid data +}; + +// Initialize the game +function init() { + state.canvas = document.getElementById('gameCanvas'); + state.ctx = state.canvas.getContext('2d'); + + // Initialize player + player.init(); + + function resize() { + state.canvas.width = window.innerWidth; + state.canvas.height = window.innerHeight; + // Center camera on player initially + centerCameraOnHex(player.position); + } + + window.addEventListener('resize', resize); + resize(); + state.canvas.addEventListener('click', handleClick); + requestAnimationFrame(gameLoop); +} + +// Center camera on a specific hex +function centerCameraOnHex(hex) { + const pixelCoord = hexToPixel(hex); + state.camera.x = pixelCoord.x - state.canvas.width / 2; + state.camera.y = pixelCoord.y - state.canvas.height / 2; +} + +// Smoothly move camera to target position +function updateCamera() { + const currentPos = player.getCurrentPosition(); + const targetPixel = hexToPixel(currentPos); + const targetCameraX = targetPixel.x - state.canvas.width / 2; + const targetCameraY = targetPixel.y - state.canvas.height / 2; + + // Smooth camera movement + state.camera.x += (targetCameraX - state.camera.x) * 0.1; + state.camera.y += (targetCameraY - state.camera.y) * 0.1; +} + +// Convert hex coordinates to pixel coordinates +function hexToPixel(hex) { + const x = HEX_SIZE * (3/2 * hex.q); + const y = HEX_SIZE * (Math.sqrt(3)/2 * hex.q + Math.sqrt(3) * hex.r); + return {x, y}; +} + +// Convert pixel coordinates to hex coordinates (adjusted for camera position) +function pixelToHex(screenX, screenY) { + const x = screenX + state.camera.x; + const y = screenY + state.camera.y; + + const q = (2/3 * x) / HEX_SIZE; + const r = (-1/3 * x + Math.sqrt(3)/3 * y) / HEX_SIZE; + return hexRound(q, r); +} + +// Draw a single hex +function drawHex(ctx, x, y) { + // Adjust position for camera + const screenX = x - state.camera.x; + const screenY = y - state.camera.y; + + // Only draw if hex is visible on screen (with padding) + if (screenX < -HEX_WIDTH || screenX > state.canvas.width + HEX_WIDTH || + screenY < -HEX_HEIGHT || screenY > state.canvas.height + HEX_HEIGHT) { + return; + } + + ctx.beginPath(); + for (let i = 0; i < 6; i++) { + const angle = 2 * Math.PI / 6 * i; + const xPos = screenX + HEX_SIZE * Math.cos(angle); + const yPos = screenY + HEX_SIZE * Math.sin(angle); + if (i === 0) { + ctx.moveTo(xPos, yPos); + } else { + ctx.lineTo(xPos, yPos); + } + } + ctx.closePath(); + ctx.stroke(); +} + +// Calculate which hexes should be drawn +function calculateViewportHexes() { + const hexes = []; + const halfGrid = Math.floor(GRID_SIZE / 2); + + for (let r = -halfGrid; r < halfGrid; r++) { + for (let q = -halfGrid; q < halfGrid; q++) { + hexes.push({q, r}); + } + } + return hexes; +} + +// Main game loop +function gameLoop() { + state.ctx.clearRect(0, 0, state.canvas.width, state.canvas.height); + + // Update game state + player.update(); + updateCamera(); + + // Draw hex grid + const viewportHexes = calculateViewportHexes(); + viewportHexes.forEach(hex => { + const pixel = hexToPixel(hex); + drawHex(state.ctx, pixel.x, pixel.y); + }); + + // Draw player + player.draw(state.ctx, hexToPixel, state.camera, HEX_SIZE); + + requestAnimationFrame(gameLoop); +} + +// Handle click/tap with camera offset +function handleClick(event) { + const rect = state.canvas.getBoundingClientRect(); + const x = event.clientX - rect.left; + const y = event.clientY - rect.top; + + const hexCoord = pixelToHex(x, y); + player.moveTo(hexCoord); +} + +// Round hex coordinates to nearest hex +function hexRound(q, r) { + let x = q; + let z = r; + let y = -x-z; + + let rx = Math.round(x); + let ry = Math.round(y); + let rz = Math.round(z); + + const x_diff = Math.abs(rx - x); + const y_diff = Math.abs(ry - y); + const z_diff = Math.abs(rz - z); + + if (x_diff > y_diff && x_diff > z_diff) { + rx = -ry-rz; + } else if (y_diff > z_diff) { + ry = -rx-rz; + } else { + rz = -rx-ry; + } + + return {q: rx, r: rz}; +} + +// Start the game +init(); \ No newline at end of file diff --git a/html/rogue/js/player.js b/html/rogue/js/player.js index 270b26f..5b4a875 100644 --- a/html/rogue/js/player.js +++ b/html/rogue/js/player.js @@ -1,64 +1,140 @@ -const createPlayer = (x, y) => ({ - x, - y, - width: 32, - height: 32, - velocityX: 0, - velocityY: 0, - speed: 300, - jumping: false -}); +// Player state and controls +const player = { + position: { q: 0, r: 0 }, // Current hex position + target: null, // Target hex to move to + path: [], // Array of hex coordinates to follow + movementProgress: 0, // Progress of current movement (0 to 1) + moveSpeed: 0.1, // Movement speed (0 to 1 per frame) + + // Initialize player + init() { + this.position = { q: 0, r: 0 }; + this.target = null; + this.path = []; + return this; + }, -const updatePlayer = (player, deltaTime) => { - const keys = getKeys(); - const seconds = deltaTime / 1000; + // Get neighbors that share an edge with the given hex + getEdgeNeighbors(hex) { + const directions = [ + {q: 1, r: 0}, // East + {q: 0, r: 1}, // Southeast + {q: -1, r: 1}, // Southwest + {q: -1, r: 0}, // West + {q: 0, r: -1}, // Northwest + {q: 1, r: -1} // Northeast + ]; + + return directions.map(dir => ({ + q: hex.q + dir.q, + r: hex.r + dir.r + })); + }, - let velocityX = 0; - let velocityY = player.velocityY; + // Find path from current position to target + findPath(targetHex) { + const start = this.position; + const goal = targetHex; + + // Simple breadth-first search + const queue = [[start]]; + const visited = new Set(); + const key = hex => `${hex.q},${hex.r}`; + visited.add(key(start)); + + while (queue.length > 0) { + const path = queue.shift(); + const current = path[path.length - 1]; + + if (current.q === goal.q && current.r === goal.r) { + return path; + } + + const neighbors = this.getEdgeNeighbors(current); + for (const neighbor of neighbors) { + const neighborKey = key(neighbor); + if (!visited.has(neighborKey)) { + visited.add(neighborKey); + queue.push([...path, neighbor]); + } + } + } + + return null; // No path found + }, - // Horizontal movement - if (keys.ArrowLeft) velocityX -= player.speed; - if (keys.ArrowRight) velocityX += player.speed; + // Start moving to a target hex + moveTo(targetHex) { + if (!this.target) { + const path = this.findPath(targetHex); + if (path) { + this.path = path.slice(1); // Remove starting position + if (this.path.length > 0) { + this.target = this.path.shift(); + this.movementProgress = 0; + } + } + } + }, - // 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 - }; + // Update player position + update() { + if (this.target) { + this.movementProgress += this.moveSpeed; + + if (this.movementProgress >= 1) { + // Movement to current target complete + this.position = this.target; + this.target = null; + this.movementProgress = 0; + + // If there are more points in the path, move to the next one + if (this.path.length > 0) { + this.target = this.path.shift(); + this.movementProgress = 0; + } + } + } + }, - // Handle collisions with the world - return handleWorldCollisions(updatedPlayer, window.gameState.world); -}; + // Get current interpolated position + getCurrentPosition() { + if (!this.target) { + return this.position; + } -const renderPlayer = (ctx, player) => { - ctx.fillStyle = '#f00'; - ctx.fillRect(player.x, player.y, player.width, player.height); -}; + // Interpolate between current position and target + return { + q: this.position.q + (this.target.q - this.position.q) * this.movementProgress, + r: this.position.r + (this.target.r - this.position.r) * this.movementProgress + }; + }, -// Key handling -const keys = {}; + // Draw the player + draw(ctx, hexToPixel, camera, HEX_SIZE) { + const currentPos = this.getCurrentPosition(); + const pixelPos = hexToPixel(currentPos); + const screenX = pixelPos.x - camera.x; + const screenY = pixelPos.y - camera.y; -window.addEventListener('keydown', (e) => { - keys[e.key] = true; -}); - -window.addEventListener('keyup', (e) => { - keys[e.key] = false; -}); - -const getKeys = () => ({...keys}); + ctx.fillStyle = 'red'; + ctx.beginPath(); + ctx.arc(screenX, screenY, HEX_SIZE/3, 0, Math.PI * 2); + ctx.fill(); + + // Optionally, draw the remaining path + if (this.path.length > 0) { + ctx.strokeStyle = 'rgba(255,0,0,0.3)'; + ctx.beginPath(); + let lastPos = this.target || this.position; + this.path.forEach(point => { + const from = hexToPixel(lastPos); + const to = hexToPixel(point); + ctx.moveTo(from.x - camera.x, from.y - camera.y); + ctx.lineTo(to.x - camera.x, to.y - camera.y); + lastPos = point; + }); + ctx.stroke(); + } + } +}; \ No newline at end of file diff --git a/html/side-scrolling-rogue-thing/index.html b/html/side-scrolling-rogue-thing/index.html new file mode 100644 index 0000000..ef37885 --- /dev/null +++ b/html/side-scrolling-rogue-thing/index.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <title>Rogue</title> + <style> + body { + margin: 0; + overflow: hidden; + } + canvas { + display: block; + } + </style> +</head> +<body> + <canvas id="gameCanvas"></canvas> + <!-- Load config first since other files depend on it --> + <script src="js/config.js"></script> + <script src="js/renderer.js"></script> + <script src="js/input.js"></script> + <script src="js/world.js"></script> + <script src="js/player.js"></script> + <script src="js/camera.js"></script> + <script src="js/rogue.js"></script> +</body> +</html> diff --git a/html/rogue/js/camera.js b/html/side-scrolling-rogue-thing/js/camera.js index e5d5d14..e5d5d14 100644 --- a/html/rogue/js/camera.js +++ b/html/side-scrolling-rogue-thing/js/camera.js diff --git a/html/rogue/js/config.js b/html/side-scrolling-rogue-thing/js/config.js index 77100e1..77100e1 100644 --- a/html/rogue/js/config.js +++ b/html/side-scrolling-rogue-thing/js/config.js diff --git a/html/rogue/js/input.js b/html/side-scrolling-rogue-thing/js/input.js index 047321c..047321c 100644 --- a/html/rogue/js/input.js +++ b/html/side-scrolling-rogue-thing/js/input.js diff --git a/html/side-scrolling-rogue-thing/js/player.js b/html/side-scrolling-rogue-thing/js/player.js new file mode 100644 index 0000000..270b26f --- /dev/null +++ b/html/side-scrolling-rogue-thing/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/renderer.js b/html/side-scrolling-rogue-thing/js/renderer.js index 617b4c7..617b4c7 100644 --- a/html/rogue/js/renderer.js +++ b/html/side-scrolling-rogue-thing/js/renderer.js diff --git a/html/rogue/js/rogue.js b/html/side-scrolling-rogue-thing/js/rogue.js index 64716a4..64716a4 100644 --- a/html/rogue/js/rogue.js +++ b/html/side-scrolling-rogue-thing/js/rogue.js diff --git a/html/rogue/js/world.js b/html/side-scrolling-rogue-thing/js/world.js index 2b2529a..2b2529a 100644 --- a/html/rogue/js/world.js +++ b/html/side-scrolling-rogue-thing/js/world.js |