Posted January 08, 2020 by Ximo
#pico8
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.
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:
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.
For each scene I use a table with 4 elements, all of them are optional:
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