python-2.7classpropertiespygame

Creating a Class Attribute dependent on Another Attribute


I am currently working on a small RPG in Pygame to get used to object oriented coding.

When looking into how to auto-update a property I came across the following:

class P:

    def __init__(self,x):
        self.x = x

    @property
    def x(self):
        return self.__x

    @x.setter
    def x(self, x):
        if x < 0:
            self.__x = 0
        elif x > 1000:
            self.__x = 1000
        else:
            self.__x = x

I tried applying it to my code but I get the following error:

  File "weapons.py", line 13, in __init__
    self.name = '{} {}'.format(ammo, self.raw_name)

TypeError: name() takes exactly 3 arguments (2 given)

I understand what the error is but I don't get how to solve it since I need both the raw_name and the ammo attributes to auto-update my Arrow instance's name.

My class is as such:

class Projectile(Item):
    def __init__(self, name, value, image, x, y, speed, dmg, dmg_modif, ammo):
        super(Projectile, self).__init__(name, value, image, x, y)
        self.dest = (self.rect[0],self.rect[1])
        self.speed = speed
        self.dmg_modif = dmg_modif
        self.dmg = dmg
        self.orientation = 0
        self.ammo = ammo
        
    @property
    def name(self):
        return self.___name  
        

    @name.setter
    def name(self, raw_name, ammo):
        if '{} {}'.format(raw_name,ammo) != self.___name:
            self.___name = '{} {}'.format(raw_name,ammo)

The child class which returns the error is:

class Arrow(Projectile):
    def __init__(self, ammo): #name, value, image, x, y, dmg
        self.raw_name = 'Arrows'
        self.name = '{} {}'.format(ammo, self.raw_name)
        self.value = 5
        self.image = variables.quiver_img
        self.speed = 4
        self.dmg = 2
        self.dmg_modif = 1
        super(Arrow, self).__init__(self.name, self.value, self.image, 200, 150, self.speed, self.dmg, self.dmg_modif, ammo)

And the parent classes are, Item and MySprite:

class Item(MySprite):
 
    def __init__(self, name, value, image, x, y):
        # Call the parent class (Sprite) constructor
        super(Item, self).__init__(image, x, y)
 
        self.name = name
        self.value = value 
        self.inv_pos = -1

and

class MySprite(pygame.sprite.Sprite):
    def __init__(self,image,x,y):
 
        # Call the parent class (Sprite) constructor
        super(MySprite, self).__init__()
        self.image = image
        self.rect = self.image.get_rect().move(x, y) #initial placement
        self.top_cp = (self.rect[0]+self.rect[2]/2,self.rect[1])
        self.bot_cp = (self.top_cp[0],self.rect[1]+self.rect[3])
        self.left_cp = (self.rect[0],self.rect[1]+self.rect[3]/2)
        self.right_cp = (self.left_cp[0]+self.rect[2],self.left_cp[1])
        self.center = self.rect.center
        self.pos = self.rect.topleft
        self.blit_order = 1
        self.level =  variables.current_level #Level(1)#level to which sprite belongs

Solution

  • So I eventually managed to solve my problem:

    class Projectile(object):
        def __init__(self, raw_name, ammo):
            self.raw_name = raw_name
            self.name = self.raw_name
            self.ammo = ammo
    
        @property
        def ammo(self):
            return self._ammo
    
        @ammo.setter
        def ammo(self, ammo):
            self.name = str(ammo) + self.raw_name
            self._ammo = ammo
    
    
    class Arrow(Projectile):
    
        def __init__(self):
            self.raw_name = ' Arrows'
            self.name = self.raw_name
            super(Arrow, self).__init__(self.raw_name, ammo
            = 10)
    
    arrow = Arrow()
    print arrow.ammo 
    print arrow.name 
    arrow.ammo = 15
    print arrow.ammo 
    print arrow.name 
    

    gives:

    >>>10
    >>>10 Arrows
    >>>15
    >>>15 Arrows