蚊章汇 - Pygame
type: channel
link: https://linuxcn.bwsl.wang/tag/Pygame/
items: 通过创建视频游戏来学习 Python
items: 添加声音到你的 Python 游戏
items: 在你的 Python 游戏中添加投掷机制
items: 添加计分到你的 Python 游戏
items: 在你的 Python 平台类游戏中放一些奖励
items: 使你的 Python 游戏玩家能够向前和向后跑
items: 为你的 Python 平台类游戏添加跳跃功能
items: 在你的 Python 游戏中模拟引力
items: 在 Pygame 游戏中放置平台
items: 如何向你的 Python 游戏中添加一个敌人

通过创建视频游戏来学习 Python
type: item
date: 2021-01-19T07:45:39+08:00
description: 使用我们的新电子书中的分步说明，以有趣的方式了解 Python。Python 是目前最流行的程序设计语言之一。不管是为了工作还是娱乐为目的学习 Python，它都是一门功能强大且非常有用的编程语言。你可以创建应用程序来帮助你完成日常任务，创建你和朋友们喜欢玩的游戏，创建用于处理数据的脚本，创建用于生成或分析信息的应用程序等等。无论你计划使用程序设计语言做什么，我们都认为通过创建游戏来学习比通过处理数字或变换字符串来学习更为有趣。然而，如果你完全是一个编程的新手，当你能看到代码在视频游戏等熟悉的环境中工作时，你会更容易理解为什么要用代码做某事。你可能不会选择 Python 作为最好的编程语言（每个人对此都有自己的答案），但它不是一门令人恐惧的编程语言。 Python 可以使用很多关键字（例如 is 和 is not）代替符号（例如 = 和 !=）。它还能管理许多低级任务，因此你通常不必担心数据类型和垃圾收集之类的事情。通常，这意味着你马上就可以开始编写代码，而不会像在 C 或 Java 那样的复杂编程语言面前遇到挫折。为了帮助你学习 Python，我们编写了一本电子书，教你如何使用 Python 创建平台类视频游戏。在制作视频游戏的同时逐步通过课程学习 Python。另外一个好处是，你还将学习编程逻辑、语法、运算符等更多的内容。你可以在学习过程中立即看到结果，因此你学到的所有内容都会得到及时巩固。一分钟上手 PythonPython 是一种用途广泛的编程语言，这意味着它（与大多数语言一样）提供了函数来对数字和字符做处理的“简单技巧”。Linux 操作系统用户已经安装了 Python。 Mac 操作系统用户使用的是较旧版本的 Python，但是你可以从 Python.org 网站 安装最新版本。Windows 操作系统用户可以从这篇 在 Windows 上安装 Python 的文章中学习如何安装 Python。安装完成后，你可以启动交互式 Python Shell 进行算术运算：$ python3 >>> 5+6 11 >>> 11/2 5.5 >>> 11//2 5 >>> 11%2 1 从该示例可以了解，需要一些特殊的符号，但学过数学的人都最熟悉不过了。也许你不喜欢数字，而更喜欢字母：$ python3 >>> string = "hello world" >>> print(string) hello world >>> print(string.upper()) HELLO WORLD >>> print(string[0]) h >>> print(string[1]) e >>> print(string[2]) l >>> print(string[3]) l >>> print(string[4]) o 同样，相对地说基础的任务有特殊的符号表示法，但是即使没有说明，你也可能已经发现 [0] 和 [1] 符号表示法是将数据“切片”并且利用 print 函数将其中的数据显示在屏幕上。五分钟用上 Pygame如果你只想使用 Python 来创建一个视频游戏或任何超越基本计算的项目，这可能需要投入大量的学习、努力和时间。幸运的是，Python 诞生已有二十年了，开发者已经开发了代码库来帮助你（相对）轻松地完成典型的程序壮举。Pygame 是一套用于创建视频游戏的代码模块。它 不是唯一的这种类库，但是它是最古老的（不论好坏），因此在线上有很多文档和示例。首先学习 推荐的 Python 虚拟环境工作流程：$ python3 -m venv mycode/venv $ cd mycode $ source ./venv/bin/activate (venv)$ 进入虚拟环境后，可以安全地将 Pygame 安装到项目文件夹中：(venv)$ echo "pygame" >> requirements.txt (venv)$ python -m pip install -r requirements.txt [...] Installing collected packages: pygame Successfully installed pygame-x.y.z 现在你已经安装了 Pygame，就可以创建一个简单的演示应用程序。它比你想象的要容易。Python 可以进行所谓的面向对象编程（OOP），这是一个漂亮的计算机科学术语，用于描述当代码结构化时，就像你在使用代码创建物理对象一样。然而，程序员并没有受到迷惑。他们知道在编写代码时并不是真的在制造物理对象，但是这样有助于想象，因为这样你就可以了解编程世界的局限性。例如，如果你被困在一个荒岛上并想要一杯咖啡，那么你就必须收集一些黏土，做一个杯子，然后烘烤它。如果你足够聪明，先创建一…

添加声音到你的 Python 游戏
type: item
date: 2020-12-02T17:23:15+08:00
description: 通过添加声音到你的游戏中，听听当你的英雄战斗、跳跃、收集战利品时会发生什么。学习如何在这个 Pygame 系列的第十三篇文章中，创建一个声音平台类精灵。在 Python 3 中使用 Pygame 模块来创建电脑游戏的系列文章仍在进行中，这是第十三部分。先前的文章是:通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程使用 Python 和 Pygame 模块构建一个游戏框架如何在你的 Python 游戏中添加一个玩家用 Pygame 使你的游戏角色移动起来如何向你的 Python 游戏中添加一个敌人在 Pygame 游戏中放置平台在你的 Python 游戏中模拟引力为你的 Python 平台类游戏添加跳跃功能使你的 Python 游戏玩家能够向前和向后跑在你的 Python 平台类游戏中放一些奖励添加计分到你的 Python 游戏在你的 Python 游戏中加入投掷机制Pygame 提供了一种简单的方法来集成声音到你的 Python 电脑游戏中。Pygame 的 mixer 模块 可以依据命令播放一个或多个声音，并且你也可以将这些声音混合在一起，例如，你能够在听到你的英雄收集奖励或跳过敌人声音的同时播放背景音乐。集成 mixer 模块到一个已存在的游戏中是很容易的，因此，与其给你代码示例来向你展示放置它们的位置，不如在这篇文章解释在你的应用程序中获得声音所需的四个步骤。启动 mixer首先，在你代码的设置部分，启动 mixer 进程。你的代码已经启动 Pygame 和 Pygame 字体，因此将它们归类到一起是一个很好的主意:pygame.init() pygame.font.init() pygame.mixer.init() # add this line 定义声音接下来，你必需定义你想要使用的声音。这样就要求你的计算机上有声音文件，就像使用字体就要求你有字体文件，使用图像就要求你有图像文件一样。你还必需把这些声音与你的游戏捆绑在一起，以便任何玩你游戏的人都有这些声音文件。为将一个声音与你的游戏捆绑在一起，首先在你的游戏目录中创建一个新的目录，就像你为你图像和字体创建的目录一样。称它为 sound:s = 'sound' 尽管在互联网上有很多声音文件，下载这些声音文件并将其与你的游戏一起分发并不一定是合法的。这看起来是很奇怪的，因为这么多来自著名电脑游戏的声音是流行文化的一部分，但法律就是这样运作的。如果你想与你的游戏一起分发一个声音文件，你必需找到一个开源或共创许可的声音文件，它们准许与游戏一起提供声音。这里有一些专门提供自由和合法的声音文件的网站，包括:Freesound 托管存储所有种类的音效。Incompetech 托管存储背景音乐。Open Game Art 托管存储一些音效和音乐。一些声音文件只要你给予作曲家或声音设计师一个致谢就可以自由使用。在与你的游戏捆绑前，仔细阅读使用条件！音乐家和声音设计师在声音上的工作就像你在代码上的工作一样努力，因此即使他们不要求，给予他们致谢也是极好的。给予你的声音源文件一些致谢，在一个名为 CREDIT 的文本文件中列出你使用的声音，并在你的游戏文件夹中放置该文本文件。你也可以尝试制作你自己的音乐。优秀的 LMMS 音频工作站易于使用，并带有很多有趣的声音。它在所有主要的平台上都可以使用，也可以导出为 Ogg Vorbis（OGG）音频格式。添加声音到 Pygame当你找到你喜欢的一个声音文件时，下载它。如果它是一个 ZIP 或 TAR 文件，提取它并将其移动到你游戏目录中的 sound 文件夹中。如果声音文件的名字带有空格或特殊字符，重新命名它。文件名称是完全随意的，它的名称越简单，你就越容易输入到你的代码中。大多数的电脑游戏使用 OGG 格式声音文件，因为这种格式可以占有较小空间而提供高质量的声音。当你下载一个声音文件时，它可能是一个 MP3、WAVE、FLAC 或者其它的音频格式。为保持你的文件的较高兼容性和降低下载文件大小，使用一个像 fre:ac 或 Miro 这样的工具来转换这些的文件格式为 Ogg 格式。例如，假设你已经下载一个称为 ouch.ogg 的声音文件。在你代码的设置部分中，创建一个变量，代表你想使用的声音文件：ouch = pygame.mixer.Sound(os.path.join(s, 'ouch.ogg')) 触发一个声音为使用一个声音，你所要做的就是在你想触发它的时候调用这个变量。例如，当你的玩家击中一名敌人时，触发 OUCH 声音效果:for enemy in enemy_hit_list: pygame.mixer.Sound.play(ouch) score -= 1 你可以为各种动作创建声音，例如，跳跃、收集奖励、投掷、碰撞，…

在你的 Python 游戏中添加投掷机制
type: item
date: 2020-11-30T20:46:00+08:00
description: 四处奔跑躲避敌人是一回事，反击敌人是另一回事。学习如何在这系列的第十二篇文章中在 Pygame 中创建平台游戏。这是仍在进行中的关于使用 Pygame 模块在 Python 3 中创建电脑游戏的第十二部分。先前的文章是：通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程使用 Python 和 Pygame 模块构建一个游戏框架如何在你的 Python 游戏中添加一个玩家用 Pygame 使你的游戏角色移动起来如何向你的 Python 游戏中添加一个敌人在 Pygame 游戏中放置平台在你的 Python 游戏中模拟引力为你的 Python 平台类游戏添加跳跃功能使你的 Python 游戏玩家能够向前和向后跑在你的 Python 平台类游戏中放一些奖励添加计分到你的 Python 游戏我的上一篇文章本来是这一系列文章的最后一篇，它鼓励你为这个游戏编写自己的附加程序。你们很多人都这么做了！我收到了一些电子邮件，要求帮助我还没有涵盖的常用机制：战斗。毕竟，跳起来躲避坏人是一回事，但是有时候让他们走开是一件非常令人满意的事。在电脑游戏中向你的敌人投掷一些物品是很常见的，不管是一个火球、一支箭、一道闪电，还是其它适合游戏的东西。与迄今为止你在这个系列中为你的平台游戏编程的任何东西不同，可投掷物品有一个生存时间。在你投掷一个物品后，它会如期在移动一段距离后消失。如果它是一支箭或其它类似的东西，它可能会在通过屏幕的边缘时而消失。如果它是一个火球或一道闪电，它可能会在一段时间后熄灭。这意味着每次生成一个可投掷的物品时，也必须生成一个独特的衡量其生存时间的标准。为了介绍这个概念，这篇文章演示如何一次只投掷一个物品。（换句话说，每次仅存在一个投掷物品）。 一方面，这是一个游戏的限制条件，但另一方面，它却是游戏本身的运行机制。你的玩家不能每次同时投掷 50 个火球，因为每次仅允许一个投掷物品，所以当你的玩家释放一个火球来尝试击中一名敌人就成为了一项挑战。而在幕后，这也使你的代码保持简单。如果你想启用每次投掷多个项目，在完成这篇教程后，通过学习这篇教程所获取的知识来挑战你自己。创建 Throwable 类如果你跟随学习这系列的其它文章，那么你应该熟悉在屏幕上生成一个新的对象基础的 __init__ 函数。这和你用来生成你的 玩家 和 敌人 的函数是一样的。这里是生成一个 throwable 对象的 __init__ 函数来：class Throwable(pygame.sprite.Sprite): """ 生成一个 throwable 对象 """ def __init__(self, x, y, img, throw): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(os.path.join('images',img)) self.image.convert_alpha() self.image.set_colorkey(ALPHA) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.firing = throw 同你的 Player 类或 Enemy 类的 __init__ 函数相比，这个函数的主要区别是，它有一个 self.firing 变量。这个变量保持跟踪一个投掷的物品是否在当前屏幕上活动，因此当一个 throwable 对象创建时，将变量设置为 1 的合乎情理的。判断存活时间接下来，就像使用 Player 和 Enemy 一样，你需要一个 update 函数，以便投掷的物品在瞄准敌人抛向空中时，它会自己移动。测定一个投掷的物品存活时间的最简单方法是侦测它何时离开屏幕。你需要监视的屏幕边缘取决于你投掷的物品的物理特性。如果你的玩家正在投掷的物品是沿着水平轴快速移动的，像一只弩箭或箭或一股非常快的魔法力量，而你想监视你游戏屏幕的水平轴极限。这可以通过 worldx 定义。如果你的玩家正在投掷的物品是沿着垂直方向或同时沿着水平方向和垂直方向移动的，那么你必须监视你游戏屏幕的垂直轴极限。这可以通过 worldy 定义。这个示例假设你投掷的物品向前移动一点并最终落到地面上。不过，投掷的物品不会从地面上反弹起来，而是继续掉落出屏幕。你可以尝试不同的设置来看看什么最适合你的游戏： def update(self,worldy): ''' 投掷物理学 ''' if self.rect.y < worldy: #垂直轴 self.rect.x += 15 #它向前移动的速度有多快 self.rect.y += 5 #它掉落的速度有多快 else: self.kill(…

添加计分到你的 Python 游戏
type: item
date: 2020-02-01T23:48:00+08:00
description: 在本系列的第十一篇有关使用 Python Pygame 模块进行编程的文章中，显示玩家获得战利品或受到伤害时的得分。这是仍在进行中的关于使用 Pygame 模块来在 Python 3 在创建电脑游戏的第十一部分。先前的文章是：通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程使用 Python 和 Pygame 模块构建一个游戏框架如何在你的 Python 游戏中添加一个玩家用 Pygame 使你的游戏角色移动起来如何向你的 Python 游戏中添加一个敌人在 Pygame 游戏中放置平台在你的 Python 游戏中模拟引力为你的 Python 平台类游戏添加跳跃功能使你的 Python 游戏玩家能够向前和向后跑在你的 Python 平台类游戏中放一些奖励如果你已经跟随这一系列很久，那么已经学习了使用 Python 创建一个视频游戏所需的所有基本语法和模式。然而，它仍然缺少一个至关重要的组成部分。这一组成部分不仅仅对用 Python 编程游戏重要；不管你探究哪个计算机分支，你都必需精通：作为一个程序员，通过阅读一种语言的或库的文档来学习新的技巧。幸运的是，你正在阅读本文的事实表明你熟悉文档。为了使你的平台类游戏更加美观，在这篇文章中，你将在游戏屏幕上添加得分和生命值显示。不过，教你如何找到一个库的功能以及如何使用这些新的功能的这节课程并没有多神秘。在 Pygame 中显示得分现在，既然你有了可以被玩家收集的奖励，那就有充分的理由来记录分数，以便你的玩家看到他们收集了多少奖励。你也可以跟踪玩家的生命值，以便当他们被敌人击中时会有相应结果。你已经有了跟踪分数和生命值的变量，但是这一切都发生在后台。这篇文章教你在游戏期间在游戏屏幕上以你选择的一种字体来显示这些统计数字。阅读文档大多数 Python 模块都有文档，即使那些没有文档的模块，也能通过 Python 的帮助功能来进行最小的文档化。Pygame 的主页面 链接了它的文档。不过，Pygame 是一个带有很多文档的大模块，并且它的文档不像在 Opensource.com 上的文章一样，以同样易理解的（和友好的、易解释的、有用的）叙述风格来撰写的。它们是技术文档，并且列出在模块中可用的每个类和函数，各自要求的输入类型等等。如果你不适应参考代码组件描述，这可能会令人不知所措。在烦恼于库的文档前，第一件要做的事，就是来想想你正在尝试达到的目标。在这种情况下，你想在屏幕上显示玩家的得分和生命值。在你确定你需要的结果后，想想它需要什么的组件。你可以从变量和函数的方面考虑这一点，或者，如果你还没有自然地想到这一点，你可以进行一般性思考。你可能意识到需要一些文本来显示一个分数，你希望 Pygame 在屏幕上绘制这些文本。如果你仔细思考，你可能会意识到它与在屏幕上渲染一个玩家、奖励或一个平台并多么大的不同。从技术上讲，你可以使用数字图形，并让 Pygame 显示这些数字图形。它不是达到你目标的最容易的方法，但是如果它是你唯一知道的方法，那么它是一个有效的方法。不过，如果你参考 Pygame 的文档，你看到列出的模块之一是 font，这是 Pygame 使得在屏幕上来使打印文本像输入文字一样容易的方法。解密技术文档font 文档页面以 pygame.font.init() 开始，它列出了用于初始化字体模块的函数。它由 pygame.init() 自动地调用，你已经在代码中调用了它。再强调一次，从技术上讲，你已经到达一个足够好的点。虽然你尚不知道如何做，你知道你能够使用 pygame.font 函数来在屏幕上打印文本。然而，如果你阅读更多一些，你会找到这里还有一种更好的方法来打印字体。pygame.freetype 模块在文档中的描述方式如下：pygame.freetype 模块是 pygame.fontpygame 模块的一个替代品，用于加载和渲染字体。它有原函数的所有功能，外加很多新的功能。在 pygame.freetype 文档页面的下方，有一些示例代码：import pygame import pygame.freetype你的代码应该已经导入了 Pygame，不过，请修改你的 import 语句以包含 Freetype 模块：import pygame import sys import os import pygame.freetype在 Pygame 中使用字体从 font 模块的描述中可以看出，显然 Pygame 使用一种字体（不管它的你提供的或内置到 Pygame 的默认字体）在屏幕上渲染字体。滚动浏览 pygame.freetype 文档来找到 pygame.freetype.Font 函数：pygame.freetype.Font 从支持的字体文件中创建一个新的字体实…

在你的 Python 平台类游戏中放一些奖励
type: item
date: 2020-01-29T21:12:48+08:00
description: 这部分是关于在使用 Python 的 Pygame 模块开发的视频游戏总给你的玩家提供收集的宝物和经验值的内容。这是正在进行的关于使用 Python 3 的 Pygame 模块创建视频游戏的系列文章的第十部分。以前的文章有:通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程使用 Python 和 Pygame 模块构建一个游戏框架如何在你的 Python 游戏中添加一个玩家用 Pygame 使你的游戏角色移动起来如何向你的 Python 游戏中添加一个敌人在 Pygame 游戏中放置平台在你的 Python 游戏中模拟引力为你的 Python 平台类游戏添加跳跃功能使你的 Python 游戏玩家能够向前和向后跑如果你已经阅读了本系列的前几篇文章，那么你已经了解了编写游戏的所有基础知识。现在你可以在这些基础上，创造一个全功能的游戏。当你第一次学习时，遵循本系列代码示例，这样的“用例”是有帮助的，但是，用例也会约束你。现在是时候运用你学到的知识，以新的方式应用它们了。如果说，说起来容易做起来难，这篇文章展示了一个如何将你已经了解的内容用于新目的的例子中。具体来说，就是它涵盖了如何使用你以前的课程中已经了解到的来实现奖励系统。在大多数电子游戏中，你有机会在游戏世界中获得“奖励”或收集到宝物和其他物品。奖励通常会增加你的分数或者你的生命值，或者为你的下一次任务提供信息。游戏中包含的奖励类似于编程平台。像平台一样，奖励没有用户控制，随着游戏世界的滚动进行，并且必须检查与玩家的碰撞。创建奖励函数奖励和平台非常相似，你甚至不需要一个奖励的类。你可以重用 Platform 类，并将结果称为“奖励”。由于奖励类型和位置可能因关卡不同而不同，如果你还没有，请在你的 Level 中创建一个名为 loot 的新函数。因为奖励物品不是平台，你也必须创建一个新的 loot_list 组，然后添加奖励物品。与平台、地面和敌人一样，该组用于检查玩家碰撞: def loot(lvl,lloc): if lvl == 1: loot_list = pygame.sprite.Group() loot = Platform(300,ty*7,tx,ty, 'loot_1.png') loot_list.add(loot) if lvl == 2: print(lvl) return loot_list你可以随意添加任意数量的奖励对象；记住把每一个都加到你的奖励清单上。Platform 类的参数是奖励图标的 X 位置、Y 位置、宽度和高度（通常让你的奖励精灵保持和所有其他方块一样的大小最为简单），以及你想要用作的奖励的图片。奖励的放置可以和贴图平台一样复杂，所以使用创建关卡时需要的关卡设计文档。在脚本的设置部分调用新的奖励函数。在下面的代码中，前三行是上下文，所以只需添加第四行:enemy_list = Level.bad( 1, eloc ) ground_list = Level.ground( 1,gloc,tx,ty ) plat_list = Level.platform( 1,tx,ty ) loot_list = Level.loot(1,tx,ty)正如你现在所知道的，除非你把它包含在你的主循环中，否则奖励不会被显示到屏幕上。将下面代码示例的最后一行添加到循环中: enemy_list.draw(world) ground_list.draw(world) plat_list.draw(world) loot_list.draw(world)启动你的游戏看看会发生什么。你的奖励将会显示出来，但是当你的玩家碰到它们时，它们不会做任何事情，当你的玩家经过它们时，它们也不会滚动。接下来解决这些问题。滚动奖励像平台一样，当玩家在游戏世界中移动时，奖励必须滚动。逻辑与平台滚动相同。要向前滚动奖励物品，添加最后两行: for e in enemy_list: e.rect.x -= scroll for l in loot_list: l.rect.x -= scroll要向后滚动，请添加最后两行： for e in enemy_list: e.rect.x += scroll for l in loot_list: l.rect.x += scroll再次启动你的游戏，看看你的奖励物品现在表现得像在游戏世界里一样了，而不是仅仅画在上面。检测碰撞就像平台和敌人一样，你可以检查奖励物品和玩家之间的碰撞。逻辑与其他碰撞相同，除了撞击不会（必然）影响重力或生命值。取而代之的是，命中会导致奖励物品会消失并增加玩家的分数。当你的玩家触摸到一个奖励对象时，你可以从 loot_list 中移除该对象。这意味着当你的主循环在 loot_list 中重绘所有奖励物品时，…

使你的 Python 游戏玩家能够向前和向后跑
type: item
date: 2020-01-26T06:07:00+08:00
description: 使用 Pygame 模块来使你的 Python 平台开启侧滚效果，来让你的玩家自由奔跑。这是仍在进行中的关于使用 Pygame 模块来在 Python 3 中在创建电脑游戏的第九部分。先前的文章是：通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程使用 Python 和 Pygame 模块构建一个游戏框架如何在你的 Python 游戏中添加一个玩家用 Pygame 使你的游戏角色移动起来如何向你的 Python 游戏中添加一个敌人在 Pygame 游戏中放置平台在你的 Python 游戏中模拟引力为你的 Python 平台类游戏添加跳跃功能在这一系列关于使用 Pygame 模块来在 Python 3 中创建电脑游戏的先前文章中，你已经设计了你的关卡设计布局，但是你的关卡的一些部分可能已近超出你的屏幕的可视区域。在平台类游戏中，这个问题的普遍解决方案是，像术语“ 侧滚 side-scroller ”表明的一样，滚动。滚动的关键是当玩家精灵接近屏的幕边缘时，使在玩家精灵周围的平台移动。这样给予一种错觉，屏幕是一个在游戏世界中穿梭追拍的摄像机。这个滚动技巧需要两个在屏幕边缘的绝对区域，在绝对区域内的点处，在世界滚动期间，你的化身静止不动。在侧滚动条中放置卷轴如果你希望你的玩家能够后退，你需要一个触发点来向前和向后。这两个点仅仅是两个变量。设置它们各个距各个屏幕边缘大约 100 或 200 像素。在你的设置部分中创建变量。在下面的代码中，前两行用于上下文说明，所以仅需要添加这行后的代码：player_list.add(player) steps = 10 forwardX = 600 backwardX = 230在主循环中，查看你的玩家精灵是否在 forwardx 或 backwardx 滚动点处。如果是这样，向左或向右移动使用的平台，取决于世界是向前或向后移动。在下面的代码中，代码的最后三行仅供你参考： # scroll the world forward if player.rect.x >= forwardx: scroll = player.rect.x - forwardx player.rect.x = forwardx for p in plat_list: p.rect.x -= scroll # scroll the world backward if player.rect.x <= backwardx: scroll = backwardx - player.rect.x player.rect.x = backwardx for p in plat_list: p.rect.x += scroll ## scrolling code above world.blit(backdrop, backdropbox) player.gravity() # check gravity player.update()启动你的游戏，并尝试它。滚动像预期的一样工作，但是你可能注意到一个发生的小问题，当你滚动你的玩家和非玩家精灵周围的世界时：敌人精灵不随同世界滚动。除非你要你的敌人精灵要无休止地追逐你的玩家，你需要修改敌人代码，以便当你的玩家快速撤退时，敌人被留在后面。敌人卷轴在你的主循环中，你必须对卷轴平台为你的敌人的位置的应用相同的规则。因为你的游戏世界将（很可能）有不止一个敌人在其中，该规则应该被应用于你的敌人列表，而不是一个单独的敌人精灵。这是分组类似元素到列表中的优点之一。前两行用于上下文注释，所以只需添加这两行后面的代码到你的主循环中： # scroll the world forward if player.rect.x >= forwardx: scroll = player.rect.x - forwardx player.rect.x = forwardx for p in plat_list: p.rect.x -= scroll for e in enemy_list: e.rect.x -= scroll来滚向另一个方向： # scroll the world backward if player.rect.x <= backwardx: scroll = backwardx - player.rect.x player.rect.x = backwardx for p in plat_list: p.rect.x += scroll for e in enemy_list: e.rect.x += scroll再次启动游戏，看看发生什么。这里是到目前为止你已经为这个 Python 平台所写所有的代码：#!/usr/bin/env python3 # draw a world # add …

为你的 Python 平台类游戏添加跳跃功能
type: item
date: 2020-01-17T05:49:55+08:00
description: 在本期使用 Python Pygame 模块编写视频游戏中，学会如何使用跳跃来对抗重力。在本系列的 前一篇文章 中，你已经模拟了重力。但现在，你需要赋予你的角色跳跃的能力来对抗重力。跳跃是对重力作用的暂时延缓。在这一小段时间里，你是向上跳，而不是被重力拉着向下落。但你一旦到达了跳跃的最高点，重力就会重新发挥作用，将你拉回地面。在代码中，这种变化被表示为变量。首先，你需要为玩家精灵建立一个变量，使得 Python 能够跟踪该精灵是否正在跳跃中。一旦玩家精灵开始跳跃，他就会再次受到重力的作用，并被拉回最近的物体。设置跳跃状态变量你需要为你的 Player 类添加两个新变量：一个是为了跟踪你的角色是否正在跳跃中，可通过你的玩家精灵是否站在坚实的地面来确定一个是为了将玩家带回地面将如下两个变量添加到你的 Player 类中。在下方的代码中，注释前的部分用于提示上下文，因此只需要添加最后两行： self.movex = 0 self.movey = 0 self.frame = 0 self.health = 10 # 此处是重力相关变量 self.collide_delta = 0 self.jump_delta = 6第一个变量 collide_delta 被设为 0 是因为在正常状态下，玩家精灵没有处在跳跃中的状态。另一个变量 jump_delta 被设为 6，是为了防止精灵在第一次进入游戏世界时就发生反弹（实际上就是跳跃）。当你完成了本篇文章的示例，尝试把该变量设为 0 看看会发生什么。跳跃中的碰撞如果你是跳到一个蹦床上，那你的跳跃一定非常优美。但是如果你是跳向一面墙会发生什么呢？（千万不要去尝试！）不管你的起跳多么令人印象深刻，当你撞到比你更大更硬的物体时，你都会立马停下。（LCTT 译注：原理参考动量守恒定律）为了在你的视频游戏中模拟这一点，你需要在你的玩家精灵与地面等东西发生碰撞时，将 self.collide_delta 变量设为 0。如果你的 self.collide_delta 不是 0 而是其它的什么值，那么你的玩家就会发生跳跃，并且当你的玩家与墙或者地面发生碰撞时无法跳跃。在你的 Player 类的 update 方法中，将地面碰撞相关代码块修改为如下所示： ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False) for g in ground_hit_list: self.movey = 0 self.rect.y = worldy-ty-ty self.collide_delta = 0 # 停止跳跃 if self.rect.y > g.rect.y: self.health -=1 print(self.health)这段代码块检查了地面精灵和玩家精灵之间发生的碰撞。当发生碰撞时，它会将玩家 Y 方向的坐标值设置为游戏窗口的高度减去一个瓷砖的高度再减去另一个瓷砖的高度。以此保证了玩家精灵是站在地面上，而不是嵌在地面里。同时它也将 self.collide_delta 设为 0，使得程序能够知道玩家未处在跳跃中。除此之外，它将 self.movey 设为 0，使得程序能够知道玩家当前未受到重力的牵引作用（这是游戏物理引擎的奇怪之处，一旦玩家落地，也就没有必要继续将玩家拉向地面）。此处 if 语句用来检测玩家是否已经落到地面之下，如果是，那就扣除一点生命值作为惩罚。此处假定了你希望当你的玩家落到地图之外时失去生命值。这个设定不是必需的，它只是平台类游戏的一种惯例。更有可能的是，你希望这个事件能够触发另一些事件，或者说是一种能够让你的现实世界玩家沉迷于让精灵掉到屏幕之外的东西。一种简单的恢复方式是在玩家精灵掉落到地图之外时，将 self.rect.y 重新设置为 0，这样它就会在地图上方重新生成，并落到坚实的地面上。撞向地面模拟的重力使你玩家的 Y 坐标不断增大（LCTT 译注：此处原文中为 0，但在 Pygame 中越靠下方 Y 坐标应越大）。要实现跳跃，完成如下代码使你的玩家精灵离开地面，飞向空中。在你的 Player 类的 update 方法中，添加如下代码来暂时延缓重力的作用： if self.collide_delta < 6 and self.jump_delta < 6: self.jump_delta = 6*2 self.movey -= 33 # 跳跃的高度 self.collide_delta += 6 self.jump_delta += 6根据此代码所示，跳跃使玩家精灵向空中移动了 33 个像素。此处是负 33 是因为在 Pygame 中，越小的数代表距离屏幕顶端越近。不过此事件视条件而定，只有当 …

在你的 Python 游戏中模拟引力
type: item
date: 2020-01-14T06:39:00+08:00
description: 学习如何使用 Python 的 Pygame 模块编程电脑游戏，并开始操作引力。真实的世界充满了运动和生活。物理学使得真实的生活如此忙碌和动态。物理学是物质在空间中运动的方式。既然一个电脑游戏世界没有物质，它也就没有物理学规律，使用游戏程序员不得不模拟物理学。从大多数电脑游戏来说，这里基本上仅有两个方面的物理学是重要的：引力和碰撞。当你添加一个敌人到你的游戏中时，你实现了一些碰撞检测，但是这篇文章要添加更多的东西，因为引力需要碰撞检测。想想为什么引力可能涉及碰撞。如果你不能想到任何原因，不要担心 —— 它会随着你开发示例代码工作而且显然。在真实世界中的引力是有质量的物体来相互吸引的倾向性。物体（质量）越大，它施加越大的引力作用。在电脑游戏物理学中，你不必创建质量足够大的物体来证明引力的正确；你可以在电脑游戏世界本身中仅编程一个物体落向假设的最大的对象的倾向。添加一个引力函数记住你的玩家已经有了一个决定动作的属性。使用这个属性来将玩家精灵拉向屏幕底部。在 Pygame 中，较高的数字更接近屏幕的底部边缘。在真实的世界中，引力影响一切。然而，在平台游戏中，引力是有选择性的 —— 如果你添加引力到你的整个游戏世界，你的所有平台都将掉到地上。反之，你可以仅添加引力到你的玩家和敌人精灵中。首先，在你的 Player 类中添加一个 gravity 函数： def gravity(self): self.movey += 3.2 # 玩家掉落的多快这是一个简单的函数。首先，不管你的玩家是否想运动，你设置你的玩家垂直运动。也就是说，你已经编程你的玩家总是在下降。这基本上就是引力。为使引力函数生效，你必须在你的主循环中调用它。这样，当每一个处理循环时，Python 都应用下落运动到你的玩家。在这代码中，添加第一行到你的循环中： player.gravity() # 检查引力 player.update()启动你的游戏来看看会发生什么。要注意，因为它发生的很快：你是玩家从天空上下落，马上掉出了你的游戏屏幕。你的引力模拟是工作的，但是，也许太好了。作为一次试验，尝试更改你玩家下落的速度。给引力添加一个地板你的游戏没有办法发现你的角色掉落出世界的问题。在一些游戏中，如果一个玩家掉落出世界，该精灵被删除，并在某个新的位置重生。在另一些游戏中，玩家会丢失分数或一条生命。当一个玩家掉落出世界时，不管你想发生什么，你必须能够侦测出玩家何时消失在屏幕外。在 Python 中，要检查一个条件，你可以使用一个 if 语句。你必需查看你玩家是否正在掉落，以及你的玩家掉落的程度。如果你的玩家掉落到屏幕的底部，那么你可以做一些事情。简化一下，设置玩家精灵的位置为底部边缘上方 20 像素。使你的 gravity 函数看起来像这样： def gravity(self): self.movey += 3.2 # 玩家掉落的多快 if self.rect.y > worldy and self.movey >= 0: self.movey = 0 self.rect.y = worldy-ty然后，启动你的游戏。你的精灵仍然下落，但是它停在屏幕的底部。不过，你也许不能看到你在地面层之上的精灵。一个简单的解决方法是，在精灵碰撞游戏世界的底部后，通过添加另一个 -ty 到它的新 Y 位置，从而使你的精灵弹跳到更高处： def gravity(self): self.movey += 3.2 # 玩家掉落的多快 if self.rect.y > worldy and self.movey >= 0: self.movey = 0 self.rect.y = worldy-ty-ty现在你的玩家在屏幕底部弹跳，恰好在你地面精灵上面。你的玩家真正需要的是反抗引力的方法。引力问题是，你不能反抗它，除非你有一些东西来推开引力作用。因此，在接下来的文章中，你将添加地面和平台碰撞以及跳跃能力。在这期间，尝试应用引力到敌人精灵。到目前为止，这里是全部的代码：#!/usr/bin/env python3 # draw a world # add a player and player control # add player movement # add enemy and basic collision # add platform # add gravity # GNU All-Permissive License # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # …

在 Pygame 游戏中放置平台
type: item
date: 2019-05-27T04:36:59+08:00
description: 在这个从零构建一个 Python 游戏系列的第六部分中，为你的角色创建一些平台来旅行。这是仍在进行中的关于使用 Pygame 模块来在 Python 3 中创建电脑游戏的系列文章的第六部分。先前的文章是：通过构建一个简单的掷骰子游戏去学习怎么用 Python 编程使用 Python 和 Pygame 模块构建一个游戏框架如何在你的 Python 游戏中添加一个玩家用 Pygame 使你的游戏角色移动起来如何向你的 Python 游戏中添加一个敌人一个平台类游戏需要平台。在 Pygame 中，平台本身也是个妖精，正像你那个可玩的妖精。这一点是重要的，因为有个是对象的平台，可以使你的玩家妖精更容易与之互动。创建平台有两个主要步骤。首先，你必须给该对象编写代码，然后，你必须映射出你希望该对象出现的位置。编码平台对象要构建一个平台对象，你要创建一个名为 Platform 的类。它是一个妖精，正像你的 Player 妖精 一样，带有很多相同的属性。你的 Platform 类需要知道很多平台类型的信息，它应该出现在游戏世界的哪里、它应该包含的什么图片等等。这其中很多信息可能还尚不存在，这要看你为你的游戏计划了多少，但是没有关系。正如直到移动你的游戏角色那篇文章结束时，你都没有告诉你的玩家妖精移动速度有多快，你不必事先告诉 Platform 每一件事。在这系列中你所写的脚本的开头附近，创建一个新的类。在这个代码示例中前三行是用于说明上下文，因此在注释的下面添加代码：import pygame import sys import os ## 新代码如下： class Platform(pygame.sprite.Sprite): # x location, y location, img width, img height, img file def __init__(self,xloc,yloc,imgw,imgh,img): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(os.path.join('images',img)).convert() self.image.convert_alpha() self.image.set_colorkey(ALPHA) self.rect = self.image.get_rect() self.rect.y = yloc self.rect.x = xloc当被调用时，这个类在某个 X 和 Y 位置上创建一个屏上对象，具有某种宽度和高度，并使用某种图像作为纹理。这与如何在屏上绘制出玩家或敌人非常类似。平台的类型下一步是绘制出你的平台需要出现的地方。瓷砖方式实现平台类游戏世界有几种不同的方法。在最初的横向滚轴游戏中，例如，马里奥超级兄弟和刺猬索尼克，这个技巧是使用“瓷砖”方式，也就是说有几个代表地面和各种平台的块，并且这些块被重复使用来制作一个关卡。你只能有 8 或 12 种不同的块，你可以将它们排列在屏幕上来创建地面、浮动的平台，以及你游戏中需要的一切其它的事物。有人发现这是制作游戏最容易的方法了，因为你只需要制作（或下载）一小组关卡素材就能创建很多不同的关卡。然而，这里的代码需要一点数学知识。SuperTux ，一个基于瓷砖的电脑游戏。手工绘制方式另一种方法是将每个素材作为一个整体图像。如果你喜欢为游戏世界创建素材，那你会在用图形应用程序构建游戏世界的每个部分上花费很多时间。这种方法不需要太多的数学知识，因为所有的平台都是整体的、完整的对象，你只需要告诉 Python 将它们放在屏幕上的什么位置。每种方法都有优势和劣势，并且根据于你选择使用的方式，代码稍有不同。我将覆盖这两方面，所以你可以在你的工程中使用一种或另一种，甚至两者的混合。关卡绘制总的来说，绘制你的游戏世界是关卡设计和游戏编程中的一个重要的部分。这需要数学知识，但是没有什么太难的，而且 Python 擅长数学，它会有所帮助。你也许发现先在纸张上设计是有用的。拿一张表格纸，并绘制一个方框来代表你的游戏窗体。在方框中绘制平台，并标记其每一个平台的 X 和 Y 坐标，以及它的宽度和高度。在方框中的实际位置没有必要是精确的，你只要保持数字合理即可。譬如，假设你的屏幕是 720 像素宽，那么你不能在一个屏幕上放 8 块 100 像素的平台。当然，不是你游戏中的所有平台都必须容纳在一个屏幕大小的方框里，因为你的游戏将随着你的玩家行走而滚动。所以，可以继续绘制你的游戏世界到第一屏幕的右侧，直到关卡结束。如果你更喜欢精确一点，你可以使用方格纸。当设计一个瓷砖类的游戏时，这是特别有用的，因为每个方格可以代表一个瓷砖。一个关卡地图示例。坐标系你可能已经在学校中学习过笛…

如何向你的 Python 游戏中添加一个敌人
type: item
date: 2019-05-22T03:16:23+08:00
description: 在本系列的第五部分，学习如何增加一个坏蛋与你的好人战斗。在本系列的前几篇文章中（参见 第一部分、第二部分、第三部分 以及 第四部分)，你已经学习了如何使用 Pygame 和 Python 在一个空白的视频游戏世界中生成一个可玩的角色。但没有恶棍，英雄又将如何？如果你没有敌人，那将会是一个非常无聊的游戏。所以在此篇文章中，你将为你的游戏添加一个敌人并构建一个用于创建关卡的框架。在对玩家妖精实现全部功能之前，就来实现一个敌人似乎就很奇怪。但你已经学到了很多东西，创造恶棍与与创造玩家妖精非常相似。所以放轻松，使用你已经掌握的知识，看看能挑起怎样一些麻烦。针对本次训练，你能够从 Open Game Art 下载一些预创建的素材。此处是我使用的一些素材：印加花砖（LCTT 译注：游戏中使用的花砖贴图）一些侵略者妖精、角色、物体以及特效创造敌方妖精是的，不管你意识到与否，你其实已经知道如何去实现敌人。这个过程与创造一个玩家妖精非常相似：创建一个类用于敌人生成创建 update 方法使得敌人能够检测碰撞创建 move 方法使得敌人能够四处游荡从类入手。从概念上看，它与你的 Player 类大体相同。你设置一张或者一组图片，然后设置妖精的初始位置。在继续下一步之前，确保你有一张你的敌人的图像，即使只是一张临时图像。将图像放在你的游戏项目的 images 目录（你放置你的玩家图像的相同目录）。如果所有的活物都拥有动画，那么游戏看起来会好得多。为敌方妖精设置动画与为玩家妖精设置动画具有相同的方式。但现在，为了保持简单，我们使用一个没有动画的妖精。在你代码 objects 节的顶部，使用以下代码创建一个叫做 Enemy 的类：class Enemy(pygame.sprite.Sprite): ''' 生成一个敌人 ''' def __init__(self,x,y,img): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(os.path.join('images',img)) self.image.convert_alpha() self.image.set_colorkey(ALPHA) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y如果你想让你的敌人动起来，使用让你的玩家拥有动画的 相同方式。生成一个敌人你能够通过告诉类，妖精应使用哪张图像，应出现在世界上的什么地方，来生成不只一个敌人。这意味着，你能够使用相同的敌人类，在游戏世界的任意地方生成任意数量的敌方妖精。你需要做的仅仅是调用这个类，并告诉它应使用哪张图像，以及你期望生成点的 X 和 Y 坐标。再次，这从原则上与生成一个玩家精灵相似。在你脚本的 setup 节添加如下代码：enemy = Enemy(20,200,'yeti.png') # 生成敌人 enemy_list = pygame.sprite.Group() # 创建敌人组 enemy_list.add(enemy) # 将敌人加入敌人组在示例代码中，X 坐标为 20，Y 坐标为 200。你可能需要根据你的敌方妖精的大小，来调整这些数字，但尽量生成在一个范围内，使得你的玩家妖精能够碰到它。Yeti.png 是用于敌人的图像。接下来，将敌人组的所有敌人绘制在屏幕上。现在，你只有一个敌人，如果你想要更多你可以稍后添加。一但你将一个敌人加入敌人组，它就会在主循环中被绘制在屏幕上。中间这一行是你需要添加的新行： player_list.draw(world) enemy_list.draw(world) # 刷新敌人 pygame.display.flip()启动你的游戏，你的敌人会出现在游戏世界中你选择的 X 和 Y 坐标处。关卡一你的游戏仍处在襁褓期，但你可能想要为它添加另一个关卡。为你的程序做好未来规划非常重要，因为随着你学会更多的编程技巧，你的程序也会随之成长。即使你现在仍没有一个完整的关卡，你也应该按照假设会有很多关卡来编程。思考一下“关卡”是什么。你如何知道你是在游戏中的一个特定关卡中呢？你可以把关卡想成一系列项目的集合。就像你刚刚创建的这个平台中，一个关卡，包含了平台、敌人放置、战利品等的一个特定排列。你可以创建一个类，用来在你的玩家附近创建关卡。最终，当你创建了一个以上的关卡，你就可以在你的玩家达到特定目标时，使用这个类生成下一个关卡。将你写的用于生成敌人及其群组的代码，移动到一个每次生成新关卡时都会被调用的新函数中。你需要做一些修改，使得每次你创建新关卡时，你都能够创建一些敌人。class Level(): def bad(lvl,eloc): …