Tutorial: Game scenes


To create a game in PICO-8 you just need to write some code into the functions _init, _update and _draw and the engine will take care of the rest for us. It is very cool for simple stuff  but when the project  grows in complexity it soon becomes unmanageable to have everything in these 3 functions.

Imagine you already have written the _draw for your platformer that draws the map and the entities of the game. How would you update it if you want to add a title screen at the beginning of the game? You can have a global variable that will have the value "title" or "play" and branch your code based on it.

function _draw()
 if screen == 'title' then
  -- draw the title screen
 elseif screen == 'play' then
  -- draw the game screen
 end
end

This is quick workaround but has the effect of increased the indentation for your original code so it may not fit the tiny PICO8 string. Also when you need to add new screens such as credits or the world map you will need to add more branches there.

In this article I want to talk about the approach I used  to organise the flow of Lazy Farm. It is the simple way I found to separate and encapsulate the different parts of the project.

Scenes

For me a scene is a stage of the execution of a game. It covers what you see on screen (_draw) and what happens (_update) and it is initialized when you load it (_init). Only one scene is active at any given time and there are mechanisms to move from one scene to another.

Some developers or engines may have a different name for a similar concept. For example in Gamemaker Studio the closest thing we have to the scenes I'm referring to are the rooms.

The main scenes in Lazy Farm are:

  • TITLE: for the title screen
  • MENU: for the level selection menu
  • PLAY: for the actual game
  • CREDITS: for the credits screen

Here is a basic diagram of how we can move from one scene to another.

From TITLE you can only load the MENU. The MENU allow you to see the CREDITS screen or PLAY a level. The scene PLAY can either return to the menu or load the CREDITS if it is the last level. From the CREDITS you can only go back to the menu.

There are a few more that were added over time like the CHEATS_MENU and PLAY was divided in several sub-scenes to make the code simpler.

Implementation

For each scene I use a table with 4 elements, all of them are optional:

  • Name of the scene. This is mostly for debugging, so I can print on screen which is the current scene.
  • init: A reference to an initialisation function for the scene. Will be called every time we load the scene.
  • update: A reference to a function that will be called every frame to update the game state
  • draw: A reference to a function that will be called every frame to draw the scene

This is an example of a scene:

function title_draw()
 cls()
 color(8)
 print('hello, world', 0, 0)
end
function title_update()
 -- do nothing
end
function title_init()
 -- do nothing
end
scene_title = {
 name = 'title',
 init = title_init,
 update = title_update,
 draw = draw_update
}

The way I use to move from one scene to another is also very simple. We just change the current _update and _draw functions to the ones in the scene and continue the execution:

function set_scene(s)
 _update = s.update
 _draw = s.draw
 if s.init != nil then
 s.init()
 end
end

_update and _draw are swapped in every scene change so the code in each of them is kept relatively simple. As the last line in your code or in the _init you should set the initial scene

function _init()
 set_scene(scene_title)
end

If we had another scene called scene_menu we could just move from scene_title to it with:

function title_update()
 if btnp(4) then
  set_scene(scene_menu)
 end
end

Get Pico Lazy Farm

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.