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
self.rect = pygame.Rect(0, 0, self.settings.bullet_width, self.settings.bullet_height)
self.rect.midtop = ai_game.ship.rect.midtop
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)
来添加子弹的设置。在Bullet类中导入并继承了Sprite类。Sprite可以将游戏中相关的元素编组,进而同时操作编组中的所有元素。由于子弹并非基于图像,所以必须使用pygame.Rect()从头开始创建矩形。
将子弹的midtop设置为飞船的midtop,子弹就可以从飞船的顶部出发。通过update()管理子弹的位置,沿直线垂直向上飞行。通过draw_bullet()绘制子弹,这个函数使用存储在self.color中的颜色填充表示子弹的rect占据的屏幕部分。
self.bullets = pygame.sprite.Group()
为了能够使用Bullet类,首先需要在创建用于存储子弹的编组,并在while循环中更新子弹的位置。对编组调用update()时,编组自动对其中的每个sprite调用update()。
为了让子弹开火,需要注意:
1. 增加空格键(开火键)检测
2. 增加开火的方法,创建Bullet类的实例,并将实例加入到存储子弹的编组中。
3. 更新屏幕上的图像,对编组中的每一个子弹都要调用Bullet类中的draw_bullet()
def run_game(self):
while True:
self._check_events()
self.ship.update()
self.bullets.update()
for bullet in self.bullets.copy():
if bullet.rect.bottom < 0:
self.bullets.remove(bullet)
self._update_screen()
子弹离开屏幕后,实际上依然存在,会继续消耗内存和处理能力,因此需要将这些消失的子弹删除。
使用for循环遍历列表或Pygame编组时,Python要求该列表的长度在整个循环中保持不变,所以必须遍历编组的副本。从而能够在循环中修改编组。