Chief Kief
Chief Kief

Reputation: 13

Python appending to wrong list?

I can make no sense of this problem. I have a Player object and some Enemy objects that both inherit from the Actor class. Both Player and Enemy have shoot(self) methods that makes them shoot a bullet. This bullet is supposed to be added to their respective list of projectiles, but when the program calls self.projectiles.append(Projectile()) for an enemy, it adds it to the player's list of projectiles.

I've run the program where the only Actor shooting any bullets was the enemies and I watch as len(player.projectiles) returns greater and greater values, even though it should not be growing. Any help is appreciated. This block runs every time the program updates, it goes through the Game object's list of enemies and updates each one respectively:

for enemy in self.enemies:
    enemy.update(self.player)

Here's the Enemy class:

class Enemy(Actor):

    def shoot(self):
        image = pygame.transform.rotate(ProjectileImage, self.angle)
        self.projectiles.append(Projectile(self.getCenter()[0] - 6, self.getCenter()[1] - 16, 12, 32, image, 5, self.angle, True))
        shootingSound.play()

    def tryToShoot(self):
        if self.attackCoolDown >= 30:
            self.attackCoolDown = 0
            self.shoot()

    def update(self, player):
        self.pointTowards(player.x, player.y)
        Actor.update(self)
        self.tryToShoot()

The Actor class initializes projectiles:

class Actor(Entity):
    projectiles = []

Upvotes: 1

Views: 96

Answers (2)

xkcdjerry
xkcdjerry

Reputation: 983

When you add projectiles as a class varable,both Enemy and Player inheret the same list object .

Also,when you ref something using self (and it can't be found in the instance dictionary) , it defaults to the class varable, that is why your player's and enemy's lenths are both growing:they share the same list object.

To fix this,put the projectiles=[] line into the __init__ method:

Change:

class Actor(Entity):
    projectiles = []

To:

class Actor(Entity):
    def __init__(self):
        self.projectiles = []

To fix the bug.

PS: You don't seem to have a update method in the Actor class. And if you do, using super().update() will be more Pythonic than Actor.update(self).

Upvotes: 0

Prune
Prune

Reputation: 77867

Your posted code shows projectiles as a class attribute, not an instance attribute. Thus, all Actors share a single projectiles list. To make separate lists, initialize the attribute inside the __init__ method.

Upvotes: 3

Related Questions