AttributeError: 'Player' object has no attribute 'radius'

Viewed 25

I am getting this Error AttributeError: 'Player' object has no attribute 'radius'

The Player class:

import pyglet
from pyglet import shapes, text

from .Entity import Entity


@Entity.register
class Player(Entity):

    def __init__(self, name, x, y, handler, dN=False):
        super().__init__(name, x, y, handler, dN)
        self.speed = 2
        self.radius = 5
        self.direction = (0, 0)

    def getShape(self, batch: pyglet.graphics.Batch):
        # [...]
        return shapes.Circle(x=self.x, y=self.y, radius=self.radius, color=(255, 0, 0), batch=batch) # works

    def calcDirection(self):
        # does not access self.radius
        pass

    def tick(self):
        self.calcDirection()
        self.x += self.direction[0] * self.speed
        self.y += self.direction[1] * self.speed
        if self.x < self.radius: # no error
            self.x = self.radius
        if self.y < self.radius:
            self.y = self.radius
        if self.x > self.handler.getWidth() - self.radius:
            self.x = self.handler.getWidth() - self.radius
        if self.y > self.handler.getHeight() - self.radius:
            self.y = self.handler.getHeight() - self.radius
        self.hitbox.tick()

    def getWidth(self):
        return self.radius * 2 # Attribute Error

    def getHeight(self):
        return self.radius * 2

The Error occurs in the getWidth() method. I can access self.radius in every other method.

Here is the Entity Base class

import abc

import pyglet

from Game.Handler import Handler
from .HitBox import HitBox

# Entity Base
class Entity(abc.ABC):
    def __init__(self, name: str, x: int, y: int,handler:Handler, displayName:bool=False, hitboxMarginX:int=0, hitboxMarginY:int=0):
        self.name = name
        self.x = x
        self.y = y
        self.displayName = displayName
        self.handler = handler
        self.hitbox = HitBox(self, hitboxMarginX, hitboxMarginY)

    @abc.abstractmethod
    def getShape(self, batch: pyglet.graphics.Batch):
        pass

    @abc.abstractmethod
    def tick(self):
        pass

    @abc.abstractmethod
    def getWidth(self):
        pass

    @abc.abstractmethod
    def getHeight(self):
        pass

I have read that this Error occurs if you have indentation mistakes in your application. I have searched my whole project for mistakes but found none. I have also used the in-built "Convert Indentation to Spaces" function of Visual Studio Code on every python file in my project.

Full Traceback:

Traceback (most recent call last):
  File "C:\Users\Noah\Desktop\coding\projects\python-game\main.py", line 4, in <module>
    Launcher()
  File "C:\Users\Noah\Desktop\coding\projects\python-game\Game\Launcher.py", line 6, in __init__
    self.game = Game.Game(title="Game", width=500, height=500)
  File "C:\Users\Noah\Desktop\coding\projects\python-game\Game\Game.py", line 34, in __init__
    self.entityManager = EntityManager(self.handler)
  File "C:\Users\Noah\Desktop\coding\projects\python-game\Entities\EntityManager.py", line 28, in __init__
    self.addEntity(Player("Player", center[0], center[1], self.handler, True))
  File "C:\Users\Noah\Desktop\coding\projects\python-game\Entities\Player.py", line 19, in __init__
    super().__init__(name, x, y, handler, dN)
  File "C:\Users\Noah\Desktop\coding\projects\python-game\Entities\Entity.py", line 24, in __init__
    self.hitbox = HitBox(self, hitboxMarginX, hitboxMarginY)
  File "C:\Users\Noah\Desktop\coding\projects\python-game\Entities\HitBox.py", line 8, in __init__
    self.width = entity.getWidth()
  File "C:\Users\Noah\Desktop\coding\projects\python-game\Entities\Player.py", line 83, in getWidth
    return self.radius * 2
AttributeError: 'Player' object has no attribute 'radius'
1 Answers

Your problem is here:

@Entity.register
class Player(Entity):

    def __init__(self, name, x, y, handler, dN=False):
        super().__init__(name, x, y, handler, dN)
        self.speed = 2
        self.radius = 5

super().__init__() is called first in the Player constructor.

That means Entity.__init__() runs before anything else in Player.__init__ including self.radius = 5.

This wouldn't be a problem but self.hitbox = HitBox(self, hitboxMarginX, hitboxMarginY) is called in Entity.__init__().

This also wouldn't be a problem but according to your traceback:

  File "C:\Users\Noah\Desktop\coding\projects\python-game\Entities\Entity.py", line 24, in __init__
    self.hitbox = HitBox(self, hitboxMarginX, hitboxMarginY)
  File "C:\Users\Noah\Desktop\coding\projects\python-game\Entities\HitBox.py", line 8, in __init__
    self.width = entity.getWidth()
  File "C:\Users\Noah\Desktop\coding\projects\python-game\Entities\Player.py", line 83, in getWidth
    return self.radius * 2

That causes entity.getWidth() to be called which accesses self.radius and at this point, self.radius is not set yet.

Related