Python 项目:外星人入侵--第二部分

2023-05-26,

外星人入侵

6.驾驶飞船

玩家左右移动飞船,用户按左或右按键时作出响应。

6.1响应按键

当用户在按键时,在python中注册一个事件,事件都是通过方法pygame.event.get()获取的。
在函数check_events()中,需要制定要检查哪些类型的事件,每次按键都被注册为一个KEYDOWN事件
检测到KEYDOWN事件时,需要检查按下的是否是特定的键。

# settings.dy
class Settings():
'''存储《外星人入侵》的所有设置的类'''
def __init__(self):
'''初始化游戏设置''' self.screen_width = 1200 # 屏幕设置尺寸
self.screen_height = 800
self.bg_color = (230,230,230) # 屏幕背景色
# game_functions.py
# 模块sys用于退出游戏
import sys
import pygame def check_events(ship):
'''响应按键和鼠标事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
# 向右移动飞船
ship.rect.centerx += 1
def update_screen(ai_settings,screen,ship):
'''更新屏幕上的图像'''
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color)
# 调用方法screen.fill()用背景色填充屏幕,这个方法只接受一个实参:一种颜色
ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()
# alien_invasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
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("小子,你瞅啥啊")
'''创建一艘飞船'''
ship = Ship(screen)
'''开始游戏的主循环'''
while True:
'''监视键盘和鼠标事件'''
gf.check_events(ship)
'''每次循环时都重绘屏幕'''
gf.update_screen(ai_settings,screen,ship) run_game()

6.2 允许不断移动

按住右箭头不放时,飞船不断地向右移动,知道松开为止。通过一个名为moving_right的标志来实现持续移动。
飞船不动时,标志moving_right为False,按下右按键时,将这个标志设置为True,玩家松开手时,这个标志重新设置为False
飞船的属性都由Ship类控制,因此给这个类添加moving_right的属性和update()方法,方法update()检查moving_right的状态,如果这个标志为True,调整飞船的位置。

# ship.py
# ship.py
# 创建一个名为ship的模块,包含Ship类,负责管理飞船的大部分行为
import pygame
class Ship():
def __init__(self,screen): # screen指定飞船绘制到的地方
'''初始化飞船并设置其初始位置'''
self.screen = screen
# 加载飞船图像并获取其它外接矩形
self.image = pygame.image.load('C:\Study\Python\Project_外星人入侵\images\ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
#将每艘新飞船放在屏幕底部中央
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# 移动标志
self.moving_right = False
def update(self):
'''根据移动标志调整飞船的位置'''
if self.moving_right == True:
self.rect.centerx += 1
def blitme(self):
'''在指定位置绘制飞船'''
self.screen.blit(self.image,self.rect)
# game_functions.py
# 模块sys用于退出游戏
import sys
import pygame def check_events(ship):
'''响应按键和鼠标事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
ship.moving_right = False def update_screen(ai_settings,screen,ship):
'''更新屏幕上的图像'''
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color)
# 调用方法screen.fill()用背景色填充屏幕,这个方法只接受一个实参:一种颜色
ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()
# alien_inbasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
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("小子,你瞅啥啊")
'''创建一艘飞船'''
ship = Ship(screen)
'''开始游戏的主循环'''
while True:
'''监视键盘和鼠标事件'''
gf.check_events(ship)
# 根据移动标志调整飞船的位置
ship.update()
'''每次循环时都重绘屏幕'''
gf.update_screen(ai_settings,screen,ship) run_game()

6.3 左右移动

在ship中增加左右移动的属性,填加通过响应标志,更新飞船响应位置。
在游戏用途模块中填加左右按键,按键和抬起的响应标志。

# ship.py
# 创建一个名为ship的模块,包含Ship类,负责管理飞船的大部分行为
import pygame
class Ship():
def __init__(self,screen): # screen指定飞船绘制到的地方
'''初始化飞船并设置其初始位置'''
self.screen = screen
# 加载飞船图像并获取其它外接矩形
self.image = pygame.image.load('C:\Study\Python\Project_外星人入侵\images\ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
#将每艘新飞船放在屏幕底部中央
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# 移动标志
self.moving_right = False
self.moving_left = False
def update(self):
'''根据移动标志调整飞船的位置'''
if self.moving_right == True:
self.rect.centerx += 1
if self.moving_left == True:
self.rect.centerx -= 1
def blitme(self):
'''在指定位置绘制飞船'''
self.screen.blit(self.image,self.rect)
# game_functions.py
# 模块sys用于退出游戏
import sys
import pygame def check_events(ship):
'''响应按键和鼠标事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False def update_screen(ai_settings,screen,ship):
'''更新屏幕上的图像'''
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color)
# 调用方法screen.fill()用背景色填充屏幕,这个方法只接受一个实参:一种颜色
ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()
# aline_inbasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
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("小子,你瞅啥啊")
'''创建一艘飞船'''
ship = Ship(screen)
'''开始游戏的主循环'''
while True:
'''监视键盘和鼠标事件'''
gf.check_events(ship)
# 根据移动标志调整飞船的位置
ship.update()
'''每次循环时都重绘屏幕'''
gf.update_screen(ai_settings,screen,ship) run_game()

6.调整飞船的速度

while循环中,飞船移动1像素,在Settings类中添加属性ship_speed_factor,用于控制飞船的速度。
在ship模块中设置x的值,存为小数,根据移动标志调整飞船的位置,此位置通过飞船的center值,来更新rect对象,从而更新飞船的位置。
通过game_functions.py中调用响应按键和鼠标事件及更新屏幕图像函数
最后运行aline.inbasion.py,调用run_game()函数

# settings.py
class Settings():
'''存储《外星人入侵》的所有设置的类'''
def __init__(self):
'''初始化游戏设置'''
self.screen_width = 1200 # 屏幕设置尺寸
self.screen_height = 800
self.bg_color = (230,230,230) # 屏幕背景色
# 飞船的设置
self.ship_speed_factor = 1.5
# ship.py
# 创建一个名为ship的模块,包含Ship类,负责管理飞船的大部分行为
import pygame
class Ship():
def __init__(self,ai_settings,screen): # screen指定飞船绘制到的地方
'''初始化飞船并设置其初始位置'''
self.screen = screen
self.ai_settings = ai_settings
# 加载飞船图像并获取其它外接矩形
self.image = pygame.image.load('C:\Study\Python\Project_外星人入侵\images\ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
#将每艘新飞船放在屏幕底部中央
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# 在飞船的属性center中存储小数值
self.center = float(self.rect.centerx)
# 移动标志
self.moving_right = False
self.moving_left = False
def update(self):
'''根据移动标志调整飞船的位置'''
# 更新飞船的center值,而不是rect
if self.moving_right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left:
self.center -= self.ai_settings.ship_speed_factor
# 根据self.center更新rect对象
self.rect.centerx = self.center def blitme(self):
'''在指定位置绘制飞船'''
self.screen.blit(self.image,self.rect)
# game_functions.py
# 模块sys用于退出游戏
import sys
import pygame def check_events(ship):
'''响应按键和鼠标事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False def update_screen(ai_settings,screen,ship):
'''更新屏幕上的图像'''
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color)
# 调用方法screen.fill()用背景色填充屏幕,这个方法只接受一个实参:一种颜色
ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()
# aline_inbasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
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("小子,你瞅啥啊")
'''创建一艘飞船'''
ship = Ship(ai_settings,screen)
'''开始游戏的主循环'''
while True:
'''监视键盘和鼠标事件'''
gf.check_events(ship)
# 根据移动标志调整飞船的位置
ship.update()
'''每次循环时都重绘屏幕'''
gf.update_screen(ai_settings,screen,ship) run_game()

运行:
左右按键后,飞船速度加快

6.5 限制飞船的活动范围

按住左或右按键时间足够长,飞船将移到屏幕外面,消失的无影无踪。
让飞船达到屏幕边缘后停止移动
修改ship模块update()方法

修改 self.center 的值之前检查飞船的位置。 self.rect.right 返回飞船外接矩形的右边缘的 x 坐标,如果这个值小于 self.screen_rect.right 的值,就说明飞船未触及屏幕右边缘。左边缘的情况与此类似:如果 rect 的左边缘的 x 坐标大于零,就说明飞船未触及屏幕左边缘。这确保仅当飞船在屏幕内时,才调整 self.center 的值。

# ship.py
# 创建一个名为ship的模块,包含Ship类,负责管理飞船的大部分行为
import pygame
class Ship():
def __init__(self,ai_settings,screen): # screen指定飞船绘制到的地方
'''初始化飞船并设置其初始位置'''
self.screen = screen
self.ai_settings = ai_settings
# 加载飞船图像并获取其它外接矩形
self.image = pygame.image.load('C:\Study\Python\Project_外星人入侵\images\ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
#将每艘新飞船放在屏幕底部中央
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# 在飞船的属性center中存储小数值
self.center = float(self.rect.centerx)
# 移动标志
self.moving_right = False
self.moving_left = False
def update(self):
'''根据移动标志调整飞船的位置'''
# 更新飞船的center值,而不是rect
if self.moving_right and self.rect.right <self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor # 根据self.center更新rect对象
self.rect.centerx = self.center def blitme(self):
'''在指定位置绘制飞船'''
self.screen.blit(self.image,self.rect)

运行:
飞船到达右边缘停止移动,到达左边缘停止移动

6.6 重构check_events()

随着游戏进度函数check_events()将越来越长,拆分函数,一个函数处理KEYDOWN事件,一个处理KEYUP事件
修改game.functions.py模块

# game_functions.py
# 模块sys用于退出游戏
import sys
import pygame def check_keydown_events(event,ship):
'''响应按键'''
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True def check_keyup_events(event,ship):
'''响应松开'''
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False def check_events(ship):
'''响应按键和鼠标事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event,ship)
elif event.type == pygame.KEYUP:
check_keyup_events(event,ship) def update_screen(ai_settings,screen,ship):
'''更新屏幕上的图像'''
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color)
# 调用方法screen.fill()用背景色填充屏幕,这个方法只接受一个实参:一种颜色
ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()

7.射击

添加射击功能,将编写玩家按空格时发射子弹(小矩形)的代码。子弹将在屏幕汇总向上穿行,抵达屏幕上边缘后消失。

7.1添加子弹设置

更新settings.py,在方法__init__()末尾存储新类Bullet所需的属性值:

# settings.py
class Settings():
'''存储《外星人入侵》的所有设置的类'''
def __init__(self):
'''初始化游戏设置'''
self.screen_width = 1200 # 屏幕设置尺寸
self.screen_height = 800
self.bg_color = (230,230,230) # 屏幕背景色
# 飞船的设置
self.ship_speed_factor = 1.5 # 子弹的设置
self.bullet_speed_factor = 1
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = 60,60,60

7.2创建Bullet类

Bullet类继承模块pygame.sprite中导入的Sprite类,通过使用精灵,可将游戏中相关的元素编组,进而同时操作编组中的所有元素。
为创建子弹实例,需要向__init__()传递ai_settings、screen和ship,还调用了super()来继承Sprite
创建子弹的属性rect,子弹并非基于图像的,使用pygame.Rect()类从空白开始创建一个矩形,创建这个类的实例时,必须提供左上角的x、y左边,还有矩形的宽度和高度,在(0,0)处创建矩形,并根据飞船确定子弹的位置。
设置子弹y坐标,微调子弹的速度。子弹向上移动,y逐渐减小。
调用该函数draw_bullet()绘制子弹。

# bullet.py
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
'''一个对飞船发射的子弹进行管理的类'''
def __init__(self,ai_settings,screen,ship):
'''在飞船所处的位置创建一个子弹对象'''
super().__init__()
self.screen = screen # 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
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 # 存储用小数表示的子弹位置
self.y = float(self.rect.y) self.color = ai_settings.bullet_color
self.speed_factor = ai_settings.bullet_speed_factor def update(self):
'''向上移动子弹'''
# 更新表示子弹位置的小数值
self.y -= self.speed_factor
# 更新表示子弹的rect的位置
self.rect.y = self.y def draw_bullet(self):
'''在屏幕上绘制子弹'''
pygame.draw.rect(self.screem,self.color,self.rect)

7.3 将子弹存储到编组中

玩家每次按空格键时发出一发子弹。
在alien_invasion.py中创建一个编组(group),用于存储有效的子弹,以便能够管理发射出去的所有子弹。该编组将是pygame.sprite.Group类的一个实例bullets;pygame.sprite.Group类类似于列表。
bullets传递给检查按键,更新屏幕,在check_events()中,玩家按空格键处理bullets,在update_screen()中更新要绘制到屏幕上的bullets。
对编组调用update()时,编组将自动对其中每个精灵调用update(),所以bullets.update()将为编组bullets中的每颗子弹调用bullet.update()

# aline_inbasion.py
import pygame
from pygame.sprite import Group
from settings import Settings
from ship import Ship
import game_functions as gf
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("小子,你瞅啥啊")
'''创建一艘飞船'''
ship = Ship(ai_settings,screen)
'''创建一个用于存储子弹的编组'''
bullets = Group() '''开始游戏的主循环'''
while True:
'''监视键盘和鼠标事件'''
gf.check_events(ai_settings,screen,ship,bullets)
# 根据移动标志调整飞船的位置
ship.update()
bullets.update()
'''每次循环时都重绘屏幕'''
gf.update_screen(ai_settings,screen,ship,bullets) run_game()

7.4 开火

修改check_keydown_events(),以便玩家按空格键时发射一颗子弹
修改update_screen(),确保调用flip()前在屏幕上重绘每颗子弹
编组bulltes传递给监听按键事件函数,玩家按空格键,创建一个子弹,名为new_bullet的Bullet实例,并使用add()将其加入到编组bullets中。
检测按键函数传递了形参bullets中,调用具体按键按下函数,也需要将实参bullets传递给它
方法bullets.sprites()返回一个列表,包含编组bullets中的所有精灵,需要遍历bullets中的精灵才能在屏幕上绘制所有子弹。

# game_functions.py
# 模块sys用于退出游戏
import sys
import pygame
from bullet import Bullet def check_keydown_events(event,ai_settings,screen,ship,bullets):
'''响应按键'''
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
'''创建一颗子弹,并将其加入到编组bullets中'''
new_bullet = Bullet(ai_settings,screen,ship)
bullets.add(new_bullet) def check_keyup_events(event,ship):
'''响应松开'''
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False def check_events(ai_settings,screen,ship,bullets):
'''响应按键和鼠标事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event,ai_settings,screen,ship,bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event,ship) def update_screen(ai_settings,screen,ship,bullets):
'''更新屏幕上的图像'''
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color)
# 调用方法screen.fill()用背景色填充屏幕,这个方法只接受一个实参:一种颜色 '''在飞船和外星人后面重绘所有子弹'''
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()

运行:

7.5 删除已消失的子弹

子弹抵达屏幕顶端后消失,因Pygame无法在屏幕外面绘制它们,y坐标为负数,且越来越小,将消耗内存
需删除消失的子弹,否则游戏变得越来越慢。
for循环中不应从列表或编组删除中删除条目,因此必须遍历编组的副本,使用方法copy()来复制为副本,若子弹底端值小于屏幕垂直坐标0,确认子弹消失,使用方法remove()删除编组中的元素。

# aline_inbasion.py
import pygame
from pygame.sprite import Group
from settings import Settings
from ship import Ship
import game_functions as gf
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("小子,你瞅啥啊")
'''创建一艘飞船'''
ship = Ship(ai_settings,screen)
'''创建一个用于存储子弹的编组'''
bullets = Group() '''开始游戏的主循环'''
while True:
'''监视键盘和鼠标事件'''
gf.check_events(ai_settings,screen,ship,bullets)
# 根据移动标志调整飞船的位置
ship.update()
bullets.update() '''删除已消失的子弹'''
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
print(len(bullets))
'''每次循环时都重绘屏幕'''
gf.update_screen(ai_settings,screen,ship,bullets) run_game()

运行:
子弹到达屏幕顶端,将被移除,终端显示剩余子弹数量

7.6 限制子弹数量

限制子弹数量,以鼓励玩家有效地射击目标
在settings中增加能在编组中存储最大子弹数量。
在按键响应添加判断函数,是否达到子弹数量最大范围。

# settings.py
class Settings():
'''存储《外星人入侵》的所有设置的类'''
def __init__(self):
'''初始化游戏设置'''
self.screen_width = 1200 # 屏幕设置尺寸
self.screen_height = 800
self.bg_color = (230,230,230) # 屏幕背景色
# 飞船的设置
self.ship_speed_factor = 1.5 '''子弹的设置'''
self.bullet_speed_factor = 0.5
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = 60,60,60
self.bullets_allowed = 3 # 增加编组中子弹最大数量限制
# game_functions.py
# 模块sys用于退出游戏
import sys
import pygame
from bullet import Bullet def check_keydown_events(event,ai_settings,screen,ship,bullets):
'''响应按键'''
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
'''创建一颗子弹,并将其加入到编组bullets中'''
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings,screen,ship)
bullets.add(new_bullet) def check_keyup_events(event,ship):
'''响应松开'''
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False def check_events(ai_settings,screen,ship,bullets):
'''响应按键和鼠标事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event,ai_settings,screen,ship,bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event,ship) def update_screen(ai_settings,screen,ship,bullets):
'''更新屏幕上的图像'''
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color)
# 调用方法screen.fill()用背景色填充屏幕,这个方法只接受一个实参:一种颜色 '''在飞船和外星人后面重绘所有子弹'''
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip()

运行:

7.7 创建函数update_bullets()

为使主程序文件alien_invasion.py尽可能简单,可将子弹管理代码存放至update_bullets()函数中

# game_functions.py
# 模块sys用于退出游戏
import sys
import pygame
from bullet import Bullet def check_keydown_events(event,ai_settings,screen,ship,bullets):
'''响应按键'''
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
'''创建一颗子弹,并将其加入到编组bullets中'''
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings,screen,ship)
bullets.add(new_bullet) def check_keyup_events(event,ship):
'''响应松开'''
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False def check_events(ai_settings,screen,ship,bullets):
'''响应按键和鼠标事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event,ai_settings,screen,ship,bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event,ship) def update_screen(ai_settings,screen,ship,bullets):
'''更新屏幕上的图像'''
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color)
# 调用方法screen.fill()用背景色填充屏幕,这个方法只接受一个实参:一种颜色
'''在飞船和外星人后面重绘所有子弹'''
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip() def update_bullets(bullets):
'''更新子弹的位置,并删除已消失的子弹'''
# 更新子弹的位置
bullets.update()
# 删除已消失的子弹
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
print(len(bullets))
# aline_inbasion.py
import pygame
from pygame.sprite import Group
from settings import Settings
from ship import Ship
import game_functions as gf
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("小子,你瞅啥啊")
'''创建一艘飞船'''
ship = Ship(ai_settings,screen)
'''创建一个用于存储子弹的编组'''
bullets = Group() '''开始游戏的主循环'''
while True:
'''监视键盘和鼠标事件'''
gf.check_events(ai_settings,screen,ship,bullets)
# 根据移动标志调整飞船的位置
ship.update()
gf.update_bullets(bullets)
'''每次循环时都重绘屏幕'''
gf.update_screen(ai_settings,screen,ship,bullets) run_game()

7.8 创建函数fire_bullet()

将发射子弹的代码移到一个独立的函数中,这样简化按下键响应函数中。

# game_functions.py
# 模块sys用于退出游戏
import sys
import pygame
from bullet import Bullet def check_keydown_events(event,ai_settings,screen,ship,bullets):
'''响应按键'''
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings,screen,ship,bullets) def fire_bullet(ai_settings,screen,ship,bullets):
'''创建新子弹,并将其加入到编组bullets中'''
# 如果还没有到达限制,就发射一颗子弹'
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings,screen,ship)
bullets.add(new_bullet) def check_keyup_events(event,ship):
'''响应松开'''
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False def check_events(ai_settings,screen,ship,bullets):
'''响应按键和鼠标事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event,ai_settings,screen,ship,bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event,ship) def update_screen(ai_settings,screen,ship,bullets):
'''更新屏幕上的图像'''
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color)
# 调用方法screen.fill()用背景色填充屏幕,这个方法只接受一个实参:一种颜色
'''在飞船和外星人后面重绘所有子弹'''
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
# 让最近绘制的屏幕可见
pygame.display.flip() def update_bullets(bullets):
'''更新子弹的位置,并删除已消失的子弹'''
# 更新子弹的位置
bullets.update()
# 删除已消失的子弹
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
print(len(bullets))

Python 项目:外星人入侵--第二部分的相关教程结束。

《Python 项目:外星人入侵--第二部分.doc》

下载本文的Word格式文档,以方便收藏与打印。