Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] multiple hits !
#1
im trying to get my aliens to get hit multiple times before dissapearing, i have given the aliens 2 hp and my bullet dmg is 1 so it should take two hits so far ive just made the enemies imortal, lol, can somone please help !!!!!



import sys

from time import sleep

import pygame

from bullet import Bullet

from alien import Alien

def get_number_aliens_x(ai_settings, alien_width):
    """determine the number of aliens that fit in a row"""
    avaliable_space_x = ai_settings.screen_width - 2 * alien_width
    number_aliens_x = int(avaliable_space_x / (2 * alien_width))
    return number_aliens_x

def get_number_rows(ai_settings, ship_height, alien_height):
    """ determine the number of rows of aliens fit on the screen"""
    avaliable_space_y = (ai_settings.screen_height -
                             (3 * alien_height) - ship_height)
    number_rows = int(avaliable_space_y / (2 * alien_height))
    return number_rows

def create_alien(ai_settings, screen, aliens, alien_number, row_number):
    """create an alien and place it in a row"""
    alien = Alien(ai_settings, screen)
    alien_width = alien.rect.width
    alien.x = alien_width + 2 * alien_width * alien_number
    alien.rect.x = alien.x
    alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
    aliens.add(alien)

def create_fleet(ai_settings, screen, ship, aliens):
    """creates a full fleet of aliens"""
    #create an alien and find the number of aliens in a row
    alien = Alien(ai_settings, screen)
    number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)
    number_rows = get_number_rows(ai_settings, ship.rect.height,
        alien.rect.height)
    
  #creates the fleet of aliens
    for row_number in range(number_rows):
        for alien_number in range(number_aliens_x):
            create_alien(ai_settings, screen, aliens, alien_number,
                         row_number)

def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """responds to keypresses"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True
    elif event.key == pygame.K_SPACE:
        effect = pygame.mixer.Sound('sounds/shot.wav')
        effect.play()
        fire_bullet(ai_settings, screen, ship, bullets)
    elif event.key == pygame.K_q:
        sys.exit()

def fire_bullet(ai_settings, screen, ship, bullets):
    """fire a bullet if limit not reached yet"""
        # create a new bullet and add it to the bullets group
    if len(bullets) < ai_settings.bullets_allowed:
        new_bullet = Bullet(ai_settings, screen, ship)
        bullets.add(new_bullet)

def check_keyup_events(event, ship):
    """responds to key presses"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False


#watch for keyboard and mouse events
def check_events(ai_settings, screen, stats, sb, play_button, ship, aliens,
                 bullets):
    """ responds to key and mouse events """
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event,ai_settings, screen, ship, bullets)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event, ship)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y = pygame.mouse.get_pos()
            check_play_button(ai_settings, screen, stats, sb, play_button,
                              ship, aliens, bullets, mouse_x, mouse_y)

def check_play_button(ai_settings, screen, stats, sb, play_button, ship, aliens
                      , bullets, mouse_x, mouse_y):
    """start a new game when the player clicks play"""
    button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
    if button_clicked and not stats.game_active:

        #reset the game settings
        ai_settings.initialize_dynamic_settings()

        #hide mouse cursor
        pygame.mouse.set_visible(False)
        
        #reset the game stats
        stats.reset_stats()
        stats.game_active = True

        #reser the scoreboard images
        sb.prep_score()
        sb.prep_high_score()
        sb.prep_level()
        sb.prep_ships()

        #empty the list of aliens and bullets
        aliens.empty()
        bullets.empty()

        #create new fleet and center the ship
        create_fleet(ai_settings, screen, ship, aliens)
        ship.center_ship()
            
def update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets,
                  play_button):
    """updates images on the screen and flip to the new screen"""
    #redraw the screen during each pass through the loop.
    screen.fill(ai_settings.bg_colour)
    
    #redraw all bullets behind ship and aliens
    for bullet in bullets.sprites():
        bullet.draw_bullets()
    ship.blitme()
    aliens.draw(screen)
    
    #redraw all bullets behind ship and aliens
    for bullet in bullets.sprites():
        bullet.draw_bullets()

    #draw score infomation
    sb.show_score()

    #draw the play button if the game is inactive
    if not stats.game_active:
        play_button.draw_button()

    
    #make the most recently drawn screen visable.
    pygame.display.flip()

def update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets):
    """updates position of bullets and gets rid of old ones"""
    # update bullet positions
    bullets.update()
    
    # gets rid of bullets that have dissapeared
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

    check_bullet_alien_collisions(ai_settings, screen, stats, sb,
                                  ship, aliens, bullets)

def check_bullet_alien_collisions(ai_settings, screen, stats, sb,
                                  ship, aliens, bullets):
    """respond to bullet-alien collisions"""
    #remove any bullets and aliens that have collided
    collisions = pygame.sprite.groupcollide(bullets, aliens, True, False)
    if collisions:
        for aliens in collisions.values():
            ai_settings.alien_hp -= ai_settings.bullet_dmg
            if ai_settings.alien_hp <=0:
                
                stats.score += ai_settings.alien_points * len(aliens)
                sb.prep_score()
                check_high_score(stats, sb)
                
            else:
                sb.prep_score()
                check_high_score(stats, sb)

    if len(aliens) == 0:
        #if fleet is destroyed start a new level.
        bullets.empty()
        ai_settings.increase_speed()

        #increase level
        stats.level += 1
        sb.prep_level()
        
        create_fleet(ai_settings, screen, ship, aliens)



def check_fleet_edges(ai_settings, aliens):
    """respond appropriately in any aliens have reached an edge """
    for alien in aliens.sprites():
        if alien.check_edges():
            change_fleet_direction(ai_settings, aliens)
            break

def change_fleet_direction(ai_settings, aliens):
    """drop the entire fleet and change the fleet's direction"""
    for alien in aliens.sprites():
        alien.rect.y += ai_settings.fleet_drop_speed
    ai_settings.fleet_direction *= -1

def ship_hit(ai_settings, stats, sb, screen, ship, aliens, bullets):
    """respond to ship being hit by an alien"""
    if stats.ships_left > 0:
        #decrement ships_left
        stats.ships_left -= 1

        #update scoreboard
        sb.prep_ships()

        #empty the list of aliens and bullets
        aliens.empty()
        bullets.empty()

        #create new fleet and centre the ship
        create_fleet(ai_settings, screen, ship, aliens)
        ship.center_ship()

        #pause
        sleep(0.5)
    else:
        stats.game_active = False
        pygame.mouse.set_visible(True)

def check_aliens_bottom(ai_settings, stats, sb, screen, ship, aliens, bullets):
    """check if any aliens have reached the bottom of the screen """
    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:
            #treat this the same as the ship getting hit
            ship_hit(ai_settings, stats, sb, screen, ship, aliens, bullets)
            break

def update_aliens(ai_settings, stats, sb,  screen, ship, aliens, bullets):
    """
check if the fleet is at an edge,
and then update the positions of all the aliens in the fleet
    """
    check_fleet_edges(ai_settings, aliens)
    aliens.update()
    
    #looks for alien-ship collisions
    if pygame.sprite.spritecollideany(ship, aliens):
        ship_hit(ai_settings, stats, sb, screen, ship, aliens, bullets)

    #looks for aliens hitting the bottom of the screen
    check_aliens_bottom(ai_settings, stats, sb, screen, ship, aliens, bullets)

def check_high_score(stats, sb):
    """check to see if there is a new highscore"""
    if stats.score > stats.high_score:
        stats.high_score = stats.score
        sb.prep_high_score()
Reply
#2
can you post the bullet class and alien class too?
Recommended Tutorials:
Reply
#3
alien.py

import pygame
from pygame.sprite import Sprite

class Alien(Sprite):
    """a class to represent a single alien in the fleet"""

    def __init__(self, ai_settings, screen):
        """initialize the alien and set its starting position"""
        super(Alien, self).__init__()
        self.screen = screen
        self.ai_settings = ai_settings

        #load the alien image and set its rect attribute
        self.image = pygame.image.load('images/alien.png')
        self.image = pygame.transform.scale(self.image, (100, 75))
        self.rect = self.image.get_rect()

        #start each new alien near the top of the screen
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        #store the alien's exact position
        self.x = float(self.rect.x)

    def blitme(self):
        """draw the alien at its current location"""
        self.screen.blit(self.image, self.rect)

    def check_edges(self):
        """return true if alien is at edge of screen"""
        screen_rect = self.screen.get_rect()
        if self.rect.right >= screen_rect.right:
            return True
        elif self.rect.left <= 0:
            return True

    def update(self):
        """move the alien right or left"""
        self.x += (self.ai_settings.alien_speed_factor *
                   self.ai_settings.fleet_direction)
        self.rect.x = self.x

        
----------------------------------------------------------------------------------------------------------------------------



bullet. py



import pygame
from pygame.sprite import Sprite

class Bullet(Sprite):
    """A class to manage bullets fired from the ship """

    def __init__(self, ai_settings, screen, ship):
        """create a bullet object at the ship's current position"""
        super(Bullet, self).__init__()
        self.screen = screen

        # create a bullet rect at (0, 0) and then set correct position
        self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,
                                ai_settings.bullet_height)
        self.rect.centerx = ship.rect.centerx
        self.rect.top = ship.rect.top

        #store the bullet's position as a decimal value
        self.y = float(self.rect.y)

        self.colour = ai_settings.bullet_colour
        self.speed_factor = ai_settings.bullet_speed_factor

    def update(self):
        """move the bullet up the screen"""
        # update the decimal position of the bullet
        self.y -= self.speed_factor
        # update rect position
        self.rect.y = self.y

    def draw_bullets(self):
        """draw the bullet on screen"""
        pygame.draw.rect(self.screen, self.colour, self.rect)
Reply
#4
It would be easier for us if you had put events that pertained to a particular entity inside their own class. For example a players movements in a players class, aliens effects in the aliens class, etc. Then everything you need to know about the alien would be in the alien class.

based on this
Quote:
            if ai_settings.alien_hp <=0:
                 
                stats.score += ai_settings.alien_points * len(aliens)
                sb.prep_score()
                check_high_score(stats, sb)
                 
            else:
                sb.prep_score()
                check_high_score(stats, sb)
It looks like the only thing that occurs when an alien is 0 or less is shown above in the code snippet...

Which none of those seem to remove the entity from the game. Or at least i couldnt find where you remove the entity from the game in scanning the code.

Quote:
def create_alien(ai_settings, screen, aliens, alien_number, row_number):
    """create an alien and place it in a row"""
    alien = Alien(ai_settings, screen)
    alien_width = alien.rect.width
    alien.x = alien_width + 2 * alien_width * alien_number
    alien.rect.x = alien.x
    alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
    aliens.add(alien)
You create aliens, and add them to this group, but i dont see you removing them from the group at all except for during check_play_button (which is irrelevant to the problem)
Recommended Tutorials:
Reply
#5
i have updated my script and i now have managed to make it take 3 hits before it dissapears but its treating the aliens HP as a group. please help me change this so they have individual HP, thanks

import sys

from time import sleep

import pygame

from bullet import Bullet

from alien import Alien

def get_number_aliens_x(ai_settings, alien_width):
    """determine the number of aliens that fit in a row"""
    avaliable_space_x = ai_settings.screen_width - 2 * alien_width
    number_aliens_x = int(avaliable_space_x / (2 * alien_width))
    return number_aliens_x

def get_number_rows(ai_settings, ship_height, alien_height):
    """ determine the number of rows of aliens fit on the screen"""
    avaliable_space_y = (ai_settings.screen_height -
                             (3 * alien_height) - ship_height)
    number_rows = int(avaliable_space_y / (2 * alien_height))
    return number_rows

def create_alien(ai_settings, screen, aliens, alien_number, row_number):
    """create an alien and place it in a row"""
    alien = Alien(ai_settings, screen)
    alien_width = alien.rect.width
    alien.x = alien_width + 2 * alien_width * alien_number
    alien.rect.x = alien.x
    alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
    aliens.add(alien)

def create_fleet(ai_settings, screen, ship, aliens):
    """creates a full fleet of aliens"""
    #create an alien and find the number of aliens in a row
    alien = Alien(ai_settings, screen)
    number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)
    number_rows = get_number_rows(ai_settings, ship.rect.height,
        alien.rect.height)
    
  #creates the fleet of aliens
    for row_number in range(number_rows):
        for alien_number in range(number_aliens_x):
            create_alien(ai_settings, screen, aliens, alien_number,
                         row_number)

def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """responds to keypresses"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True
    elif event.key == pygame.K_SPACE:
        effect = pygame.mixer.Sound('sounds/shot.wav')
        effect.play()
        fire_bullet(ai_settings, screen, ship, bullets)
    elif event.key == pygame.K_q:
        sys.exit()

def fire_bullet(ai_settings, screen, ship, bullets):
    """fire a bullet if limit not reached yet"""
        # create a new bullet and add it to the bullets group
    if len(bullets) < ai_settings.bullets_allowed:
        new_bullet = Bullet(ai_settings, screen, ship)
        bullets.add(new_bullet)

def check_keyup_events(event, ship):
    """responds to key presses"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False


#watch for keyboard and mouse events
def check_events(ai_settings, screen, stats, sb, play_button, ship, aliens,
                 bullets):
    """ responds to key and mouse events """
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event,ai_settings, screen, ship, bullets)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event, ship)
        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y = pygame.mouse.get_pos()
            check_play_button(ai_settings, screen, stats, sb, play_button,
                              ship, aliens, bullets, mouse_x, mouse_y)

def check_play_button(ai_settings, screen, stats, sb, play_button, ship, aliens
                      , bullets, mouse_x, mouse_y):
    """start a new game when the player clicks play"""
    button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
    if button_clicked and not stats.game_active:

        #reset the game settings
        ai_settings.initialize_dynamic_settings()

        #hide mouse cursor
        pygame.mouse.set_visible(False)
        
        #reset the game stats
        stats.reset_stats()
        stats.game_active = True

        #reser the scoreboard images
        sb.prep_score()
        sb.prep_high_score()
        sb.prep_level()
        sb.prep_ships()

        #empty the list of aliens and bullets
        aliens.empty()
        bullets.empty()

        #create new fleet and center the ship
        create_fleet(ai_settings, screen, ship, aliens)
        ship.center_ship()
            
def update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets,
                  play_button):
    """updates images on the screen and flip to the new screen"""
    #redraw the screen during each pass through the loop.
    screen.fill(ai_settings.bg_colour)
    
    #redraw all bullets behind ship and aliens
    for bullet in bullets.sprites():
        bullet.draw_bullets()
    ship.blitme()
    aliens.draw(screen)
    
    #redraw all bullets behind ship and aliens
    for bullet in bullets.sprites():
        bullet.draw_bullets()

    #draw score infomation
    sb.show_score()

    #draw the play button if the game is inactive
    if not stats.game_active:
        play_button.draw_button()

    
    #make the most recently drawn screen visable.
    pygame.display.flip()

def update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets):
    """updates position of bullets and gets rid of old ones"""
    # update bullet positions
    bullets.update()
    
    # gets rid of bullets that have dissapeared
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

    check_bullet_alien_collisions(ai_settings, screen, stats, sb,
                                  ship, aliens, bullets)

def check_bullet_alien_collisions(ai_settings, screen, stats, sb,
                                  ship, aliens, bullets):
    """respond to bullet-alien collisions"""
    #remove any bullets and aliens that have collided
    if ai_settings.alien_hp >= 0:
        collisions = pygame.sprite.groupcollide(bullets, aliens, True, False)        
        if collisions:
            ai_settings.alien_hp -= ai_settings.bullet_dmg

    elif ai_settings.alien_hp <= 0:
        collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
        if collisions:
            for aliens in collisions.values():
                stats.score += ai_settings.alien_points * len(aliens)
                sb.prep_score()
                ai_settings.alien_hp = 1
                
        check_high_score(stats, sb)

    if len(aliens) == 0:
        #if fleet is destroyed start a new level.
        bullets.empty()
        ai_settings.increase_speed()

        #increase level
        stats.level += 1
        sb.prep_level()
        
        create_fleet(ai_settings, screen, ship, aliens)



def check_fleet_edges(ai_settings, aliens):
    """respond appropriately in any aliens have reached an edge """
    for alien in aliens.sprites():
        if alien.check_edges():
            change_fleet_direction(ai_settings, aliens)
            break

def change_fleet_direction(ai_settings, aliens):
    """drop the entire fleet and change the fleet's direction"""
    for alien in aliens.sprites():
        alien.rect.y += ai_settings.fleet_drop_speed
    ai_settings.fleet_direction *= -1

def ship_hit(ai_settings, stats, sb, screen, ship, aliens, bullets):
    """respond to ship being hit by an alien"""
    if stats.ships_left > 0:
        #decrement ships_left
        stats.ships_left -= 1

        #update scoreboard
        sb.prep_ships()

        #empty the list of aliens and bullets
        aliens.empty()
        bullets.empty()

        #create new fleet and centre the ship
        create_fleet(ai_settings, screen, ship, aliens)
        ship.center_ship()

        #pause
        sleep(0.5)
    else:
        stats.game_active = False
        pygame.mouse.set_visible(True)

def check_aliens_bottom(ai_settings, stats, sb, screen, ship, aliens, bullets):
    """check if any aliens have reached the bottom of the screen """
    screen_rect = screen.get_rect()
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:
            #treat this the same as the ship getting hit
            ship_hit(ai_settings, stats, sb, screen, ship, aliens, bullets)
            break

def update_aliens(ai_settings, stats, sb,  screen, ship, aliens, bullets):
    """
check if the fleet is at an edge,
and then update the positions of all the aliens in the fleet
    """
    check_fleet_edges(ai_settings, aliens)
    aliens.update()
    
    #looks for alien-ship collisions
    if pygame.sprite.spritecollideany(ship, aliens):
        ship_hit(ai_settings, stats, sb, screen, ship, aliens, bullets)

    #looks for aliens hitting the bottom of the screen
    check_aliens_bottom(ai_settings, stats, sb, screen, ship, aliens, bullets)

def check_high_score(stats, sb):
    """check to see if there is a new highscore"""
    if stats.score > stats.high_score:
        stats.high_score = stats.score
        sb.prep_high_score()
Reply
#6
can you post it on github so we can actually run this program and tweak it...
https://python-forum.io/Thread-Basic-Cre...light=repo
Recommended Tutorials:
Reply
#7
here
https://github.com/Zanthiou5/space-invaders/issues/1
Reply
#8
please put the code in the files not issues. All you have to do is wherever your code resides on your computer, create a .git file there, and upload everything. Then we would be able to download it as you have it structured on your computer.

https://lifehacker.com/5983680/how-the-h...use-github
https://product.hubspot.com/blog/git-and...-beginners
Recommended Tutorials:
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020