首页 > 解决方案 > 方法仅在命名为“update()”时有效

问题描述

我有bullets = pygame.sprite.Group()

然后我创建并添加带有 Bullet 类的 new_bullets 到精灵组

new_bullet = Bullet(self)
self.bullets.add(new_bullet)

然后在run_game我调用的方法self.bullets.update()中 where.update()Bullet类的一部分。这一切都有效,但如果我将该方法更改为update(). 该方法从未在 Bullet 类中调用,并且我收到错误消息,抱怨更新不是子弹的一部分,因为它不是?只有new_bullets是。

为什么以及如何工作?为什么我只能调用该方法update()才能使其正常工作?

我知道new_bullet是该类的一个实例,Bullet并且可以访问该方法update(),但不是bullets,它只是一个精灵组。

bullet.py


class Bullet(Sprite):
    """A class to manage bullets fired from the shil"""
    def __init__(self,ai_game):
       """Create a bullet object at the ships current position"""
       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 the 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 bullets position as a decimal value
       self.y = float(self.rect.y)

    def update_position(self):
        """Move the bullet"""
        # Update the decimal position of t he bullet.
        self.y -= self.settings.bullet_speed
        #update the rect position.
        self.rect.y = self.y

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

main.py


class AlienInvasion:
    """Return the sum of x and y."""
    def __init__(self):
        """ Class to manage game assests and behavior"""
        pygame.init()
        self.settings = Settings()
        # Full screen code below
        # self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
        # self.settings.screen_width = self.screen.get_rect().width
        # self.settings.screen_height = self.screen.get_rect().height

        # windowed code below
        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 _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_keyup_events(self,event):
        if event.key == pygame.K_RIGHT:
            #Move the ship to the right
            self.ship.moving_right = False
        if event.key == pygame.K_LEFT:
            #Move the ship to the right
            self.ship.moving_left = False
        if event.key == pygame.K_UP:
            #Move the ship to the right
            self.ship.moving_up = False
        if event.key == pygame.K_DOWN:
            #Move the ship to the right
            self.ship.moving_down = False

    def _check_keydown_events(self,event):
        if event.key == pygame.K_RIGHT:
            #Move the ship to the right
            self.ship.moving_right = True
        if event.key == pygame.K_LEFT:
            #Move the ship to the right
            self.ship.moving_left = True
        if event.key == pygame.K_UP:
            #Move the ship to the right
            self.ship.moving_up = True
        if event.key == pygame.K_DOWN:
            #Move the ship to the right
            self.ship.moving_down = True
        if event.key == pygame.K_ESCAPE:
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

    def _fire_bullet(self):
        """Create a new bullet and add it to the group"""
        new_bullet = Bullet(self)
        self.bullets.add(new_bullet)
        print(self.bullets)

    def _update_screen(self):
        """Update images on the screen and flip to the new screen."""
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        pygame.display.flip()

    def run_game(self):
        """ Method handles running the game."""
        while True:
            self._check_events()
            self._update_screen()
            self.ship.track_ship_movement()
            self.bullets.update()


if __name__ == '__main__':
    ai = AlienInvasion()
    ai.run_game()

标签: pythonpython-3.xpygame

解决方案


您对两个不同的类都有update方法这一事实感到困惑。这个名字并不神奇,它只是这些类的 API 的一部分。

这是一个更简单的示例,它使用不同的名称,以便更清楚:

class MyContainer: # this is a standin for a pygame Group
    def __init__(self, *objects):
        self.objects = objects

    def foo(self):
        for obj in self.objects:
            obj.bar() # call a specific method on each object

class MyObject: # this is a standin for a pygame Sprite
    def bar(self):    # the class has the method called by MyContainer.foo
        print("Bar!")

class InvalidObject:  # this is not going to work if put in MyContainer
    def baz(self):
        pass

这将起作用:

c = MyContainer(MyObject(), MyObject())
c.foo()

这不会:

c = MyContainer(MyObject(), InvalidObject(), MyObject())    # setup works
c.foo()    # but this fails because InvalidObject doesn't have a bar() method

请注意,调用c.baz()也不起作用,因为该方法未在MyContainer类中定义。

要将此示例翻译为更接近您的代码,可以重命名foo和方法。尽管它们具有相同的名称,但它们是在不同的类中定义的,您不应该混淆它们。在 pygame 调用(或您的 Sprite 子类的重载实现)中。对于任意其他方法,它不会做同样的事情,只有那些是它被编写来处理的 API 的一部分。barupdateGroup.updateSprite.update


推荐阅读