about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--html/broughlike/broughlike.js150
-rw-r--r--html/broughlike/config.js32
-rw-r--r--html/broughlike/index.html2
3 files changed, 93 insertions, 91 deletions
diff --git a/html/broughlike/broughlike.js b/html/broughlike/broughlike.js
index e492a0c..5f0863f 100644
--- a/html/broughlike/broughlike.js
+++ b/html/broughlike/broughlike.js
@@ -1,45 +1,16 @@
-const COLORS = {
-    grid: '#2d2d2d',
-    walls: '#2d2d2d',
-    exit: 'teal',
-    diamond: 'gold',
-    pentagon: 'blueviolet', 
-    player: 'rgba(0, 237, 209, ',
-    enemy: 'rgba(255, 155, 28, ',
-    boss: 'rgba(255, 14, 0, ',
-    combatDotPlayer: '#00edd1',
-    combatDotEnemy: '#ff731c',
-    combatDotBoss: '#b70030'
-};
-
-const GRID_SIZE = 6;
-const PLAYER_HEALTH = 12;
-const PLAYER_MAX_HEALTH = 16;
-const PLAYER_BASE_DAMAGE = 1;
-const ENEMY_CHASE_DISTANCE = 4;
-const ENEMY_BOSS_OCCURRENCE = 10;
-const MIN_ENEMIES_ON_LEVEL = 1;
-const MAX_ENEMIES_ON_LEVEL = 4;
-const MAX_ENEMY_HEALTH = 7;
-const MIN_ENEMY_HEALTH = 2;
-const WALLS_MIN = 7;
-const WALLS_MAX = 20;
-const ITEMS_MIN = 1;
-const ITEMS_MAX = 3;
-const DOTS_PER_HIT = 7;
-
-let highScore = localStorage.getItem('highScore') || 0;
+import { CONFIG, COLORS } from './config.js';
 
 const canvas = document.getElementById('gameCanvas');
 const ctx = canvas.getContext('2d');
-let tileSize = canvas.width / GRID_SIZE;
+let tileSize = canvas.width / CONFIG.GRID_SIZE;
+let highScore = localStorage.getItem('highScore') || 0;
 
 const player = {
     x: 0,
     y: 0,
-    health: PLAYER_HEALTH,
+    health: CONFIG.PLAYER_HEALTH,
     score: 0,
-    damage: PLAYER_BASE_DAMAGE,
+    damage: CONFIG.PLAYER_BASE_DAMAGE,
     totalDamageDone: 0,
     totalDamageTaken: 0,
     cellsTraveled: 0,
@@ -47,7 +18,7 @@ const player = {
     itemsCollected: 0,
 };
 
-const exit = { x: Math.floor(Math.random() * GRID_SIZE), y: Math.floor(Math.random() * GRID_SIZE) };
+const exit = { x: Math.floor(Math.random() * CONFIG.GRID_SIZE), y: Math.floor(Math.random() * CONFIG.GRID_SIZE) };
 let walls = [];
 let enemies = [];
 let items = [];
@@ -55,8 +26,8 @@ let combatDots = {};
 
 function isValidMove(newX, newY) {
     return (
-        newX >= 0 && newX < GRID_SIZE &&
-        newY >= 0 && newY < GRID_SIZE &&
+        newX >= 0 && newX < CONFIG.GRID_SIZE &&
+        newY >= 0 && newY < CONFIG.GRID_SIZE &&
         !walls.some(wall => wall.x === newX && wall.y === newY)
     );
 }
@@ -64,8 +35,8 @@ function isValidMove(newX, newY) {
 function generateExit() {
     let distance = 0;
     do {
-        exit.x = Math.floor(Math.random() * GRID_SIZE);
-        exit.y = Math.floor(Math.random() * GRID_SIZE);
+        exit.x = Math.floor(Math.random() * CONFIG.GRID_SIZE);
+        exit.y = Math.floor(Math.random() * CONFIG.GRID_SIZE);
         distance = Math.abs(exit.x - player.x) + Math.abs(exit.y - player.y);
     } while (distance < 4);
 }
@@ -75,13 +46,13 @@ function generateEnemies() {
     // Generate between 0 and MAX_ENEMIES_ON_LEVEL enemies if the player's score is 4 or lower
     // Generate between MIN_ENEMIES_ON_LEVEL and MAX_ENEMIES_ON_LEVEL enemies if the player's score is 5 or higher
     const numEnemies = player.score > 4 
-    ? Math.floor(Math.random() * (MAX_ENEMIES_ON_LEVEL - MIN_ENEMIES_ON_LEVEL + 1)) + MIN_ENEMIES_ON_LEVEL 
-    : Math.floor(Math.random() * (MAX_ENEMIES_ON_LEVEL + 1));
+    ? Math.floor(Math.random() * (CONFIG.MAX_ENEMIES_ON_LEVEL - CONFIG.MIN_ENEMIES_ON_LEVEL + 1)) + CONFIG.MIN_ENEMIES_ON_LEVEL 
+    : Math.floor(Math.random() * (CONFIG.MAX_ENEMIES_ON_LEVEL + 1));
     for (let i = 0; i < numEnemies; i++) {
         let enemyX, enemyY;
         do {
-            enemyX = Math.floor(Math.random() * GRID_SIZE);
-            enemyY = Math.floor(Math.random() * GRID_SIZE);
+            enemyX = Math.floor(Math.random() * CONFIG.GRID_SIZE);
+            enemyY = Math.floor(Math.random() * CONFIG.GRID_SIZE);
         } while (
             (enemyX === player.x && enemyY === player.y) ||
             (enemyX === exit.x && enemyY === exit.y) ||
@@ -92,12 +63,12 @@ function generateEnemies() {
             color: COLORS.enemy,
             x: enemyX,
             y: enemyY,
-            health: Math.floor(Math.random() * (MAX_ENEMY_HEALTH - MIN_ENEMY_HEALTH + 1)) + MIN_ENEMY_HEALTH
+            health: Math.floor(Math.random() * (CONFIG.MAX_ENEMY_HEALTH - CONFIG.MIN_ENEMY_HEALTH + 1)) + CONFIG.MIN_ENEMY_HEALTH
         });
     }
 
     // Generate a boss enemy every ENEMY_BOSS_OCCURRENCE levels
-    if (player.score % ENEMY_BOSS_OCCURRENCE === 0 && player.score > 0) {
+    if (player.score % CONFIG.ENEMY_BOSS_OCCURRENCE === 0 && player.score > 0) {
         let bossX, bossY;
         do {
             bossX = exit.x; // Boss enemies always appear at the exit
@@ -110,17 +81,17 @@ function generateEnemies() {
             color: COLORS.boss,
             x: bossX,
             y: bossY,
-            health: MAX_ENEMY_HEALTH + 2
+            health: CONFIG.MAX_ENEMY_HEALTH + 2
         });
     }
 }
 
 function generateWallsNaive() {
     walls = [];
-    let numWalls = Math.floor(Math.random() * (WALLS_MAX - WALLS_MIN + 1)) + WALLS_MIN;
+    let numWalls = Math.floor(Math.random() * (CONFIG.WALLS_MAX - CONFIG.WALLS_MIN + 1)) + CONFIG.WALLS_MIN;
     while (walls.length < numWalls) {
-        const wallX = Math.floor(Math.random() * GRID_SIZE);
-        const wallY = Math.floor(Math.random() * GRID_SIZE);
+        const wallX = Math.floor(Math.random() * CONFIG.GRID_SIZE);
+        const wallY = Math.floor(Math.random() * CONFIG.GRID_SIZE);
 
         if (
             (wallX === player.x && wallY === player.y) ||                    // Check that a wall is not placed on the starting position
@@ -141,9 +112,9 @@ function generateWallsNaive() {
 
 function generateWallsDrunkardsWalk() {
     walls = [];
-    const numWalls = Math.floor(Math.random() * (WALLS_MAX - WALLS_MIN + 1)) + WALLS_MIN;
-    let wallX = Math.floor(Math.random() * GRID_SIZE);
-    let wallY = Math.floor(Math.random() * GRID_SIZE);
+    const numWalls = Math.floor(Math.random() * (CONFIG.WALLS_MAX - CONFIG.WALLS_MIN + 1)) + CONFIG.WALLS_MIN;
+    let wallX = Math.floor(Math.random() * CONFIG.GRID_SIZE);
+    let wallY = Math.floor(Math.random() * CONFIG.GRID_SIZE);
 
     while (walls.length < numWalls) {
     if (
@@ -160,9 +131,9 @@ function generateWallsDrunkardsWalk() {
     const direction = Math.floor(Math.random() * 4);
     switch (direction) {
         case 0: wallX = Math.max(0, wallX - 1); break;             // Move left
-        case 1: wallX = Math.min(GRID_SIZE - 1, wallX + 1); break; // Move right
+        case 1: wallX = Math.min(CONFIG.GRID_SIZE - 1, wallX + 1); break; // Move right
         case 2: wallY = Math.max(0, wallY - 1); break;             // Move up
-        case 3: wallY = Math.min(GRID_SIZE - 1, wallY + 1); break; // Move down
+        case 3: wallY = Math.min(CONFIG.GRID_SIZE - 1, wallY + 1); break; // Move down
     }
     }
 
@@ -173,11 +144,11 @@ function generateWallsDrunkardsWalk() {
 
 function generateWallsCellularAutomata() {
     walls = [];
-    const map = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(0));
+    const map = Array(CONFIG.GRID_SIZE).fill().map(() => Array(CONFIG.GRID_SIZE).fill(0));
 
     // Initialize a map with random walls
-    for (let x = 0; x < GRID_SIZE; x++) {
-        for (let y = 0; y < GRID_SIZE; y++) {
+    for (let x = 0; x < CONFIG.GRID_SIZE; x++) {
+        for (let y = 0; y < CONFIG.GRID_SIZE; y++) {
             if (Math.random() < 0.4) {
             map[x][y] = 1;
             }
@@ -186,11 +157,11 @@ function generateWallsCellularAutomata() {
 
     for (let i = 0; i < 4; i++) {
         // Create a new map to store the next state of the cellular automata
-        const newMap = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(0));
+        const newMap = Array(CONFIG.GRID_SIZE).fill().map(() => Array(CONFIG.GRID_SIZE).fill(0));
 
         // Iterate over each cell in the grid
-        for (let x = 0; x < GRID_SIZE; x++) {
-            for (let y = 0; y < GRID_SIZE; y++) {
+        for (let x = 0; x < CONFIG.GRID_SIZE; x++) {
+            for (let y = 0; y < CONFIG.GRID_SIZE; y++) {
                 // Count the number of neighboring walls
                 const neighbors = countNeighbors(map, x, y);
 
@@ -209,8 +180,8 @@ function generateWallsCellularAutomata() {
     }
 
     // Convert map to walls array
-    for (let x = 0; x < GRID_SIZE; x++) {
-        for (let y = 0; y < GRID_SIZE; y++) {
+    for (let x = 0; x < CONFIG.GRID_SIZE; x++) {
+        for (let y = 0; y < CONFIG.GRID_SIZE; y++) {
             if (map[x][y] === 1 && 
             (x !== player.x || y !== player.y) && 
             (x !== exit.x || y !== exit.y) && 
@@ -233,7 +204,7 @@ function countNeighbors(map, x, y) {
             if (dx === 0 && dy === 0) continue;
             const nx = x + dx;
             const ny = y + dy;
-            if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny < GRID_SIZE) {
+            if (nx >= 0 && nx < CONFIG.GRID_SIZE && ny >= 0 && ny < CONFIG.GRID_SIZE) {
                 count += map[nx][ny];
             } else {
                 count++; // Consider out-of-bounds bits as walls
@@ -245,15 +216,14 @@ function countNeighbors(map, x, y) {
 
 function generateWallsRSP() {
     walls = [];
-    const MIN_ROOM_SIZE = 2;
 
     function splitNode(x, y, width, height) {
         const splitHorizontally = Math.random() > 0.5;
-        const max = (splitHorizontally ? height : width) - MIN_ROOM_SIZE;
+        const max = (splitHorizontally ? height : width) - CONFIG.MIN_ROOM_SIZE;
 
-        if (max <= MIN_ROOM_SIZE) return [{ x, y, width, height }];
+        if (max <= CONFIG.MIN_ROOM_SIZE) return [{ x, y, width, height }];
 
-        const split = Math.floor(Math.random() * (max - MIN_ROOM_SIZE)) + MIN_ROOM_SIZE;
+        const split = Math.floor(Math.random() * (max - CONFIG.MIN_ROOM_SIZE)) + CONFIG.MIN_ROOM_SIZE;
 
         if (splitHorizontally) {
             return [
@@ -276,7 +246,7 @@ function generateWallsRSP() {
         return { x: roomX, y: roomY, width: roomWidth, height: roomHeight };
     }
 
-    const nodes = splitNode(0, 0, GRID_SIZE, GRID_SIZE);
+    const nodes = splitNode(0, 0, CONFIG.GRID_SIZE, CONFIG.GRID_SIZE);
     const rooms = nodes.map(createRoom);
 
     rooms.forEach(room => {
@@ -313,12 +283,12 @@ function generateWalls() {
 
 function generateItems() {
     items = [];
-    const numItems = Math.floor(Math.random() * (ITEMS_MAX - ITEMS_MIN + 1)) + ITEMS_MIN;
+    const numItems = Math.floor(Math.random() * (CONFIG.ITEMS_MAX - CONFIG.ITEMS_MIN + 1)) + CONFIG.ITEMS_MIN;
     for (let i = 0; i < numItems; i++) {
         let itemX, itemY;
         do {
-            itemX = Math.floor(Math.random() * GRID_SIZE);
-            itemY = Math.floor(Math.random() * GRID_SIZE);
+            itemX = Math.floor(Math.random() * CONFIG.GRID_SIZE);
+            itemY = Math.floor(Math.random() * CONFIG.GRID_SIZE);
         } while (
             (itemX === player.x && itemY === player.y) ||
             (itemX === exit.x && itemY === exit.y) ||
@@ -332,10 +302,10 @@ function generateItems() {
 }
 
 function isPassable() {
-    const visited = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(false));
+    const visited = Array(CONFIG.GRID_SIZE).fill().map(() => Array(CONFIG.GRID_SIZE).fill(false));
 
     function dfs(x, y) {
-        if (x < 0 || x >= GRID_SIZE || y < 0 || y >= GRID_SIZE) return false; // Are the coordinates in bounds?
+        if (x < 0 || x >= CONFIG.GRID_SIZE || y < 0 || y >= CONFIG.GRID_SIZE) return false; // Are the coordinates in bounds?
         if (visited[x][y]) return false;
         if (walls.some(wall => wall.x === x && wall.y === y)) return false;
         visited[x][y] = true;
@@ -349,8 +319,8 @@ function isPassable() {
 function drawGrid() {
     ctx.clearRect(0, 0, canvas.width, canvas.height);
     ctx.strokeStyle = COLORS.grid;
-    for (let row = 0; row < GRID_SIZE; row++) {
-        for (let col = 0; col < GRID_SIZE; col++) {
+    for (let row = 0; row < CONFIG.GRID_SIZE; row++) {
+        for (let col = 0; col < CONFIG.GRID_SIZE; col++) {
             ctx.strokeRect(col * tileSize, row * tileSize, tileSize, tileSize);
         }
     }
@@ -419,9 +389,9 @@ function drawEnemies() {
     enemies.forEach(enemy => {
         const x = enemy.x * tileSize + tileSize / 2;
         const y = enemy.y * tileSize + tileSize / 2;
-        const opacity = enemy.health / MAX_ENEMY_HEALTH; // Opacity based on health
+        const opacity = enemy.health / CONFIG.MAX_ENEMY_HEALTH; // Opacity based on health
         const radius = tileSize / 3;
-        const damageTaken = MAX_ENEMY_HEALTH - enemy.health;
+        const damageTaken = CONFIG.MAX_ENEMY_HEALTH - enemy.health;
 
         ctx.beginPath();
         ctx.arc(x, y, radius, 0, 2 * Math.PI);
@@ -436,7 +406,7 @@ function drawPlayer() {
     const x = player.x * tileSize + tileSize / 2;
     const y = player.y * tileSize + tileSize / 2;
     const radius = tileSize / 3;
-    const playerOpacity = player.health / PLAYER_HEALTH; // Opacity based on health
+    const playerOpacity = player.health / CONFIG.PLAYER_HEALTH; // Opacity based on health
     ctx.beginPath();
     for (let i = 0; i < 6; i++) {
         const angle = (Math.PI / 3) * i;
@@ -479,7 +449,7 @@ function handleItemCollection() {
             console.log("Collected diamond! +3 damage on this level.");
         } else if (collectedItem.type === 'pentagon') {
             const healAmount = Math.floor(Math.random() * 2) + 1;
-            player.health = Math.min(player.health + healAmount, PLAYER_MAX_HEALTH);
+            player.health = Math.min(player.health + healAmount, CONFIG.PLAYER_MAX_HEALTH);
             console.log("Collected pentagon! Healed " + healAmount + " health.");
         }
         items = items.filter(item => item !== collectedItem); // Remove collected item
@@ -500,12 +470,12 @@ function addCombatDots(x, y, color) {
     ];
 
     cellsToFill.forEach(([cellX, cellY]) => {
-        if (cellX >= 0 && cellX < GRID_SIZE && cellY >= 0 && cellY < GRID_SIZE) {
+        if (cellX >= 0 && cellX < CONFIG.GRID_SIZE && cellY >= 0 && cellY < CONFIG.GRID_SIZE) {
             const key = `${cellX},${cellY}`;
             if (!combatDots[key]) {
                 combatDots[key] = [];
             }
-            for (let i = 0; i < DOTS_PER_HIT; i++) {
+            for (let i = 0; i < CONFIG.DOTS_PER_HIT; i++) {
                 combatDots[key].push({
                     x: Math.random() * tileSize,
                     y: Math.random() * tileSize,
@@ -539,11 +509,11 @@ function movePlayer(dx, dy) {
 function moveEnemies() {
     enemies.forEach(enemy => {
         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 distanceToExit = Math.abs(enemy.x - exit.x) + Math.abs(enemy.y - exit.y); // FIXME: necessary?
 
         // If the enemy is closer to the exit than the player, move towards the exit
         // Bosses are more aggressive about chasing the player
-        const target = distanceToPlayer <= (enemy.isBoss ? ENEMY_CHASE_DISTANCE + 2 : ENEMY_CHASE_DISTANCE) ? player : exit;
+        const target = distanceToPlayer <= (enemy.isBoss ? CONFIG.ENEMY_CHASE_DISTANCE + 2 : CONFIG.ENEMY_CHASE_DISTANCE) ? player : exit;
         const path = findPath(enemy, target);
 
         if (path.length > 1) {
@@ -590,8 +560,8 @@ function findPath(start, goal) {
 
             // 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 &&
+                newX >= 0 && newX < CONFIG.GRID_SIZE &&
+                newY >= 0 && newY < CONFIG.GRID_SIZE &&
                 // Have we already been here?
                 !visited.has(key) &&
                 // Is it a wall?
@@ -659,7 +629,7 @@ function handleDamage(player, enemy) {
         enemies = enemies.filter(e => e !== enemy);                
         if (enemy.isBoss) {
             // Defeating a boss restores 3 player health
-            player.health = Math.min(player.health + 3, PLAYER_MAX_HEALTH);
+            player.health = Math.min(player.health + 3, CONFIG.PLAYER_MAX_HEALTH);
             console.log("Defeated a boss! Healed " + 3 + " health.");
         }
     }
@@ -679,8 +649,8 @@ function resetGame() {
     if (canvas.classList.contains('shake')) {
         canvas.classList.remove('shake');
     }
-    player.health = PLAYER_HEALTH;
-    player.damage = PLAYER_BASE_DAMAGE;
+    player.health = CONFIG.PLAYER_HEALTH;
+    player.damage = CONFIG.PLAYER_BASE_DAMAGE;
     player.bonusDamageTurns = 0;
     player.totalDamageDone = 0;
     player.totalDamageTaken = 0;
@@ -701,7 +671,7 @@ function resetGame() {
 function checkPlayerAtExit() {
     if (player.x === exit.x && player.y === exit.y) {
         player.score += 1;
-        player.damage = PLAYER_BASE_DAMAGE;
+        player.damage = CONFIG.PLAYER_BASE_DAMAGE;
         console.groupCollapsed("Level complete! " + player.score);
         console.log("Score: " + player.score);
         console.log("Current health: " + player.health);
@@ -794,7 +764,7 @@ const resizeCanvas = () => {
     const rect = canvas.getBoundingClientRect();
     canvas.width = rect.width;
     canvas.height = rect.height;
-    tileSize = canvas.width / GRID_SIZE; // Update tile size based on canvas dimensions
+    tileSize = canvas.width / CONFIG.GRID_SIZE; // Update tile size based on canvas dimensions
     render();
 };
 
diff --git a/html/broughlike/config.js b/html/broughlike/config.js
new file mode 100644
index 0000000..5897c27
--- /dev/null
+++ b/html/broughlike/config.js
@@ -0,0 +1,32 @@
+export const COLORS = {
+    grid: '#2d2d2d',
+    walls: '#2d2d2d',
+    exit: 'teal',
+    diamond: 'gold',
+    pentagon: 'blueviolet', 
+    player: 'rgba(0, 237, 209, ',
+    enemy: 'rgba(255, 155, 28, ',
+    boss: 'rgba(255, 14, 0, ',
+    combatDotPlayer: '#00edd1',
+    combatDotEnemy: '#ff731c',
+    combatDotBoss: '#b70030'
+};
+
+export const CONFIG = {
+    GRID_SIZE: 6,
+    PLAYER_HEALTH: 12,
+    PLAYER_MAX_HEALTH: 16,
+    PLAYER_BASE_DAMAGE: 1,
+    ENEMY_CHASE_DISTANCE: 4,
+    ENEMY_BOSS_OCCURRENCE: 10,
+    MIN_ENEMIES_ON_LEVEL: 1,
+    MAX_ENEMIES_ON_LEVEL: 4,
+    MAX_ENEMY_HEALTH: 7,
+    MIN_ENEMY_HEALTH: 2,
+    MIN_ROOM_SIZE: 4,
+    WALLS_MIN: 7,
+    WALLS_MAX: 20,
+    ITEMS_MIN: 1,
+    ITEMS_MAX: 3,
+    DOTS_PER_HIT: 7
+};
diff --git a/html/broughlike/index.html b/html/broughlike/index.html
index 62a43ac..4de1d9d 100644
--- a/html/broughlike/index.html
+++ b/html/broughlike/index.html
@@ -59,6 +59,6 @@
         </div>
     </div>
     <canvas id="gameCanvas"></canvas>
-    <script src="./broughlike.js"></script>
+    <script type="module" src="./broughlike.js"></script>
 </body>
 </html>
\ No newline at end of file