Meron

Problem with bouncing ball

30 May, 2020

Lennier M writes:

I am on page 202 of your book, but when I followed your instructions, the ball stopped moving, instead of moving in multiple directions. Here is my code:

class Ball:
    def __init__(self, canvas, color):
        self.canvas = canvas
        self.id = canvas.create_oval(10, 10, 25, 25, fill=color)

        self.canvas.move(self.id, 245, 100)

        starts = [-3, -2, -1, 1, 2, 3, ]
        random.shuffle(starts)

        self.x = starts[0]
        self.y = -3
        self.canvas_width = self.canvas.winfo_width
        self.canvas_height = self.canvas.winfo_height()

    def draw(self):
        self.canvas.move(self.id, self.x, self.y)

        pos = self.canvas.coords(self.id)

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

please help

If I run your code I get the following error:

Traceback (most recent call last):
  File "test.py", line 40, in <module>
    ball.draw()
  File "test.py", line 26, in draw
    if pos[2] >= self.canvas_width:
TypeError: '>=' not supported between instances of 'float' and 'method'

So that tells us the line which is failing, but why?

If you look at these two lines, hopefully you'll see the difference (and the reason for your problem):

        self.canvas_width = self.canvas.winfo_width
        self.canvas_height = self.canvas.winfo_height()

The missing brackets on the first line mean that you haven't actually called the winfo_width function (or method). So self.canvas_width isn't a number of pixels - it's actually a reference to the function itself. If we added a print statement at that point in the code it would be even more obvious...

print(self.canvas_width)
<bound method Misc.winfo_width of <tkinter.Canvas object .!canvas>>
print(self.canvas_height)
400

This is the reason why comparing pos[2] (which is a number - to be exact it's a floating point number) with self.canvas_width (which is the reference to a function/method) comes back with the error message: "'>=' not supported between instances of 'float' and 'method'".

If you add the missing brackets, you'll hopefully find the ball moves as expected.