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,.yand.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()(orstart.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 callsgame.frame(), likewait_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 alsoTrue. If that gets in the way, remove the button and then callgame.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.