AttributeError: 'Ball' object has no attribute 'hit_paddle'

Joined
Feb 5, 2019
Messages
1
Reaction score
0
Beginner here. I am trying to do the game bounce.
This is the error message:

Traceback (most recent call last):
File "C:\Users\Anthony\AppData\Local\Programs\Python\Python36-32\paddlebounce.py", line 76, in <module>
ball.draw()
File "C:\Users\Anthony\AppData\Local\Programs\Python\Python36-32\paddlebounce.py", line 24, in draw
if self.hit_paddle(pos) == True:
AttributeError: 'Ball' object has no attribute 'hit_paddle'
>>>

Python:
from tkinter import *
import random
import time
class Ball:
    def __init__(self, canvas, paddle, color):
        self.canvas = canvas
        self.paddle = paddle
        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_height = self.canvas.winfo_height()
        self.canvas_width = self.canvas.winfo_width()

    def draw(self):
        self.canvas.move(self.id, self.x, self.y)
        pos = self.canvas.coords(self.id)
        if pos[1] <= 0:
            self.y = 3
        if pos[3] >= self.canvas_height:
            self.y = -3
        if self.hit_paddle(pos) == True:
            self.y = -3
        if pos[0] <= 0:
            self.x = 3
        if pos[2] >= self.canvas_width:
            self.x = -3

class Paddle:
    def __init__(self, canvas, color):
            self.canvas = canvas
            self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color)
            self.canvas.move(self.id, 200, 300)
            self.x = 0
            self.canvas_width = self.canvas.winfo_width()
            self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
            self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
           
    def hit_paddle(self, pos):
        paddle_pos = self.canvas.coords(self.paddle.id)
        if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
            if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
                 return True
        return False     
   
       
    def draw(self):
        self.canvas.move(self.id, self.x, 0)
        pos = self.canvas.coords(self.id)
        if pos[0] <= 0:
            self.x = 0
        elif pos[2] >= self.canvas_width:
            self.x = 0
     
    def turn_left(self, evt):
        self.x = -2

    def turn_right(self, evt):
        self.x = 2
       
        
tk = Tk()
tk.title("Game")
tk.resizable(0, 0)
tk.wm_attributes("-topmost", 1)
canvas =Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
tk.update()

paddle = Paddle(canvas, 'blue')
ball = Ball(canvas, paddle, 'red')

while 1:
    ball.draw()
    paddle.draw()
    tk.update_idletasks()
    tk.update()
    time.sleep(0.01)

What am I doing wrong? I have been trying to figure it out for over a week.
 
Joined
Jun 27, 2018
Messages
12
Reaction score
5
I'm a little late to the party here. I haven't visited this site for a while. I hope you've already managed to fix this.
As there are no replies to this - I'll put in my two cents.....

There are two lines that I can see which are problematic in your code.

Your error message quite clearly states that your Ball class does not have a hit_paddle attribute. Which it does not!
hit_paddle is clearly an attribute of your Paddle class.

From looking at your code, I can see that your Ball class contains an instance of your Paddle class.
So the line that you are getting an error message about should be changed from:
Code:
if self.hit_paddle(pos)==True:
to:
Code:
if self.paddle.hit_paddle(pos):
Note: The "==true" part of the statement is already implicit in the if statement, so it can be left out..... If that makes sense??
In the context of the line, self refers to an active instance of your Ball class. Your Ball class does not have a hit_paddle attribute, but it's paddle attribute (an instance of Paddle) does. Hence the need to use "self.paddle.hit_paddle(pos)"

After fixing that problem - the other line that you will get an error message about is inside your hit paddle method itself. Specifically this line:
Code:
    paddle_pos = self.canvas.coords(self.paddle.id)
The problem in the above line is the "self.paddle.id" part. The Paddle class doesn't have a "paddle" attribute.
But the Paddle class does have an "id" attribute. So the attribute you are really intending to refer to is "self.id" NOT "self.paddle.id".
So change that line to:
Code:
    paddle_pos = self.canvas.coords(self.ids)

And that should fix your code.

It looks to me like you are experiencing a bit of confusion about what "self" actually refers to.

The thing to remember is that "self" always refers to an instance of the class you are inside the definition of.
So inside your Ball class, "self" always refers to an instance of your Ball class. In the Paddle class, "self" refers to an instance of your Paddle class.

So I think you just need to be a little more mindful of the way your classes are laid out.

Your Ball class contains an instance of the Paddle class.
To access the Ball classes methods/attributes from inside the Ball class you would use "self.attribute_name"
To access the Paddles methods/attributes from inside the Ball class, you would use "self.paddle.attribute_name".
To access the Paddles methods/attributes from inside the Paddle class, you would use "self.attribute_name".

Does that all make sense?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,731
Latest member
MarcyGipso

Latest Threads

Top