The shape of every game
Every game is the same three steps: open a window, make your sprites, then loop. Inside the loop you read the keys, change where things are, and call game.frame() to draw one picture and pause a heartbeat. That is what makes it move.
import game
# 1. Open the game window (width, height)
game.window(480, 360)
# 2. Make a sprite: a built-in skin, or any emoji
chicken = game.sprite("chicken", 240, 300, size=52)
# 3. The game loop: read keys, move, draw one frame, repeat
while game.playing():
if game.pressed("left"): chicken.x = chicken.x - 6
if game.pressed("right"): chicken.x = chicken.x + 6
if game.pressed("up"): chicken.y = chicken.y - 6
if game.pressed("down"): chicken.y = chicken.y + 6
game.frame()
The golden rule of the loop: every game loop ends with game.frame(). Forget it and the loop spins invisibly forever without ever drawing. Press Stop (or Ctrl+C is not needed, just the Stop button) any time to end a game. Want it extra smooth? game.frame(60) runs at 60 frames a second (things move twice as fast then, so take smaller steps to keep the same speed).
Chrome or Edge. The trick that keeps the game moving without freezing the tab needs those browsers, the same as input() and time.sleep() here. In other browsers the window shows a friendly message instead.
The built-in sprites
The library ships with a growing set of ready-made sprites in a matching style. Give game.sprite the number or the name, whichever you find easier, and any emoji works too.
hero = game.sprite("chicken", 100, 200) # by name
coin = game.sprite(4, 250, 100) # or by number
foe = game.sprite("🦖", 300, 200) # any emoji still works
Swap what a sprite shows at any time with .content, a number, a name, or an emoji:
player = game.sprite("chicken", 240, 180)
player.content = "coin" # now a coin
player.content = 6 # now a shocked face
player.content = "🍗" # now an emoji
player.size = 80 # and bigger
Moving things
A sprite lives at .x and .y. Change those numbers and it moves. Read the keyboard with game.pressed(key), which is True while a key is held: "left", "right", "up", "down", "space", or any letter like "a".
if game.pressed("left"): player.x = player.x - 6
if game.pressed("right"): player.x = player.x + 6
Collisions
a.touches(b) is True when two sprites overlap. That is how you catch, hit or dodge. Here is a catch game: steer the basket, catch the falling egg, count the score.
import game
import random
game.window(480, 360, background="#0b1020")
basket = game.sprite("basket", 240, 330, size=52)
egg = game.sprite("egg", random.randint(30, 450), 0, size=34)
board = game.label("Score: 0", 60, 24, size=22)
while game.playing():
if game.pressed("left"): basket.x = basket.x - 8
if game.pressed("right"): basket.x = basket.x + 8
egg.y = egg.y + 5 # the egg falls
if basket.touches(egg): # caught it
game.score(1)
board.content = "Score: " + str(game.score())
egg.x = random.randint(30, 450)
egg.y = 0
elif egg.y > 360: # missed, drop a new one
egg.x = random.randint(30, 450)
egg.y = 0
game.frame()
The collision box turns with the sprite's .angle and stretches with its scale. Set your own with sprite.hitbox = (width, height) for a tighter fit, or turn on game.debug(True) right after game.window(...) to see every box outlined in red.
The mouse
game.mouse_x()game.mouse_y(): where the pointer is, in your sprites' coordinates. Make something follow it:can.x = game.mouse_x().game.clicked():Trueonce per fresh click, thenFalseuntil the next. One tap, one action, great for buttons.sprite.at_mouse():Truewhile the pointer is over that sprite. Pair withgame.clicked()to click on things.game.hide_cursor(): hide the real pointer so a sprite can be the pointer (a watering can, a crosshair).game.show_cursor()brings it back.
if plant.at_mouse() and game.clicked():
plant.size = plant.size + 10
Spin & mirror
Set .angle (in degrees) to turn a sprite, and add a little every frame to make it spin. Set .scale_x = -1 to mirror it left-to-right so it faces the way it walks, the trick every side-scroller uses.
import game
game.window(480, 360)
coin = game.sprite("coin", 240, 180, size=80)
while game.playing():
coin.angle = coin.angle + 6 # turn 6 degrees every frame
game.frame()
Boxes & a scoreboard
Prefer plain coloured shapes? game.box(x, y, w, h, color) is a rectangle with a real .color you can change, and it moves and collides just like a sprite. A scoreboard is just a game.label whose .content you update, so you decide where it sits and what it says.
import game
game.window(480, 360)
player = game.box(240, 180, 40, 40, "#22cc88")
wall = game.box(380, 180, 20, 200, "#ff5577")
board = game.label("Bumps: 0", 70, 24, size=22)
bumps = 0
while game.playing():
if game.pressed("right"): player.x = player.x + 5
if game.pressed("left"): player.x = player.x - 5
if player.touches(wall):
player.color = "#ffdd00" # flash on a bump
bumps = bumps + 1
board.content = "Bumps: " + str(bumps)
game.frame()
Ending a game
game.game_over(message) shows a big banner and stops the loop:
if misses >= 3:
game.game_over("Game over! Score: " + str(game.score()))
Leaderboards with game.submit_score(points): call it whenever the score changes (or at game over) and, once you publish the game, its shared page gets a per-game leaderboard, the best score for each signed-in player who plays it there. In the Playground it quietly does nothing, so it is safe to leave in. This is separate from the site Leaderboard, which ranks creators by the upvotes on the programs they share.
game.submit_score(score)
game.game_over("Score: " + str(score))
Sound
game.sound(n) plays a short built-in arcade sound, no files needed. Pick one by number:
- 0 beep · 1 buzz · 2 coin · 3 powerup · 4 jump
- 5 laser · 6 hit · 7 explosion · 8 win · 9 lose
if basket.touches(egg):
game.score(1)
game.sound(2) # coin
if basket.touches(bomb):
game.sound(1) # buzz
game.game_over("Boom!")
The names work too, e.g. game.sound("coin"). Browsers only allow audio after a click, and a game is clicked to play, so it just works.
What it can and can't do
- Great for: catch and dodge games, mazes, top-down movers, two-player keyboard games, simple arcade fun.
- Not built for: gravity and physics engines, loading your own image or sound files (the built-in
game.sound()beeps aside). Those are what a full engine like pygame adds.
Coordinates. The top-left corner is (0, 0). x grows to the right and y grows downward, so a bigger y is further down the screen. That catches everyone out at first.
Now open the Playground, type import game, and build something. Load the "Game" example cards, change a number, and see what happens.