Using pygame.sprite.spritecollideany Python

2019-09-11 07:48发布

问题:

I am new to python programming, and I am practicing by making a Alien Invasion game. This is a classic game configuration, there are rows of aliens you have to shot down before they make it to the bottom and collide with your ship.

Here is my game_functions code:

import sys

import pygame
from bullet import Bullet
from alien import Alien

def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """Respond 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:
    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 mimit 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):
"""Respond to key releases."""
if event.key == pygame.K_RIGHT:
    ship.moving_right = False
elif event.key == pygame.K_LEFT:
    ship.moving_left = False

def check_events(ai_settings, screen, ship, bullets):
"""Respond to keypresses 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)

def update_screen(ai_settings, screen, ship, aliens, bullets):
"""Update images on the screen and flip to the new screen."""

# Redraw the screen during each pass through the loop.
screen.fill(ai_settings.bg_color)

#Redraw bullets behind the ship and aliens
for bullet in bullets.sprites():
    bullet.draw_bullet()
ship.blitme()
aliens.draw(screen)

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

def update_bullets(ai_settings, screen, bullets, aliens, ship):
"""Update position of bullets and get rid of olf bullets."""
#Update bullet position
bullets.update()
#Check for any bullets that hit an alien.
#if so, get rid of the bullet and alien

#Get rid of bullets that have disappeared
for bullet in bullets.copy():
    if bullet.rect.bottom <= 0:
        bullets.remove(bullet)

check_bullet_alien_collisons(ai_settings, screen, bullets, aliens, ship)

def check_bullet_alien_collisons(ai_settings, screen, bullets, aliens, ship):
"""Respond to bullet-alien collions."""
#Remove any bullets and aliens that collide.
collisons = pygame.sprite.groupcollide(bullets, aliens, True, True)

if len(aliens) == 0:
    #Destroy existing bullets and create new fleet.
    bullets.empty()
    create_fleet(ai_settings, screen, aliens, ship)

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

def get_number_rows(ai_settings, ship_height, alien_height):
"""Find the number of rows for screen."""
available_space_y = (ai_settings.screen_height - 
                        (3 * alien_height) - ship_height)
number_rows = int(available_space_y / (3 * alien_height))
return number_rows

def create_alien(ai_settings, screen, aliens, alien_number, row_number):
"""Create an alien and place it in the 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):
"""Create 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)

#Create 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_fleet_edges(ai_settings, aliens):
"""Respond appropriately if any aliens 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 update_aliens(ai_settings, aliens, ship):
"""Check for fleet on edge, then update positions of fleet."""
check_fleet_edges(ai_settings, aliens)
aliens.update()

#Look for alien-ship collisons.
if pygame.sprite.spritecollideany(aliens, ship):
    print("Ship hit!")

And this is my game init code so I can run the functions and play the game

import pygame
from pygame.sprite import Group

from settings import Settings
from ship import Ship
from alien import Alien
import game_functions as gf

def run_game():
#Initialze game, settings, and screen object.
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode(
    (ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion!")

#Make a ship, a group of aliens, and a group of bullets
ship = Ship(ai_settings, screen)
aliens = Group()
bullets = Group()

#Create a fleet of aliens
gf.create_fleet(ai_settings, screen, ship, aliens)

# Start the main loop for the game
while True:
    gf.check_events(ai_settings, screen, ship, bullets)
    ship.update()
    gf.update_bullets(ai_settings, screen, bullets, aliens, ship)
    gf.update_aliens(ai_settings, aliens, ship)
    gf.update_screen(ai_settings, screen, ship, aliens, bullets)

run_game()

I have most of the game done, but when I add the pygame.sprite.spritecollideany() in the game_functions file, I get

"Attribute Error: the 'Group' has no attribute 'rect'"

I know there is probably something simple I am missing, but I cannot figure it out. Sorry of the code is not correctly typed as I copied and pasted to save time when posting my question.

I am also using Ubuntu 14.04 LTS, and running python-3.4.3.

回答1:

Read Pygame doc: pygame.sprite.spritecollideany()

This function expects single sprite as first argument, and group as second argument but you use aliens which is group as first argument, and ship which is sprite as second argument.

You have to change order of arguments.


BTW: next time simply use print() - it is most popular method (if you don't know how to debug) to check what you have in variables and see what is wrong.