飞船已经创建好了,接下来就要装填弹药了。(本想将修改的代码涂红显示,但系统问题导致无法正常显示,只能尽量只贴出修改的代码了)
在setting.py中设定子弹类Bullet所需的参数:
#设置子弹属性 self.bullet_width=2 self.bullet_height=10 self.bullet_speed=1 self.bullet_color=(20,20,20)
根据参数名就能看出我们设定的是子弹的宽高颜色以及发射速度,然后我们就要创建Bullet类了,新建bullet.py:
import pygame from pygame.sprite import Sprite class Bullet(Sprite): '''我们要在飞船所处的位置创建子弹对象''' def __init__(self,ai_settings,screen,ship): super(Bullet,self).__init__() #此为2.7写法,适用于3,也可将括号中的参数去掉 self.screen=screen #在原点处创建一个表示子弹的矩形,将其放在正确的位置 self.rect=pygame.Rect(0,0,ai_settings.bullet_width,ai_settings.bullet_height) self.rect.centerx=ship.rect.centerx self.rect.top=ship.rect.top #让子弹看起来是从飞船顶部发出的 #存储子弹的位置,用小数表示子弹的y坐标,方便微调其速度 self.y=float(self.rect.y) self.color=ai_settings.bullet_color self.speed=ai_settings.bullet_speed def update(self): self.y-=self.speed #更新子弹位置,子弹往屏幕上方走,即y坐标不断减小,而x坐标不变 self.rect.y=self.y #更新表示子弹rect的位置 def draw_bullet(self): #函数draw.rect()使用存储在self.color中的颜色填充表示子弹的rect占据的屏幕部分 pygame.draw.rect(self.screen,self.color,self.rect)
Sprite称为精灵,通过使用它可将游戏中相关的元素编组,进而同时操作组中的所有元素;使用super()继承Sprite(Bullet类继承了Sprite类)
接下来就要在主程序中进行设置了,在原有的基础上添加相应的子弹属性:
import pygame from settings import Settings from ship import Ship import game_functions as gf from pygame.sprite import Group def run_game(): pygame.init() #初始化背景设置 ai_settings=Settings() #实例化 screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height)) #调用属性设置屏幕的宽高 pygame.display.set_caption("Alien Invasion") #设置标题 ship=Ship(screen,ai_settings) #实例化Ship bullets=Group() #创建一个存储子弹的组 while True: gf.check_events(ship,ai_settings,screen,bullets) #更改事件监听函数 ship.update() #每次循环都访问该函数,保证飞船的位置将在检测到键盘事件后(但在更新屏幕前)更新 bullets.update() #将为组bullets中的每一颗子弹调用bullets.update() gf.update_screen(ai_settings,screen,ship,bullets) run_game()
相较于之前,我们导入了Group类,其类似于列表,但提供了有助于开发的额外功能。这里要注意一下主循环中的方法参数,传参时别整错了。
我们要实现按空格发射子弹的功能,需要修改game_function.py中的内容:
import sys import pygame from bullet import Bullet def check_keydown(event,ship,ai_settings,screen,bullets): if event.key==pygame.K_RIGHT: ship.moving_right=True #若按下右箭头则使ship.rect.centerx加1 elif event.key==pygame.K_LEFT: ship.moving_left=True #注意这里若同时按下左右箭头将检测到两个不同事件 elif event.key==pygame.K_SPACE: new_b=Bullet(ai_settings,screen,ship) #创建子弹 bullets.add(new_b) #将子弹加入到bullets中 def check_events(ship,ai_settings,screen,bullets): for event in pygame.event.get(): #检测键盘鼠标事件 if event.type==pygame.QUIT: sys.exit() #退出程序 elif event.type==pygame.KEYDOWN: check_keydown(event,ship,ai_settings,screen,bullets) elif event.type==pygame.KEYUP: check_keyup(event,ship) def update_screen(ai_settings,screen,ship,bullets): screen.fill(ai_settings.bg_color) #调用属性设置屏幕的填充颜色 for bullet in bullets.sprites(): #对每个bullets中的小妖怪都调用draw_bullet()方法,重绘所有子弹 bullet.draw_bullet() ship.blitme() #显示飞船 pygame.display.flip() #是最近绘制的屏幕可见
我们不需要修改check_keyup(),因为当松开空格键时无需任何操作;这里还是要注意各个方法的参数,包括导入的类。
效果如下,飞船可以发射任意数量的子弹了: