AttributeError Python速成课程

时间:2019-10-21 05:25:07

标签: python python-3.x pygame

我正在遵循Python速成课程来创建Alien Invasion游戏。我对run_game()方法中的一个调用感到很困惑。在书中提到“当您在组上呼叫update()时,该组会自动为该组中的每个子画面调用update()。行self.bullets.update()会调用bullet.update()我们将所有子弹放入组子弹中。”

我尝试将self.bullets.draw_bullet()调用插入到run_game()方法中,但最终出现AttributeError:

  

“组”对象没有属性“ draw_bullet”。

为什么?小组是否应该为小组中的每个子画面自动调用draw_bullet()?为什么“ draw_bullet()”与“ update()”不同?有人可以照亮吗?谢谢。

这是书中的原始代码,正在运行。 alien_invasion.py

import sys, pygame

from settings import Settings
from ship import Ship
from bullet import Bullet

class AlienInvasion:
    """Overall class to manage game assests and behavior."""

    def __init__(self):
        """Initialize the game and create game resources."""
        pygame.init()
        self.settings = Settings()

        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        pygame.display.set_caption("Alien Invasion")

        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()

    def run_game(self):
        """Start the main loop for the game."""
        while True:
            self._check_events()
            self.ship.update()
            self.bullets.update()
            self._update_screen()

    def _check_events(self):
        """Respond to keypresses and mouse events."""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)
            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)

    def _check_keydown_events(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        elif event.key == pygame.K_q:
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

    def _check_keyup_events(self, event):
        if event.key == pygame.K_RIGHT:                                    
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False

    def _fire_bullet(self):
        new_bullet = Bullet(self)
        self.bullets.add(new_bullet)

    def _update_screen(self):
        # Redraw the screen during each pass through the loop
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()

        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

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

bullet.py

import pygame
from pygame.sprite import Sprite

class Bullet(Sprite):

    def __init__(self, ai_game):
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.color = self.settings.bullet_color

        # Create a bullet rect at (0,0) and then set correct position
        self.rect = pygame.Rect(0, 0, self.settings.bullet_width,
            self.settings.bullet_height)
        self.rect.midtop = ai_game.ship.rect.midtop

        # Store the bullet's position as a decimal value
        self.y = float(self.rect.y)

    def update(self):
        self.y -= self.settings.bullet_speed
        self.rect.y = self.y

    def draw_bullet(self):
        pygame.draw.rect(self.screen, self.color, self.rect)

1 个答案:

答案 0 :(得分:1)

当然bullets没有属性draw_bullet

bulletspygame.sprite.Group的实例,但是Bullet是从pygame.sprite.Sprite对象派生的。 Bullet的实例具有方法draw_bullet,因为您已经实现了它。

如果要绘制每个项目符号,则必须遍历这些项目符号,并为每个项目符号调用draw_bullet

for bullet in selfbullets:
    bullet.draw_bullet()

另一种选择是使用pygame.sprite.Group的{​​{3}}方法。在这种情况下,Bullet必须具有属性.rect.image,但是它根本不需要任何绘制方法(draw_bullet),因为draw()使用每个项目符号的属性来绘制它们。例如:

class Bullet(Sprite):

    def __init__(self, ai_game):
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.color = self.settings.bullet_color

        # Create a bullet rect at (0,0) and then set correct position
        self.rect = pygame.Rect(0, 0, self.settings.bullet_width,
            self.settings.bullet_height)
        self.rect.midtop = ai_game.ship.rect.midtop

        # Store the bullet's position as a decimal value
        self.y = float(self.rect.y)

        # create Surface 
        self.image = pygame.Surface(self.rect.size)   # <-----
        self.image.fill(self.color)                   # <-----

    def update(self):
        self.y -= self.settings.bullet_speed
        self.rect.y = self.y
self.bullets.draw()