Game state: is it playing, or game over?
A game is always in some state — playing, paused, or game over. Your code tracks that with a simple flag. Then it uses the flag to decide what to do.
The big idea
Game state is a value that tracks what's happening, so the game knows what to do right now.
See it in code
A state is just a flag — a True/False value. game_over starts False, and an if reads it to pick what to say:
game_over = False
if game_over:
print("Game over!")
else:
print("Still playing")Still playing
The flag didn't do anything by itself. The if read it and chose. Flip the flag and the choice flips too.
Now let the game set the flag. The player loses their last life, so lives drops to 0. We check for that and flip game_over to True:
lives = 1
game_over = False
lives = lives - 1
if lives <= 0:
game_over = True
print("game_over =", game_over)game_over = True
First something changed (lives hit 0), then the check flipped the flag. That two-step — change, then check — is how state works.
Now let the flag steer the screen. Same drop to 0 lives and the same flip to True — but this time the flag decides what shows: the game-over screen, not the scoreboard:
from game import Stage, HUD
screen = Stage.create()
Stage.clear(screen)
game_over = False
hud = HUD()
hud.lose_life()
hud.lose_life()
hud.lose_life()
if hud.lives <= 0:
game_over = True
if game_over:
HUD.game_over(screen)
else:
hud.draw(screen)
print("game_over =", game_over)game_over = True

The game_over flag changed everything. Once it was True, the game showed the game-over screen, not the HUD. One little flag steered the whole game.
Every game tracks state: a title screen, playing, paused, or game over. The state decides what the loop draws and what the buttons do. Change the state, and the whole game changes.
Try it yourself
Take away one of the lose_life() lines so lives stays above 0 — now game_over is False and the scoreboard shows instead. Then add a paused flag and decide what it should change.
The common mistake
Forgetting to check the state after changing it. Setting game_over = True does nothing on its own — you need an if game_over: somewhere to actually react to it.
What it unlocks
State is tracked with variables and booleans, and steers the game loop and score and lives.