Yuri The Doer
Yuri The Doer

Reputation: 9

Python Crash course chapter 13-5, Sideways Shooter part 2, Only see few of aliens

I am working on my own version of this assignment and I am stuck. I created rows of devils (aliens) on the right side of the surface and they look fine until I update their position.

Once I run the self.devils.update() method to move them, suddenly I see 1 row of devils only on the screen, not all of them. They still do move up and down and also towards left once they touch the edge of the screen as I planned though.

To error check, I printed len(self.devils) to see if the number is matching with self.devils group, and they do match. I also muted self.devils.update() and I see all rows of devils again, just not moving.

How can I fix this?

Here is the main class, heart_shooter.py':


    def run_game(self):
        """ Start the main loop of the game """
        while True: 
            self._check_events()
            self.shooter.update()
            self._update_arrows()
            self._update_devils()
            self._update_screen()

    def _create_fleet(self):
        """ Create a fleet of devils. """
        # Create a devil and find the number of devils that fit on the screen.
        devil = Devil(self)
        devil_width, devil_height = devil.rect.size
        available_space_x = int((self.settings.screen_width / 2 ) + devil_width)
        number_devils_x=  available_space_x // (2 * devil_width)

        # Determine the number of rows of devils that fit on the screen.
        available_space_y = self.settings.screen_height - devil_height
        number_rows = available_space_y // (2 * devil_height)

        # Create a column of devils.
        for row_number in range (number_rows):
            for devil_number in range(number_devils_x):
                # Create a devil and place it in a row.
                self._create_devil(devil_number, row_number)

    def _create_devil(self,devil_number, row_number):
        """ Create a devil """
        devil = Devil(self)
        devil_width, devil_height = devil.rect.size
        available_space_x = (self.settings.screen_width / 2 ) 
        devil.x = available_space_x + ( 2 * devil_width * devil_number)
        devil.rect.x = devil.x
        devil.rect.y = devil_height + (2 * devil_height * row_number)

        self.devils.add(devil)

    def _check_fleet_edges(self):
        """ Respond appropriately if any devil reached the edge """
        for devil in self.devils.sprites():
            if devil.check_edges():
                self._change_fleet_direction()
                break

    def _change_fleet_direction(self):
        """ Move the fleet forward and change the direction. """
        for devil in self.devils.sprites():
            devil.rect.x -= self.settings.devil_forward_speed
        self.settings.fleet_direction *= -1


    def _update_devils(self):
        """
            Check if any devil has reached the edge of the screen 
                then update the position of the entire fleet.
        """
        self._check_fleet_edges()
        self.devils.update()
    
    def _update_screen(self):
        """ Update images on the screen and flip to the new screen. """
        self.screen.fill(self.settings.bg_color)
        self.shooter.blitme()
        for arrow in self.arrows.sprites():
            arrow.draw_arrow()

        self.devils.draw(self.screen)

        # Make the most recently drawn screen visible
        pygame.display.flip()


This is the devil.py:

def __init__(self, hs_game):
    """ Initialize the devil and set its starting position"""
    super().__init__()
    self.screen = hs_game.screen
    self.screen_rect = hs_game.screen.get_rect()
    self.settings = hs_game.settings

    # Load the devil image and get its rect
    self.image = pygame.image.load('images/evil1.png')
    self.rect = self.image.get_rect()

    # Start each new devil on the right top corner of the screen
    self.rect.x= self.screen_rect.width - (1.5 * self.rect.width)
    self.rect.y = self.screen_rect.top + (self.rect.height/2)

    # Store the exact vertical position of the devil
    self.y = float(self.rect.y)

def update(self):
    """ Move the devils up and down """
    self.y += (self.settings.devil_speed
                            * self.settings.fleet_direction)
    self.rect.y = self.y

def check_edges(self):
    """ Check if any devil have reached the bottom. """
    if self.rect.bottom >= self.screen_rect.bottom or self.rect.top <= 0:
        return True

Upvotes: 0

Views: 196

Answers (1)

Yuri The Doer
Yuri The Doer

Reputation: 9

For future readers of this post who are going through the same problem, I fixed the issue by the following change.

I changed the last 3 rows of _create_devil() method in heart_shooter.py.

    def _create_devil(self,devil_number, row_number):
        """ Create a devil """
        devil = Devil(self)
        devil_width, devil_height = devil.rect.size
        available_space_x = ((self.settings.screen_width / 2 ) 
                                                   + devil_width)
        devil.rect.x = available_space_x + ( 2 * devil_width * row_number)
        devil.y = devil_height + (2 * devil_height * devil_number)
        devil.rect.y = devil.y

Originally, I wrote below.

        devil.x = available_space_x + ( 2 * devil_width * devil_number)
        devil.rect.x = devil.x
        devil.rect.y = devil_height + (2 * devil_height * row_number)
       

(I will update this answer in elaborate detail later.)

Upvotes: 1

Related Questions