215. How to build a game in Codea
Codea runs the draw function 60 times a second, which is quite different to most other programming languages, and creates a lot of confusion among people trying to build games. For example, how do you get Codea to change from showing a menu to playing the game?
In this post, I’ll try to explain some commonly used methods – I won’t claim they are the only methods, nor always the best methods, but if you’re just starting out with Codea, I hope they will help you.
Understanding how Codea works
Codea has three functions that run automatically
- setup runs once, at the very beginning, and is where you get your game ready, eg create tables of data, create variables and constants, read images, etc
- draw runs 60 times a second, and is for drawing to the screen. You can do other things apart from just drawing (eg calculating health, moving the player)
- touched runs when the screen is touched, giving information about touches
Let’s suppose you have a simple game with
- a splash screen which shows for a few seconds while the game loads,
- a menu offering a choice of Help, Settings, Play, and High Scores
- code for each of the menu items, which runs when the item is touched, and shows various things on the screen
- you also have a GameOver screen showing the results and offering to play again
Let’s look at different ways you can build this game
The “if test” approach
The most obvious way to do it is to have a variable which tells Codea what it should be doing (and drawing). This is often called a “state” variable.
You can do this by using numbers, eg state=3 means we are playing, and state=2 means we are looking at the main menu, but it’s easy to get confused with numbers. Better is to use constants, like this – I’ve capitalised them so they stand out when you look at your code.
--in the setup function, make a list of different states SPLASH,MAINMENU,HELP,SETTINGS,PLAY,HIGHSCORES,GAMEOVER=0,1,2,3,4,5,6 --create a variable for the current state state = SPLASH --set it to splash screen initially
Then you can use “if” tests to tell Codea what to do. For example, in your draw function, you might have code like this..
if state==SPLASH then --code to draw splash screen elseif state==MAINMENU then --code to draw menu on screen elseif --etc etc
and in your touched function you would have code like this
function touched(t) if state==MAINMENU then --test which menu item was touched --and change the state variable elseif state==PLAY then --etc etc
Getting functions to do the work
The problem is that your code is going to get very, very messy, and hard to debug.
A much cleaner way to do it is to use the draw and touched functions just to decide what needs to be done, and use other functions to do the work. So the draw function would look like this
if state==SPLASH then DrawSplashScreen() elseif state==MAINMENU then DrawMainMenu() elseif --etc etc
This is going to make your program much, much easier to develop and control. I recomment using functions in setup as well, eg
function setup() SetupSettings() ReadImages() SetupTables() end
and I would do the same in the touched function. This means that your three main functions – setup, draw and touched – have very little code, and it is very easy to see what they do. It is also much easier to write functions like SetupSettings when they are completely separate.
But there is another approach that is way better. Stay with me, it’s not difficult.
State functions
First, let me show you the amazing result. This is what your draw and touched functions will look like.
function draw() state.draw() end function touched(t) state.touched(t) end
That’s pretty clean, huh? This is how it works.
We set up a little table of functions for each “state”, each one with a draw and a touched function. Here is our table for the MainMenu state.
MainMenu = {} function MainMenu.draw() --code to draw the main menu end function MainMenu.touched() --code to figure out which menu item was touched --and then change the state end
..and one for the Play state..
Play = {} function Play.draw() --code to move the player, draw the scene, figure out collisions, etc end function Play.touched() --code to handle user touches, eg change of direction, shooting, etc end
What is really nice about this, is that the code for the main menu is completely separate from the code for playing, or settings, or anything else. I can ignore everything except the state I’m working on. This makes it much easier to develop and to test.
To get Codea to use (say) the MainMenu functions, I simply write state=MainMenu, and Codea will run MainMenu.draw and MainMenu.touched. If I write write state=Play, Codea will run Play.draw and Play.touched. So by setting the state variable equal to the right table of functions, we can get Codea to use any of them.
I’m building an actual example which I’ll explain in further posts.
Thanks for explaining that, I’m liking your third option, seems very clean, and I imagine it’ll morph into different tabs in future posts?
-Jon
I’ve just posted a demo that is small enough to fit in one tab, but for bigger apps, separate tabs certainly help you to organise your code, yes