Skip to content
BetaDE
Lesson 1 of 4Programming games

Programming games · Lesson 1 · 30 minutes

Your first game: shapes, loop, keys

What you'll learn

  • Draw shapes and text on a game area
  • Understand how a game loop works frame by frame
  • Steer a figure with the arrow keys and keep it inside the window

A game is a flip book

A game shows many pictures per second – like a flip book. In every picture, things are a little bit different. That makes it look as if something moves. In this lesson you build such a flip book yourself. Codelix has a small game module for it.

The game area

First you draw a single picture. The point (0, 0) is at the top left. x grows to the right, y grows downwards. That’s different from maths, but almost all games do it this way.

from codelix import game

game.window(400, 300)
game.rect(0, 250, 400, 50, "green")      # meadow
game.circle(330, 60, 35, "gold")         # sun
game.rect(80, 170, 80, 80, "tomato")     # house
game.text(10, 10, "My first picture")
CommandWhat it draws
game.window(400, 300)game area, 400 wide and 300 tall
game.rect(x, y, width, height, color)rectangle, (x, y) is the top-left corner
game.circle(x, y, radius, color)circle, (x, y) is the centre
game.line(x1, y1, x2, y2, color)line from one point to another
game.text(x, y, "Hello", color, size)text

Colours are English names like "red", "gold" or "cyan" – or codes like "#ff8800".

The game loop

For movement, you write a function. It draws one picture. game.run(update) then calls it 30 times per second. Before every frame, the game area is cleared.

from codelix import game

game.window(400, 300)
ball = {"x": 0, "y": 150}


def update():
    ball["x"] = ball["x"] + 3
    if ball["x"] > 400:
        ball["x"] = 0
    game.circle(ball["x"], ball["y"], 15, "orange")


game.run(update)

Press Stop when you’ve seen enough. Otherwise the ball runs forever.

Why a dictionary? ball holds the values that change. Because update() only changes values inside the dictionary, this works without an extra command. With a normal variable like x = x + 3 you would need to write global x in the function.

Steering with the arrow keys

game.key("left") is True as long as you hold the key down. You can use it to move a figure:

from codelix import game

game.window(400, 300)
player = {"x": 180}


def update():
    if game.key("left"):
        player["x"] = player["x"] - 5
    if game.key("right"):
        player["x"] = player["x"] + 5
    game.rect(player["x"], 260, 40, 20, "cyan")
    game.text(10, 10, "Arrow keys ← →", "white", 16)


game.run(update)

How to steer: After the start, the game area has the focus, so the arrow keys work right away. If you click somewhere else, just click the game area again. Esc leaves it. On a phone, use the buttons below the game area.

These keys exist: "left", "right", "up", "down", "space", "enter" and "w", "a", "s", "d".

Try it: hold ← for a long time. The player disappears on the left! That’s exactly what you fix in the task.

Your task

Your turn

The player already moves left and right with ← and →. Add two things: 1. With ↑ and ↓ it should also move up and down (5 pixels per frame). 2. It must never leave the window: x stays between 0 and 360, y between 0 and 280 (the window is 400 × 300, the player 40 × 20).

from codelix import game

game.window(400, 300)
player = {"x": 180, "y": 140}


def update():
    if game.key("left"):
        player["x"] = player["x"] - 5
    if game.key("right"):
        player["x"] = player["x"] + 5
    # Up and down are missing here

    # The edges are missing here

    game.rect(player["x"], player["y"], 40, 20, "cyan")


game.run(update)

Solve it without hints to earn a ⭐ on your progress page.

Show solution

Try it yourself first – mistakes teach you the most. Here is one possible solution:

from codelix import game

game.window(400, 300)
player = {"x": 180, "y": 140}


def update():
    if game.key("left"):
        player["x"] = player["x"] - 5
    if game.key("right"):
        player["x"] = player["x"] + 5
    if game.key("up"):
        player["y"] = player["y"] - 5
    if game.key("down"):
        player["y"] = player["y"] + 5

    if player["x"] < 0:
        player["x"] = 0
    if player["x"] > 360:
        player["x"] = 360
    if player["y"] < 0:
        player["y"] = 0
    if player["y"] > 280:
        player["y"] = 280

    game.rect(player["x"], player["y"], 40, 20, "cyan")


game.run(update)