Vegpy
Vegpy

Reputation: 23

Python Crash Course, 2nd edition. Sideways shooter. Aliens keep moving down until the top row hits the bottom

Hello I'm working on getting my sideways shooter game up to speed. but I ran into a problem when I try to move the fleet of aliens down and to the left. I have set the self.rect.bottom >= screen_rect.bottom. but this code is only responsive to my top row of aliens. I tried setting a number value instead but that does not give me the desired result. any help greatly appreciated.

this is my code for the aliens:

alien.py

def check_edges(self):
    """Return True if alien is at edge of screen."""
    screen_rect = self.screen.get_rect()
    if self.rect.bottom >= screen_rect.bottom or self.rect.top <= 0:
        return True

def update(self):
    """Move the alien up or down."""
    self.y += (self.settings.alien_speed *
                    self.settings.fleet_direction)

    self.rect.y = self.y

and in alien_invasion.py

def _update_aliens(self):
    """
    Check if the fleet is at an edge,
      then update the positions of all aliens in the fleet.
    """
    self._check_fleet_edges()
    self.aliens.update()


def _create_fleet(self):
    """Create the fleet of aliens."""
    # Create an alien and find the number of aliens in a row.
    # Spacing between each alien is equal to one alien height.
    alien = Alien(self)
    alien_width = alien.rect.width
    
    alien_height = alien.rect.height
    
    # Determine the number of  rows of aliens that fit on the screen.
    ship_width = self.ship.rect.width 
    available_space_x = (self.settings.screen_width - 
        (2 * alien_width) + ship_width)
    number_rows = available_space_x // (3 * alien_width)

    
    available_space_y = self.settings.screen_height + (2 * alien_height)
    number_aliens_y = available_space_y // (2 * alien_height)

    # Create full fleet of aliens.
    for alien_number in range(number_aliens_y):
        for row_number in range(number_rows):
            self._create_alien(alien_number, row_number)
        
def _create_alien(self, alien_number, row_number):
    """Create an alien and place it in the row."""
    alien = Alien(self)
    alien_width = alien.rect.width
    alien_height = alien.rect.height

    alien.rect.x = 1200 - (2 * alien_width) - (2 * alien.rect.width) * row_number
    
    alien.y = alien_height + 2 * alien_height * alien_number
    alien.rect.y = alien.y
    self.aliens.add(alien)

def _check_fleet_edges(self):
    """Respond appropriately if any aliens have reached an edge."""
    for alien in self.aliens.sprites():
        if alien.check_edges():
            self._change_fleet_direction()
            break

def _change_fleet_direction(self):
    """Drop the entire fleet and change the fleet's direction"""
    for alien in self.aliens.sprites():
        alien.rect.x -= self.settings.fleet_left_speed
    self.settings.fleet_direction *= -1

Upvotes: 2

Views: 309

Answers (2)

Vegpy
Vegpy

Reputation: 23

So I stumbled my way to a solution eventually. It works but I'm not sure it's the best way to do it. I ended up keeping the def _change_fleet_direction(self):

should I keep it as it's own helper function or could I included it in the def _set_fleet_direction(self, direction): somehow?

I feel like the game is lagging a bit more then my original alien_invasion game.

Any tips?

This was the solution I ended up with:

def _check_fleet_edges(self):
    screen_rect = self.screen.get_rect()
    for alien in self.aliens.sprites():
        
        if alien.rect.top <= screen_rect.top:
            self._set_fleet_direction(1)  # new direction is down
            break

        elif alien.rect.bottom >= screen_rect.bottom:
            self._set_fleet_direction(-1) # new direction is up
            break

    for alien in self.aliens.sprites():
        if alien.check_edges():
            self._change_fleet_direction()
            break


def _change_fleet_direction(self):
    """Moving the aliens left"""
    for alien in self.aliens.sprites():
        alien.rect.x -= self.settings.fleet_left_speed

def _set_fleet_direction(self, direction):
    self.settings.fleet_direction = abs(self.settings.fleet_direction) *     
    direction

Upvotes: 0

Rabbid76
Rabbid76

Reputation: 211135

Your for-loop breaks immediately after the 1st alien.

for alien in self.aliens.sprites():
   if alien.check_edges():
       self._change_fleet_direction()
   break

The break statement must be in code block of the if-statement. It's a matter of Indentation

for alien in self.aliens.sprites():
    if alien.check_edges():
        self._change_fleet_direction()
        break

I recommend to make your code more robust. If an alien reaches the top, the new fleet direction should be downwards. If an alien reaches the bottom, the new fleet direction should be upwards.

Write a method _set_fleet_direction instead of _change_fleet_direction. The method has a direction parameter that indicates the new direction. The argument has to be 1 for downwards and -1 for upwards. The new fleet_direction can be calculated with the current absolute value (abs(x)) multiplied by the new direction:

def _set_fleet_direction(self, direction):
    self.settings.fleet_direction = abs(self.settings.fleet_direction) * direction

Set the direction dependent on the range check:

def _check_fleet_edges(self):
    """Respond appropriately if any aliens have reached an edge."""

    screen_rect = self.screen.get_rect()
    for alien in self.aliens.sprites():

        if alien.top <= screen_rect.top:
            self._set_fleet_direction(1)  # new direction is down
            break

        elif alien.bottom >= screen_rect.bottom
            self._set_fleet_direction(-1) # new direction is up
            break

Upvotes: 1

Related Questions