Python · Extra

Libraries & import

You do not have to write everything yourself. Other people have already written brilliant, tested code and packed it up so you can borrow it in one line. That is what a library is, and import is how you reach for one. This page shows you the idea, meets the famous pygame library, then introduces the little game library we built right here at Hallam so you can make games in your browser.

1. What does import even do?

Think of a library as a toolbox someone else filled and shared. When you write import, you are opening that toolbox and giving yourself all the tools inside. You did not have to build the hammer; you just picked it up.

Here is the classic first example, rolling a dice. Python does not know how to be random on its own, but the random library does, so we borrow it:

import random

roll = random.randint(1, 6)
print("You rolled a", roll)

Watch the brackets. It is random.randint(1, 6) with two numbers: the lowest and the highest you want. A common slip is writing random.randint(1) with just one number, which crashes, because the computer has no idea where the range should stop.

Once a library is imported, you reach into it with a dot: the library name, a dot, then the tool you want. So random.randint means "the randint tool from the random toolbox".

2. Batteries included

Python comes with a big pile of libraries already built in. Nothing to download; they are just there. People call this the standard library, or "batteries included". Here are three you will use all the time. Press Run on any of them (Python loads the first time, then it is instant).

random · surprises and shuffling

import random

# pick a random whole number from 1 to 6
print("Dice:", random.randint(1, 6))

# pick one item out of a list
fruits = ["apple", "banana", "cherry"]
print("Snack:", random.choice(fruits))

math · the tricky sums

import math

print(math.sqrt(144))   # square root: 12.0
print(math.pi)         # the number pi
print(round(math.pi, 2))  # 3.14

Three ways to import

They all do a similar job; pick whichever reads best:

import random               # then use random.randint(1, 6)
from random import randint    # then just use randint(1, 6)
import random as r          # then use r.randint(1, 6)

The first is the safest to read, because random.randint tells you exactly where randint came from. That matters more than you would think once a program gets long.

3. Bigger libraries you install

Not every library ships with Python. Some are made by other programmers around the world and you have to install them first, download them onto your computer, before you can import them. The tool that fetches libraries is called pip, and on a real computer you would type something like this into a terminal:

pip install pygame

After that finishes, import pygame would work in your programs. There are thousands of libraries out there: for drawing charts, reading spreadsheets, controlling robots, building websites, and, yes, making games.

4. pygame, the famous game library

pygame is probably the best known way to make games in Python. It is a real, powerful library that people use to build actual desktop games: platformers, shooters, puzzles, the lot. A pygame program opens a window on your computer and looks a bit like this:

import pygame
pygame.init()
screen = pygame.display.set_mode((480, 360))

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
    # ... draw everything, then flip the screen ...
    pygame.display.flip()

You can already spot the shape of a game here: open a window, then loop forever, checking for input and redrawing the screen each time around. Hold onto that idea, because our library uses exactly the same shape.

So why can't I import pygame on this website?

Two reasons, and both are actually good news about how browsers work:

  • Browsers are locked down on purpose. A web page is not allowed to install software or pop open windows on your computer. That is a safety feature: you would not want any old website doing that. But it means pygame, which needs to open a real desktop window, has nowhere to go.
  • pygame is big and built for desktops. It is megabytes of code that expects a proper operating system underneath it, not a web page.

So instead of forcing a giant desktop library into a place it does not fit, we built a tiny one that speaks the browser's own language.

5. Meet import game, our Hallam library

A browser already knows how to draw shapes and pictures, on something called a canvas, and it already knows when you press a key. So we wrote a small library, just for this website, that hands those powers to you in plain, friendly Python. We called it game.

It is not a cut-down copy of pygame; it is our own little thing. But it teaches the very same ideas, a window, sprites, a game loop, reading the keyboard, spotting collisions, so if you ever move on to pygame or another engine later, it will all feel familiar.

  • No install. Just type import game in the Sandbox and go.
  • Ready-made art, or any emoji. Ten built-in Hallam sprites give your game a matching look (see the table below), and every emoji works too. 🚀 👾 take your pick.
  • It runs in Chrome or Edge. The trick that keeps the game moving without freezing the tab needs those browsers, the same as input() and time.sleep() do here.

6. Your first game, line by line

Here is a whole tiny game: a chicken you steer with the arrow keys. Read the comments, they explain every new piece.

import game

# 1. Open the game window (width, height)
game.window(480, 360)

# 2. Make a sprite: an emoji at a starting spot
chicken = game.sprite("🐔", 240, 300, size=48)

# 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 three steps are always the same: 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 before the next one. That is what makes it look like it is moving.

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 any time to end a game.

7. The game cheat sheet

Everything the game library can do, in one place. Tap a heading to open it.

Starting up
CallWhat it does
game.window(w, h) Opens the game window, w wide and h tall. Always call this first. Add background="#0b1020" to set the colour.
game.background(color) Changes the background colour at any time, e.g. game.background("skyblue").
Things you can put on screen
CallWhat it does
game.sprite(skin, x, y, size=40) A sprite at (x, y). The skin can be a built-in art number (0 chicken, 1 dog, 2 bird, 3 egg, 4 coin, 5 basket), its name like "chicken", or any emoji: game.sprite("🚀", 100, 200).
game.box(x, y, w, h, color) A coloured rectangle, w by h, centred on (x, y). Great for platforms, walls or a plain coloured player.
game.label(text, x, y, size, color, background) Draws words on the screen, centred on (x, y). This is how you show a score or a message. color sets the text colour; the optional background draws a filled box behind the words so they stay readable on any scene, e.g. game.label("Score: 0", 80, 24, color="#ffffff", background="#000000"). Keep x away from the left edge (say 60 or more) so longer text is not cut off.
The game loop
CallWhat it does
game.playing() Is the game still running? Use it as the loop condition: while game.playing():
game.frame(fps=30) Draws one frame and waits a moment. Put it at the end of the loop. fps is how many frames a second (higher is faster and smoother).
game.game_over(message) Shows a big banner and stops the game.
game.hide_cursor() Hides the real mouse pointer while it is over the game window, so a sprite can be the pointer instead (a watering can, a crosshair). game.show_cursor() brings it back.
game.debug(True) Draws a red outline around every sprite's hit box: the exact area .touches() checks for a collision. Put it right after game.window(...). If a collision fires when things only look close, this shows why. The box is a square around the centre and does not spin or stretch with the sprite, so a rotated car keeps a straight box. Turn it off with game.debug(False).
Input and score
CallWhat it does
game.pressed(key) True while a key is held down. Keys: "left", "right", "up", "down", "space", or any letter like "a" or "w".
game.mouse_x() game.mouse_y() Where the mouse pointer is, in the same coordinates as your sprites. Make something follow the mouse: pet.x = game.mouse_x(). (game.mouse_in() is True while the pointer is over the game window.)
game.clicked() True once per fresh click on the game window, then False until the next click. One tap, one action: perfect for buttons and menus. Pair it with .at_mouse() to click on a sprite.
game.mouse_down() True while the mouse button is held, like pressed() but for the mouse.
game.score(points) A running total counter. game.score(1) adds one and gives back the new total; game.score() just reads it. It draws nothing on its own, show it with a label (see below).
game.submit_score(points) Gives your game its own leaderboard in the Game Gallery. When someone plays your published game, this saves their best score to it. Call it when the run ends, right before game.game_over(...). In the Sandbox it quietly does nothing, so you can test without filling the board.
Every sprite, box and label can...
PropertyWhat it does
.x .yWhere it is. Change these to move it.
.sizeHow big an emoji or label is.
.w .hThe width and height of a box.
.contentWhat it shows. Set it to a skin number, a name or an emoji to swap the picture: player.content = "coin". On a label it is the words shown.
.angleSpin it. The angle is in degrees, so coin.angle = 45 tips it over, and adding a little every frame makes it spin.
.scale_x .scale_yStretch or mirror it. 1 is normal, 2 is twice as big, and -1 flips it. Set .scale_x = -1 to make a sprite face the other way, handy for a side-scroller or a fighter.
.colorThe colour of a box or label. (Emoji keep their own colours, so this does nothing to an emoji.)
.layerWhich things draw on top. A higher number sits above a lower one; things on the same layer keep the order you made them in. Everything starts at 0, except labels, which start at 1000 so a scoreboard stays on top of the action. Want a sprite over the text? Give it a bigger number, like player.layer = 2000. Want the label behind instead? Set board.layer = 0.
.touches(other)True if this sprite is overlapping another one. This is how you catch, hit or collide: if basket.touches(egg):. The collision box turns with the sprite's .angle and stretches with its scale, so a rotated car checks a rotated box. Turn on game.debug(True) to see the boxes.
.hitboxThe size of the collision box, as (width, height). By default it is picked to roughly fit the art (a car is wide, an egg is tall), but you can set your own: car.hitbox = (46, 26) for a tighter fit, or car.hitbox = None to go back to automatic. Pair it with game.debug(True) to line it up.
.at_mouse()True while the mouse pointer is inside this sprite's box. Click on a sprite: if plant.at_mouse() and game.clicked():
.hide() .show()Make it vanish or come back.
.remove()Delete it for good once it is caught or destroyed. Keep many objects in a list and remove them as the player clears them.

Coordinates. The top-left corner is (0, 0). x grows to the right, and y grows downward. So bigger y means further down the screen, which catches everyone out at first.

8. Customising: how far can you push it?

You asked what you can change. Quite a lot, actually.

The built-in sprites

The library comes with ten ready-made sprites in a matching style. Give game.sprite the number or the name, whichever you find easier to remember:

PictureNumberName
0"chicken"
1"dog"
2"bird"
3"egg"
4"coin"
5"basket"
6"shocked"
7"calm"
8"turtle"
9"car"
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 the sprite

Change what a sprite shows mid-game by setting .content. Give it a skin number, a name, or an emoji, whichever you like:

player = game.sprite("chicken", 240, 180)
player.content = "coin"   # now it is a coin
player.content = 6        # now a shocked face
player.content = "🍗"     # now an emoji
player.size = 80          # and twice as big

Make it spin

Set .angle (in degrees) to turn a sprite, and add a little every frame to make it spin. Nothing fancy under the hood: the screen just turns before it draws the emoji.

import game
game.window(480, 360)

coin = game.sprite("🪙", 240, 180, size=80)

while game.playing():
    coin.angle = coin.angle + 6   # turn 6 degrees every frame
    game.frame()

Face the other way (side-scrollers and fighters)

Set .scale_x = -1 to mirror a sprite left-to-right, so it faces the way it is walking. .scale_y flips it top-to-bottom, and any number bigger than 1 stretches it. This is how a side-scroller makes one emoji face both directions.

import game
game.window(480, 360, background="#87ceeb")

runner = game.sprite("🐔", 240, 200, size=60)

while game.playing():
    if game.pressed("left"):
        runner.x = runner.x - 5
        runner.scale_x = 1     # face left
    if game.pressed("right"):
        runner.x = runner.x + 5
        runner.scale_x = -1    # mirror to face right
    game.frame()

Coloured squares, no emoji needed

If you would rather have plain coloured shapes, use game.box. It has a real .color you can set, and it moves and collides just like an emoji sprite:

import game
game.window(480, 360)

# a green square you can drive around
player = game.box(240, 180, 40, 40, "#22cc88")
wall = game.box(380, 180, 20, 200, "#ff5577")

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 yellow on a bump
    game.frame()

A scoreboard is just a label

There is no magic score display. You make a label and update its text yourself, which means you decide where it sits and what it says:

board = game.label("Score: 0", 60, 22, size=22)
# ... later, when the player scores ...
game.score(1)
board.content = "Score: " + str(game.score())

What it can and cannot do

Being honest about the limits, because knowing them helps you plan a game that will actually work:

  • Great for: catch and dodge games, mazes, top-down movers, two-player keyboard games, simple arcade fun.
  • Not built for: gravity and physics, loading your own picture files, mouse control, or sound. Those are the sort of things a full engine like pygame adds.

That is the trade. Our library is tiny and instant and needs no install, and in return it keeps things simple. For what you make in Year 7 to 10, simple goes a very long way.

9. Now have a go

Open the Sandbox, type import game, and build something. The two example cards there, "move the chicken" and "catch the eggs", are a good place to start: load one, then change a number and see what happens.

Open the Sandbox