Docs › game library

game.button()

Put a real button on your game: Start, Play again, Shop, Jump. It works with a mouse and with a finger on a phone.

How to write it

game.button(label, x, y, width, submits=None)
label
The words on the button, like "Start".
x, y
Where the middle of the button goes, in game coordinates. Optional: leave them out and it sits in the middle of the bottom edge.
width
Optional. How wide the button is, in game pixels. Leave it out and the button is just wide enough for its label.
submits
Optional. A text box from game.textbox(). Clicking the button then sends whatever is typed in that box, just like pressing Enter (see Send buttons).

It gives back the button. Keep it in a variable, then ask start.clicked() in your loop: it is True once for each click, then False until the next click.

A full example

A Start menu, a 10-second coin catcher, and a Play again button at the end:

import game
import random

game.window(480, 360, background="#0b1020")

def wait_for(button):
    # Keep the game drawing until the button is clicked,
    # then take the button away.
    while game.playing():
        if button.clicked():
            button.remove()
            return
        game.frame()

def play_round():
    basket = game.sprite("basket", 240, 320, size=60)
    coin = game.sprite("coin", random.randint(30, 450), 0, size=36)
    board = game.label("Score: 0", 70, 24)
    score = 0
    frames = 10 * 30                # 10 seconds at 30 frames a second
    while game.playing() and frames > 0:
        if game.pressed("left"):
            basket.x = basket.x - 8
        if game.pressed("right"):
            basket.x = basket.x + 8
        coin.y = coin.y + 6
        if basket.touches(coin) or coin.y > 380:
            if basket.touches(coin):
                score = score + 1
                board.content = "Score: " + str(score)
            coin.x = random.randint(30, 450)
            coin.y = 0
        frames = frames - 1
        game.frame()
    basket.remove()
    coin.remove()
    board.remove()
    return score

title = game.label("Coin Catcher", 240, 120, size=40, color="#ffd23f")
start = game.button("Start", 240, 220, width=160)
wait_for(start)                     # the menu
title.hide()

while game.playing():
    score = play_round()
    title.content = "You scored " + str(score)
    title.show()
    again = game.button("Play again", 240, 220, width=200)
    wait_for(again)
    title.hide()

The menu trick: a menu is just a small loop of its own. It keeps calling game.frame() until the button is clicked, then the program carries on to the next part. The wait_for() function above does exactly that, so you can reuse it for every button.

Good to know

  • It's a real button, not a sprite. It floats on top of the game window, above every sprite and label, and it never touches anything. You can't change its colour or shape: every game button looks the same.
  • Change the words with .text: sound_btn.text = "Sound: off".
  • Move or resize it with .x, .y and .width.
  • Hide it for a while with .hide() and bring it back with .show(). Take it away for good with .remove().
  • Several buttons can be on screen at once. Each one has its own .clicked().
left = game.button("Left", 80, 330, width=120)
right = game.button("Right", 400, 330, width=120)

while game.playing():
    if left.clicked():
        player.x = player.x - 40
    if right.clicked():
        player.x = player.x + 40
    game.frame()

Send buttons: submits=

Pair a button with a game.textbox() and clicking the button sends what's typed, just like pressing Enter. That's the easy way to send on a phone. Read what was sent with the text box's .typed():

import game

game.window(480, 360, background="#0b1020")

hello = game.label("What's your name?", 240, 120, size=26)
name_box = game.textbox("Type your name", 240, 200, width=260)
send = game.button("OK", 240, 260, width=120, submits=name_box)

while game.playing():
    name = name_box.typed()        # None until something is sent
    if name:
        hello.content = "Hi, " + name + "!"
        name_box.remove()
        send.remove()
    game.frame()

A Send button's own .clicked() stays False: its click goes to the text box instead. Check name_box.typed(), not send.clicked().

Why isn't my button working?

  • The button is still there after the menu. A button stays on screen until you take it away, even after the game is over. Call start.remove() (or start.hide()) as soon as it has done its job.
  • The menu is skipped straight away. You wrote if start.clicked(): once, outside a loop. .clicked() never waits: it just answers "was I clicked?" and moves on. Ask it again and again in a loop that calls game.frame(), like wait_for() above.
  • Hundreds of buttons appear. You made the game.button(...) inside the loop, so there's a new one every frame. Make it once, before the loop.
  • Clicking the button also does something in the game. A click on a button counts as a click on the game window too, so game.clicked() is also True. If that gets in the way, remove the button and then call game.clicked() once to throw that click away.
  • My Send button never says clicked. With submits=, read the text box's .typed() instead (see above).
  • The button covers my player. Buttons always sit on top. Put it where nothing important happens, or hide it while you play.