Python Crash Course读书笔记 - 第13章:ALIENS!
项目目标
创建外星人舰队,外星人在顶端移动,当舰队全部被飞船击中则产生新舰队。
外星人同时也发射子弹? 飞船被击中则重新来过,总共只能有三艘飞船。
创建第一个外星人
和Ship
一样,我们为外星人创建Alien
类。
和子弹一样,外星人也是一组,因此同样继承Sprite
类,以便批量操作。
外星人的其上位置是屏幕左上角。 外星人的x坐标用浮点数又存了一份,这是用于设置其速度的,原理和子弹和飞船类似。
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
"""A class to represent a single alien in the fleet."""
def __init__(self, ai_game):
"""Initialize the alien and set its starting position."""
super().__init__()
self.screen = ai_game.screen
# Load the alien image and set its rect attribute.
self.image = pygame.image.load('images/alien.bmp')
self.rect = self.image.get_rect()
# Start each new alien near the top left of the screen.
self.rect.x = self.rect.width
self.rect.y = self.rect.height
# Store the alien's exact horizontal position.
self.x = float(self.rect.x)
外星人舰队
在主程序中,存储外星人的变量定义如下:
self.aliens = pygame.sprite.Group()
所以,所谓舰队,就是往其中添加对象。
本节会先添加一行外星人,行边距以及外星人之间的艰巨为一个外星人宽度。
在计算一行可以放置多少外星人时,用了floor division
运算符//
,两数相除时,运算的结果会去除余数,例如:
>>> 25//3
8
>>> 27//4
6
还有外星人通过以下语句来描绘:
self.aliens.draw(self.screen)
这个方法应是在sprite.Group类中定义好了的,可以看下帮助。
第一行添加完毕后,继续添加其它行。
规则是最底下一行离非常两个外星人的高度,行间距是一个外星人的高度。
使舰队移动
为更新外星人位置,我们需要定义Alien类的update方法,然后在主程序中通过self.aliens.update()
调用,这样舰队中的每一个外星人都会调用此方法更新位置。
舰队的移动规则为,舰队先向右侧移动,当任何一外星人到达边界时,整个舰队下落一段距离,然后向反方向(左)移动。
到达左边界后下落一段距离再向右移动,如此循环往复,直到到达底部,被击中或与飞船碰撞。
这里有个问题,就是多久移动一次,多久刷新一次频率?就是一个While死循环,也许这就是固定模式吧:
def run_game(self):
"""Start the main loop for the game."""
while True:
self._check_events()
self.ship.update()
self._update_bullets()
self._update_aliens()
self._update_screen()
射杀外星人
子弹和外星人都是定义的sprite.Group,使用sprite.groupcollide()
可以判断两个Group中的长方形是否有重叠,然后返回字典,每一个键值对的键时子弹,值是外星人。
"""Respond to bullet-alien collisions."""
# Remove any bullets and aliens that have collided.
collisions = pygame.sprite.groupcollide(
self.bullets, self.aliens, True, True)
这段代码不仅判断是否重叠,而且还会删除重叠的子弹和外星人。如果将第一个True置为False,还可以使子弹具有穿透能力。
可以修改设置以方便测试,如将子弹改成很宽,使屏幕变小等,加快子弹速度等。
如果外星人全部被射杀,将重新生成舰队。
结束游戏
实际使指结束游戏的条件。包括:
- 外星人到达底部,飞船数量减1
- 外星人与飞船碰撞,飞船数量减1
- 飞船数为0,最初飞船数为3
判断飞船和外星人是否相撞仍是用spritecollideany
。
当飞船数量减1时,仍然用的是同一飞船实例,并不会产生新的实例。