本章最重要的是了解此游戏设计的逻辑。Pygame
模块倒是其次,而且在本章中的应用也不难。
规划你的项目
键盘操纵的打飞机游戏,总共有三条命。
安装Pygame
Pygame的文档参见这里。
需要用pip安装Pygame模块。pip是安装Python模块的程序,从3.4版本起包含在Python安装中。--user
表示?
## pip的--user参数表示只为当前用户安装,而不是系统所有用户
$ python3 -m pip install --user pygame
Collecting pygame
Downloading https://files.pythonhosted.org/packages/8e/24/ede6428359f913ed9cd1643dd5533aefeb5a2699cc95bea089de50ead586/pygame-1.9.6-cp36-cp36m-manylinux1_x86_64.whl (11.4MB)
100% |████████████████████████████████| 11.4MB 110kB/s
Installing collected packages: pygame
Successfully installed pygame-1.9.6
Pygame需要图形界面,如无,报错如下:
$ python3 alien_invasion.py
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "alien_invasion.py", line 36, in <module>
ai = AlienInvasion()
File "alien_invasion.py", line 16, in __init__
(self.settings.screen_width, self.settings.screen_height))
pygame.error: No available video device
开始游戏项目
看一下主程序alien_invasion.py
,了解一下固定模式。设置在另一文件settings.py
中:
import sys
import pygame
from settings import Settings
class AlienInvasion:
"""Overall class to manage game assets and behavior."""
def __init__(self):
"""Initialize the game, and create game resources."""
pygame.init() # 初始化
self.settings = Settings()
# 设置屏幕尺寸
self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("Alien Invasion")
def run_game(self):
"""Start the main loop for the game."""
while True:
# Watch for keyboard and mouse events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# Redraw the screen during each pass through the loop.
self.screen.fill(self.settings.bg_color)
# Make the most recently drawn screen visible.
pygame.display.flip()
if __name__ == '__main__':
# Make a game instance, and run the game.
ai = AlienInvasion()
ai.run_game()
添加飞船图片
免费图片是从Pixabay获取的。Pygame默认的图片格式为bmp,图片最好是透明背景,否则需要将屏幕背景设置与图片背景一致。
无论图片形状如何,Pygame都将其视为长方形,包括屏幕,这样可以很方便的判断两个物体是否相撞。
坐标系中, (0,0)是左上角,因此右下角就是(1200,800)
为飞船构建的类ship.py
如下:
import pygame
class Ship:
"""A class to manage the ship."""
def __init__(self, ai_game):
"""Initialize the ship and set its starting position."""
# self是飞船本身,ai_game是类alien_invasion,带屏幕属性
self.screen = ai_game.screen
self.screen_rect = ai_game.screen.get_rect()
# Load the ship image and get its rect.
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
# Start each new ship at the bottom center of the screen.
self.rect.midbottom = self.screen_rect.midbottom
def blitme(self):
"""Draw the ship at its current location."""
self.screen.blit(self.image, self.rect)
重构: _check_events() 和 _update_screen() 方法
这两个方法都是helper method,在Python中的惯例是以下划线(_
)开头的。大致框架如下:
...
def run_game(self):
"""Start the main loop for the game."""
while True:
self._check_events()
self._update_screen()
def _check_events(self):
"""Respond to keypresses and mouse events."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
def _update_screen(self):
"""Update images on the screen, and flip to the new screen."""
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
pygame.display.flip()
...
重构是对代码的优化,在本节中并未涉及程序行为的改变。
驾驶飞船
本节将让飞船响应键盘事件(KEYDOWN
)。
大致思路是这样的,以右键为例,设置一个布尔变量moving_right初始值为False,如果检测到右键按下将其置为True,同时更新飞船位置;右键抬起则重置为False。左键同样处理。
此外还设置了全屏模式,按q
键退出,设置右键速度(默认是1,可以设为>1的浮点数如1.5),以及一系列help method。
快速回顾
目前为止定义了3个Class:
- alien_invasion.py - 主程序,处理事件
- settings.py - 全局设置
- ship.py - 画飞船,更新位置
发射子弹
子弹没有使用图片,而是程序画的长方形,子弹的全局设置如尺寸,颜色和速度存放在文件settings.py
中。子弹是通过空格键发射的。
要点1:
我们定义的类Bullet
只是一颗子弹,但由于子弹可以有多发,因此在主程序中添加的属性bullets类型为sprite.Group(),这类似于一个列表,可以增删子弹,但最重要的是可以做批量操作,例如同时更新所有的子弹,因此Bullet
类继承了类Sprite
。
要点2:
按下空格键会新增Bullet
对象,删除对象则是在子弹到达顶部时,这时坐标系的有值会<0。
同时我们现在了子弹的个数,也就是只允许bullets中存3个Bullet
对象。