diff options
Diffstat (limited to 'html/broughlike/index.html')
-rw-r--r-- | html/broughlike/index.html | 133 |
1 files changed, 92 insertions, 41 deletions
diff --git a/html/broughlike/index.html b/html/broughlike/index.html index e643527..71cd9d7 100644 --- a/html/broughlike/index.html +++ b/html/broughlike/index.html @@ -39,18 +39,18 @@ }; const GRID_SIZE = 6; - const PLAYER_HEALTH = 10; - const PLAYER_MAX_HEALTH = 12; + const PLAYER_HEALTH = 12; + const PLAYER_MAX_HEALTH = 16; const PLAYER_BASE_DAMAGE = 1; const ENEMY_CHASE_DISTANCE = 4; - const MAX_ENEMIES_ON_LEVEL = 4; + const MAX_ENEMIES_ON_LEVEL = 3; const MAX_ENEMY_HEALTH = 7; const MIN_ENEMY_HEALTH = 2; const WALLS_MIN = 5; const WALLS_MAX = 20; - const ITEMS_MIN = 0; + const ITEMS_MIN = 1; const ITEMS_MAX = 3; - const DOTS_PER_HIT = 5; + const DOTS_PER_HIT = 7; const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); @@ -121,11 +121,10 @@ const wallY = Math.floor(Math.random() * GRID_SIZE); if ( - (wallX === player.x && wallY === player.y) || - (wallX === exit.x && wallY === exit.y) || - enemies.some(enemy => enemy.x === wallX && enemy.y === wallY) || - (wallX === 0 && wallY === 0) || // Don't block the player spawn - items.some(item => item.x === wallX && item.y === wallY) + (wallX === player.x && wallY === player.y) || // Check that a wall is not placed on the starting position + (wallX === exit.x && wallY === exit.y) || // Check that a wall is not placed on the exit + enemies.some(enemy => enemy.x === wallX && enemy.y === wallY) || // Check that a wall is not placed on any enemies + items.some(item => item.x === wallX && item.y === wallY) // Check that a wall is not placed on any items ) continue; if (!walls.some(wall => wall.x === wallX && wall.y === wallY)) { @@ -150,7 +149,8 @@ (itemX === player.x && itemY === player.y) || (itemX === exit.x && itemY === exit.y) || walls.some(wall => wall.x === itemX && wall.y === itemY) || - enemies.some(enemy => enemy.x === itemX && enemy.y === itemY) + enemies.some(enemy => enemy.x === itemX && enemy.y === itemY) || + items.some(item => item.x === itemX && item.y === itemY) ); const itemType = Math.random() < 0.5 ? 'diamond' : 'pentagon'; // 50% chance for each type items.push({ x: itemX, y: itemY, type: itemType }); @@ -258,6 +258,7 @@ drawCharacterBorder(x, y, radius, damageTaken); }); } + function drawPlayer() { const x = player.x * tileSize + tileSize / 2; @@ -313,14 +314,13 @@ } } - // Function to add dots for damage in combat (including adjacent cells) function addCombatDots(x, y, color) { const cellsToFill = [ - [x, y], // Center - [x - 1, y], // Left - [x + 1, y], // Right - [x, y - 1], // Up - [x, y + 1], // Down + [x, y], // Center + [x - 1, y], // Left + [x + 1, y], // Right + [x, y - 1], // Up + [x, y + 1], // Down [x - 1, y - 1], // Top-left [x + 1, y - 1], // Top-right [x - 1, y + 1], // Bottom-left @@ -347,44 +347,95 @@ function movePlayer(dx, dy) { const newX = player.x + dx; const newY = player.y + dy; - if (isValidMove(newX, newY)) { + if (isValidMove(newX, newY) && !enemies.some(enemy => enemy.x === newX && enemy.y === newY)) { + if (newX !== player.x || newY !== player.y) player.cellsTraveled++; + player.x = newX; + player.y = newY; + handleItemCollection(); // Did the player collect an item? + checkPlayerAtExit(); // Did the player get to the exit after moving? + } else { + // If an enemy is in the target cell, player stays put and does combat const enemyInTargetCell = enemies.find(enemy => enemy.x === newX && enemy.y === newY); - if (!enemyInTargetCell) { - if (newX !== player.x || newY !== player.y) player.cellsTraveled++; - player.x = newX; - player.y = newY; - handleItemCollection(); // Check if the player collected an item - checkPlayerAtExit(); // Check if player reached the exit after moving - } else { - // Enemy in the target cell, stay in place and do combat + if (enemyInTargetCell) { handleDamage(player, enemyInTargetCell); } } moveEnemies(); render(); } - - // Chase logic (naive) + function moveEnemies() { enemies.forEach(enemy => { - const distance = Math.abs(enemy.x - player.x) + Math.abs(enemy.y - player.y); - if (distance <= ENEMY_CHASE_DISTANCE) { - let dx = 0, dy = 0; - if (enemy.x < player.x && isValidMove(enemy.x + 1, enemy.y)) dx = 1; - else if (enemy.x > player.x && isValidMove(enemy.x - 1, enemy.y)) dx = -1; - else if (enemy.y < player.y && isValidMove(enemy.x, enemy.y + 1)) dy = 1; - else if (enemy.y > player.x && isValidMove(enemy.x, enemy.y - 1)) dy = -1; - - if (!enemies.some(e => e.x === enemy.x + dx && e.y === enemy.y)) { - enemy.x += dx; - enemy.y += dy; + const distanceToPlayer = Math.abs(enemy.x - player.x) + Math.abs(enemy.y - player.y); + const distanceToExit = Math.abs(enemy.x - exit.x) + Math.abs(enemy.y - exit.y); + + const target = distanceToPlayer <= ENEMY_CHASE_DISTANCE ? player : exit; + const path = findPath(enemy, target); + + if (path.length > 1) { + const nextStep = path[1]; + const enemyInNextStep = enemies.find(e => e.x === nextStep.x && e.y === nextStep.y); + + // Is the next step occupied by an enemy? + if (!enemyInNextStep && !(nextStep.x === player.x && nextStep.y === player.y)) { + // Move to the next place + enemy.x = nextStep.x; + enemy.y = nextStep.y; + } else if (nextStep.x === player.x && nextStep.y === player.y) { + // If the player is in the next step, stay put and do combat + handleDamage(player, enemy); } } }); } + function findPath(start, goal) { + const queue = [{ x: start.x, y: start.y, path: [] }]; + const visited = new Set(); + visited.add(`${start.x},${start.y}`); + + while (queue.length > 0) { + const { x, y, path } = queue.shift(); + const newPath = [...path, { x, y }]; + + if (x === goal.x && y === goal.y) { + return newPath; + } + + const directions = [ + { dx: 1, dy: 0 }, + { dx: -1, dy: 0 }, + { dx: 0, dy: 1 }, + { dx: 0, dy: -1 } + ]; + + directions.forEach(({ dx, dy }) => { + const newX = x + dx; + const newY = y + dy; + const key = `${newX},${newY}`; + + // Check if the new position is within the level and if it is passable + if ( + newX >= 0 && newX < GRID_SIZE && + newY >= 0 && newY < GRID_SIZE && + // Have we already been here? + !visited.has(key) && + // Is it a wall? + !walls.some(wall => wall.x === newX && wall.y === newY) && + // Is there an enemy already there? + !enemies.some(enemy => enemy.x === newX && enemy.y === newY) + ) { + queue.push({ x: newX, y: newY, path: newPath }); + visited.add(key); + } + }); + } + + return []; + } + function handleDamage(player, enemy) { - const enemyMisses = Math.random() < 0.2; // 1 in 5 chance the enemy misses you + const enemyMisses = Math.random() < 0.5; // 50% chance the enemy misses you const cellX = player.x; const cellY = player.y; @@ -457,10 +508,10 @@ function render() { drawGrid(); + drawPlayer(); drawExit(); drawItems(); drawEnemies(); - drawPlayer(); drawWalls(); drawCombatDots(); } |