python入门到实践里的飞机游戏,在添加子弹与外星人碰撞之前一切正常,但添加碰撞后错误

题目描述

不加pygame.sprite.groupcollide()代码,运行一切正常没有问题
加了pygame.sprite.groupcollide()代码运行时按下空格就发生错误了。不按空格就正常运行

Traceback (most recent call last):
  File "alien_invasion.py", line 41, in <module>
    run_game()
  File "alien_invasion.py", line 33, in run_game
    gf.update_bullet(bullets,aliens)
  File "G:\python_work\alien_invasion\game_functions.py", line 115, in update_bullet
    cllisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
  File "C:\Users\靖\AppData\Roaming\Python\Python36\site-packages\pygame\sprite.py", line 1550, in groupcollide
    c = SC(s, groupb, dokillb, collided)
  File "C:\Users\靖\AppData\Roaming\Python\Python36\site-packages\pygame\sprite.py", line 1513, in spritecollide
    spritecollide = sprite.rect.colliderect
AttributeError: 'Bullet' object has no attribute 'rect'

题目来源及自己的思路

题目时python编程入门到实践的例题,自己打的和书上没什么差别

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)

# alien_invasion.py

import pygame
from settings import Settings
from ship import Ship
import game_functions as gf 
from pygame.sprite import Group

def run_game():
    #初始化游戏并创建一个屏幕对象
    pygame.init()
    #实例化Settings类
    ai_settings = Settings()
    #创建指定大小的屏幕      
    screen = pygame.display.set_mode(
        (ai_settings.screen_width,ai_settings.screen_height))
    #创建一个用于储存子弹,外星飞船的编组
    bullets = Group()
    aliens = Group()
    #游戏标题
    pygame.display.set_caption('Alien Invasion')
    #创建飞船,实例化Ship类
    ship = Ship(ai_settings,screen)
    #创造外星人飞船
    gf.create_fleet(aliens,screen,ai_settings,ship.ship_rect.height)
    
    #游戏主循环
    while True:
        #监视鼠标与键盘的事件
        gf.check_events(ship,screen,ai_settings,bullets)
        #更新飞机位置
        ship.update()
        #更新子弹位置并删除无用子弹
        gf.update_bullet(bullets,aliens)    
        #更新外星人位
        gf.update_alien(aliens,ai_settings)
        #更新屏幕
        gf.update_screen(ai_settings,screen,ship,bullets,aliens)
        
        
        
run_game()
# settings.py
class Settings():
    '''储存游戏的各种设置'''
    def __init__(self):
        #屏幕大小
        self.screen_width = 1200
        self.screen_height = 800
        #背景颜色
        self.background_color = (255,255,255)
        #飞船速度
        self.ship_rl_speed_factor = 1.5
        self.ship_ud_speed_factor = 1
        #子弹参数
        self.bullet_speed_factor = 1
        self.bullet_color = 80, 80, 80
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_allowed = 5
        #外星人移动速度
        self.alien_speed_factor = 1
        self.alien_drop = 10
        self.speed_argue = 1
#ship.py
import pygame

class Ship():
    '''初始化飞船,并设置初始位置'''
    def __init__(self,ai_settings,screen):
        #导入屏幕和设置参数
        self.screen = screen
        self.ai_settings = ai_settings
        #导入飞船图形
        self.image = pygame.image.load('images/ship.bmp')
        #获得飞船与屏幕的矩形数据
        self.ship_rect = self.image.get_rect()
        self.screen_rect = self.screen.get_rect()
        #设置飞船的初始位置
        self.ship_rect.centerx = self.screen_rect.centerx
        self.ship_rect.bottom = self.screen_rect.bottom
        #移动标志
        self.moving_right = False
        self.moving_left = False
        self.moving_down = False
        self.moving_up = False
        #移动位置
        self.center = float(self.ship_rect.centerx)
        self.bottom = self.ship_rect.bottom
    
    def update(self):
        '''更新飞机位置'''
        if self.moving_right and (
            self.ship_rect.right < self.screen_rect.right):
            self.center += self.ai_settings.ship_rl_speed_factor
        if self.moving_left and self.ship_rect.left > 0:
            self.center -= self.ai_settings.ship_rl_speed_factor
        if self.moving_up and self.ship_rect.top > 0:
            self.bottom -= self.ai_settings.ship_ud_speed_factor
        if self.moving_down and (
            self.ship_rect.bottom < self.screen_rect.bottom):
            self.bottom += self.ai_settings.ship_ud_speed_factor
        #根据self.center更新ship位置
        self.ship_rect.centerx = self.center
        self.ship_rect.bottom = self.bottom
    
    def blitme(self):
        '''屏幕上的指定位置上画指定形状飞机'''
        self.screen.blit(self.image,self.ship_rect)
# game_functions.py
import sys

import pygame
from bullet import Bullet
from alien import Alien


'''按键事件函数'''
def check_keydown_events(event,ship,screen,ai_settings,bullets):
    '''鼠标按下事件'''
    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_UP:
        ship.moving_up = True
    elif event.key == pygame.K_DOWN:
        ship.moving_down = True
    elif event.key == pygame.K_SPACE:
        #按下space时生成一个子弹并保存到编组
        fire_bullet(screen,ai_settings,ship,bullets)
    #按下q退出
    elif event.key == pygame.K_q:
        sys.exit()        

def check_keyup_events(event,ship):
    '''鼠标抬起事件'''
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    if event.key == pygame.K_LEFT:
        ship.moving_left = False
    if event.key == pygame.K_UP:
        ship.moving_up = False
    if event.key == pygame.K_DOWN:
        ship.moving_down = False

def check_events(ship,screen,ai_settings,bullets):
    #监视鼠标与键盘的事件
    for event in pygame.event.get():
        #鼠标按下,移动标志变true,抬起变false
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event,ship,screen,ai_settings,bullets)
        elif event.type == pygame.KEYUP:
            check_keyup_events(event,ship)

'''外星飞船函数'''
def get_number_rows(ai_settings,alien_height,ship_height):
    '''获得外星人飞船行数的数量'''
    available_space_y = (ai_settings.screen_height - 
        (7 * alien_height) - ship_height)
    rows_number = int(available_space_y / (2 * alien_height))
    return rows_number
    
def get_alien_number_x(alien_width,ai_settings):
    '''一行外星人的数量'''
    alien_create_space = ai_settings.screen_width - (2 * alien_width)
    alien_create_number = int(alien_create_space/(2 * alien_width))
    return alien_create_number

def create_alien(screen,ai_settings,aliens,alien_number,row_number):
    '''在左上角创造一个外星人,添加到编组'''
    alien = Alien(screen,ai_settings)
    alien_width = alien.alien_rect.width
    alien_height = alien.alien_rect.height
    alien.x = alien_width + 2 * alien_number * alien_width
    alien.y = alien_height + 2 * row_number * alien_height
    alien.alien_rect.x = alien.x
    alien.alien_rect.y = alien.y
    aliens.add(alien)
    
def create_fleet(aliens,screen,ai_settings,ship_height):
    '''将整个屏幕的外星人飞船都创造,并添加到编组'''
    alien = Alien(screen,ai_settings)
    alien_width = alien.alien_rect.width
    alien_height = alien.alien_rect.height
    alien_number_x = get_alien_number_x(alien_width,ai_settings)
    row_number_y = get_number_rows(ai_settings,alien_height,ship_height)
    for row_number in range(row_number_y):
        for alien_number in range(alien_number_x):
            create_alien(screen,ai_settings,aliens,alien_number,
                row_number)

def update_alien(aliens,ai_settings):
    '''检测外星人有没有到边缘,并更新位置'''
    check_edges(aliens,ai_settings)
    aliens.update()
    
def check_edges(aliens,ai_settings):
    '''外星人达到边缘时下移并改变方向'''
    for alien in aliens.sprites():
        if alien.check_alien_edges():
            check_drop_alien(aliens,ai_settings)
            ai_settings.speed_argue *= -1
            break

def check_drop_alien(aliens,ai_settings):
    '''让外星人群下移'''
    for alien in aliens.sprites():
        alien.alien_rect.y += ai_settings.alien_drop        
        
'''子弹函数'''
def fire_bullet(screen,ai_settings,ship,bullets):
    '''开火子弹'''
    if len(bullets) < ai_settings.bullet_allowed:
        new_bullet = Bullet(screen,ai_settings,ship)
        bullets.add(new_bullet)

def update_bullet(bullets,aliens):
    '''更新子弹情况'''
    #更新子弹位置
    bullets.update()
    #检测是否外星人与子弹有碰撞,有就删除他们
    cllisions = pygame.sprite.groupcollide(bullets,aliens,True,True)
    #删除无用子弹
    
    for bullet in bullets.copy():
        if bullet.bullet_rect.bottom <= 0:
            bullets.remove(bullet)
    
'''更新屏幕函数'''
def update_screen(ai_settings,screen,ship,bullets,aliens):
    #每次循环都重设背景色
    screen.fill(ai_settings.background_color)
    #画出飞船
    ship.blitme()
    #sprite方法从编组中返回一个列表,并将每个子弹都更新一次
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    for alien in aliens.sprites():
        alien.blitme()
    #让最近绘制的屏幕可见
    pygame.display.flip()
# bullet.py
import pygame
from pygame.sprite import Sprite

class Bullet(Sprite):
    '''子弹参数和更新子弹位置'''
    def __init__(self,screen,ai_settings,ship):
        super().__init__()
        #让后面能在屏幕上指定位置(0,0)制作子弹
        self.screen = screen
        #生成子弹矩形
        self.bullet_rect = pygame.Rect(
            0,0,ai_settings.bullet_width,ai_settings.bullet_height)
        #子弹生成位置
        self.bullet_rect.centerx = ship.ship_rect.centerx
        self.bullet_rect.top = ship.ship_rect.top
        #子弹速度
        self.speed_y = float(ai_settings.bullet_speed_factor)
        self.y = float(self.bullet_rect.y)
        #子弹颜色
        self.color = ai_settings.bullet_color
        
    def update(self):
        '''更新子弹位置'''
        self.y -= self.speed_y
        self.bullet_rect.y = self.y
    
    def draw_bullet(self):
        '''在屏幕指定位置画出指定颜色的矩形子弹'''
        pygame.draw.rect(self.screen,self.color,self.bullet_rect)
# alien.py
import pygame
from pygame.sprite import Sprite

class Alien(Sprite):
    
    def __init__(self,screen,ai_settings):
        super().__init__()
        #获取屏幕和游戏设定值
        self.screen = screen
        self.ai_settings = ai_settings
        #获取外星人图和矩形
        self.image = pygame.image.load('images/alien_aircraft.bmp')
        self.alien_rect = self.image.get_rect()
        #设定外星人最初位置
        self.alien_rect.x = self.alien_rect.width
        self.alien_rect.y = self.alien_rect.height
    
    def blitme(self):
        '''在屏幕上画出外星人飞船'''
        self.screen.blit(self.image,self.alien_rect)
    
    def update(self):
        '''更新外星人的位置'''
        self.speed = self.ai_settings.alien_speed_factor
        self.x += self.speed * self.ai_settings.speed_argue
        self.alien_rect.x = self.x
    
    def check_alien_edges(self):
        '''检测边缘函数所用的数据是外星人矩形坐标和屏幕坐标,放在外星人中'''
        screen_rect = self.screen.get_rect()
        if self.alien_rect.right >= screen_rect.right:
            return True
        elif self.alien_rect.left <= screen_rect.left:
            return True
        

你期待的结果是什么?实际看到的错误信息又是什么?

阅读 3.5k
1 个回答
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题