about summary refs log tree commit diff stats
path: root/html/broughlike/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'html/broughlike/index.html')
-rw-r--r--html/broughlike/index.html548
1 files changed, 37 insertions, 511 deletions
diff --git a/html/broughlike/index.html b/html/broughlike/index.html
index ef547e7..4de1d9d 100644
--- a/html/broughlike/index.html
+++ b/html/broughlike/index.html
@@ -8,6 +8,7 @@
     <style>
         body {
             background-color: #f0f0f0;
+            font-size: x-large;
         }
         canvas {
             width: 90vw; 
@@ -19,520 +20,45 @@
             margin: 0 auto;
             background-color: #f0f0f0;
         }
+        @keyframes shake {
+            0% { transform: translate(0.5px, 0.5px) rotate(0deg); }
+            10% { transform: translate(-0.5px, -1px) rotate(-0.5deg); }
+            20% { transform: translate(-1.5px, 0px) rotate(0.5deg); }
+            30% { transform: translate(1.5px, 1px) rotate(0deg); }
+            40% { transform: translate(0.5px, -0.5px) rotate(0.5deg); }
+            50% { transform: translate(-0.5px, 1px) rotate(-0.5deg); }
+            60% { transform: translate(-1.5px, 0.5px) rotate(0deg); }
+            70% { transform: translate(1.5px, 0.5px) rotate(-0.5deg); }
+            80% { transform: translate(-0.5px, -0.5px) rotate(0.5deg); }
+            90% { transform: translate(0.5px, 1px) rotate(0deg); }
+            100% { transform: translate(0.5px, -1px) rotate(-0.5deg); }
+        }
+        .shake {
+            animation: shake 0.5s;
+            animation-iteration-count: 1;
+            animation-timing-function: steps(10, end);
+        }
+        .header {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            padding: 0 0.5em;
+            background-color: #f0f0f0;
+        }
+        .toggleButton {
+            padding: 0.75em;
+            margin: 0.5em;
+        }
     </style>
 </head>
 <body>
-    <p><a href="about.html">About</a></p>
+    <div class="header">
+        <p><a href="about.html">About</a></p>
+        <div>
+            <button class="toggleButton" id="toggleShake" onclick="toggleShake()">Turn Shake Off</button>
+        </div>
+    </div>
     <canvas id="gameCanvas"></canvas>
-    <script>
-
-        const COLORS = {
-            grid: '#2d2d2d',
-            walls: '#2d2d2d',
-            exit: 'teal',
-            diamond: 'gold',
-            pentagon: 'blueviolet', 
-            player: 'rgba(0, 237, 209, ',
-            enemy: 'rgba(255, 155, 28, ',
-            combatDotPlayer: '#00edd1',
-            combatDotEnemy: '#ff731c'
-        };
-
-        const GRID_SIZE = 6;
-        const PLAYER_HEALTH = 10;
-        const PLAYER_MAX_HEALTH = 12;
-        const PLAYER_BASE_DAMAGE = 1;
-        const ENEMY_CHASE_DISTANCE = 4;
-        const MAX_ENEMIES_ON_LEVEL = 4;
-        const MAX_ENEMY_HEALTH = 7;
-        const MIN_ENEMY_HEALTH = 2;
-        const WALLS_MIN = 5;
-        const WALLS_MAX = 20;
-        const ITEMS_MIN = 0;
-        const ITEMS_MAX = 3;
-        const DOTS_PER_HIT = 5;
-
-        const canvas = document.getElementById('gameCanvas');
-        const ctx = canvas.getContext('2d');
-        let tileSize = canvas.width / GRID_SIZE;
-
-        const player = {
-            x: 0,
-            y: 0,
-            health: PLAYER_HEALTH,
-            score: 0,
-            damage: PLAYER_BASE_DAMAGE,
-            totalDamageDone: 0,
-            totalDamageTaken: 0,
-            cellsTraveled: 0
-        };
-
-        const exit = { x: Math.floor(Math.random() * GRID_SIZE), y: Math.floor(Math.random() * GRID_SIZE) };
-        let walls = [];
-        let enemies = [];
-        let items = [];
-        let combatDots = {};
-
-        function isValidMove(newX, newY) {
-            return (
-                newX >= 0 && newX < GRID_SIZE &&
-                newY >= 0 && newY < GRID_SIZE &&
-                !walls.some(wall => wall.x === newX && wall.y === newY)
-            );
-        }
-
-        function generateExit() {
-            let distance = 0;
-            do {
-                exit.x = Math.floor(Math.random() * GRID_SIZE);
-                exit.y = Math.floor(Math.random() * GRID_SIZE);
-                distance = Math.abs(exit.x - player.x) + Math.abs(exit.y - player.y);
-            } while (distance < 4);
-        }
-
-        function generateEnemies() {
-            enemies = [];
-            const numEnemies = Math.floor(Math.random() * (MAX_ENEMIES_ON_LEVEL + 1)); // Between 0 and the constant value.
-            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);
-                } while (
-                    (enemyX === player.x && enemyY === player.y) ||
-                    (enemyX === exit.x && enemyY === exit.y) ||
-                    walls.some(wall => wall.x === enemyX && wall.y === enemyY)
-                );
-                enemies.push({
-                    x: enemyX,
-                    y: enemyY,
-                    health: Math.floor(Math.random() * (MAX_ENEMY_HEALTH - MIN_ENEMY_HEALTH + 1)) + MIN_ENEMY_HEALTH
-                });
-            }
-        }
-
-        function generateWalls() {
-            walls = [];
-            let numWalls = Math.floor(Math.random() * (WALLS_MAX - WALLS_MIN + 1)) + WALLS_MIN;
-            while (walls.length < numWalls) {
-                const wallX = Math.floor(Math.random() * GRID_SIZE);
-                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)
-                ) continue;
-
-                if (!walls.some(wall => wall.x === wallX && wall.y === wallY)) {
-                    walls.push({ x: wallX, y: wallY });
-                }
-            }
-
-            if (!isPassable()) {
-                generateWalls();
-            }
-        }
-
-        function generateItems() {
-            items = [];
-            const numItems = Math.floor(Math.random() * (ITEMS_MAX - ITEMS_MIN + 1)) + 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);
-                } while (
-                    (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)
-                );
-                const itemType = Math.random() < 0.5 ? 'diamond' : 'pentagon'; // 50% chance for each type
-                items.push({ x: itemX, y: itemY, type: itemType });
-            }
-        }
-
-        function isPassable() {
-            const visited = Array(GRID_SIZE).fill().map(() => Array(GRID_SIZE).fill(false));
-
-            function dfs(x, y) {
-                if (x < 0 || x >= GRID_SIZE || y < 0 || y >= GRID_SIZE) return false;
-                if (visited[x][y]) return false;
-                if (walls.some(wall => wall.x === x && wall.y === y)) return false;
-                visited[x][y] = true;
-                if (x === exit.x && y === exit.y) return true;
-
-                return dfs(x + 1, y) || dfs(x - 1, y) || dfs(x, y + 1) || dfs(x, y - 1);
-            }
-
-            return dfs(player.x, player.y);
-        }
-
-        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++) {
-                    ctx.strokeRect(col * tileSize, row * tileSize, tileSize, tileSize);
-                }
-            }
-        }
-
-        function drawExit() {
-            const x = exit.x * tileSize + tileSize / 2;
-            const y = exit.y * tileSize + tileSize / 2;
-            ctx.beginPath();
-            ctx.moveTo(x, y - tileSize / 3);
-            ctx.lineTo(x + tileSize / 3, y + tileSize / 3);
-            ctx.lineTo(x - tileSize / 3, y + tileSize / 3);
-            ctx.closePath();
-            ctx.fillStyle = COLORS.exit;
-            ctx.fill();
-        }
-
-        function drawWalls() {
-            ctx.fillStyle = COLORS.walls;
-            walls.forEach(wall => {
-                ctx.fillRect(wall.x * tileSize, wall.y * tileSize, tileSize, tileSize);
-            });
-        }
-
-        function drawItems() {
-            items.forEach(item => {
-                const x = item.x * tileSize + tileSize / 2;
-                const y = item.y * tileSize + tileSize / 2;
-                ctx.fillStyle = item.type === 'diamond' ? COLORS.diamond : COLORS.pentagon;
-                ctx.beginPath();
-                if (item.type === 'diamond') {
-                    ctx.moveTo(x, y - tileSize / 4);
-                    ctx.lineTo(x + tileSize / 4, y);
-                    ctx.lineTo(x, y + tileSize / 4);
-                    ctx.lineTo(x - tileSize / 4, y);
-                } else {
-                    const sides = 5;
-                    const radius = tileSize / 4;
-                    for (let i = 0; i < sides; i++) {
-                        const angle = (i * 2 * Math.PI) / sides - Math.PI / 2;
-                        const pointX = x + radius * Math.cos(angle);
-                        const pointY = y + radius * Math.sin(angle);
-                        if (i === 0) ctx.moveTo(pointX, pointY);
-                        else ctx.lineTo(pointX, pointY);
-                    }
-                }
-                ctx.closePath();
-                ctx.fill();
-            });
-        }
-
-        function drawCharacterBorder(x, y, radius, damageTaken) {
-            const dashLength = 5;
-            const gapLength = Math.max(1, damageTaken * 2); // More damage, larger gaps
-
-            ctx.lineWidth = 2;
-            ctx.strokeStyle = '#2d2d2d';
-            ctx.setLineDash([dashLength, gapLength]);
-            ctx.beginPath();
-            ctx.arc(x, y, radius, 0, 2 * Math.PI);
-            ctx.stroke();
-            ctx.setLineDash([]); // Reset to a solid line
-        }
-
-        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 radius = tileSize / 3;
-                const damageTaken = MAX_ENEMY_HEALTH - enemy.health;
-
-                ctx.beginPath();
-                ctx.arc(x, y, radius, 0, 2 * Math.PI);
-                ctx.fillStyle = `${COLORS.enemy}${opacity})`;
-                ctx.fill();
-
-                drawCharacterBorder(x, y, radius, damageTaken);
-            });
-        }
-
-        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
-            ctx.beginPath();
-            for (let i = 0; i < 6; i++) {
-                const angle = (Math.PI / 3) * i;
-                const hexX = x + radius * Math.cos(angle);
-                const hexY = y + radius * Math.sin(angle);
-                if (i === 0) {
-                    ctx.moveTo(hexX, hexY);
-                } else {
-                    ctx.lineTo(hexX, hexY);
-                }
-            }
-            ctx.closePath();
-            ctx.fillStyle = `${COLORS.player}${playerOpacity})`;
-            ctx.fill();
-            ctx.lineWidth = 2;
-            ctx.strokeStyle = '#2d2d2d';
-            ctx.stroke();
-        }
-
-        function drawCombatDots() {
-            for (const key in combatDots) {
-                const [cellX, cellY] = key.split(',').map(Number);
-                const dots = combatDots[key];
-                dots.forEach(dot => {
-                    ctx.beginPath();
-                    ctx.arc(cellX * tileSize + dot.x, cellY * tileSize + dot.y, 2, 0, Math.PI * 2);
-                    ctx.fillStyle = dot.color;
-                    ctx.fill();
-                    ctx.closePath();
-                });
-            }
-        }
-
-        function handleItemCollection() {
-            const collectedItem = items.find(item => item.x === player.x && item.y === player.y);
-            if (collectedItem) {
-                if (collectedItem.type === 'diamond') {
-                    player.damage += 3;
-                    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);
-                    console.log("Collected pentagon! Healed " + healAmount + " health.");
-                }
-                items = items.filter(item => item !== collectedItem); // Remove collected item
-            }
-        }
-
-        // 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 - 1, y - 1], // Top-left
-                [x + 1, y - 1], // Top-right
-                [x - 1, y + 1], // Bottom-left
-                [x + 1, y + 1]  // Bottom-right
-            ];
-
-            cellsToFill.forEach(([cellX, cellY]) => {
-                if (cellX >= 0 && cellX < GRID_SIZE && cellY >= 0 && cellY < GRID_SIZE) {
-                    const key = `${cellX},${cellY}`;
-                    if (!combatDots[key]) {
-                        combatDots[key] = [];
-                    }
-                    for (let i = 0; i < DOTS_PER_HIT; i++) {
-                        combatDots[key].push({
-                            x: Math.random() * tileSize,
-                            y: Math.random() * tileSize,
-                            color: color
-                        });
-                    }
-                }
-            });
-        }
-
-        function movePlayer(dx, dy) {
-            const newX = player.x + dx;
-            const newY = player.y + dy;
-            if (isValidMove(newX, newY)) {
-                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
-                    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;
-                    }
-                }
-            });
-        }
-
-        function handleDamage(player, enemy) {
-            const enemyMisses = Math.random() < 0.2; // 1 in 5 chance the enemy misses you
-            const cellX = player.x;
-            const cellY = player.y;
-
-            if (!enemyMisses) {
-                player.health--;
-                player.totalDamageTaken++;
-                addCombatDots(cellX, cellY, COLORS.combatDotPlayer); // Add dots for player damage
-                console.log("Enemy hit! Player health: " + player.health);
-            } else {                
-                console.log("Enemy missed!");
-            }
-
-            enemy.health = enemy.health - player.damage;
-            player.totalDamageDone++;
-            addCombatDots(cellX, cellY, COLORS.combatDotEnemy); // Add dots for enemy damage
-            console.log("Player hit! Enemy health: " + enemy.health);
-
-            if (enemy.health <= 0) {
-                enemies = enemies.filter(e => e !== enemy);
-            }
-
-            if (player.health <= 0) {
-                alert(`Dead\n\nScore: ${player.score}\nDistance Traveled: ${player.cellsTraveled}\nTotal Damage Dealt: ${player.totalDamageDone}\nTotal Damage Received: ${player.totalDamageTaken}`);
-                resetGame();
-            }
-        }
-
-        function resetGame() {
-            player.health = PLAYER_HEALTH;
-            player.damage = PLAYER_BASE_DAMAGE;
-            player.bonusDamageTurns = 0;
-            player.totalDamageDone = 0;
-            player.totalDamageTaken = 0;
-            player.cellsTraveled = 0;
-            player.score = 0;
-            player.x = 0;
-            player.y = 0;
-            combatDots = {};
-            generateExit();
-            generateEnemies();
-            generateItems();
-            generateWalls();
-            render();
-        }
-
-        function checkPlayerAtExit() {
-            if (player.x === exit.x && player.y === exit.y) {
-                player.score += 1;
-                player.damage = PLAYER_BASE_DAMAGE;
-                console.group("Level complete! " + player.score);
-                console.log("Score: " + player.score);
-                console.log("Current health: " + player.health);
-                console.log("Distance Traveled: " + player.cellsTraveled);
-                console.log("Total Damage Dealt: " + player.totalDamageDone);
-                console.log("Total Damage Received: " + player.totalDamageTaken);
-                console.groupEnd();
-                combatDots = {};
-                generateExit();
-                generateEnemies();
-                generateItems();
-                generateWalls();
-                render();
-            }
-        }
-
-        function render() {
-            drawGrid();
-            drawExit();
-            drawItems();
-            drawEnemies();
-            drawPlayer();
-            drawWalls();
-            drawCombatDots();
-        }
-
-        const directionMap = {
-            ArrowUp: [0, -1],
-            ArrowDown: [0, 1],
-            ArrowLeft: [-1, 0],
-            ArrowRight: [1, 0],
-            w: [0, -1],
-            s: [0, 1],
-            a: [-1, 0],
-            d: [1, 0],
-            h: [-1, 0],
-            j: [0, 1],
-            k: [0, -1],
-            l: [1, 0]
-        };
-
-        document.addEventListener('keydown', (e) => {
-            const direction = directionMap[e.key];
-            if (direction) {
-                movePlayer(...direction);
-                checkPlayerAtExit();
-                render();
-            }
-        });
-
-        let touchStartX = 0;
-        let touchStartY = 0;
-
-        canvas.addEventListener('touchstart', (e) => {
-            e.preventDefault(); // Prevent scrolling on touchstart
-            touchStartX = e.touches[0].clientX;
-            touchStartY = e.touches[0].clientY;
-        });
-
-        canvas.addEventListener('touchend', (e) => {
-            e.preventDefault(); // Prevent scrolling on touchend
-            const touchEndX = e.changedTouches[0].clientX;
-            const touchEndY = e.changedTouches[0].clientY;
-            const dx = touchEndX - touchStartX;
-            const dy = touchEndY - touchStartY;
-
-            if (Math.abs(dx) > Math.abs(dy)) {
-                // Horizontal swipe
-                if (dx > 0) {
-                    movePlayer(1, 0); // Swipe right
-                } else {
-                    movePlayer(-1, 0); // Swipe left
-                }
-            } else {
-                // Vertical swipe
-                if (dy > 0) {
-                    movePlayer(0, 1); // Swipe down
-                } else {
-                    movePlayer(0, -1); // Swipe up
-                }
-            }
-
-            render();
-        }, { passive: false }); // TIL you can use passive set to false to help make preventDefault actually work? Feels like superstition
-
-        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
-            render();
-        };
-
-        window.addEventListener('resize', resizeCanvas);
-        resizeCanvas();
-
-        // Initial level setup
-        generateExit();
-        generateEnemies();
-        generateItems();
-        generateWalls();
-        render();
-    </script>
+    <script type="module" src="./broughlike.js"></script>
 </body>
 </html>
\ No newline at end of file