From 83140c20ccbd7c251e45aa560de4b99475b975b5 Mon Sep 17 00:00:00 2001 From: elioat Date: Sun, 7 Jul 2024 00:01:23 -0400 Subject: * --- js/puzzle-dungeon/game.js | 267 +++++++++++++++++++++++++++------------------- 1 file changed, 159 insertions(+), 108 deletions(-) (limited to 'js/puzzle-dungeon/game.js') diff --git a/js/puzzle-dungeon/game.js b/js/puzzle-dungeon/game.js index f742844..4ca91d3 100644 --- a/js/puzzle-dungeon/game.js +++ b/js/puzzle-dungeon/game.js @@ -1,131 +1,182 @@ -const canvas = document.getElementById('gameCanvas'); -const ctx = canvas.getContext('2d'); -const cellSize = canvas.width / 10; -const stepDuration = 200; // Duration for each step +// game.js +export let grid = createGrid(10, 10); // Example grid size +export let player = { + position: { x: 0, y: 0 }, + inventory: [], + health: 10, + endurance: 10, + score: 0, + steps: 0, + flashing: false +}; +let targetPosition = { x: 0, y: 0 }; -let player = { x: 0, y: 0 }; - -function drawGrid() { - ctx.clearRect(0, 0, canvas.width, canvas.height); - for (let x = 0; x <= canvas.width; x += cellSize) { - ctx.moveTo(x, 0); - ctx.lineTo(x, canvas.height); - } - for (let y = 0; y <= canvas.height; y += cellSize) { - ctx.moveTo(0, y); - ctx.lineTo(canvas.width, y); +function createGrid(rows, cols) { + let grid = []; + for (let i = 0; i < rows; i++) { + let row = []; + for (let j = 0; j < cols; j++) { + row.push(null); + } + grid.push(row); } - ctx.strokeStyle = '#ddd'; - ctx.stroke(); + return grid; } -function drawPlayer() { - ctx.fillStyle = 'blue'; - ctx.fillRect(player.x * cellSize, player.y * cellSize, cellSize, cellSize); +function generateCollectables(grid, numCollectables) { + const collectableTypes = ['potion', 'shield', 'food']; + const collectableColors = { + 'potion': 'purple', + 'shield': 'gold', + 'food': 'red' + }; + for (let i = 0; i < numCollectables; i++) { + let x, y; + do { + x = Math.floor(Math.random() * grid.length); + y = Math.floor(Math.random() * grid[0].length); + } while (x === 0 && y === 0); // Ensure no items at (0,0) + const type = collectableTypes[Math.floor(Math.random() * collectableTypes.length)]; + grid[x][y] = { type, color: collectableColors[type] }; + } } -document.getElementById('commandForm').addEventListener('submit', function (e) { - e.preventDefault(); - const commands = document.getElementById('commands').value.trim(); - try { - const parsedCommands = parseLispCommands(commands); - console.log("Parsed Commands:", JSON.stringify(parsedCommands, null, 2)); // Debugging output - executeCommands(parsedCommands); - } catch (error) { - console.error("Error parsing commands:", error); +function generateDamagingSpaces(grid, numSpaces) { + for (let i = 0; i < numSpaces; i++) { + let x, y; + do { + x = Math.floor(Math.random() * grid.length); + y = Math.floor(Math.random() * grid[0].length); + } while (x === 0 && y === 0); // Ensure no damaging spaces at (0,0) + grid[x][y] = { type: 'damage', color: 'pink' }; } -}); +} -function parseLispCommands(commands) { - const parse = input => { - const tokens = tokenize(input); - const ast = buildAST(tokens); - return ast; - }; +function generateTargetBlock(grid) { + let x, y; + do { + x = Math.floor(Math.random() * grid.length); + y = Math.floor(Math.random() * grid[0].length); + } while (x === 0 && y === 0); // Ensure no target block at (0,0) + grid[x][y] = { type: 'target', color: 'green' }; // Target block represented by 'X' + targetPosition = { x, y }; // Store the target block position +} - const tokenize = input => { - return input.replace(/\(/g, ' ( ').replace(/\)/g, ' ) ').trim().split(/\s+/); - }; +export function drawGrid(grid) { + const canvas = document.getElementById('gameCanvas'); + const ctx = canvas.getContext('2d'); + const cellSize = Math.min(canvas.width / grid.length, canvas.height / grid[0].length); + + ctx.clearRect(0, 0, canvas.width, canvas.height); - const buildAST = tokens => { - if (!tokens.length) throw new SyntaxError("Unexpected end of input"); + grid.forEach((row, x) => { + row.forEach((cell, y) => { + ctx.strokeStyle = 'black'; + ctx.strokeRect(x * cellSize, y * cellSize, cellSize, cellSize); - const token = tokens.shift(); - if (token === '(') { - const list = []; - while (tokens[0] !== ')') { - list.push(buildAST(tokens)); - if (!tokens.length) throw new SyntaxError("Missing closing parenthesis"); + if (cell && cell.color) { + ctx.fillStyle = cell.color; + ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize); + ctx.fillStyle = 'black'; + ctx.font = `${cellSize / 2}px Arial`; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + let char = ''; + if (cell.type === 'potion') char = 'p'; + if (cell.type === 'shield') char = 's'; + if (cell.type === 'food') char = 'f'; + if (cell.type === 'damage') char = '!'; + if (cell.type === 'target') char = 'X'; + ctx.fillText(char, x * cellSize + cellSize / 2, y * cellSize + cellSize / 2); } - tokens.shift(); - return list; - } else if (token === ')') { - throw new SyntaxError("Unexpected ')'"); - } else { - return isNaN(token) ? token : Number(token); - } - }; + }); + }); - return parse(commands); + // Draw player + ctx.fillStyle = player.flashing ? 'white' : 'blue'; + ctx.fillRect(player.position.x * cellSize, player.position.y * cellSize, cellSize, cellSize); + ctx.fillStyle = 'black'; + ctx.font = `${cellSize / 2}px Arial`; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText('@', player.position.x * cellSize + cellSize / 2, player.position.y * cellSize + cellSize / 2); } -function executeCommands(commands) { - if (commands[0] !== 'move') { - console.error("Invalid command: root command must be 'move'"); - return; - } +export function initializeGame() { + grid = createGrid(10, 10); // Reset grid + generateCollectables(grid, 10); // Adjust the number as needed + generateDamagingSpaces(grid, Math.floor(Math.random() * 7) + 1); // Random number of damaging spaces, no more than 7 + generateTargetBlock(grid); // Add target block + player.position = { x: 0, y: 0 }; // Reset player position + player.inventory = []; // Clear inventory + player.health = 10; // Reset health + player.endurance = 10; // Reset endurance + player.steps = 0; // Reset steps + resizeCanvas(); + drawGrid(grid); + updatePlayerStatus(); +} - let delay = 0; - commands.slice(1).forEach(moveCommand => { - const steps = moveCommand[1]; - for (let i = 0; i < steps; i++) { - setTimeout(() => { - movePlayer([moveCommand[0], 1]); - drawGrid(); - drawPlayer(); - }, delay); - delay += stepDuration; - } - if (moveCommand[0] === 'rest') { - setTimeout(() => { - drawGrid(); - drawPlayer(); - }, delay); - delay += stepDuration; - } - }); +export function resizeCanvas() { + const canvas = document.getElementById('gameCanvas'); + const width = Math.min(window.innerWidth, window.innerHeight) * 0.9; + canvas.width = width; + canvas.height = width; + drawGrid(grid); } -function movePlayer(moveCommand) { - const direction = moveCommand[0]; - const steps = moveCommand[1]; +export function updatePlayerPosition(newX, newY) { + player.position.x = newX; + player.position.y = newY; + checkForDamageOrTarget(); + drawGrid(grid); + updatePlayerStatus(); +} - if (typeof direction !== 'string' || typeof steps !== 'number') { - console.error(`Invalid move command: ${JSON.stringify(moveCommand)}`); - return; - } +export function updatePlayerStatus() { + document.getElementById('playerPosition').textContent = `Position: (${player.position.x}, ${player.position.y})`; + document.getElementById('playerHealth').textContent = `Health: ${player.health}`; + document.getElementById('playerEndurance').textContent = `Endurance: ${player.endurance}`; + document.getElementById('playerInventory').textContent = `Inventory: [${player.inventory.join(', ')}]`; + document.getElementById('playerScore').textContent = `Score: ${player.score}`; +} - switch (direction) { - case 'north': - player.y = Math.max(0, player.y - steps); - break; - case 'south': - player.y = Math.min(9, player.y + steps); - break; - case 'east': - player.x = Math.min(9, player.x + steps); - break; - case 'west': - player.x = Math.max(0, player.x - steps); - break; - case 'rest': - // No movement, just wait for the duration - break; - default: - console.error(`Unknown direction: ${direction}`); - return; +function checkForDamageOrTarget() { + const { x, y } = player.position; + const cell = grid[x][y]; + if (cell && cell.type === 'damage') { + const shieldIndex = player.inventory.indexOf('shield'); + if (shieldIndex > -1) { + player.inventory.splice(shieldIndex, 1); // Use one shield + console.log('Used shield to avoid damage'); + } else { + player.health -= 2; + console.log(`Stepped on damaging space, health is now ${player.health}`); + if (player.health <= 0) { + alertGameOver(); + return; + } + flashPlayer(); + } + } else if (x === targetPosition.x && y === targetPosition.y) { + player.score += 1; + console.log(`Reached target block, score is now ${player.score}`); + initializeGame(); // Generate new level and reset player position } } -drawGrid(); -drawPlayer(); +export function alertGameOver() { + alert('You have lost the game!'); + initializeGame(); +} + +function flashPlayer(callback) { + player.flashing = true; + drawGrid(grid); + setTimeout(() => { + player.flashing = false; + drawGrid(grid); + updatePlayerStatus(); + if (callback) callback(); + }, 250); // Flash duration +} -- cgit 1.4.1-2-gfad0