外星人入侵

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 项目:外星人入侵--第二部分的更多相关文章

  1. 以正确的方式开源 Python 项目

    以正确的方式开源 Python 项目 大多数Python开发者至少都写过一个像工具.脚本.库或框架等对其他人也有用的工具.我写这篇文章的目的是让现有Python代码的开源过程尽可能清 晰和无痛.我不是 ...

  2. 以正确的方式开源 Python 项目(转)

    大多数Python开发者至少都写过一个像工具.脚本.库或框架等对其他人也有用的工具.我写这篇文章的目的是让现有Python代码的开源过程尽可能清晰和无痛.我不是简单的指——“创建一个GitHub库,提 ...

  3. python项目推荐(转载知乎)

    作者:Wayne Shi链接:https://www.zhihu.com/question/29372574/answer/88744491来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商 ...

  4. 这10个Python项目超有趣!

    前言: Python可谓是现在很多人正在学或者想学的一个脚本语言了,提到学习自然就少不了拿项目练手,可是一般的项目根本提不起兴趣嘛,这10个项目可是非常有趣的,不信你看看. [Python 图片转字符 ...

  5. python项目实现配置统一管理的方法

    一个比较大的项目总是会涉及到很多的参数,最好的方法就是在一个地方统一管理这些参数.最近看了不少的python项目,总结了两种很有意思的配置管理方法. 第一种 基于easydict实现的配置管理 首先需 ...

  6. Linux04 /创建虚拟环境、在linux环境运行Python项目

    Linux04 /创建虚拟环境.在linux环境运行Python项目 目录 Linux04 /创建虚拟环境.在linux环境运行Python项目 1. 大体流程 2. linux环境安装python3 ...

  7. 少儿编程:python趣味编程第二课,如何在pygame中写文字

    python趣味编程第二课:本文仅针对8-16岁的青少年,所以流程是按如何去教好中小学生走的,并不适合成人找工作学习,因为进度也是按照青少年走的 大家好,我是C大叔,上一篇文章已经跟大家介绍了一款开发 ...

  8. 给缺少Python项目实战经验的人

    我们在学习过程中最容易犯的一个错误就是:看的多动手的少,特别是对于一些项目的开发学习就更少了! 没有一个完整的项目开发过程,是不会对整个开发流程以及理论知识有牢固的认知的,对于怎样将所学的理论知识应用 ...

  9. Python开发【第二篇】:初识Python

    Python开发[第二篇]:初识Python   Python简介 Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏 ...

  10. 正确地组织python项目的结构

    统一的项目结构 写了不少python项目后, 越来越认识到python项目结构重要性. 不管项目是否要开源, 是否要提交pypi, 项目结构的一致性带来的好处还有很多: 多人合作开发大家都有个基本的g ...

随机推荐

  1. 如何设置表格的高度 element 的table 组件

    <el-table :row-style="{ height: '30px' }" :cell-style="{ padding: 0 }" :data= ...

  2. 002基本的Dos命令

    002基本的Dos命令 1.开启Dos控制台的几种方式 几种打开CMD的方式: 直接在菜单中搜索"命令提示符". Win+R,输入cmd.(推荐) 在任意文件夹下面,按住Shift ...

  3. Docker基本概念及命令

    1.Docker三个重要概念:仓库(Repository).镜像(image)和容器(Container) Docker基本用法: docker  命令关键字(COMMAND) 一系列的参数 dock ...

  4. vs2019配置boost库(转载)

    网址:https://blog.csdn.net/qq_42214953/article/details/105087015 关于途中的执行文件,可以使用b2.exe,不用跟着教程走. 如果本来就有b ...

  5. IDEA 文件夹下无法新建java class文件问题处理:

    主要问题 1 未设置为源文件夹. 2 包名中包含关键字,也无法创建. 解决方式 1 文件夹右键---Mark Directory as----Test Sources Root 即可. 2 重命名

  6. 把OSC_IN/OSC_OUT引脚作为GPIO端口PD0/PD1

    外部振荡器引脚OSC_IN/OSC_OUT可以用做GPIO的PD0/PD1,通过设置复用重映射和调试I/O配置寄存器(AFIO_MAPR)实现.这个重映射只适用于36. 48和64脚的封装(100脚和 ...

  7. C#的Event事件

    一直不明白事件,今天写了一下,做个笔记吧. 先建一个类,里面有一个方法,返回bool型 public class Subject { public bool IsPass(int x) { Conso ...

  8. IP rDNS(PTR)信息从理解到情报挖掘

    什么是IP的rdns信息? 过去很多人,将IP的rDNS信息理解为解析到IP的反查域名信息.IP的rDNS信息和IP反查域名信息完全是两个不同的信息.IP的rdns信息被称之为反向DNS解析(rDNS ...

  9. 代码大全_V2(1,2章笔记)

    译序 这本书讲什么 代码大全 原名叫 code complete,它是什么,又不是什么? 不是IDE中的代码自动补全功能 不是软件源代码 "大全" 是 "编码完成&quo ...

  10. VMware虚拟机扩容--保姆级教学

    由于项目逐步的完善,需要搭建的中间件,软件越来越多,导致以前虚拟机配置20G的内存不够用了,又不想重新创建新的虚拟机,退而求更精,选择扩容. 1.外部先进入虚拟机设置,将磁盘先扩展,具体提示如下图所示 ...