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.
Lua's small set of value types.
A text-only launch-status program.
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.