python - 方法仅在命名为“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()
解决方案
您对两个不同的类都有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 的一部分。bar
update
Group.update
Sprite.update