Repository navigation
Dungeon Generation
JSON describes the rooms and their connections. The dungeon system builds one active room at a time from rooms.json.
rooms.json
↓ FileLoader
WorldConfig and RoomConfig
↓ RoomManager selects one room
RoomFactory
↓
Active room entity and its components
↓ RoomCreated event
Enemies, obstacles, exits and walls are spawned
The main classes are:
-
WorldConfig: holds the complete room graph and validates its references. -
RoomConfig: describes one room's size and contents. -
RoomManager: owns the active room, player, camera and runtime progress. -
RoomFactory: assembles a room entity from oneRoomConfig. -
TerrainFactory: creates the room's dungeon floor. -
EnemyManagerComponent,ObstacleComponentandExitComponent: create the configured room contents.
When MainGameScreen is created:
-
FileLoaderreadsconfigs/rooms.jsoninto aWorldConfig. -
RoomManagervalidates the world references. - It finds
startRoomIdandstartEntryPointId. -
RoomFactorycreates the starting room entity. -
RoomManager.create()registers the room and player. - The room receives a
RoomCreatedevent. - The player is placed at the configured starting entry point.
RoomFactory.createRoom(room, camera, cleared) builds an ECS entity containing:
| Component | Responsibility |
|---|---|
RoomAssetsComponent |
Loads the shared dungeon, enemy, fixture and audio assets. |
GameAreaDisplay |
Displays the room title and temporary status messages. |
TerrainComponent |
Renders terrain using the configured width and height. |
WallComponent |
Creates four physics boundaries around the terrain. |
FollowingCameraComponent |
Keeps the camera focused on the player within the room. |
ObstacleComponent |
Creates every configured rock and barrel. |
ExitComponent |
Creates the visible doors and bookshelves. |
EnemyManagerComponent |
Creates and tracks the room's configured enemies. |
RoomConfig.mapWidth and mapHeight determine the terrain bounds. TerrainFactory fills those bounds with the Fantasy Dreamland floor and applies scattered floor variants.
Every position in JSON is stored in tiles. Components call TerrainComponent.tileToWorldPosition() when placing entities, so the configuration does not depend on renderer scale.
The JSON does not currently choose every individual floor tile. It controls room dimensions and gameplay content placed on top of the shared terrain.
Once the room is registered, its components create their owned entities:
-
WallComponentcreates four invisible boundary walls. -
ObstacleComponentreads each obstacle type and callsObstacleFactory. -
ExitComponentrenders doors and bookshelves at their declared positions. -
EnemyManagerComponentcreates each configured enemy throughNPCFactoryand tracks it until death.
Entities created by these components belong to the active room. Disposing the room also removes its walls, fixtures, enemies and room-owned projectiles.
Pressing E emits the player's interact event. RoomManager then:
- Finds the nearest configured exit within interaction range.
- Shows a message if the exit is unavailable.
- Blocks entry into an already completed dungeon.
- Blocks exits marked
requiresClearwhile enemies remain. - Records the current room as cleared when appropriate.
- Records dungeon completion when
completesDungeonis true. - Stores the requested destination for the next safe update.
The transition is not performed directly inside the input event. MainGameScreen first completes physics and entity updates, then calls RoomManager.update(). This keeps room creation and disposal outside a locked Box2D update.
A paired door points to a door in another room, and that destination door points back. WorldConfig.validate() ensures the references are reciprocal and their sides are opposite.
When the transition runs, the player is positioned three tiles inside the destination door:
-
LEFT: move right from the door. -
RIGHT: move left from the door. -
TOP: move down from the door. -
BOTTOM: move up from the door.
This makes returning through a door place the player beside the corresponding physical entrance rather than at a generic room spawn.
EnemyManagerComponent fires roomCleared after all tracked enemies are defeated. RoomManager keeps two small runtime hashsets:
-
clearedRoomIds: rooms that should not respawn enemies. -
completedDungeonIds: entire dungeons that can no longer be selected.
The in-game terminal command below clears every tracked enemy in the active room:
room clear