-- Room management: selection, spawning, transitions RoomManager = {} RoomManager.__index = RoomManager function RoomManager:new(assetLoader) self = setmetatable({}, RoomManager) self.assetLoader = assetLoader self.currentBiomeIdx = 0 self.currentBiome = nil self.roomCount = 0 self.currentRoomCollision = nil self.currentRoomVisual = nil self.currentRoomConfig = nil return self end function RoomManager:getCurrentBiome() if self.roomCount % Config.ROOMS_PER_BIOME == 0 then self.currentBiomeIdx = self.currentBiomeIdx + 1 local biomePool = Config.BIOME_SELECT[self.currentBiomeIdx] self.currentBiome = Utils.pickRandomKeyFromWeightedTable(biomePool) end return self.currentBiome end function RoomManager:selectNextRoom() local currentBiome = self:getCurrentBiome() return Utils.pickRandomKeyFromWeightedTable(Config.BIOMES[currentBiome].rooms) end function RoomManager:loadRoom(roomName) local asset = self.assetLoader:loadRoom(roomName) self.currentRoomCollision = asset.imageDataLoader("collision_mask") self.currentRoomVisual = RoomVisuals[asset.config.visual or "default"]:new(asset) self.currentRoomConfig = asset.config or {} self.roomCount = self.roomCount + 1 end function RoomManager:findPlayerSpawnPosition() -- Scan left area columns, find lowest solid pixel in each column local spawnAreaMinWidth = 32 local spawnAreaMinHeight = 32 for x = 0, Config.ROOM_W do for y = Config.ROOM_H - spawnAreaMinWidth, 0, -1 do if not self:isSolidAt(x, y) and not self:isSolidAt(x + spawnAreaMinWidth, y) and not self:isSolidAt(x, y - spawnAreaMinHeight) and not self:isSolidAt(x + spawnAreaMinWidth, y - spawnAreaMinHeight) then return x, y end end end return 0, 0 end function RoomManager:findFloor(x, y, entityHeight) for y = y, Config.ROOM_H - entityHeight do if self:isSolidAt(x, y) then return x, y - (entityHeight / 2) end end return 0, 0 end function RoomManager:isSolidAt(x, y) if self.currentRoomCollision then return Utils.maskIsSolidAt(x, y, self.currentRoomCollision) end return false end return RoomManager