Docs · Guide

The game library

Type import game in the Playground and make a game right in the browser: sprites, the keyboard, the mouse, collisions and a score, no install. This is the hands-on how-to; the one-line reference for every call is on the Docs page. Every example here has a Try it button that drops it into the Playground.

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(): True once per fresh click, then False until the next. One tap, one action, great for buttons.
  • sprite.at_mouse(): True while the pointer is over that sprite. Pair with game.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 and game.circle(x, y, w, h, color) is a round one (leave h out for a true circle, or give it to squash the circle into an oval). Both have a real .color you can change, and both move and collide 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.

Saving progress

Games forget everything when they stop — unless you save. game.save(key, value) remembers a value in this browser, and game.load(key, default) reads it back next time. Perfect for a garden that keeps growing, coins that add up, or levels you've unlocked.

  • game.save("coins", 120) — store a value under a name. It can be a number, text, True/False, or a list/dict of those.
  • game.load("coins", 0) — read it back. The very first time (nothing saved yet) you get the default, so a new player starts fresh.
  • game.clear_save() — wipe this game's save (a "New game" button). Pass a key to forget just one thing.
import game
game.window(480, 360)

coins  = game.load("coins", 0)     # 0 the first ever run
plants = game.load("plants", 0)

# ...play: earn a coin, grow a plant...
coins += 5
plants += 1

game.save("coins", coins)          # save when things change,
game.save("plants", plants)        # not every frame
# Run it again and the garden is exactly where you left it.

It's per-game and per-browser. Each program keeps its own save, and it lives on this device only (it isn't synced across computers or accounts). Save when something actually changes rather than every frame.

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.

Open the Playground Full call reference