'use strict'; // === GAME STATE === let gameState; function initGameState() { gameState = window.gameState = { // Screen/dungeon state currentDungeon: null, currentRoomIdx: 0, dungeonRooms: null, currentRoom: null, // Player player: { x: 0, y: 0, hp: 12, maxHp: 12, dir: 0, // 0=down, 1=up, 2=left, 3=right moveTimer: 0, attackTimer: 0, attackAnim: 0, hitTimer: 0, invincibleTimer: 0, invincible: false, weapons: [], activeWeapon: null, items: [], bombs: 0, arrows: 0, keys: 0, }, // Room state layout: null, rocks: [], targets: [], chests: [], enemies: [], exit: null, exitOpen: false, torches: [], doors: [], levers: [], switches: [], traps: [], softwalls: [], currentBoss: null, floorItems: [], // Messages message: '', messageTimer: 0, // Particles particles: [], // Stats roomsCleared: 0, enemiesDefeated: 0, dungeonsCompleted: 0, }; } function resetPlayer() { gameState.player.hp = gameState.player.maxHp; gameState.player.x = 0; gameState.player.y = 0; gameState.player.dir = 0; gameState.player.moveTimer = 0; gameState.player.attackTimer = 0; gameState.player.attackAnim = 0; gameState.player.hitTimer = 0; gameState.player.invincibleTimer = 1000; } function showMessage(text) { gameState.message = text; gameState.messageTimer = MESSAGE_DURATION; } // === ROOM LOADING === function loadDungeonRoom(dungeonIdx, roomIdx) { const rooms = gameState.dungeonRooms; if (!rooms || roomIdx >= rooms.length) return; gameState.currentDungeon = dungeonIdx; gameState.currentRoomIdx = roomIdx; const room = rooms[roomIdx]; // BSP generator produces room.tiles; legacy generators produce room.layout gameState.layout = room.layout ? cloneLayout(room.layout) : (room.tiles ? cloneLayout(room.tiles) : createEmptyLayout()); // Compute player start position if (room.playerStart) { gameState.player.x = room.playerStart.x; gameState.player.y = room.playerStart.y; } else { // Default: entrance starts at left-center, boss at left-center, others at center if (room.type === 'entrance') { gameState.player.x = 2; gameState.player.y = Math.floor(ROWS / 2); } else if (room.type === 'boss') { gameState.player.x = 2; gameState.player.y = Math.floor(ROWS / 2); } else { gameState.player.x = Math.floor(COLS / 2); gameState.player.y = Math.floor(ROWS / 2); } } gameState.rocks = room.rocks ? room.rocks.map(r => ({ ...r })) : []; gameState.targets = room.targets ? room.targets.map(t => ({ ...t })) : []; gameState.chests = room.chests ? room.chests.map(c => ({ ...c, opened: false })) : []; gameState.enemies = room.enemies ? room.enemies.map(e => ({ ...e, moveTimer: ENEMY_MOVE_INTERVAL, attackTimer: ENEMY_ATTACK_INTERVAL, hitTimer: 0, projectileTimer: 0, specialTimer: 0, phase: 0, stunned: false, frozen: false, })) : []; gameState.exit = room.exit ? { ...room.exit } : (room.hasBoss ? { x: COLS - 1, y: Math.floor(ROWS / 2), dir: 3 } : null); gameState.exitOpen = room.exitOpen || false; gameState.torches = room.torches ? room.torches.map(t => [...t]) : []; gameState.doors = room.doors ? room.doors.map(d => ({ ...d })) : []; gameState.levers = room.levers ? room.levers.map(l => ({ ...l })) : []; gameState.switches = room.switches ? room.switches.map(s => ({ ...s, activated: false })) : []; gameState.traps = room.traps ? room.traps.map(t => ({ ...t, triggered: false })) : []; gameState.softwalls = room.softwalls ? room.softwalls.map(s => [...s]) : []; gameState.currentRoom = room; gameState.currentBoss = room.boss ? { ...room.boss, moveTimer: ENEMY_MOVE_INTERVAL, attackTimer: ENEMY_ATTACK_INTERVAL, hitTimer: 0, phase: 0, rng: createRNG((gameState.currentDungeon + 1) * 1000 + roomIdx) } : null; gameState.floorItems = room.floorItems ? room.floorItems.map(i => ({ ...i, collected: false })) : []; gameState.particles = []; gameState.message = room.name || `Room ${roomIdx + 1}`; gameState.messageTimer = MESSAGE_DURATION; } if (typeof module !== 'undefined' && module.exports) { module.exports = { initGameState, loadDungeonRoom, showMessage, resetPlayer }; }