Search code examples
pythonpygameself

Enemies Not Unpausing In Pygame


The sprites in the Enemy group move in random directions. If they hit the window's edge, they bounce back(left to right, right to left). When P is pressed, .stop() causes all the enemies to pause. .start() unpauses it. However, now the enemies fly off-screen pass the boundaries set to the left and right of the window. .start() should have kept didn't change anything set in .update().

class Enemy(pygame.sprite.Sprite):
    def __init__(self, position, speed):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("enemy-spaceship-sprite.png")
        self.image = self.image.convert()
        self.image = pygame.transform.scale( self.image, (50, 50))
        self.image.set_colorkey( self.image.get_at( (1,1) ) )
        self.rect = self.image.get_rect() 
        self.rect.center = position
        (self.speedX, self.speedY) = speed
        self.speedHolder = speed

    def update(self):
        self.rect.center = (self.rect.centerx + self.speedX, self.rect.centery + self.speedY)

        if self.rect.left < 0:
            self.speedX = abs(self.speedX)
        if self.rect.right > WIDTH :
            self.speedX = -1 * abs(self.speedX)
        if self.rect.top < 0:
            self.speedY = abs(self.speedY)
        if self.rect.top > HEIGHT:
            self.rect.bottom = 0

    def stop(self):
        self.speedY = 0
        self.speedX = 0
    def start(self):
        (self.speedX, self.speedY) = self.speedHolder

Game Loop:

keepGoing = True
while keepGoing:
    # Set FPS of the game - 30 frames per second/tick
    clock.tick(CLOCK_TICK)
    # Every 30 ticks is a second
    tickCount += 1

    # Pause everything in the game
    if pause == True:
        for eachEnemy in enemyGroup:
            eachEnemy.stop()
    else:
        for eachEnemy in enemyGroup:
            eachEnemy.start()

########### Bunch of skipped code ###########
        missileGroup.clear(screen, background)
        missileGroup.update()
        missileGroup.draw(screen)

        pygame.display.flip()

Solution

  • I suspect you are using a list for the initial enemy speed parameter, rather than a tuple.

    The difference is important, because a Python list will be passed as a reference, and a tuple passed as a value. So when the speed is passed as a list, the initialiser self.speedHolder = speed does not make a copy of the values, it just keeps pointing to the original list. Probably all your instances of an Enemy use the same list.

    If this list is changed, the value pointed to in Enemy.start() obviously changes too. So you would see the described behaviour.

    Ensure that when you create an instance of an Enemy, that speed is a tuple, e.g.:

    position = ( 100, 100 )
    speed    = ( 3, 3 )                       # speed is a tuple
    monster  = new Enemy( position, speed )   # <<-- tuples pass by value (copy)
    speed    = ( 20, -3 )                     # nothing happens to monster
    

    and NOT:

    position = [ 100, 100 ]
    speed    = [ 3, 3 ]                       # speed is a list
    monster  = new Enemy( position, speed )   # <<-- lists passed by reference
    speed    = [ 20, -3 ]                     # monster now moves erratically