0

I'm currently trying to run my code in the main GameScene by drawing a PlayerPaddle. I'm currently refactoring my code by using Sprites. Right now, I'm getting errors saying my PlayerPaddle object has no attribute centery. If I comment that line out, then I'm getting how other attributes, such as centerx and rect are also not attributes, though I'm not sure how to fix self.rect.center with sprites...

Here is the PlayerPaddle class, which inherits from the Paddle Class, which inherits from the Image class.

class Image(pygame.sprite.Sprite):

    def __init__(self, screen_size, color=(255,0,0)):
        super().__init__()
        self.screen_size = screen_size

        self.angle = 0
        self.dir = 0

        self.original_image = pygame.image.load('naruto.png').convert()
        self.colorkey = self.original_image.get_at((0,0))

        self.original_image = pygame.transform.scale(self.original_image, (20, 100))

        self.update()

Paddle Class

class Paddle(Image):

    def __init__(self, screen_size, color = (255,0,0)):
        super().__init__(screen_size, color = (255, 0, 0))

    def update(self):
        super().update()

    def Render(self, screen_size):
        super().draw(screen_size)

PlayerPaddle class

class PlayerPaddle(Image):

def __init__(self, screen_size, color = (255,0,0)):

    self.rect.centerx = 10
    self.rect.centery = screen_size[1] // 2

    self.height = 100
    self.width = 20

    self.speed = 3
    self.direction = 0


    super().__init__(screen_size, color = (255, 0, 0))

def update(self):

    super().update()
    self.centery += self.direction*self.speed
    #self.rect.centery += self.direction*self.speed 
    self.rect.center = (self.centerx, self.centery)

    if self.rect.top < 0:
        self.rect.top = 0

    if self.rect.bottom > self.screen_size[1]-1:
        self.rect.bottom = self.screen_size[1]-1


    def draw(self, screen_size):

        super().draw(screen_size)

Finally, here is my GameScreen, which inherits from a Scene Class(not pictured). This is where I create my objects and define all the events and updates.

class GameScreen(SceneBase):

    def __init__(self):
        SceneBase.__init__(self)

        self.player_paddle = classes.PlayerPaddle(screen_size)
        self.my_font = pygame.font.SysFont("Arial", 50)

    def ProcessInput(self, events, pressed_keys):
        for event in events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    self.player_paddle.direction = -1
                elif event.key == pygame.K_DOWN:
                    self.player_paddle.direction = 1       

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP and self.player_paddle.direction == -1:
                    self.player_paddle.direction = 0
                elif event.key == pygame.K_DOWN and self.player_paddle.direction == 1:
                    self.player_paddle.direction = 0

    def Update(self):
        self.player_paddle.update() 

    def Render(self):
        screen.fill(WHTIE)
        self.player_paddle.Render(screen)

    def SwitchToScene(self, next_scene):
        self.next = next_scene

I'm not sure why I'm returning attribute errors, since I defined attributes in the PlayerPaddle class, such as self.centerx and self.centery. Also, how do I deal with self.rect.center with the case of my code? Thanks and much appreciation.

Traceback (most recent call last):
  File "C:\Users\matth\OneDrive\Documents\15-112\Term Project\TP3Pong\run_game.py", line 50, in <module>
    run_game(1200, 800, 64, scenes.GameScreen())
  File "C:\Users\matth\OneDrive\Documents\15-112\Term Project\TP3Pong\scenes.py", line 94, in __init__
    self.player_paddle = classes.PlayerPaddle(screen_size)
  File "C:\Users\matth\OneDrive\Documents\15-112\Term Project\TP3Pong\classes.py", line 172, in __init__
    self.rect.centerx = 10
AttributeError: 'PlayerPaddle' object has no attribute 'rect)
turtlefish12
  • 241
  • 3
  • 12
  • always put **FULL** error message (Traceback) in question (as text, not screenshot). There are other usefull informations. – furas Dec 05 '17 at 11:56
  • BTW: you could put all method from `Paddle` directly in `Image` and use only `Image` (or even rename it into `Paddle`. – furas Dec 05 '17 at 11:58
  • you don't have to do `def update(self): super().update()` in `Paddle` because if you don't create `update()` then `Paddle` will automatically use `update()` from `Image`. It's **inheritance**. BTW: the same with `def draw(self, screen_size)` in `PlayerPaddle()`. But you should use `super().update()` inside `PlayerPaddle.update()` - without `super().update()` it will never execute code from `Image.update()` in `PlayerPaddle` – furas Dec 05 '17 at 12:02
  • instead `self.centerx`, `self.centery` I would use only `self.rect.centerx`, `self.rect.centery` - why to keep the same value in two variables. And `self.rect` is needed to `blit()` image. – furas Dec 05 '17 at 12:10
  • see [PEP 8 -- Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) - there is suggestion to use `lower_case_names` for variables, functions and methods - `update()`, `switch_to_scene()`. `CamelCaseNames` we use only for class names. Many editors, IDEs (even Stackoverflow) know this and use special color for class names to make code more readable. – furas Dec 05 '17 at 12:14
  • I made the change to self.rect.centerx and self.rect.centery, and I have already blitted thed image by inheriting from Image (not shown above. I'm still returning the same attribute error (shown in the EDIT) – turtlefish12 Dec 05 '17 at 14:47
  • Now error message shows where problem is in code :) Problem is because you didn't use `super().update()` inside `PlayerPaddle.update()` so it doesn't execute `Image.update()` which creates `self.rect` and later `self.rect.top < 0` makes problem because it can't find `self.rect` – furas Dec 05 '17 at 15:17
  • I'm receiving the same error for my other variables. I put the error in the edit. self.centery is clearly defined in my PlayerPaddle class, so I don't know what's causing this error. – turtlefish12 Dec 05 '17 at 15:31
  • Now problem is because before `self.centerx = 10` it runs `super().__init__()` which runs `self.update()` - so it runs `PlayerPaddle.update()` and there is `self.centery += ...`. So finally it try to change `self.centery += ...` before it is created `self.centerx = 10`. One method is to put `self.centerx = 10` before `super().__init__()`. Sechod method is to stop using `self.centerx` and use only `self.rect.centerx` BTW: if you put `print()` in all method (before and after `super().xxx`) then you will see in which order they are executed. – furas Dec 05 '17 at 15:44
  • Updated with both suggestions, and now I don't have a rect attribute. Also, I feel like a lot of these problems are caused by calling update() in the init function. My teacher says you shouldn't update in object creation. – turtlefish12 Dec 05 '17 at 16:13
  • you have to use one of sugesstion - not both. Put `self.centerx` before `super().__init__()` **OR** use `self.rect.center` but do put it before `super().__init__()` – furas Dec 05 '17 at 16:17
  • Thank you, I have finally fixed this part! – turtlefish12 Dec 05 '17 at 16:37

0 Answers0