You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pygame精灵按空格发射子弹触发AttributeError报错如何修复

报错原因
  • 核心触发点:car.py中shoot方法错误调用对象。你在car.py里将加载的子弹图片Surface对象命名为bullets,却尝试调用bullets.Bullet()创建子弹实例,bullets是图片对象而非模块,不存在Bullet属性,直接触发AttributeError。
  • 同时存在多个隐藏问题会导致后续报错:
    1. 循环导入:bullet.py导入autopilot.py的变量,autopilot.py又导入car.py,如果car.py导入Bullet类会触发循环导入异常。
    2. 各模块重复初始化Pygame窗口、重复定义screen变量,会引发未知渲染异常。
    3. car.py和autopilot.py中定义的bullet_group是独立分组,子弹加入car.py的分组后不会被主循环渲染更新。
修复方案

1. 修改car.py

删除顶部重复的屏幕初始化、screen定义、子弹图片加载、bullet_group定义代码,调整类方法如下:

import pygame
from bullet import Bullet

class Player(pygame.sprite.Sprite):
    def __init__(self, scale, speed, bullet_group):
        pygame.sprite.Sprite.__init__(self)
        self.bullet_group = bullet_group
        self.speed = speed
        self.moving = True
        self.frame = 0
        self.flip = False
        self.direction = 0

        # 加载车辆图片逻辑不变
        self.images = []
        img = pygame.image.load('car/car.png').convert_alpha()
        img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
        self.images.append(img)
        self.image = self.images[0]
        self.rect = self.image.get_rect()
        self.update_time = pygame.time.get_ticks()
        self.movingLeft = False
        self.movingRight = False
        self.rect.x = 465
        self.rect.y = 325

    def draw(self, screen):
        screen.blit(self.image, (self.rect.centerx, self.rect.centery))

    def move(self):
        dx = 0
        dy = 0
        if self.movingLeft and self.rect.x > 33:
            dx -= self.speed
            self.flip = True
            self.direction = -1
        if self.movingRight and self.rect.x < 900:
            dx += self.speed
            self.flip = False
            self.direction = 1
        self.rect.x += dx
        self.rect.y += dy

    def shoot(self):
        bullet = Bullet(self.rect.centerx + 18, self.rect.y + 30, self.direction)
        self.bullet_group.add(bullet)

2. 修改bullet.py

删除顶部重复的屏幕初始化代码、screen定义、循环导入语句,调整碰撞检测逻辑:

import pygame

bullet_img = pygame.image.load('car/bullet.png').convert_alpha()

class Bullet(pygame.sprite.Sprite):
    def __init__(self, x, y, direction):
        pygame.sprite.Sprite.__init__(self)
        self.speed = 5
        self.image = bullet_img
        self.rect = self.image.get_rect()
        self.rect.center = (x,y)
        self.direction = direction

    def update(self, debris):
        self.rect.centery -= self.speed
        # 子弹出屏销毁
        if self.rect.top < 1:
            self.kill()
        # 碰撞检测
        if pygame.sprite.collide_rect(self, debris) and debris.alive:
            debris.health -= 25
            self.kill()

3. 修改debris.py

删除顶部重复的屏幕初始化代码,调整draw方法:

import pygame

class Debris(pygame.sprite.Sprite):
    def __init__(self, scale, speed):
        pygame.sprite.Sprite.__init__(self)
        self.x = 400
        self.y = 0
        self.speed = speed
        self.vy = 0
        self.on_ground = True
        self.move = True
        self.health = 100
        self.max_health = self.health
        self.alive = True

        # 加载障碍物图片逻辑不变
        self.images = []
        img = pygame.image.load('debris/cement.png').convert_alpha()
        img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
        self.images.append(img)
        self.image = self.images[0]
        self.rect = self.image.get_rect()
        self.rect.x = self.x
        self.rect.y = self.y

    def draw(self, screen):
        screen.blit(self.image,(self.x,self.y))

4. 修改autopilot.py

调整类实例初始化逻辑,传入必要参数,删除重复的帧更新代码:

import pygame
import car
import debris

pygame.init()

# 屏幕设置
WIDTH = 1000
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("AutoPilot")
screen.fill((255, 255, 255))

# 帧率设置
FPS = 120
clock = pygame.time.Clock()

# 加载背景图
bg = pygame.image.load('background/street.png').convert_alpha()

# 精灵分组
bullet_group = pygame.sprite.Group()
debris_group = pygame.sprite.Group()

# 实例化游戏对象
debris = debris.Debris(1, 5)
player = car.Player(1, 5, bullet_group)
debris_group.add(debris)

# 主循环
run = True
while run:
    screen.blit(bg, [0, 0])

    # 更新并渲染子弹
    bullet_group.update(debris)
    bullet_group.draw(screen)

    # 渲染其他对象
    debris.draw(screen)
    player.draw(screen)
    player.move()

    # 事件监听
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                run = False
            if event.key == pygame.K_a:
                player.movingLeft = True
            if event.key == pygame.K_d:
                player.movingRight = True
            if event.key == pygame.K_SPACE:
                player.shoot()
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_a:
                player.movingLeft = False
            if event.key == pygame.K_d:
                player.movingRight = False

    pygame.display.update()
    clock.tick(FPS)

pygame.quit()

内容的提问来源于stack exchange,提问作者J.R. BEATS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 09:45:03