Programming Games

Class 12 - State Machines, and Distribution

Play homework

gif from These Out of Control Booty Shaking Kittens Are Ruining my Castlevania!

Celeste 2 (Pico-8) by Maddy Thorson, Noel Berry, Lena Raine, Kevin Regamey

Topics

Description

This week we’ll learn how to structure and handle creating a complex games with various scenes a player can encounter. We also cover game distribution. Then work on playtesting.

Class notes

Level Design

Finite State Machine Concept

A finite-state machine (FSM) or finite-state automaton (FSA, plural: automata), finite automaton, or simply a state machine, is a mathematical model of computation. It is an abstract “machine” that can be in exactly one of a finite number of states at any given time. The FSM can change from one state to another in response to some inputs; the change from one state to another is called a transition. An FSM is defined by a list of its states, its initial state, and the inputs that trigger each transition.

The behavior of state machines can be observed in many devices in modern society that perform a predetermined sequence of actions depending on a sequence of events with which they are presented. Simple examples are: vending machines, which dispense products when the proper combination of coins is deposited; elevators, whose sequence of stops is determined by the floors requested by riders; traffic lights, which change sequence when cars are waiting; combination locks, which require the input of a sequence of numbers in the proper order.

An example of a simple mechanism that can be modeled by a state machine is a turnstile. A turnstile, used to control access to subways and amusement park rides, is a gate with three rotating arms at waist height, one across the entryway. Initially the arms are locked, blocking the entry, preventing patrons from passing through. Depositing a coin or token in a slot on the turnstile unlocks the arms, allowing a single customer to push through. After the customer passes through, the arms are locked again until another coin is inserted.

Considered as a state machine, the turnstile has two possible states: Locked and Unlocked. There are two possible inputs that affect its state: putting a coin in the slot (coin) and pushing the arm (push). In the locked state, pushing on the arm has no effect; no matter how many times the input push is given, it stays in the locked state. Putting a coin in – that is, giving the machine a coin input – shifts the state from Locked to Unlocked. In the unlocked state, putting additional coins in has no effect; that is, giving additional coin inputs does not change the state. However, a customer pushing through the arms, giving a push input, shifts the state back to Locked.

The turnstile state machine can also be represented by a directed graph called a state diagram (above). Each state is represented by a node (circle). Edges (arrows) show the transitions from one state to another. Each arrow is labeled with the input that triggers that transition. An input that doesn’t cause a change of state (such as a coin input in the Unlocked state) is represented by a circular arrow returning to the original state. The arrow into the Locked node from the black dot indicates it is the initial state.

Title Screen or Menu

A two-state machine. At title screen pressing start changes to the Gameplay state. During the gameplay state if lives become less than 1 the game state is set back to Title screen.

Initializing

The love.load() happens once at the state. We set the game state to the initial state.

function love.load()
  state=="title-screen"
end

Update

The love.update() is where gameplay elements are changed (like a timer).

The update checks which state we are in and runs the correct update code depending on that state.

function love.update()
  if state=="title-screen" then
    update_title_screen()
  elseif state=="gameplay" then
    update_gameplay()
  end
end

Drawing

The function love.draw() is called to draw things to the screen. There’s some repetition in this one. Compare to our love.update() function above.

function love.draw()
  if state=="title-screen" then
    draw_title_screen()
  elseif state=="gameplay" then
    draw_gameplay()
  end
end

The rest of our update code, and changing states

In our 2 state diagram from above, translated to code below:

To change states:

function love.keypressed(key, scancode, isrepeat)
  if state=="title-screen" then
    if key == "return" then
      state=="gameplay"
    end
  end
end

function update_title_screen()
  --title screen update code
end

function update_gameplay()
  --gameplay update code
  --move enemies (change their x,y positions)
  --move player based on key presses
  if player.lives<1 then
    state=="title-screen"
  end
end

More states

A finite state machine graph of a game with 3 levels

You can add more states to your game. It pays to draw a diagram first and then to turn that into code.

Below is an example update function checking for variosu states:

function love.update()
    if state=="animation" then
	  update_anim()
    elseif state=="startscreen" then
	  update_startscreen()
    elseif state=="info" then
	  update_startscreen()
    elseif state=="dead" then
	  update_dead()
    else
	  update_game()
    end
end

Inside each of these update functions you would be checking for various events to occur (pressing a button to start, losing all lives, etc) and then changing the state based on the event.

The updates are paired with related functions called in love.draw().

function love.draw()
    if state=="animation" then
	  draw_anim()
    elseif state=="startscreen" then
	  draw_startscreen()
    elseif state=="info" then
	  draw_howtoplay()
    elseif state=="dead" then
	  draw_dead()
    else
	  draw_game()
    end
end

Distributing your game

You made a game, and you want to share it with others. You could make them install LÖVE on their computer, but that is not necessary.

First, we need to change the title and icon. For that we will use a config file.

Create a new file called conf.lua, and put in the following code

function love.conf(t)
	t.window.title = "Panda Shooter!"
	t.window.icon = "panda.png"
end

Save the file. Now when you run the game you’ll see the game has the title “Panda Shooter!”, and that the icon is the panda.

This is what the config file is for. LÖVE loads conf.lua before it starts the game and applies the configurations. For a full list of options check out the wiki.

Now that our game has the correct title and icon, let’s turn it into an executable.

First we need to package our game in a zip file. Go to the folder of your game, select all the files. Now right click, go to Send to and click on Compressed (zipped) folder. The filename is not important, but we need to change the extension to .love (by default .zip).

Note: This part is Windows only. Go here to get info on building your game for other platforms.

If you can’t see file extensions

Press Windows + pause/break. In the upper-left corner of the new opened window click on Control Panel. Now go to Appearance and Personalization.

Click on File Explorer options.

A new window opens. Click on the tab View. In Advanced options, make sure that Hide extension for known filetypes is unchecked.

I wrote a bat file that packages the game for you. Download this zip file, and unzip all the files in a folder.

Now move your .love file on top of build.bat. This creates a .zip file in the same folder. This is the file that you will want to share with people. They have to extract all the files in a folder and open the .exe file.

Now you need to find a place to share your game. Check out itch.io.

For more information on building your game, check out the LÖVE wiki page for it. It also tells you how to build your game for other platforms.


Summary

With conf.lua you can configure things about your game like title and icon. Select all the files in the folder of your game, put them in a zip. Change the file’s extension from .zip to .love. Download this zip file, and unzip all the files in a folder. Move your .love on top of build.bat to create a .zip. People will have to unzip all the files in a folder and open the .exe to play your game. We can also use Castle which is a client that allows us to share our LÖVE games.

Code homework

Complete your platformer

Credits