Dropping power ups from destroyed aliens – Alien Invasion

Question:

I’m currently trying to get my aliens to have a random chance to drop powerups when they are destroyed. I seem to have the basic structure and logic figure out, but I’m running into an error.

When an alien is hit and it DOES spawn a power up, my game crashes and I’m greeted with an error.

Traceback (most recent call last):
  File "/Users/austintesch/Documents/GitHub/alien_invasion/alien_invasion.py", line 358, in <module>
    ai.run_game()
  File "/Users/austintesch/Documents/GitHub/alien_invasion/alien_invasion.py", line 52, in run_game
    self._update_bullets()
  File "/Users/austintesch/Documents/GitHub/alien_invasion/alien_invasion.py", line 153, in _update_bullets
    self._check_bullet_alien_collisions()
  File "/Users/austintesch/Documents/GitHub/alien_invasion/alien_invasion.py", line 168, in _check_bullet_alien_collisions
    pow = Pow(aliens.rect.center)
AttributeError: 'list' object has no attribute 'rect'

I’m still pretty new to coding in general so I’m not sure how to go about fixing this, as to my understanding this should work, but there is clearly something simple I’m missing here.

class AlienInvasion:
    """Overall class to manage game assets and behavior."""

    def __init__(self):
        """Initlize the game, and create game resources."""
        pygame.init()
        self.settings = Settings()

        self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
        self.settings.screen_width = self.screen.get_rect().width
        self.settings.screen_height = self.screen.get_rect().height

        pygame.display.set_caption("Alien Invasion")

        self.stats = GameStats(self)
        self.sb = Scoreboard(self)

        self.ship = Ship(self)

        self.walls = Wall(self)
        self.wall_direction = self.settings.wall_speed

        self._create_groups()
        self._create_fleet()
        self._create_buttons()
 def _check_bullet_alien_collisions(self):
        """respond to bullet-alien collisions"""
        collisions = pygame.sprite.groupcollide(
            self.bullets, self.aliens, True, True
        )

        if collisions:
            for aliens in collisions.values():
                self.stats.score += self.settings.alien_points * len(aliens)
            self.sb.prep_score()
            self.sb.check_high_score()

            #Here is where I'm getting the error.
            if random.random() > 0.9:
                pow = Pow(aliens.rect.center)
                self.powerups.add(pow)


        if not self.aliens:
            self.bullets.empty()
            self._create_fleet()
            self.settings.increse_speed()

            self.stats.level += 1
            self.sb.prep_level()
 def _update_screen(self):
        """Update images on screen and flip to the new screen."""
        #fill our background with our bg_color
        self.screen.fill(self.settings.bg_color)

        # draw scoreboard to screen
        self.sb.show_score()

        #draw ship to screen
        self.ship.blitme()

        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

        self.alien_bombs.update()
        self.alien_bombs.draw(self.screen)

        self.aliens.draw(self.screen)

        self.powerups.update() 

        if self.stats.game_active and self.stats.level >= 5:
            self.walls.draw_wall()
            self.walls.update(self.wall_direction)
            self.check_wall_edges()
            self._check_wall_collosions()

        # draw play button if game is inactive
        if not self.stats.game_active:
            if self.stats.level == 1:
                self.play_button.draw_button()

            elif not self.stats.ships_left:
                self.game_over_button.draw_button()
                pygame.mouse.set_visible(True)

            elif self.stats.ships_left != 0:
                self.continue_button.draw_button()

        #Make the most recently drawn screen visible.
        #this clears our previous screen and updates it to a new one
        #this gives our programe smooth movemnt
        pygame.display.flip()

powerups.py

"""attempt to make aliens drop powerups when killed"""
import random
import pygame
from pygame.sprite import Sprite

class Pow(Sprite):
    def __init__(self, center):
        super().__init__()

        self.type = random.choice(['shield', 'gun'])
        self.image = powerup_images[self.type]
        self.rect = self.image.get_rect()
        self.rect.center = center
        self.speedy = 2

    def update(self):
        self.rect.y += self.speedy
        if self.rect.top >= self.settings.screen_height:
            self.kill()

powerup_images = {'shield': pygame.image.load('images/shield.bmp')}
powerup_images['gun'] = pygame.image.load ('images/gun.bmp')
Asked By: Zoidberg

||

Answers:

pygame.sprite.groupcollide returns a dictionary, where the elements are a list. Therefore aliens is a list:

pow = Pow(aliens.rect.center)

collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)
if collisions:
    for aliens in collisions.values():
        self.stats.score += self.settings.alien_points * len(aliens)
           
        for alien in aliens:
            if random.random() > 0.9:
                pow = Pow(alien.rect.center)
                self.powerups.add(pow)
Answered By: Rabbid76
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.