The game loop

Game loops are the kernels of games that drive the whole thing. LÖVE defines the low-level loop of updating the state, rendering, processing input, etc., but a roguelike engine needs a turn-based loop that waits for the player to do something.

In prism, we’ve implemented the game loop as a Lua coroutine. The following diagram describes the main loop.

Fetch next actor

No

Yes

Input received

Start

Call their controller

Did it yield?

Perform action

Wait for input

The core game loop

Level defines the loop, and LevelState holds the coroutine and determines when to continue it. If no Controller yields a Decision the loop will run indefinitely, forcing you to catch when there are no player controlled actors left in the level.

What actually happens on an actor’s turn is defined in prism.turn(). By default, it calls the Controller and performs the action returned:

local action = controller:act(level, actor)

-- we make sure we got an action back from the controller for sanity's sake
assert(action, "Actor " .. actor:getName() .. " returned nil from act()")

level:perform(action)

If actors can perform multiple actions, you would need to override this.