为在屏幕上显示飞船,我们对编组调用了draw()。Pygame将绘制每艘飞船。 为在游戏开始时让玩家知道他有多少艘飞船,我们在开始新游戏时调用prep_ships()。这是 在game_functions.py的check_play_button()中进行的:
game_functions.py
def check_play_button(ai_settings, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y): """在玩家单击Play按钮时开始新游戏""" button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y) if button_clicked and not stats.game_active: --snip-- # 重置记分牌图像 sb.prep_score() sb.prep_high_score() sb.prep_level() sb.prep_ships() --snip--
我们还在飞船被外星人撞到时调用prep_ships(),从而在玩家损失一艘飞船时更新飞船图像:
game_functions.py
1 def update_aliens(ai_settings, screen, stats, sb, ship, aliens, bullets): --snip-- # 检测外星人和飞船之间的碰撞 if pygame.sprite.spritecollideany(ship, aliens): 2 ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets) # 检查是否有外星人抵达屏幕底端 3 check_aliens_bottom(ai_settings, screen, stats, sb, ship, aliens, bullets) 4 def ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets): """响应被外星人撞到的飞船""" if stats.ships_left > 0: # 将ships_left减1 stats.ships_left -= 1 # 更新记分牌 5 sb.prep_ships() # 清空外星人列表和子弹列表 --snip--
首先,我们在update_aliens()的定义中添加了形参sb(见1)。然后,我们向ship_hit()(见 2)和check_aliens_bottom()(见3)都传递了sb,让它们都能够访问记分牌对象。 接下来,我们更新了ship_hit()的定义,使其包含形参sb(见4)。我们在将ships_left的值 减1后调用了prep_ships()(见5),这样每次损失了飞船时,显示的飞船数都是正确的。 在check_aliens_bottom()中需要调用ship_hit(),因此对这个函数进行更新:
game_functions.py
def check_aliens_bottom(ai_settings, screen, stats, sb, ship, aliens, bullets): """检查是否有外星人抵达屏幕底端""" screen_rect = screen.get_rect() for alien in aliens.sprites(): if alien.rect.bottom >= screen_rect.bottom: # 像飞船被外星人撞到一样处理 ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets) break
现在,check_aliens_bottom()包含形参sb,并在调用ship_hit()时传递了实参sb。 最后,在alien_invasion.py中修改调用update_aliens()的代码,向它传递实参sb:
alien_invasion.py
# 开始游戏主循环 while True: --snip-- if stats.game_active: ship.update() gf.update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets) gf.update_aliens(ai_settings, screen, stats, sb, ship, aliens, bullets) --snip--
图14-6显示了完整的记分系统,它在屏幕左上角指出了还余下多少艘飞船。
14.4 小结
在本章中,你学习了如何创建用于开始新游戏的Play按钮,如何检测鼠标事件,以及在游戏 处于活动状态时如何隐藏光标。你可以利用学到的知识在游戏中创建其他按钮,如用于显示玩法 说明的Help按钮。你还学习了如何随游戏的进行调整其节奏,如何实现记分系统,以及如何以文 本和非文本方式显示信息。
第15 章
生成数据
15.1 安装 matplotlib
首先,需要安装matplotlib,我们将使用它来制作开始的几个图表。如果你还未使用过pip, 请参阅12.2.1节。
15.1.1 在 Linux 系统中安装 matplotlib
如果你使用的是系统自带的Python版本,可使用系统的包管理器来安装matplotlib,为此只需 执行一行命令:
$ sudo apt-get install python3-matplotlib
如果你使用的是Python 2.7,请执行如下命令:
$ sudo apt-get install python-matplotlib
如果你安装了较新的Python版本,就必须安装matplotlib依赖的一些库:
$ sudo apt-get install python3.5-dev python3.5-tk tk-dev $ sudo apt-get install libfreetype6-dev g++
再使用pip来安装matplotlib:
$ pip install --user matplotlib
15.1.2 在 OS X 系统中安装 matplotlib
Apple的标准Python安装自带了matplotlib。要检查系统是否安装了matplotlib,可打开一个终 端会话并尝试导入matplotlib。如果系统没有自带matplotlib,且你的Python是使用Homebrew安装 的,则可以像下面这样安装matplotlib:
$ pip install --user matplotlib
注意
安装包时可能需要使用pip3,而不是pip。另外,如果这个命令不管用,你可能需要删除 标志--user。
15.1.3 在 Windows 系统中安装 matplotlib
在Windows系统中,首先需要安装Visual Studio。为此,请访问https://dev.windows.com/,单 击Downloads,再查找Visual Studio Community——一组免费的Windows开发工具。请下载并运行 该安装程序。 接下来,需要下载matplotlib安装程序。为此,请访问https://pypi.python.org/pypi/matplotlib/, 并查找与你使用的Python版本匹配的wheel文件(扩展名为.whl的文件)。例如,如果你使用的是 32位的Python 3.5,则需要下载matplotlib-1.4.3-cp35-none-win32.whl。
注意
如果找不到与你安装的Python版本匹配的文件,请去http://www.lfd.uci.edu/-gohlke/ pythonlibs/#matplotlib看看,这个网站发布安装程序的时间通常比matplotlib官网早些。
将这个.whl文件复制到你的项目文件夹,打开一个命令窗口,并切换到该项目文件夹,再使 用pip来安装matplotlib:
> cd python_work python_work> python -m pip install --user matplotlib-1.4.3-cp35-none-win32.whl
15.1.4 测试 matplotlib
安装必要的包后,对安装进行测试。为此,首先使用命令python或python3启动一个终端会 话,再尝试导入matplotlib:
$ python3 >>> import matplotlib >>>
如果没有出现任何错误消息,就说明你的系统安装了matplotlib,可以接着阅读下一节。
注意
如果你在安装过程中遇到了麻烦,请参阅附录C。如果依然无济于事,请向他人寻求帮助。 对于你遇到的问题,只要向经验丰富的Python程序员提供少量的信息,他们很可能很快 就能帮你解决。
import matplotlib.pyplot as plt squares = [1, 4, 9, 16, 25] plt.plot(squares) plt.show()
15.1.5 matplotlib 画廊
要查看使用matplotlib可制作的各种图表,请访问http://matplotlib.org/的示例画廊。单击画廊 中的图表,就可查看用于生成图表的代码。
15.2 绘制简单的折线图
下面来使用matplotlib绘制一个简单的折线图,再对其进行定制,以实现信息更丰富的数据可 视化。我们将使用平方数序列1、4、9、16和25来绘制这个图表。 只需向matplotlib提供如下数字,matplotlib就能完成其他的工作:
mpl_squares.py
我们首先导入了模块pyplot,并给它指定了别名plt,以免反复输入pyplot。在线示例大都这 样做,因此这里也这样做。模块pyplot包含很多用于生成图表的函数。
我们创建了一个列表,在其中存储了前述平方数,再将这个列表传递给函数plot(),这个函 数尝试根据这些数字绘制出有意义的图形。plt.show()打开matplotlib查看器,并显示绘制的图形, 如图15-1所示。查看器让你能够缩放和导航图形,另外,单击磁盘图标可将图形保存起来。
15.2.1 修改标签文字和线条粗细
图15-1所示的图形表明数字是越来越大的,但标签文字太小,线条太细。所幸matplotlib让你 能够调整可视化的各个方面。 下面通过一些定制来改善这个图形的可读性,如下所示:
mpl_squares.py
import matplotlib.pyplot as plt squares = [1, 4, 9, 16, 25] 1 plt.plot(squares, linewidth=5) # 设置图表标题,并给坐标轴加上标签 2 plt.title("Square Numbers", fontsize=24) 3 plt.xlabel("Value", fontsize=14) plt.ylabel("Square of Value", fontsize=14) # 设置刻度标记的大小 4 plt.tick_params(axis='both', labelsize=14) plt.show()
参数linewidth(见1)决定了plot()绘制的线条的粗细。函数title()(见2)给图表指定标 题。在上述代码中,出现了多次的参数fontsize指定了图表中文字的大小。
函数xlabel()和ylabel()让你能够为每条轴设置标题(见3);而函数tick_params()设置刻度 的样式(见4),其中指定的实参将影响x轴和y轴上的刻度(axes='both'),并将刻度标记的字号 设置为14(labelsize=14)。 最终的图表阅读起来容易得多了,如图15-2所示:标签文字更大,线条也更粗。
15.2.2 校正图形
图形更容易阅读后,我们发现没有正确地绘制数据:折线图的终点指出4.0的平方为25!下 面来修复这个问题。 当你向plot()提供一系列数字时,它假设第一个数据点对应的x坐标值为0,但我们的第一个 点对应的x值为1。为改变这种默认行为,我们可以给plot()同时提供输入值和输出值:
mpl_squares.py
import matplotlib.pyplot as plt input_values = [1, 2, 3, 4, 5] squares = [1, 4, 9, 16, 25] plt.plot(input_values, squares, linewidth=5) # 设置图表标题并给坐标轴加上标签 --snip--
现在plot()将正确地绘制数据,因为我们同时提供了输入值和输出值,它无需对输出值的生 成方式作出假设。最终的图形是正确的,如图15-3所示。
使用plot()时可指定各种实参,还可使用众多函数对图形进行定制。本章后面处理更有趣的 数据集时,将继续探索这些定制函数。