Restarting the Bounce game (revisited)

04 Mar, 2018

Robin T writes (excerpted):

I am currently at chapter 14, i already made my first game called "Bounce". When the game is over, i want the user to push a button or a mouse click to restart the game. But i don't know how to do this.

Someone else asked a similar question a few years ago, so here's my post from back then, with some ideas about adding a restart button: "Restarting the game". In terms of creating a function to restart the game, you might want to use the canvas coords function to move the ball and paddle back to their starting position, and then set the values of all the other variables to the same as they started as well (for example, setting the hit_bottom variable to False; if you've added a score, setting the score back to zero; and so on). coords takes 5 parameters: the id of the object to move, the x and y position and the width and height of the object. So moving both objects back to their starting position might look something like this:

self.canvas.coords(, 200, 300, 300, 310)
self.canvas.coords(, 245, 100, 260, 115)

Hopefully that helps.

Problem with paddle-ball animation

19 Feb, 2018

Hayden B writes:

I am trying to code the bouncing red ball in Chapter 13 but the animation is not working. I have checked the code, and it makes sense, but I am getting these errors when I run:

RESTART: C:\Users\rf\AppData\Local\Programs\Python\Python36-32\Files .py\ Traceback (most recent call last):   File "C:\Users\rf\AppData\Local\Programs\Python\Python36-32\Files .py\", line 33, in <module>     ball.draw()   File "C:\Users\rf\AppData\Local\Programs\Python\Python36-32\Files .py\", line 15, in draw     self.canvas.move(, self.x, self.y)   File "C:\Users\rf\AppData\Local\Programs\Python\Python36-32\lib\", line 2585, in move, 'move') + args)_ _tkinter.TclError: invalid command name ".!canvas"

...and the red ball gets "stuck" at the top "jiggling" but not bouncing or returning down as it is supposed to. I cannot figure out what the problem is. Can you help?

Your code is almost right, there's just one thing you've mistyped. Here's a snippet from my code:

canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)

And here's your code:

canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)

Check the difference in the last line. Why do the missing brackets cause such a problem? The reason is that Python can't calculate the height of the canvas (400 pixels) until you call pack() and then update(). You are calling tk.update which is effectively just dumping information about the function, rather than calling the function itself. Here's what happens if I try that code:

>>> tk.update
<bound method Misc.update of <tkinter.Tk object .>>

And, because you aren't actually calling the update function, this line...

        self.canvas_height = self.canvas.winfo_height()

...actually results in canvas_height being 1 pixel, rather than 400. As a consequence, your ball then gets stuck jiggling at the top of the screen because both these if-statements end up being true:

        if pos[1] <= 0:
             self.y = 1
        if pos[3] >= self.canvas_height:
             self.y = -1

(so pos[1] ends up being less than or equal to 0, and pos[3] ends up being >= to the canvas_height)

By the way, you can ignore the error message -- that has nothing to do with your code. When you close the game window, your program is still trying to call the move function and so you get an error message because the canvas no longer exists (effectively).

Hope that helps.

Restarting the game

29 Aug, 2014

Lyna M writes (excerpted):

I bought your book Python for Kids with the intention to teach my son Python later on but have now been using it myself to learn Python as I find your book to be quite comprehensive even if it was 'for kids'.

I've been doing the Bounce tutorial and would like to find a way to add a restart button so that each time the game ends, the player can restart the game if they want to.

I've applied the codes for Game Over but would like to add a restart button after that.

if ball.hit_bottom == True:     time.sleep     canvas.itemconfig(game_over_text, state='normal')     btn = Button(tk, text="Click to Restart Game")     btn.pack() tk.update_idletasks() tk.update() time.sleep(0.01)

tk = Tk() btn = Button(tk, text="Click to Restart Game") btn.pack()

How to tie in the button so that it restarts the game when clicked? I've been trying out codes from forums and blogs but they don't seem to work or are too hard to understand.

There's a few ways you can handle the restart. If you look at the programming puzzles in Chapter 14, the first challenge is to delay the game start using the <Button-1> binding to tie a mouse button click to a function which starts the game. You could adapt that function to also restart the game once it's over. That's probably the most seamless approach. If you really want to use a button, you need a way to add it just once -- because where you've added it (inside the loop), you'll get one button added to the window for every iteration of the loop. After the loop finishes isn't really the right place either.

First of all you'll need a Game class which will tie all the game objects together. Basically the new class would have object variables to 'store' the paddle, the ball, the score, the game-over-text, and also your restart button (initially the restart button variable would be set to None). So rather than adding the button inside the if-statement, you might do something like this:

    game = Game(canvas, paddle, ball, score, game_over_text)

        --- ✂ ---

    while 1:

            --- ✂ ---

        if ball.hit_bottom == True:
            canvas.itemconfig(game_over_text, state='normal')
            if game.restart_button is None:

In the above code, if the game variable restart_button is None (not currently displayed), we call a function add_restart - so that fixes the problem of adding the button more than once. Here's the code for adding the button:

class Game:

        --- ✂ ---

    def add_restart(self):
        self.restart_button = Button(tk, text="Click to Restart Game", command=self.restart)

The command associated with the button is the function on our Game class called restart - this is the guy that takes care of hiding the game over text, putting the ball and paddle back in their starting positions, and so on.

Hope that helps somewhat.