报错Bullet object has no attribute 'rect' 如何解决

报错Bullet object has no attribute 'rect' 如何解决

main.py

from game.war import PlaneWar

def main():
    war = PlaneWar()
    while True:
        # 设置帧速率
        war.set_frame()
        # 监听事件
        war.monitor_event()
        # 更新游戏状态
        war.reset_game()

if __name__ == '__main__':
    main()

war.py

import sys, pygame
import constants
from game.plane import MyPlane, EnermyPlane


class PlaneWar(object):
    enermy_group = pygame.sprite.Group()

    def __init__(self):
        """ 初始化 """
        pygame.init()
        self.width, self.height = 640, 640
        self.screen = pygame.display.set_mode((self.width, self.height))
        pygame.display.set_caption('test')

        # 加载开始图片
        self.start = pygame.image.load(constants.START_DIR)
        self.start_rect = self.start.get_rect()
        self.start_w, self.start_h = self.start.get_size()
        self.start_rect.topleft = (int((self.width - self.start_w) / 2), int((self.height - self.start_h) / 2))

        self.my_plane = MyPlane(self.screen, 15)

        self.add_enermy_plane(6)

        # 设置帧速率
        self.frame = 0
        self.clock = pygame.time.Clock()

        self.status = 0

    def add_enermy_plane(self, num):
        for i in range(num):
            enermy_plane = EnermyPlane(self.screen, 8)
            self.enermy_group.add(enermy_plane)

    def run_game(self):
        # 设置帧速率
        self.set_frame()

        # 监听事件
        self.monitor_event()
        # 更新游戏状态
        self.reset_game()

        pygame.display.flip()

    def set_frame(self):
        # 设置帧速率
        self.clock.tick(60)
        self.frame += 1
        if self.frame >= 60:
            self.frame = 0

    def monitor_event(self):
        # 监听事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if self.status == 0:
                    self.status = 1
            elif event.type == pygame.KEYDOWN:
                if self.status == 1:
                    if event.key == pygame.K_w or event.key == pygame.K_UP:
                        self.my_plane.move_up()
                    elif event.key == pygame.K_s or event.key == pygame.K_DOWN:
                        self.my_plane.move_down()
                    elif event.key == pygame.K_a or event.key == pygame.K_LEFT:
                        self.my_plane.move_left()
                    elif event.key == pygame.K_d or event.key == pygame.K_RIGHT:
                        self.my_plane.move_right()
                    elif event.key == pygame.K_SPACE:
                        self.my_plane.shoot()

    def reset_game(self):
        if self.status == 0:
            self.screen.blit(self.start, self.start_rect)
        # 绘制
        elif self.status == 1:
            self.screen.fill(pygame.Color(255, 255, 255))

            self.my_plane.update()
            self.my_plane.bullets.update(self)
            self.enermy_group.update()

        pygame.display.flip()

plane.py

import pygame
import constants
from game.bullet import Bullet
import random


class Plane(pygame.sprite.Sprite):
    img = []
    b_imag = []
    b_music = None

    bullets = pygame.sprite.Group()

    active = True

    def __init__(self, screen, speed=None):
        super(Plane, self).__init__()
        self.screen = screen
        self.speed = speed or 15

        self.img_obj =[]
        self.b_img_obj = []
        self.b_music_obj = []

        self.load_src()

        self.img_obj_rect = self.get_img.get_rect()
        self.screen_w, self.screen_h = self.screen.get_size()
        self.width, self.height = self.get_img.get_size()
        self.img_obj_rect.topleft = (int((self.screen_w - self.width) / 2), int(self.screen_h - self.height))

    def load_src(self):
        """ 加载静态资源 """
        for img in self.img:
            self.img_obj.append(pygame.image.load(img))
        if self.b_imag:
            for img in self.b_imag:
                self.b_img_obj.append(img)
        if self.b_music:
            self.b_music_obj = pygame.mixer.Sound(self.b_music)

    @property
    def get_img(self):
        return self.img_obj[0]

    def move_up(self):
        self.img_obj_rect.top -= self.speed

    def move_down(self):
        self.img_obj_rect.top += self.speed

    def move_left(self):
        self.img_obj_rect.left -= self.speed

    def move_right(self):
        self.img_obj_rect.left += self.speed

    def update(self, *args):
        ''' 绘制以及改变位置 '''
        self.screen.blit(self.get_img, self.img_obj_rect)

    def shoot(self):
        bullet = Bullet(self, self.screen, speed=8)
        self.bullets.add(bullet)

class MyPlane(Plane):
    img = [constants.PLANE1_DIR]
    b_imag = []
    b_music = None

    @property
    def get_img(self):
        """ 获取图片 """
        return self.img_obj[0]

    def set_rect(self):
        """ 设置图片位置 """
        self.img_obj_rect.topleft = (int((self.screen_w - self.width)/2), self.screen_h)

    def move_up(self):
        self.img_obj_rect.top -= self.speed
        if self.img_obj_rect.top <= 0: self.img_obj_rect.top = 0

    def move_down(self):
        self.img_obj_rect.top += self.speed
        if self.img_obj_rect.top > self.screen_h - self.height: self.img_obj_rect.top = self.screen_h - self.height

    def move_left(self):
        self.img_obj_rect.left -= self.speed
        if self.img_obj_rect.left <= 0:self.img_obj_rect.left = 0

    def move_right(self):
        self.img_obj_rect.left += self.speed
        if self.img_obj_rect.left > self.screen_w - self.width: self.img_obj_rect.left = self.screen_w - self.width


class EnermyPlane(Plane):
    img = [constants.PLANE_DIR]
    b_imag = []
    b_music = None
    def __init__(self, screen, speed=None):
        super(EnermyPlane, self).__init__(screen, speed)

        # 初始敌方飞机位置
        self.set_rect()

    def set_rect(self):
        """ 设置敌方飞机位置 """
        self.img_obj_rect.top = random.randint(-5 * self.height, self.height)
        self.img_obj_rect.left = random.randint(0, self.screen_w - self.width)

    def blit_me(self):
        self.screen.blit(self.img_obj[0], self.img_obj_rect)

    def reset(self):
        self.active = True
        self.set_rect()
        
    def update(self, *args):
        self.move_down()

        self.blit_me()
        if self.img_obj_rect.top >= self.screen_h:
            self.active = False

            # 复位飞机
            self.reset()

bullet.py

import pygame
import constants


class Bullet(pygame.sprite.Sprite):

    def __init__(self, plane, screen, speed=None):
        """ 这是写死的程序,不可更改"""
        super(Bullet, self).__init__()
        self.speed = speed or 15
        self.screen = screen
        self.plane = plane

        active = True

        # 加载图片
        self.imag = constants.BULLET_DIR
        self.bullet = pygame.image.load(self.imag)

        # 设置子弹图片初始位置
        self.bullet_rect = self.bullet.get_rect()

        self.width, self.height = self.bullet.get_size()
        self.screen_w, self.screen_h = self.screen.get_size()

        self.bullet_rect.centerx = self.plane.img_obj_rect.centerx
        self.bullet_rect.top = self.plane.img_obj_rect.top

    def update(self, war):
        """ 更新子弹位置 """
        # 改变子弹位置,改变位置变量
        self.bullet_rect.top -= self.speed
        if self.bullet_rect.top < 0:
            self.remove(self.plane.bullets)
        self.screen.blit(self.bullet, self.bullet_rect)

        result = pygame.sprite.spritecollide(self, war.enermy_group, False)
        for r in result:
            # 消除子弹和碰撞飞机
            self.kill()
            # 播放爆炸动画
            # 更新敌方飞机
            r.reset()

constants.py

import os

# 基础路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# assets路径
ASSETS_DIR = os.path.join(BASE_DIR, 'assets')

# 开始界面
START_DIR = os.path.join(ASSETS_DIR, 'images\\start.png')
# 飞机
# 敌方飞机
PLANE_DIR = os.path.join(ASSETS_DIR, 'images\\plane.png')
# 我方飞机
PLANE1_DIR = os.path.join(ASSETS_DIR, 'images\\plane1.png')

# 子弹
BULLET_DIR = os.path.join(ASSETS_DIR, 'images\\bullet.png')

报错:

D:\Python_act\envs\2d_game\Scripts\python.exe D:/Python_act/2d_game/main.py

pygame 1.9.6

Hello from the pygame community. https://www.pygame.org/contribute.html

Traceback (most recent call last):

  File "D:/Python_act/2d_game/main.py", line 14, in <module>

    main()

  File "D:/Python_act/2d_game/main.py", line 11, in main

    war.reset_game()

  File "D:\Python_act\2d_game\game\war.py", line 85, in reset_game

    self.my_plane.bullets.update(self)

  File "D:\Python_act\envs\2d_game\lib\site-packages\pygame\sprite.py", line 463, in update

    s.update(*args)

  File "D:\Python_act\2d_game\game\bullet.py", line 37, in update

    result = pygame.sprite.spritecollide(self, war.enermy_group, False)

  File "D:\Python_act\envs\2d_game\lib\site-packages\pygame\sprite.py", line 1534, in spritecollide

    spritecollide = sprite.rect.colliderect

AttributeError: 'Bullet' object has no attribute 'rect'


正在回答

登陆购买课程后可参与讨论,去登陆

1回答

同学,你好。Bullet对象没有rect属性,这是该spritecollide函数所必需的,同学可根据图2图3修改,在子弹类和飞机类中,使用get_rect()得到位置时赋值给rect即可

http://img1.sycdn.imooc.com//climg/5f292abd093be55413320131.jpg

http://img1.sycdn.imooc.com//climg/5f292b5709e871e806500109.jpghttp://img1.sycdn.imooc.com//climg/5f292b960918194607660135.jpg

如果我的回答解决了您的疑惑,请采纳!祝学习愉快~~~~

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
1.Python零基础入门
  • 参与学习           人
  • 提交作业       2727    份
  • 解答问题       8160    个

想要进入Python Web、爬虫、人工智能等高薪领域,你需要掌握本阶段的Python基础知识,课程安排带你高效学习轻松入门,学完你也能听得懂Python工程师的行业梗。

了解课程
请稍等 ...
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师