Core Game Loop and Turn Management
Relevant source files
The following files were used as context for generating this wiki page:
- core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java
- core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Actor.java
- SPD-classes/src/main/java/com/watabou/noosa/Game.java
- core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java
- core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java
- core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/changelist/v1_X_Changes.java
- core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/changelist/v0_7_X_Changes.java
The core game loop and turn management system is the foundation of Shattered Pixel Dungeon's gameplay. It orchestrates the sequence of actions for all characters (the hero, monsters, and allies) in a turn-based manner. This system is driven by a time-based cooldown mechanism, where each action consumes a certain amount of time, and the character with the lowest cooldown gets to act next.
The main components are the Game class, which handles the top-level update loop; the GameScene, which manages the gameplay state and actor turns; and the Actor class, which defines the behavior and action cost for all characters. The Dungeon and Level classes serve as central repositories for the current game and floor state, respectively.
System Architecture
The game loop is initiated by the Game class and delegated to the active GameScene. The GameScene then manages the turn-based logic by iterating through all active Actor instances, allowing them to perform actions based on their cooldown value.
Key Classes and Their Roles
| Class | Role | Relevant Files |
|---|---|---|
Game | The main application class. Its update() method drives the entire game, calling the current scene's update method. | SPD-classes/src/main/java/com/watabou/noosa/Game.java |
GameScene | Manages the primary gameplay screen. Its update() method contains the logic for processing actor turns. | core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java |
Dungeon | A static class that acts as a global state container for the current run, holding references to the hero, current level, gold, etc. | core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java |
Level | Represents a single floor of the dungeon. It contains collections of mobs, items (heaps), traps, and other level-specific data. | core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java |
Actor | The base class for all characters in the game (Hero, Mobs). It manages the core turn logic through its cooldown and act() method. | core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Actor.java |
Architectural Diagram
The following diagram illustrates the relationships between the core classes involved in the game loop and turn management.
Sources: SPD-classes/src/main/java/com/watabou/noosa/Game.java, core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java, core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java, core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java, core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Actor.java
The Game Loop
The game loop is a continuous process that updates the game state and renders the screen. In Shattered Pixel Dungeon, this loop is tied to the turn-based mechanics.
Entry Point: Game.update()
The loop begins in com.watabou.noosa.Game.update(). This method is called on every frame. It calculates the time elapsed since the last frame and calls the update() method of the currently active scene, which is typically GameScene during gameplay.
Sources: SPD-classes/src/main/java/com/watabou/noosa/Game.java:115-122
GameScene.update()
The GameScene.update() method is the heart of the turn-based logic. It repeatedly calls processTurn() as long as the hero has a pending action or there are other actors ready to act.
The core logic is as follows:
- If the hero has a defined
nextAction, it is executed. - If not, the system finds the actor with the lowest
cooldown. - If that actor's
cooldownis greater than 0, it means all actors are waiting, and their cooldowns are decremented. - If the actor's
cooldownis 0 or less, that actor'sact()method is called. - The loop continues until it's the hero's turn and they have no pending action, at which point the game waits for player input.
Sources: core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java:232-254
This diagram shows the high-level flow of the main game loop.
Turn and Time Management
Shattered Pixel Dungeon uses a time-based system to manage turns. Every action has a time cost, and actors can only act when their cooldown reaches zero.
The Cooldown System
The Actor class contains a cooldown field, which represents the amount of time that actor must wait before it can act again.
cooldown: Afloatvalue. When it is0or less, the actor is ready to act.act(): This method is called when it is the actor's turn. It contains the logic for what the actor does (e.g., AI for mobs, executing player commands for the hero).spend(float time): After performing an action, an actor calls this method to add the action's time cost to itscooldown. A standard move or attack costs1.0time.
Sources: core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Actor.java:60, 207, 223
Actor Turn Sequence
The following sequence diagram illustrates how the GameScene manages turns between the Hero and other actors (Mobs).
Action Costs
Most standard actions, like moving or attacking, cost 1.0 turn. However, some actions have different costs. For example, the wait action always costs exactly 1 turn, regardless of hero speed. This is a specific balance change made to standardize its behavior.
Sources: core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/changelist/v1_X_Changes.java:319
Dropping an item costs 1.0 turn, a change from a previous value of 0.5.
Sources: core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/changelist/v0_7_X_Changes.java:505
State Management
The state of the game is managed by a combination of the Dungeon and Level classes.
Dungeon Class
The Dungeon class is a static singleton that holds the global state for the entire run. This includes:
hero: The player character instance.level: The currentLevelobject the hero is on.depthandbranch: The current location in the dungeon.goldandenergy: Global player resources.challenges: Bitmask of active challenges.seed: The seed for the current run.
It also contains the primary methods for saving and loading the game state, saveGame() and loadGame().
Sources: core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java:116-140, 608-683
Level Class
The Level class encapsulates the state of a single dungeon floor. When the player moves between floors, a new Level object is created or loaded, and the Dungeon.level static field is updated.
Key responsibilities of the Level class include:
- Storing the map layout (
map) and terrain properties (passable,losBlocking, etc.). - Managing all
Mobinstances on the floor in aHashSet<Mob> mobs. - Managing all items on the ground in a
SparseArray<Heap> heaps. - Handling mob spawning via
createMob()and aMobSpawner.
When a turn is processed, the GameScene iterates through the actors in the current Dungeon.level.mobs collection, plus the Dungeon.hero.
Sources: core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java:123-137, 442-452
Saving and Loading
The game's state is persisted through a serialization process using Bundle objects.
Dungeon.saveGame(): Saves global run information (hero stats, inventory, depth, seed, challenges, etc.) to a main game file.Dungeon.saveLevel(): Saves the state of the currentLevel(mob positions, item heaps, map state) to a separate file named after the depth and branch.Dungeon.loadGame()/Dungeon.loadLevel(): The corresponding methods to restore the state from files.
This separation allows the game to keep only the current level in memory, loading other floors from disk as needed. The generatedLevels list in Dungeon tracks which floors have been created and have a corresponding save file.
Sources: core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java:608-726