首页 » 父与子的编程之旅:与小卡特一起学Python » 父与子的编程之旅:与小卡特一起学Python全文在线阅读

《父与子的编程之旅:与小卡特一起学Python》24.6 电子宠物

关灯直达底部

我们将要建立一个简化了的电子宠物程序,正如前面所说的一样,这是一种仿真。你可以购买电子宠物玩具(比如有一个小屏幕的钥匙链),下载电子宠物软件,还有一些网站(如 Neopets 和 Webkinz),就采用了电子宠物的形式。当然,所有这些也都是仿真。它们会模仿一些真实动物的行为,会饿,会感到孤单,会觉得累。要让它们快乐健康,你必须给它们喂食,和它们玩,还要带它们看病。

我们的电子宠物会简单得多,与你购买或在线玩的电子宠物相比没有那么真实,因为我只是想让你有一些基本认识,而且我不希望代码太过复杂。不过你可以在这个简化版本的基础上,根据你的想法进行扩展或改进。

我们的程序要具备以下特性。

  • 对这个宠物可以有 4 种活动:给它喂食、带它散步、和它玩或者带它看病。

  • 可以监测这个宠物的 3 种统计信息:饥饿感、快乐度和健康度。

  • 宠物可以醒着或者睡觉。

  • 饥饿感会随时间增加。可以通过喂食减少饥饿感。

  • 宠物睡觉时饥饿感的增加会减慢。

  • 如果宠物在睡觉,你做任何活动都会让它醒过来。

  • 如果宠物太饿了,它的快乐度会减少。

  • 如果宠物实在太饿了,它的健康度会减少。

  • 带宠物散步会同时增加它的快乐度和健康度。

  • 与宠物玩会让它的快乐度增加。

  • 带宠物看病会让它的健康度增加。

  • 宠物有 6 个不同的图片:

    • 一个睡觉的图片;

    • 一个醒着但什么也不做的图片;

    • 一个散步的图片;

    • 一个玩耍的图片;

    • 一个进食的图片;

    • 一个看病的图片。

图片可以使用一些简单的动画。后面几节我们将看到如何把所有这些整合在一起构成一个程序。

GUI

卡特和我为我们的电子宠物程序创建了一个 PyQt GUI。其中有一些按钮(实际上是工具条上的图标)用来完成活动,还有一些进度条显示重要的统计信息。另外还留有一个位置显示宠物的图片(宠物正在做什么)。

注意,窗口的标题栏上写着 Virtual Pet(虚拟宠物)。怎么设置窗口标题呢?在 Qt Designer 应用中新建一个窗口,然后在对象检查器中点击 MainWindow 对象。之后,在属性编辑器中找到 windowTitle 属性,将它改为 Virtual Pet(或者你想在标题栏中显示的任意文字)。

用来控制宠物活动的一组按钮是 PyQt 中一种叫做工具栏(Toolbar)的组件。工具栏和菜单栏一样也有行为,但不同之处在于,工具栏中的每个行为都有一个与之关联的图标。

要添加一个工具栏,右键点击主窗口,然后选择 Add Toolbar(添加工具栏)。这会在窗口顶部创建一个非常小的工具栏。在对象检查器中找到工具栏,点击它。然后在属性编辑器中找到 minimumSize 属性,将它的宽设为 100,高设为 50。

要将行为(图标)添加到工具栏上,点击 Qt Designer 右下角的 Action Editor(行为编辑器)标签。在 Action Editor 面板中任意位置点击右键,然后选择 New(新建)。你会看到一个用来添加新行为的对话框。你唯一需要输入的是 Text,Qt Designer 会自动填写对象名称。然后在中间找到三个点(...)的小按钮,点击右边的向下箭头,选择 Choose File,接着选择你想在工具栏按钮上使用的图片文件。

要在工具栏中添加新图标还有最后一步要做。一旦你创建了新的行为,就能在 Action Editor 的列表中看到它。现在你需要将它拖到工具栏上。当你拖过来时,你为新行为选择的图像将会作为工具栏的新图标出现。Qt Designer 会自动缩放图片以适应工具栏的大小。

血量是名为 Progress Bar(进度条)的组件类型。主图像是一个 Push Button(我们之前用过),通过设置它的属性,可以让它看起来不像普通的按钮,而是显示一幅图像。

窗口中其余部分的文本是 Label 组件。

你可以像这样使用 PyQt Designer 创建一个 GUI。你也可以(从示例文件夹中)将我们创建好的 GUI 加载到 Qt Desinger 中,以检查这些组件和它们的属性。

算法

要为电子宠物程序写代码,需要更明确地了解宠物的行为。以下是我们要使用的算法。

  • 我们把宠物的一“天”分为 60 个部分,每一部分称为一个“滴答”。每个滴答的实际时间是 5 秒钟,所以宠物的“一天”就是我们实际时间的 5 分钟。

  • 宠物在 48 个滴答中都醒着,然后它想睡 12 个滴答。你可以把它叫醒,不过这样会让它很不高兴!

  • 饥饿感、快乐度和健康度的范围都是 0 到 8。

  • 醒着时,饥饿感每个滴答会增加 1 个单位,快乐度每 2 个滴答减少 1 个单位(除非在散步或者玩)。

  • 睡觉时,饥饿感每 3 个滴答增加 1 个单位。

  • 进食时,饥饿感每个滴答减少 2 个单位。

  • 玩时,快乐度每个滴答增加 1 个单位。

  • 散步时,快乐度和健康度每 2 个滴答增加 1 个单位。

  • 看病时,健康度每个滴答增加 1 个单位。

  • 如果饥饿感达到 7,健康度每 2 个滴答减少 1 个单位。

  • 如果饥饿感达到 8,健康度每个滴答减少 1 个单位。

  • 如果睡觉时被叫醒,快乐度减少 4 个单位。

  • 如果程序不在运行,宠物可能醒着(什么也不做),也可能在睡觉。

  • 程序重启时,我们会统计过去了多少滴答,并对应过去的每个滴答更新统计信息。

看起来好像规则很多,不过编写代码其实很容易。实际上,你可能还想增加更多的行为,让它更加有趣。稍后就会给出代码(还会做一些解释)。

简单动画

并不总是需要 Pygame 才能完成动画。我们可以在 PyQt 中通过使用定时器完成简单的动画。定时器每隔一段时间会创建一个事件。可以编写一个事件处理器,在定时器到时间时让某个事情发生。这就类似于为一个用户动作编写事件处理器,比如说点击一个按钮,只不过定时器事件是由程序(而不是用户)生成的。定时器到时间时生成的事件类型是 timeout 事件。

我们的电子宠物 GUI 将使用两个定时器:一个用于动画,另一个用于滴答。动画每半秒(0.5 秒)更新一次,滴答每 5 秒发生一次。

动画定时器时间到时,我们会所显示宠物的图像。每个活动(进食、玩等)都有自己的一组图像来实现动画,每组图像将存储在一个列表中。动画会循环显示这个列表中的所有图像。程序将根据正在进行的活动来确定使用哪个列表。

试一试,再试一试

这个程序中还要使用一个新内容,这称为 try-except 块。

如果程序要做一件事情,而且这个事情有可能导致错误,那么最好提供一种办法来收集错误消息并进行处理,而不是让程序直接停止。这可以利用 try-except 块来做到。

例如,如果想打开一个文件,但是这个文件并不存在,你就会得到一条错误消息。如果你没有处理这个错误,程序会在这里停止。不过,也许你想让用户重新输入文件名(没准她只是敲错了)。利用 try-except 块,你可以获取到错误信息并继续执行。

对于打开文件的例子,try-except 块如下所示:

try:    file = open(/"somefile.txt/", /"r/")except:    print /"Couldn/'t open the file.  Do you want to reenter the filename?/"  

你想尝试的部分(可能导致一个错误)要放在 try 块中。在这个例子中就是尝试打开一个文件。如果可以打开文件而不会导致错误,就会跳过 except 部分。

如果 try 块中的代码确实导致一个错误,就会运行 except 块中的代码。except 块中的代码告诉程序一旦出现错误该做些什么。你可以这样来考虑:

try:    做这件事 ( 不做其他事情……)except:    如果有错误,就做这件事  

try-except 语句是 Python 处理错误所采用的方法,这通常称为错误处理(error handling)。错误处理允许你编写可能出错的代码(甚至是很严重的错误,倘若没有错误处理,这些错误在正常情况下甚至会让你的程序停止),使程序仍能继续运行。我们不打算在这本书里更详细地讨论错误处理,不过我希望你能了解一些基础知识,因为在电子宠物代码中就会看到错误处理。

下面来看这个代码,见代码清单 24-4。这里的说明已经对大部分工作做了解释。这个代码有点长,所以如果你不想自己键入,可以在 ExamplesVirtualPet 文件夹找到这个程序(如果你运行了本书的安装程序)。也可以从这本书的网站(www.helloworldbook2.com)下载。PyQt UI 文件和所有图片也都已经提供。试着运行这个程序,然后再看代码,确保你能理解它是如何工作的。

代码清单 24-4 VirtualPet.py

sleep_test 函数使用了 PyQt 的“警告信息”对话框。一系列的参数告诉它要显示哪些按钮,以及哪个是默认按钮。代码清单 24-4 中的注释解释了这一点。当对话框弹出来时(你试图叫醒你的宠物时),看起来是这样的:

即使你不能完全读懂这个代码也不用担心。如果你希望学习更多有关 PyQt 的内容,可以先看看 PyQt 网站:www.riverbankcomputing.co.uk/software/pyqt/into。

在本章中,我们只是稍稍了解了计算机仿真的一点皮毛,知道了模拟真实世界中一些方面的基本思想,比如重力和时间。实际上,计算机仿真在科学、工程、医药、金融和很多其他领域都得到了广泛使用。其中很多仿真非常复杂,即使用最快的计算机运行也需要花费几天甚至几个星期。不过钥匙链上的小电子宠物也是一种仿真,有时最简单的仿真也是最有意思的。

你学到了什么

在这一章,你学到了以下内容。

  • 什么是计算机仿真,为什么使用计算机仿真。

  • 如何模拟重力、加速度和作用力。

  • 如何跟踪和模拟时间。

  • 如何使用 pickle 将时间戳保存到文件。

  • 关于错误处理的一点知识(try-except)。

  • 如何使用定时器生成周期性的事件。

测试题

1. 列出使用计算机仿真的 3 个原因。

2. 列出你见过或知道的 3 种计算机仿真。

3. 使用哪种对象来存储两个日期或时间之差?

动手试一试

1. 为 Lunar Lander 程序增加一个“脱离轨道”测试。如果飞船飞出了窗口顶边,而且速度超过 +100m/s,就停止程序,并显示一条消息,比如“You have escaped the moon/'s gravity. No landing today!”(你已经脱离月球重力,无法着陆!)

2. 为 Lunar Lander 用户增加一个选项,可以在飞船着陆后继续玩这个游戏,而不必重启程序。

3. 为电子宠物 GUI 增加一个 Pause 按钮。这会让宠物的时间停止,不论程序是否在运行。(提示:这说明可能需要在 pickle 文件中保存“暂停”状态。)