Learning

Lua + LÖVE: Make a Game · Lesson 02 · 35 min

Think in Lua values

Use variables, operators, strings, booleans, nil, and conditions to express game rules.

Learn

Lua's small set of value types.

Build

A text-only launch-status program.

Prove it

Add a fuel rule without guessing.

A game is a collection of values changing over time. The player has a position. The score is a number. The current screen might be the string "playing". A ship is alive until a boolean becomes false.

For this lesson, create practice.lua outside your game and run it with a standalone Lua interpreter if you have one:

lua practice.lua

If you do not have the lua command, put the examples at the top of main.lua, run the game with LÖVE, and read terminal output from print.

Start local

Create variables with local:

local callsign = "Nova"
local score = 12
local fuel = 0.75
local shieldsUp = true
local destination = nil

Lua is dynamically typed: a variable does not have a permanent type, but every value does.

Type Example Typical game use
number 12, 0.75, -4 positions, time, health, speed
string "Nova" labels, state names, filenames
boolean true, false flags such as paused or alive
nil nil no value / missing value
function function() end behavior
table {} lists and game objects

Use type when you want Lua to tell you what a value is:

print(type(score))       -- number
print(type(callsign))    -- string
print(type(destination)) -- nil

Why local matters

Without local, assignment creates or changes a global variable. Globals can be modified from anywhere, which makes larger games hard to reason about. Default to local; use a wider scope deliberately.

Calculate with numbers

Lua’s arithmetic looks familiar:

local score = 10
score = score + 5     -- 15
score = score * 2     -- 30

local lives = 7 % 3  -- 1, the remainder
local area = 8 ^ 2   -- 64, exponentiation

Lua does not have +=. Write score = score + 1.

Comparison operators produce booleans:

score == 30  -- equal
score ~= 10  -- not equal
score > 20
score <= 30

One equals sign assigns. Two compare:

score = 30   -- put 30 into score
score == 30  -- ask whether score equals 30

Join strings

Lua concatenates strings with two dots:

local callsign = "Nova"
local score = 12
local message = callsign .. " scored " .. score
print(message) -- Nova scored 12

Lua converts the number here, but explicit conversion is useful when the intent is less obvious:

local text = tostring(score)
local parsed = tonumber("42") -- 42

Useful string escapes include \n for a new line and \" for a quote inside a double-quoted string.

Make decisions

Conditions choose which code runs:

local fuel = 0.75

if fuel <= 0 then
  print("Engines offline")
elseif fuel < 0.25 then
  print("Fuel critical")
else
  print("Ready to launch")
end

Lua closes an if block with end. Parentheses around the condition are optional and usually omitted.

Combine conditions with words:

local fuel = 0.75
local shieldsUp = true
local docked = false

local canLaunch = fuel > 0.2 and shieldsUp and not docked

if canLaunch then
  print("Launch approved")
end

and, or, and not are operators. There is no && or ! in Lua.

Lua’s truth rule

Only false and nil are false in a condition. Everything else is true—including 0 and the empty string "".

if 0 then
  print("This runs")
end

This surprises programmers coming from some other languages. If zero has a special meaning, compare it explicitly:

if lives == 0 then
  print("Game over")
end

The or operator is handy for defaults:

local savedName = nil
local displayName = savedName or "Pilot"
print(displayName) -- Pilot

Build a launch-status program

Type this complete program:

local pilot = "Nova"
local fuel = 62
local shields = 80
local meteorAlert = false

local hasFuel = fuel >= 25
local hasShields = shields > 0
local safeRoute = not meteorAlert
local canLaunch = hasFuel and hasShields and safeRoute

print("Pilot: " .. pilot)
print("Fuel: " .. fuel .. "%")

if canLaunch then
  print("Status: cleared for launch")
elseif meteorAlert then
  print("Status: wait for meteor alert to clear")
elseif not hasFuel then
  print("Status: refuel required")
else
  print("Status: repair shields")
end

Before running it, predict the output. Then change one input at a time and predict again.

Your turn

Add a warning when fuel is at least 25 but below 40. Keep the final launch decision correct. There is more than one valid solution.

One solution

Add this before the final decision:

if fuel >= 25 and fuel < 40 then
  print("Warning: limited range")
end

This is an independent message, so it uses its own if rather than becoming another mutually exclusive branch of the status chain.

Translate this back to a game

Orbit Runner will eventually have state like this:

local score = 0
local lives = 3
local gameState = "title"
local playerInvulnerable = false

And rules like this:

if lives <= 0 then
  gameState = "gameover"
end

That is game programming at its core: name the state clearly, then write the rule that changes it.

Checkpoint

You are ready to continue when you can explain the difference between = and ==, name Lua's two false values, and write a three-branch if without looking it up.