首页 > 解决方案 > NameError:名称“子弹”未定义

问题描述

我正在 python 速成课程书中创建外星人入侵游戏,但我收到一个名称错误,提示未定义子弹。所以我将“子弹”更改为“子弹”,这给了我一个属性错误,说子弹没有属性“精灵”。到目前为止,这是我的代码。

外星人入侵.py

import pygame
from pygame.sprite import Group

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

def run_game():
# Initialize pygame, 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.
ship = Ship(ai_settings, screen)
# Make a group to store bullets in.
bullets = Group()

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

run_game()

设置.py

class Settings():
"""A class to store all settings for Alien Invasion."""

def __init__(self):
    """Initialize the game's settings."""
    # Screen settings
    self.screen_width = 1200
    self.screen_height = 600
    self.bg_color = (230, 230, 230)

    # Ship settings
    self.ship_speed_factor = 1.5

    # Bullet settings
    self.bullet_speed_factor = 1
    self.bullet_width = 3
    self.bullet_height = 15
    self.bullet_color = 60, 60, 60

船.py

import pygame

class Ship():

def __init__(self, ai_settings, screen):
    """Initialize the ship and set its starting position."""
    self.screen = screen
    self.ai_settings = ai_settings

    # Load the ship image and get its rect.
    self.image = pygame.image.load('images/ship.bmp')
    self.rect = self.image.get_rect()
    self.screen_rect = screen.get_rect()

    # Start each new ship at the bottom center of the screen.
    self.rect.centerx = self.screen_rect.centerx
    self.rect.bottom = self.screen_rect.bottom

    # Store a decimal value for the ship's center.
    self.center = float(self.rect.centerx)

    # Movement flags
    self.moving_right = False
    self.moving_left = False

def update(self):
    """Update the ship's position based on movement flags."""
    # Update the ship's center value, not the rect.
    if self.moving_right and self.rect.right < self.screen_rect.right:
        self.center += self.ai_settings.ship_speed_factor
    if self.moving_left and self.rect.left > 0:
        self.center -= self.ai_settings.ship_speed_factor

    # Update rect object from self.center.
    self.rect.centerx = self.center

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

游戏功能.py

import sys

import pygame
from bullet import Bullet

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:
        # Create a new bullet and add it to the bullets group.
        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, ai_settings, ship)

# Redraw all bullets behind ship and aliens.
for bullet in Bullet.sprites():
    bullet.draw_bullet()

def update_screen(ai_settings, screen, ship, bullets):
    """Update images on the screenand flip to the new screen."""
    # Redraw the screen during each pass through the loop.
    screen.fill(ai_settings.bg_color)
    # Redraw all bullets behind ship and aliens.
    for bullet in Bullet.sprites():
        bullet.draw_bullet()
    ship.blitme()

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

子弹.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().__init__()
    self.screen = screen

    # Create a bullet rect at (0, 0) and then set the 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.color = ai_settings.bullet_color
    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 the rect position.
    self.rect.y = self.y

def draw_bullet(self):
    """Draw the bullet to the screen."""
    pygame.draw.rect(self.screen, self.color, self.rect)

这是原始错误:

    game_functions.py, line 36, in <module>
        for bullet in bullets.sprites():
    NameError: name 'bullets' is not defined

这是我将 'bullets' 更改为 'Bullet' 以匹配 bullet.py 中的“class Bullet(Sprite)”后的错误:

    game_functions.py, line 36, in <module>
        for bullet in Bullet.sprites():
    AttributeError: type object 'Bullet' has no attribute 'sprites'

如果问题得到解决,我将不胜感激。这也是我第一次提出问题,因为我对编码比较陌生。如果我在问这个问题时做错了什么,请告诉我。

标签: python-3.x

解决方案


错误来自不在任何函数内部的两行 for 循环。仅当导入 game_functions 模块时才会执行这些行。这似乎没有用。您可能只需删除这些行而不破坏任何内容。

相同的两行出现在紧随其后的 update_screen 函数中。在名称bullets和之间Bullet,只有一个有sprites()方法。那是你的 for 循环所需要的。


推荐阅读