字数 24601,阅读大约需 124 分钟
小游戏开发之乐
原文:Joys of Small Game Development[1] by ABA Games 许可协议:CC BY 4.0[2]引言
游戏开发是一片展现创造力的沃土。尤其是小游戏,制作简单、即玩即乐,让人能够迅速沉浸于其中。本文旨在深入探讨制作小游戏的乐趣。
在《制作小游戏本身就是一种乐趣》一节中,将探讨什么是小游戏以及为什么制作它们令人愉快。开发小游戏不仅仅是通往更大项目的练兵场,它本身就具有独特的魅力。
当你着手制作一款小游戏时,选择使用哪种编程语言或游戏引擎是第一道门槛。在《目标设备与开发环境》一节中,我汇总了相关的信息。
构思核心创意是小游戏创作中的关键。《如何为小游戏想点子》一节提供了头脑风暴的技巧。此外,在《约束:激发创意与完成游戏的催化剂》中,讨论了通过对游戏输入方式或分辨率施加约束来催生更好创意的方法。
在小游戏中,随着游戏推进逐渐提升难度是常见做法。《小游戏中什么才是合适的难度》探讨了如何设置让玩家感到适度挑战的难度水平。
没有调味料的游戏是索然无味的。在《让游戏"多汁"》中,围绕"juicy"(多汁)这一概念,介绍了通过添加效果和音效来丰富游戏的方法。
在《打造自己的游戏开发工具》中,叙述延伸到在制作游戏的同时创建自定义库或游戏引擎。虽然为游戏打造工具非常有趣,但这也是一把双刃剑——陷得太深可能会阻碍游戏的完成。
为了快速制作小游戏,有一种自动生成图形和声音的方法。《通过自动化提升开发效率》介绍了让计算机生成像素画、背景音乐、音效和关卡的方式。
如果计算机能够创作游戏,将进一步减轻人类的负担。《小游戏能否自我生成?》探讨了计算机从零开始开发游戏的可能性,重点关注 AI 聊天机器人的应用。
我在本文中编织了关于小游戏开发的诸多话题。通过这些叙述,希望读者能感受到小游戏开发的魅力,也希望这能成为更多人拿起挑战创造之笔的契机。
- • 许可协议:CC BY 4.0[2]
- • 仓库:joys-of-small-game-development-en[3]
- • 本文首页:Introduction - Joys of Small Game Development[1]
- • 作者主页:ABA Games[4]
制作小游戏本身就是一件令人愉悦的事情。那么,什么是小游戏呢?根据"小游戏宣言"(Small Games Manifesto)[^1],它指的是在 10 分钟内即可完成、并且可以在浏览器中轻松游玩的游戏。
按照这个定义,我已经创作了超过 350 款小游戏。[^2] 其中有一年我制作了 139 款小游戏,[^3] 可见我对小游戏的热爱毋庸置疑。
举个例子,一款让你把红色棍子切成等份的简单游戏,就是小游戏的典型代表(点击下图可直接在浏览器中游玩)。
TIMBER TEST [5]
另一个例子是一款通过点击来剪断绳子的游戏,需要确保绳子不碰到屏幕底部——这也是一款小游戏,在智能手机等触屏设备上游玩体验极佳。
C NODES [6]
小游戏吸引人的魅力在于它们所需的开发时间极短。一款游戏大约可以在 2 小时内快速完成,即使遇到困难,10 小时左右也差不多了。不过,一旦开始深入美术资源的制作,时间投入就可能变得没有尽头。本文所讨论的小游戏,是在"一周一游戏"(Game A Week)[^4] 等活动框架下制作的游戏,开发者的目标是每周制作一款新游戏。这些游戏从开发者的角度来看也是"小型"的,因为它们的开发时间非常有限。
开发时间短意味着你可以轻松地尝试各种创意。我很享受构思和测试那些不落俗套的游戏。
关于小游戏的普遍说法是,制作它们是开发更大、更精致游戏的重要准备步骤。许多文章极力建议初学者从小游戏开始。
一篇题为"Make and release lots of small games before making a big one"(先做很多小游戏再做大的)[^5] 的博客文章强调了在进行大型项目之前这种实践的重要性。
之所以这样说,是因为直接跳到大型游戏作为你的"第一个"游戏,恰恰是让你丧失动力、永远无法完成它的原因,或者最终得到的成果吞噬了你好几年的生命,而你甚至无法忍受再看到它。
但故事并没有到此为止。小游戏拥有它们独有的、无法被替代的魅力。这是我深信不疑的。
有一篇题为"How To Make Good Small Games"(如何制作优秀的小游戏)[^6] 的博客文章,阐述了优秀的小游戏确实存在,并详细说明了如何制作它们。
这份类似宣言的文档"How To Make Good Small Games"(如何制作优秀的小游戏),试图与这种观点寻求一个折中。它分为十二条思考,主要由一些深邃的创作理论组成(为什么我喜欢小游戏?为什么我喜欢制作小游戏?),同时也希望提供一些切实可行的建议。我可以告诉你"把范围缩小 uwu",但如果你根本不相信小游戏也能做到优秀,那你听到的只不过是在制作你真正在意的游戏之前不得不完成的作业。
这 12 条思考涵盖以下内容:
- 1. 游戏的品质与其规模无关。小游戏不仅容易制作,也容易做好。游戏越大,需要关注的方面就越多,失败的概率也越高。
- 2. 游戏的品质与其情感范围无关。正如短篇小说与长篇小说或史诗的功能不同,构成"成功"的条件在小规模游戏中也各不相同。
- 3. 游戏定义了自身成功的标准。接受它们本来的样子,再评判它是好是坏。
- 4. 游戏在兑现承诺时就是成功的。引入新角色或新机制就是一种承诺。与其引入一个有趣的创意然后迅速抛弃,不如确保它不断进化,并为游戏的整体进程做出贡献。
- 5. 游戏做出更小的承诺,就更容易成功。减少机制、敌人、资源、角色和关卡。引入 3 个创意并将它们发展到令人满意的高潮,比同时应对 10 个或 100 个创意要容易得多。
- 6. 以有趣且令人愉悦的方式兑现承诺。什么能让你微笑?这就是你的个人风格在制作一款真正属于"你"的游戏时闪耀的地方。
- 7. 不要过度兑现你的承诺。游戏应该在恰当的时刻结束,而不是不必要地拖长。
- 8. 形式也是游戏承诺的一部分。尽量减少向玩家呈现的信息,确保玩家在游戏启动后就能立即开始游玩,从而改变玩家的预期。
- 9. 在发布前完成你的游戏。在以"Demo"(演示版)的标签发布或添加"Prologue"(序章)副标题之前,先问问自己为什么要在完成之前发布它。
- 10. 系列化不是捷径。将游戏分成两集或更多,在较长时间内陆续发布,几乎总是一个坏主意。
- 11. 不要担心能不能爆红。在游戏中追求小而具体的目标,吸引的也是小而特定的受众。
- 12. 够好就是好。一旦你能持续创作出令自己满意、感觉确实不错的游戏,你就已经领先于许许多多的游戏开发者了。
此外,该文章还提出了第 13 条思考:"Have fun :)"(享受其中)。构思新的机制,并以体现你个人风格的方式将其融入游戏。我认为这个过程本身就是令人愉悦的,如果能有一定数量的人体验并享受我创作的成果,那就更令人欣慰了。
制作小游戏通常在磨练游戏开发技能的语境下被讨论。然而,头脑风暴各种游戏创意、不断实验、在兴奋与沮丧间坐过山车、偶尔向他人展示你的作品——这个过程本身就很快乐,这也是一段宝贵的体验。
小游戏应在 10 分钟或更短时间内完成,最好能在网络浏览器中游玩。目标设备与开发环境
当你考虑制作一款小游戏时,首先需要思考的问题之一就是游戏将运行在什么设备上——PC、智能手机还是游戏主机。
如果你没有特别的偏好,推荐为 PC 网页浏览器制作游戏。现代浏览器已经成熟为能够运行在各种开发环境下开发的游戏的平台。而且让别人游玩你的游戏也很方便——只需发布一个 URL 就能实现无缝的游戏体验。
对于享受游戏制作过程的人来说,开发环境、编程语言和游戏引擎的选择可以源于个人喜好。这与游戏的规模并没有太大关系,选择你喜欢的就好。不过,如果你的目标是小型 2D 游戏,像 Unreal Engine [^7] 这样的引擎可能有些大材小用了。
为浏览器制作游戏时,有各种开发选项可供选择:
- JavaScript
在浏览器中运行的游戏是用 JavaScript 编写的,这使得它成为游戏开发的自然之选。利用 p5.js [^8] 或 Phaser [^9] 等库可以简化渲染等繁琐任务。使用 p5.js,初学者可以立即通过学习内容 [^10] 或参考文档 [^11],在网页编辑器 [^12] 中跟着操作。
- 幻想主机(Fantasy Consoles)
幻想主机是轻量级游戏引擎,集成了游戏执行和开发环境,包括角色、关卡和声音编辑器。代表性的有 PICO-8、[^13] Pyxel、[^14] 和 TIC-80。[^15] 这些一体化环境有意限制了功能,非常适合小游戏项目。它们支持不同的编程语言,找到适合你偏好的即可。如果你想尝试 PICO-8,可以参考手册 [^16] 或 API 参考 [^17],同时使用教育版。[^18]
- 游戏引擎
许多游戏引擎如 Unity、[^19] GameMaker、[^20] 和 Godot [^21] 支持将游戏导出为浏览器(HTML5)格式,使在浏览器上游玩所创建的游戏变得轻而易举。它们提供全面的资源管理功能,并且不仅能将游戏发布在浏览器上,还可以发布在 PC 和移动平台上,这是显著的优势。
- 制作工具(Maker Tools)
如果你想制作 RPG 或视觉小说,有专门的类型化工具可用。例如 RPG Maker MV [^22] 在这个类别中一直很受欢迎,这类工具传统上被称为"Maker"(制作工具)。除了 RPG Maker 之外,还有用于 RPG 的 WOLF RPG Editor [^23] 以及用于视觉小说的 TyranoBuilder Visual Novel Studio。[^24] 许多近年的制作工具都包含了浏览器导出功能。
- 可视化编程语言
对于不习惯基于文本编程的人,可以使用 Scratch [^25] 或 MakeCode [^26] 等可视化编程语言。虽然制作复杂游戏可能有些困难,但它们内置了预制好的图形和声音,适合小型项目。
- 其他编程语言
现代浏览器可以通过 WebAssembly [^27] 等技术运行 JavaScript 以外的语言。不过编译过程可能比较复杂,所以如果可以的话,利用幻想主机或游戏引擎会更方便。例如,用 Pyxel 来写 Python,或用 Unity 来写 C#。
为浏览器制作游戏时,确保你的游戏支持触摸操作(或 PC 上的鼠标操作),这样就能兼容移动设备。如果你想触达更广泛的受众,这一点值得考虑。
从游戏制作体验本身获得的乐趣并不一定需要面向浏览器的方法。为 PC 或移动设备制作应用,或者使用 SmileBASIC 4 [^28] 在 Switch 上创作游戏,也是不错的选择。用 MakeCode 制作的游戏可以在你喜欢的掌机上玩,[^29] 有些人甚至在上面运行 PICO-8 游戏。[^30]
创作的动力不必仅仅来源于"让更多人方便游玩"的愿望——对某个特定设备的兴趣本身也可以成为动力。让我们自由地创作吧。
如何为小游戏想点子
为小游戏构思创意既是有趣的,也是充满挑战的。现在我准备好制作一款小游戏了,但问题是:我应该做什么类型的游戏?
构思阶段令人兴奋,但也需要付出相当的努力。一个好的创意能推动制作顺利前进,而一个平庸的创意则可能让道路坎坷不平。不过,对于小游戏来说,如果一个想法行不通,直接丢掉就好了。
网上有许多关于游戏创意生成的文章,粗略搜索一下,找到一种适合你的方法即可。例如,我在 Reddit 的 r/gamedev 上一个题为"How do you guys come up with ideas for your games?"(你们怎么想出游戏点子的?)[^31] 的帖子中找到了一种很有说服力的方法。
- 1. 从你最喜欢的现有游戏中汲取灵感。
- 2. 将看似不搭的元素组合在一起,比如卡牌游戏 + 钓鱼、塔防 + Minecraft,或者 Pac-Man 变成 FPS。
- 3. 分析其他游戏,思考它们的开发过程。如果是你,你会怎么做得不同?
- 4. 将你的创意缩小到一个切实可行的子集。聚焦在"你想做的"和"你能做的"的交集上。
- 5. 拥抱限制。从你的创意中剥离各种复杂性,在过程中创造新的东西。
组合、提炼和增强现有游戏的元素来创造新事物——这个经过验证的过程对于小游戏尤其有用,它通过将元素极致简化来帮助打造具有引人入胜核心机制的游戏。
GameMaker 网站上一篇题为"14 WAYS TO GENERATE S-TIER VIDEO GAME IDEAS"(14 种产生顶级游戏创意的方法)[^32] 的文章也提供了有见地的建议。提取与小游戏相关的要点如下:
- • 游玩过去的传奇游戏。例如,当你玩 Super Mario Brothers 时,你正在体验一款为所有未来 2D 平台游戏奠定基础的游戏。你会如何为新玩家扩展和现代化这个基础?
- • 从零开始凭空构想一个游戏概念是困难的。先选择一个类型,围绕它构建你的创意。
- • 如果执着于某个类型很困难,就聚焦于一个角色。利用角色的特征来展开围绕他们的世界。
- • 使用思维导图记录创意。从游戏的核心方面(如类型或主角)出发,记下相关的关键词和想法,探索玩法机制、功能、故事主题和美术风格。
- • 灵感可能在意想不到的时刻闪现。手边备一个记事本,全天随时记录涌现的想法。
- • 对现有游戏运用 SCAMPER 方法,思考哪些方面可以替换、组合、添加、修改、消除或重新排列,或者某个方面能否用于其他用途或反转。
- • 将目光转向其他媒体。电视、电影、音乐、书籍、传统艺术——它们都能点燃游戏创意。
- • 从现实世界中汲取灵感。现实世界充满了值得用于游戏开发的惊人概念。
- • 利用你自己的经历。你以一种独特的方式看到了这个世界——无论正面还是负面——这些经历可以成为绝佳游戏创意的基础,展开只有你才能讲述的故事。
- • 使用随机显示游戏类型、规则和主题的游戏创意生成器。
- • 参加有主题的游戏 Jam。它们是有设定主题和严格截止日期的短期游戏开发比赛,能磨练你的专注力并激发创造力。
- • 深入游戏社区,直接询问玩家。浏览帖子、提出问题,了解玩家想要什么、喜欢什么、不喜欢什么。
这是一份涵盖了激发创意的技巧和日常习惯的全面清单。虽然小游戏可能不需要如此大量的努力,但在构思时记住这些方法会有所帮助。
让我分享一些我个人在创意生成方面采用的方法。
在我大量制作小游戏的那段时期,我在博客上写了一些方法,取材自受欢迎游戏的特点和我在构思方面的经验。这些方法包括:
- • 高效地从现有游戏中借鉴主题和规则,不仅限于电子游戏,还可以考虑传统体育运动。
- • 从复古游戏中获取灵感,将复古游戏的一部分重新打造成独立的游戏。
- • 融入连锁反应和重力等经典机制。
- • 以收集和击败对象所获得的高分作为享受游戏的基础。
- • 将自然现象或几何学中的有趣行为进行转译。
- • 将物理行为与控制联系起来以产生乐趣。
- • 在视觉上标示成功的操作,以增强成就感。
- • 基于限制(如单按钮控制)设计互动方式。
- • 始终考虑风险与回报之间的平衡。
- • 风险驱动的开发:从向玩家呈现的风险角度来思考新的机制。
- • 平衡爽快感与紧张感。
- • 寻找提升游戏节奏的规则。
- • 呈现游戏设定或背景故事,将游戏与叙事联系起来。
- • 通过去除让玩家困惑的新奇元素来使游戏更易上手。
我创造了一个类似老虎机的工具术语,用于随机输出游戏创作的主题——游戏创意生成器。[^33] 虽然它是获取构思起点的不错工具,但对于小游戏来说,它的建议往往过于模糊。因此,我制作了一个专门针对小型动作游戏的游戏创意生成器。[^34] 它会输出诸如"deflect missiles"(偏转导弹)、"roofs fighting"(屋顶战斗)或"enlarge electricity"(放大电力)等天马行空的创意,当这些创意被开发成游戏时,可能会产生创新性的成果。
头脑风暴游戏创意有各种技巧,利用前人的智慧可以加速这个过程。然而,最好的方法是创造性地思考和大量地创作。幸运的是,对于小游戏来说,构思和实现创意都可以迅速完成。如果一个想法失败了,直接丢掉就好。以这种轻松的心态,何不试一试呢?
解构与组装游戏机制
构思游戏创意的一种方式是理解先前创作的游戏背后的机制。分析这些机制如何为玩家提供乐趣和挑战,可以提供一种系统化的方法。通过组合这些机制,可以创造出新的游戏。
例如,我对迄今为止制作的游戏进行了解构。我整理了每款游戏由玩家角色、武器、障碍物、场地、规则和控制组成的方式,并用标签进行了分类 [^35](点击图片进入首页)。
按下每个标签的"Detail"(详情)按钮后,可以查看该标签的说明以及带有该标签的游戏列表。
标签对应各种机制,例如:
- • 玩家角色旋转 [^36]:配合旋转时机进行操作。
- • 武器沿抛物线飞行 [^37]:投掷方式、投掷物和落地效果各有变化。
- • 混入带有惩罚的物品 [^38]:不能盲目持续攻击,需要仔细观察屏幕状况来把握攻击时机。
- • 一维场地 [^39]:游戏画面可以用一个维度来表示,角色只能左右(或上下)移动。
- • 邻近奖励 [^40]:通过在障碍物附近放置奖励分数,实现风险与回报的基本形式。
- • 按钮按下时属性反转 [^41]:通过设计属性可以实现各种特殊行为。
这些页面的使用方式如下:
- • 查看标签列表页面,了解可以整合到动作小游戏中的机制。
- • 查看标签详情页面,考虑使用该机制的其他游戏。
- • 任意组合多个标签,构思使用这些机制的游戏概念。
这类游戏机制通常被称为游戏机制(game mechanics)。[^42] 游戏机制指的是玩家在游戏中可以执行的有序动作,以及这些动作所触发的事件。游戏机制被用来分析游戏的设计方式,或在构思新游戏时作为辅助。玩法通常被描述为游戏机制之间的流转,[^43] 基于这些机制,可以通过思考如何挑战玩家来塑造游戏体验。
识别游戏机制的粒度水平似乎没有特定的标准。虽然回合制、资源管理和风险与回报等抽象元素可以列为机制,但更精细的游戏内动作——如跳跃、格挡、旋转和强化——也可以列为机制。
这一次,为了辅助构思新的动作小游戏,整理工作聚焦于更精细的游戏内动作。重点是查看每个机制的实际示例,了解它们如何与其他机制组合,以及识别向玩家提供的风险(挑战)和奖励。展示了这些机制的游戏已可查看和游玩。
通过使用自制游戏作为整理的示例,内容不可否认地偏向于动作小游戏,尤其是单按钮游戏,但这种展示方式为头脑风暴游戏创意提供了一个范例。
约束:创造力与游戏完成的催化剂
产生创意的一种方法是事先对自己施加某些约束。通过思考如何在这些约束下使游戏变得有趣,可以预期产生与以往不同的创意。此外,思考如何利用这些约束还能增强创意的独特性。
可以设想什么样的约束呢?例如 Game Jam 等游戏开发比赛中的格式、规则和主题。在许多 Game Jam 中,会对可提交的游戏设置一些约束,鼓励参与者在这些约束下集中精力创作游戏。
在视频"Different Game Jam Formats"[^44] 中,列举了以下类型的约束:
- 工具:指定可使用的游戏引擎。
- 素材:预先提供可在游戏中使用的图片等素材。
- 画面:限制分辨率和颜色数量。
- 目标:定义游戏的目标,例如"收集更多物品"。
- 交互:限制玩家与游戏交互的方式,例如"只能使用两个按钮"。
- 类型:指定类型,如"平台跳跃"或"Roguelike"。
- 时间限制:在规定时间内完成游戏。
为了激发创意,关于交互、画面和目标的约束可能较为有益。
关于交互,常见的约束包括限制可用按钮数量、仅使用鼠标、使用整个键盘或双摇杆输入。当可用按钮数量受限时,需要仔细考虑为每个按钮分配什么操作。例如,将使用传统方向键加两个按钮的游戏转换为单按钮游戏,就面临一个棘手的难题,而在构思强制解决方案的过程中,有可能催生全新的创意。
画面约束主要只影响外观,不影响游戏规则。然而,在极端约束的情况下,例如极低的 16x16 像素数,或本质上只允许一条垂直线的一维空间,就需要创造性的方案来克服这些约束。过去甚至有只允许 1x1 像素、两色显示作为输出的 Game Jam。[^45]
关于目标,仅仅设置平凡的目标并不能引导创意探索。通过设计具有不寻常目标的游戏,如"摧毁自身"、"做出牺牲"或"利用敌人获胜",可以构想出全新的游戏体验。有趣的是,这些独特的目标正是由 Game Jam Theme Generator 生成的。[^46] 该生成器不仅限于目标,还能输出各种 Game Jam 主题,可用作辅助头脑风暴的创意生成器。
工具、素材、类型和时间限制更多是关于在有限时间内完成游戏,而非创意生成。通过不花时间选择工具和素材,专注于在时间限制内创作指定类型的游戏,这种标准化方法有助于快速完成游戏创作。
如果你有志于创作大量游戏,为创作过程建立自己的一套规则和规范是明智的策略。标准化创作内容和创作方式,以最大限度地减少开发中的工作量。[^47]
在游戏开发中施加一些约束可以帮助产生新创意或快速完成游戏。过于严格的约束会使克服它们变得困难,因此建议找到并有效利用适合自己感觉的约束。
单按钮游戏的可能性
在 Game Jam 中,有一种将交互限制为仅一个按钮的设置,即创建所谓的单按钮游戏。
不同于除了一个按钮外还有摇杆用于移动的情况,这里的"单按钮游戏"指的是所有游戏交互都仅使用一个按钮。
单按钮游戏的优势在于操作简单,在触摸设备上容易操作。本质上,按下按钮即可执行玩家的所有可用操作,几乎不需要操作说明。此外,在触摸设备上,只需在屏幕任意位置点击或长按即可进行控制,避免了其他游戏中虚拟方向键不灵敏的常见问题。
缺点自然是难以引入操作变化。即使是用摇杆就能轻松实现的简单横向移动,也需要采用非常规的操作方式,例如每次按下按钮时反转方向。
因此,开发单按钮游戏时的关键问题是:如何仅用一个按钮在游戏交互中引入变化。在这方面,我想根据独特的机制对我迄今为止创建的一些单按钮游戏进行分类。
融入独特操作
通常,在单按钮游戏中,玩家按下按钮后执行以下操作:
- • 反转移动方向,或旋转 90 度。
- • 跳跃或扇翅。
- • 射击。
例如,在我制作的游戏 THUNDER 中(点击图片可玩),即使只有两个方向的移动,也可以通过巧妙利用障碍物和奖励物品来制作单按钮游戏。但它缺乏单按钮游戏独有的特色。
THUNDER [8]
如果按下按钮触发的操作在传统游戏中很少见,就能强烈地给玩家留下单按钮操控方案的独特印象。
瞬移
屏幕上预设若干点,按下按钮后瞬移到最近的点。这一机制使仅用一个按钮即可实现快速移动。
分裂
每次按下按钮使导弹分裂。持续按住按钮可增强攻击力,但需要设置约束,例如引入不应被击中的目标,以防止无脑疯狂按键。
选择
在某些节点,玩家选择转向或跳到另一个平台等操作。关键是让玩家清楚地理解选择的时机及其后果,这需要精心设计游戏场地的布局和呈现方式。
属性反转
每次按下按钮,磁极等属性就会切换。游戏设计的关键在于决定使用哪些属性以及它们如何与环境交互。
其他特殊机制
适时投放移动平台和梯子,类似于单按钮的方块下落游戏。
NUMBER LINE [14]
将流动的数字相加,这是一个相当奇特的例子,说明分配给按钮的操作可以非常多样。
利用按住按钮的操作
单按钮游戏通常在按下按钮时触发操作,但也可以在按住按钮期间持续产生操作。
调整角度或距离
在高尔夫游戏中很常见,按住按钮时角度逐渐增加,玩家必须在恰当时机松开按钮击球。在这个游戏中,当球上的数字与地板上的数字匹配时地板会消失,这是一个与传统高尔夫不同的奇特规则。
FROOOOG [16]
青蛙的跳跃距离取决于按住按钮的时长;这是解决如何用一个按钮将玩家从一个位置移动到多个位置的方案。
伸展
按住按钮时棍子伸展,松开时收缩。伸展的棍子可以钩住物体,配合特定地形特征帮助推进。
SQUARE BAR [18]
与几何形状结合时,即使仅仅是伸展也能产生复杂的运动。
TAPE J [19]
伸展越长得分越高,但风险也越大,创造了平衡的风险-回报情境。
防御 / 闪避
按住按钮时,玩家对子弹无敌。但如果一直不动会被坦克碾压,所以需要引诱坦克靠近,松开按钮纵向闪避,观看坦克互相战斗。
REFLECTOR [21]
防御墙始终在下方提供保护,反射敌人火力,但按住按钮可以发动强力反击,代价是防御墙缩小。
BAMBOO [22]
按下按钮可以让玩家穿过竹子,并通过在竹子之间弹跳快速切割竹子。
其他特殊机制
蓄力能量,管理蓄力量对游戏体验至关重要。
LASER FORTRESS [24]
扫射,射击的超级强化版。混合敌我单位确保过于强大的攻击可能适得其反。
SHINY [25]
晴天或雨天,雨天加速人类移动,使其更快地撤离到右端。这种奇特的机制似乎不容易移植到其他游戏中。
组合多种操作
组合上述操作是经典的方法。
SCRAMBIRD [26]
扇翅 + 射击,
TILTED [27]
多次跳跃 + 反转方向,
UP SHOT [28]
射击 + 停止。
此外,一个操作可以在游戏中产生多种效果。
BOMB UP [29]
例如,用按钮投放/引爆炸弹,爆炸同时将玩家弹射出去。通过调整爆炸和玩家的位置可以控制玩家移动。这种方法可以用一个按钮实现相当复杂的操作,但过于复杂会导致操作困难,因此适度是关键。
结合旋转运动
类似于角度调整,但这里玩家或炮台始终在旋转,把握跳跃或射击的时机至关重要。
ORBIT MAN [30]
跳跃方向不断旋转,玩家必须精确把握朝向星星跳跃的时机。
ARCFIRE [31]
炮台旋转时,玩家必须精确把握面向敌人时的射击时机。这款游戏允许通过按住按钮调整射程和攻击范围,以及射击方向的微小提前量,实现一个按钮的多种操作。
利用地形
如果输入变化难以实现,根据玩家所在的地形改变玩家操作是一个可行的解决方案。
TURBULENT [32]
即使是跳跃这样简单的操作,将跳跃地形变为波涛汹涌的海面,就能根据时机改变跳跃方向。
SUB JUMP [33]
将屏幕分为水下和水上,按下按钮在水下时上升,在水上时跳跃,根据地形赋予按钮多种功能。
利用道具
除了地形,利用道具是另一种方法。拾取道具会改变某种模式,选择拾取或忽略道具替代了输入的多样性。
MIRROR FLOOR [34]
金币切换重力方向;玩家必须观察下一个平台的位置来决定是否收集金币,这会影响跳上下一个平台的能力。
LIFT UP [35]
收集道具改变移动方向。需要在收集金币的同时巧妙收集反转道具,避免碰到左右两边的尖刺。
REBIRTH [36]
被卡车撞到会将玩家传送到反转世界。卡车是否算作道具可以商榷,但玩家需要根据下一个钻石的位置决定是否要被撞。
R WHEEL [37]
收集道具向下发射激光,摧毁尖刺障碍。这款游戏在跳跃时也会向下发射激光,尖刺会回旋到玩家身边,跳跃时出现道具。跳跃动作在这款游戏中触发了多个事件。
结论
与认为单按钮游戏无法提供太多操作变化的假设相反,这里列举的例子证明可以创建种类繁多的游戏类型。通过发挥单按钮游戏的潜力,我期待在未来开发更多样的游戏。
虽然单按钮游戏的简洁性是优势,但也带来了意想不到的陷阱。例如,游戏可能无意中演变成重复的疯狂按键或持续按住按钮的模式,玩家可以获得无限分数。因此,必须测试这些重复游玩模式,以确保游戏体验平衡且引人入胜。
最后,重要的是要记住,作为单按钮游戏和作为有趣的游戏是两回事。因此,确保游戏有趣、有畅快感和紧张感、风险与回报平衡等愉快游戏体验的各方面至关重要。然后再考虑如何将那种乐趣融入单按钮游戏的格式中。
在有限大小约束下创作游戏
Game Jam 经常对游戏二进制文件或源代码的大小施加约束。著名的例子包括 js13kGames[^48],它挑战参与者在 13 千字节内创建浏览器游戏。
使用短代码实现多样化表达的尝试跨越许多领域,不仅限于游戏。例如,使用 ggplot2[^49],可以在 280 个字符内创建精美的几何图案。[^50] 此外,在 140 个字符[^51]内使用 SuperCollider[^52] 和在 Dwitter[^53] 等平台上使用 JavaScript 创建的音乐和生成艺术合集。
紧凑编码作品的精髓在于密集打包信息的美感。它们体现了用最少组件实现最大效果的巧思。
在 Dwitter 上,用户不仅分享图形和音乐,还分享游戏。例如,游戏 Crossy Tortoise[^54] 涉及引导乌龟穿越马路,展示了在 140 个字符内实现的单按钮游戏。但它缺少计分系统,一旦完成穿越游戏就结束了。
要称得上是游戏,以下要素是理想的:
- • 具有计分系统。
- • 有游戏结束条件。
- • 难度递增。
- • 最好有音效。
考虑到包含这些要素,我们来思考短代码的合理规则:
- • 编写每帧更新的 JavaScript 函数,最大长度 256 个字符。
- • 引入 p5.js[^55]、Tone.js[^56] 和 lodash.range[^57] 等库,提供适合游戏的便捷函数。
- • 为
p5.mouseIsPressedp5.mouseXp5.mouseYp5.random()Tone.synth.triggerAttackRelease()_.range()分别赋予MXYRNA等单字符别名,以便在更少的字符内调用函数。 - • 变量
S代表分数,显示在顶部;变量T代表游戏开始以来的帧计数,用于难度调整。
按照这些规则创建了几个示例游戏[^58](点击图片可玩)。
其中一个游戏 springcar,涉及一辆点击后跳跃的汽车。代码如下:
clear(),
T || ((s = A(9).map((i) => [10 * i])), (y = v = 0)),
(d = 1 + T / 999),
s.map((u) => text("", (u[0] = u[0] < 99 ? u[0] + d : -R(30)), 80)),
(y += v += (M ? 0.1 : 0.2) * d),
get(74, y)[3] + get(82, y)[3] > 0 && ((v = -1), (y = 72), S++, N(333, 0.1)),
y > 70 && v < 1 && M && ((v = -3), N(444, 0.2)),
y > 95 && ((S = y = T = 0), N(222, 0.5)),
text("", 75, y);按照这些规则,创建一个游戏仍然是可行的。还有在更严格的规则下创建的 Pong,例如不允许添加库,整个 HTML 包含在 226 字节内。[^59] 你可以在 codegolf JS[^60] 中看到更多类似的优秀代码。
按照这些规则,大约一小时内制作一个基本游戏是可行的。然而,256 个字符的约束很严格,尝试实现复杂的动作很快就会超出字符限制。当你精心制作了一个约 270 个字符的游戏时,尽管使用了巧妙的技巧,但为了满足限制而缩减就必须要缩小游戏系统,这令人沮丧。然而,没有 256 个字符的约束,就有无限添加效果和调整游戏平衡的可能。因此,即使令人沮丧,放弃这些额外的部分也是挑战的一部分。
有限大小游戏开发能够快速产出的特性很有趣。在如此有限的大小内就能制作游戏这一事实,意味着规则和机制被极大地精简。这样的约束能产生有趣的游戏,是优秀创意的宝库。
然而,自我施加的大小约束往往更多是束缚而非有助于提前完成,因此建议只有那些觉得克服大小约束有趣的人才去尝试。存在大量用于大小压缩的库和技术。[^61] 你可以参考这些来判断自己是否有兴趣,根据你是否觉得这个概念有趣来确认自己的天赋。
小游戏中什么构成适当的难度
太难的游戏会令人沮丧,太简单的游戏则令人无聊。适当的难度是好游戏不可或缺的要素;然而达到正确的平衡可能颇具挑战。所需的难度水平因游戏类型而异——从 Soul-like 游戏中无情的挑战和反复重试,到轻松易通的三消益智游戏。游戏类型极大地影响了所需的难度水平。
正如 Mihaly Csikszentmihalyi 的心流模型中所提到的,提供与个人技能水平相对应的挑战可以提高参与度和沉浸感。[^62]
在 Mihaly Csikszentmihalyi 的心流模型中,实现技能与挑战之间的平衡是关键。小游戏中维持这种平衡的常用方法是随着时间推移逐步提高难度。难度水平,即挑战水平,持续上升直到匹配玩家的技能水平,一旦超越该水平,任何失误都会导致"游戏结束"。
如果提高难度的方法和节奏得当,这种方法可以很好地创造有趣的游戏。什么被认为是正确的方法呢?当难度增加且玩家犯错时,如果玩家认为是由于自己技能不足,那么难度水平就被认为是适当的。相反,如果游戏变得不公平地困难,例如玩家面临不可避免的攻击,那么难度水平就被认为是不适当的。
调整难度常用的参数是游戏速度。随着游戏进行,游戏速度加快,玩家和敌人的速度都增加。这要求玩家更快速地反应,任何误操作都会导致"游戏结束"。这种自 Game & Watch[^63] 时代——指任天堂早期掌上游戏时期——就使用的传统难度调整方法至今仍然有效。使用游戏速度调整难度的一个好处是,它最大限度地减少了变得不公平的可能性。当游戏速度变化时,敌人和玩家的速度按比例增加,避免了早期可以躲避的敌人在后期变得无法躲避的情况。
然而,仅依靠游戏速度来调整难度可能会变得单调。在这种情况下,增加敌人数量或扩大障碍物等方法可以用来提高挑战。因此,进行调整以确保不会出现诸如障碍物变得大到玩家跳跃能力无法躲避而导致不公平的情况,这是至关重要的。
通过组合各种难度调整方法,游戏变得更加复杂,玩家也不容易失去兴趣。理想情况下,引入要求玩家高级技巧的新元素,如新敌人、武器、地形、道具等,可以增强游戏体验。然而,在小游戏中实现成本较高,这可能是一项具有挑战性的任务。
上升的难度曲线
适当的难度提升意味着什么,应该以什么节奏进行?这在很大程度上取决于你希望玩家在游戏中投入多长时间。例如,假设一款游戏应持续 3 分钟,你将难度设计为在从初始翻倍时大多数玩家淘汰,可以考虑以下公式来计算难度:
[难度] = sqrt([已过帧数] * 0.0001) + 1这里,"帧"是时间单位,代表游戏中 1/60 秒。已过帧数每秒 60,每分钟 3600。sqrt指平方根。不使难度与帧数线性成正比,而是使用sqrt函数确保在经过一定时间后难度上升更为平缓。将 3 分钟的帧数 10800 代入上述公式,得到的难度为 2.04,与初始假设一致。
然而,这个难度设置可能并不适合所有小游戏。在某些情况下,更快地提升难度可以创造更紧张、更引人入胜的体验。
不将难度提升应用到游戏中并观察结果,很难判断什么样的难度提升是适当的。因此,我将难度随时间上升的情况可视化为曲线,准备了调整该曲线的 UI,并将其反映到示例游戏中(点击图片前往演示页面)。
在 diff-tween 页面中,在右侧 UI 上调整难度曲线,然后点击左侧游戏画面即可开始一款躲避落石的游戏。初始曲线设置旨在让人清楚理解难度提升,30 秒内难度翻倍。
每条难度曲线由其公式(sqrt、linear、pow)和提升速率(climb)定义,并可以调整为锯齿波(saw),即以固定间隔降低难度。锯齿波是引入难度变化的好方法,这一技术也用于 Game & Watch。此外,还可以调整多个参数,如落石速度和大小。
当有多个参数受难度影响时,调优变得更加困难。玩过游戏后会发现,虽然玩家可以通过技能应对更快的落石,但一旦石头达到一定大小就无法应对了。更快的落石也许还能设法躲避,但更大的石头给人一种不可避免、不公平的印象。
因此,可以使用 sqrt 函数来提升石头大小以减轻不公平感,同时使用线性增加来从游戏开始就维持落石速度的紧张感,偶尔用锯齿波来缓和节奏。
此外,这种调整确实有缺点——初始难度可能让人觉得太简单、太无聊。在这种情况下,引入诸如靠近石头通过时获得奖励分数等机制,鼓励玩家冒着风险换取奖励,从游戏早期阶段就提供紧张感。
基于关卡的难度设定
到目前为止,讨论主要围绕没有关卡(舞台、回合)概念的游戏展开。但是,当考虑由多个关卡组成、每个关卡各有难度设定的游戏时,可以有哪些难度配置方式呢?
随着关卡推进,游戏必须逐渐变得更具挑战性,否则就会缺乏紧张感。然而,仅仅是线性增加难度可能导致缺乏变化。如何设计一种随着关卡推进越来越难、同时又有足够波动的关卡设计呢?下面以使用以下图表的方法为例进行说明。
横轴表示从random函数获取的 0 到 1 之间的随机值。纵轴表示难度,0 为最简单,1 为最具挑战性。在开始一个关卡之前,从random函数获取一个值作为横轴值,对应的难度即作为该关卡的难度等级。
该图表中的难度通过以下公式计算:
pow(random(), 100 / ([current level number] + 1))在早期关卡中,关卡数较低时,难度倾向于停留在低端,随着关卡数增加,难度向上扩展。因此,更高的关卡倾向于拥有更高的难度设定,尽管偶尔由于random函数的返回值,某个关卡可能会明显比其关卡号所暗示的更容易或更难。
这种难度也可以应用于多个参数,例如:
- • 敌人数量
- • 敌人射击频率
- • 子弹速度
通过对上述公式分别设定每个参数的难度并使用随机函数,可以实现更复杂的变化组合。在某些关卡中可能有很多敌人但它们不常射击,或者可能只有一个敌人但它射出极快的子弹,等等。
在游戏的后期关卡中,所有参数都趋向于难度 1,导致一系列普遍高难度的关卡。但由于难度本身被限制在 1,与单纯线性增加难度相比,这种设定可以实现某种约束。
这种方法也有缺点。最终所有参数都会固定在难度 1,无法创造无限增加难度的关卡。在难度封顶为 1 的状态下设定合适的难度是一项挑战。
即使采用其他方法,确保难度增加不单调也是至关重要的。通过改变玩家所体验的紧张感,可以实现更令人愉快的游戏进程。
让游戏变得"多汁"
仅仅依靠核心规则、最少的视觉效果和没有声音就能令人满意的游戏,是极为罕见的共识。除了基本规则之外,游戏还需要对玩家感官的刺激,如视觉和听觉效果,以及增强体验的演出效果。
游戏开发者将这些元素被恰当运用的游戏称为"多汁"(juicy)游戏。通过让一个简单的打砖块游戏变得"多汁",很容易看出同样的规则如何让游戏变得更加有趣。这一概念在一些视频中有很好的说明,它们展示了如何通过添加"汁液"来让游戏变得多汁,[^64] 或者通过演示来展示多汁游戏带来的差异。[^65]
文章《研究:制作一款"多汁"的游戏》[^66] 包含了上述视频的内容,并介绍了让游戏多汁化的方法。其中提出的方法包括:
- • 添加色彩。
- • 利用缓动(tweening)和缓动曲线(easing)实现平滑动画。
- • 根据事件改变或弹跳对象大小。
- • 加入音效和音乐。
- • 用大量粒子显示烟雾、破坏效果或拖尾。
- • 震动画面以传达冲击感。
- • 为对象添加眼睛和微笑,让它们对环境做出反应。眼睛跟踪物体并眨眼,嘴巴表达情感。
- • 让环境跟随音乐节奏做出反应。
- • 在攻击时添加命中停顿或击退等动画。
有效运用这些方法的游戏被称为"多汁"游戏。然而,"多汁"这个术语有些模糊。
文章《"多汁":一个有用的游戏设计术语?》[^67] 探讨了"多汁"所代表的含义,但并未得出一个明确的定义。其中提到了 PopCap[^68] 等公司的休闲多汁游戏,尤其是 Peggle[^69],因其各种赞美玩家的演出效果而备受称赞。简单来说,Peggle 是一款玩家从屏幕顶部发射球并观看球击中钉子的游戏。但每次连击时,一只名叫 Jimmy Lightning 的海狸会用"太酷了!"或"太创新了!"等话语欢呼,保持高昂的氛围。其他演出效果还包括在击中最后一个钉子之前的鼓点和放大特写,成功后会播放贝多芬第九交响曲——真是一款多汁的游戏。
在游戏中加入这样生动的演出效果,即使在简单的游戏中也能大大提升玩家的乐趣。虽然在短开发周期内添加丰富的演出效果可能有挑战,但也有更简单而有效的方法,比如粒子效果或响应式音效来增加多汁感。
虽然与"多汁感"略有不同,但改善游戏的"手感"(feel)[^70] 同样至关重要。通过宽容玩家的小失误并使正确操作更容易执行,可以提供更舒适的游戏体验。
关注核心机制之外的方面,游戏可以进化为对玩家来说更加有趣的体验。
创造你自己的游戏开发工具
让游戏创作更有乐趣的一种方式是开发自己的工具来简化和加速这个过程。这里的"工具"指的是面向游戏的库、像素画绘制工具、音乐作曲工具等等。如果有足够的热情,开发者可以创造各种各样的基础游戏开发工具,包括幻想主机(fantasy consoles)、游戏引擎,甚至编程语言。
尽管已有大量现有工具,创造自己的工具有何意义?一个原因是获得高度熟悉、内部运作完全理解的工具。既然是你自己创建的,自然清楚如何操控它们以获得期望的结果。此外,你还可以自由添加自己喜欢的功能。应用程序编程接口(API)和用户界面(UI)的设计可以根据你的偏好量身定制,从而营造舒适的的开发环境。
此外,工具创建过程本身就带来乐趣。与游戏开发不同——在创作过程中探索最终形态——这些工具有相对明确的目的,在游戏创作过程中可以作为很好的调剂。看到你需要的功能逐步扩展,是很有成就感的。
问题在于这个过程可能变得过于令人愉快。游戏开发者中有一句俗语很好地概括了这个问题:"不要造游戏引擎,去造游戏。"这是对沉迷于创建外围工具、从而忽视游戏本身导致游戏永远完不成的警示。
保持适当的平衡,工具创造可以为游戏开发带来新一层的乐趣。
为小型浏览器游戏创建库
游戏库或游戏引擎应该包含哪些功能?一篇题为《如何制作自己的游戏引擎(以及为什么)》[^71] 的文章列出了以下功能:
- • 基本功能:
- • 系统初始化:准备窗口、启动渲染和音频系统。
- • 帧时序控制:以 1/60 秒间隔定期调用的更新处理。
- • 输入:处理按钮输入等。
- • 渲染:绘制 2D 或 3D 纹理、模型等。
- • 算术工具:向量运算和其他游戏所需的函数。
- • 高级功能:
- • 游戏对象与场景管理:管理多个对象以及在多个场景之间切换。
- • 音频:使用音频框架播放音频。
- • 文件管理:管理文件和资源。
- • 网络:多人游戏的通信功能。
此外还提到了碰撞检测、物理计算、序列化、动画、UI 等,但并非必需。现有的游戏引擎提供了经多年经验支撑的功能集,了解它们的功能在创建自己的游戏库或引擎时会非常有帮助。
该文章还概述了创建自定义游戏引擎时应有的心态:
- • 同时构建引擎和游戏:引擎应该拥有的功能是由你想创建的游戏的需求所支撑的。
- • 不要在需要之前创建功能:避免过度工程化你的游戏不需要的功能。
- • 使用你熟悉的编程语言:构建引擎是一项具有挑战性的任务,不应在学习新编程语言的同时进行。
- • 不要从一开始就寻求正确答案:经过多次构建引擎的经验之后,你最终会创建出一个可用的引擎。
那么,面向小型浏览器游戏的游戏库应该具备哪些功能呢?上面提到的基本功能是必需的,但高级功能可以有限度地实现。此外,如果目标是快速将创意变为现实,专注于实现游戏所需的机制会更好。
基于这些考虑,我创建了一个名为 crisp-game-lib[^72] 的游戏库。该库具有以下特点:
- • 标题、游戏中、游戏结束等场景在库内标准化,无需为每个游戏单独开发。
- • 提供小型游戏特别需要的功能,如高分管理和回放。
- • 对分辨率、颜色和声音施加约束,减少耗时制作丰富表现的需要。
- • 让游戏变得"多汁"变得容易。具体来说,可以轻松添加各种视觉和音效。
在 crisp-game-lib 中,只需编写一个 JavaScript 文件,[^73] 包含游戏的title、description和每秒调用 60 次的update函数,就可以创建在 PC 和移动端都能运行的浏览器游戏。
一个在其他库中找不到的独特功能是,渲染盒子、线条、弧线、文本和角色时,集成了碰撞检测。
ref_collision screenshot [40]
当使用函数绘制一个元素时,返回值会告诉你该元素是否与屏幕上已有的其他形状、文本或角色重叠。只需检查这个值,即使对线条和弧线等复杂形状也能检测碰撞,无需特定的碰撞检测处理。
此外,该库还具有以下让游戏多汁化的功能:
- • 只需选择所需声音名称即可播放的音效。[^74]
- • 将选项 [^75]
isPlayingBgm设为 true 即可自动生成 BGM。 - • 将
isReplayEnabled设为 true 即可启用回放功能。 - • 外观改变功能,如复古 CRT 风格或像素画风格,可通过定义
theme来设定。 - • 像素画可通过
characters数组轻松定义。
创建自己的游戏库,根据自身需求裁剪功能,可以是一种愉快的、更高效开发游戏的方式。思考什么样的功能在你符合你游戏开发风格的库中是理想的,然后尝试创建你自己的原创库。
为 DIY 手持设备开发游戏
最近出现了一种趋势:以 Arduino [^76] 等单板微控制器为核心,加上显示屏和按钮,来创建 DIY 手持游戏机。优点是可以根据自己的喜好创建游戏机。缺点是各种设备层出不穷,没有一款是很多人共同拥有的通用设备。
这些设备的游戏通常用 C 语言编写。因此,配套的库也需要用 C 语言实现。
这次,我将最初为浏览器用 JavaScript(TypeScript)实现的自定义库移植到了 C 语言。我将其命名为 crisp-game-lib-portable。[^77]
PyBadge crisp-game-lib-portable screenshot
用 crisp-game-lib-portable 创建的游戏兼容 M5StickC PLUS [^78] 和 Adafruit PyBadge [^79] 等设备。此外,通过利用 Emscripten,[^80] 现在也可以在浏览器上运行。
库核心 [^81] 和游戏代码 [^82] 被设计为包括浏览器在内的所有设备通用,目标是只需要最少量的设备特定代码。
需要在设备特定代码中编写的处理包括:
- • 设备初始化(如 Arduino 中的
setup()),并从中调用initGame() - • 帧更新处理(如 Arduino 中的
loop()),通过调用setButtonState()通知按钮状态,并调用updateFrame() - • 在
machineDependent.h中定义的绘图和声音相关处理。[^83]
通过这种方式,通用设备所需的设备特定实现大约为 250 行。
在 PyBadge 等设备上适配这些函数可能有些麻烦,因为只能使用analogWrite()调节蜂鸣器音量,需要手动管理声音时序和生成方波。
显示像素画的md_drawCharacter(unsigned char grid[CHARACTER_HEIGHT][CHARACTER_WIDTH][3], float x, float y, int hash)函数也需要一些功夫。最后一个哈希值用于缓存像素画的图案定义,而不是每次都解析并绘制。如果你使用 LovyanGFX 库 [^84] 进行绘图,应该将 LGFX_Sprite 和哈希值作为一对保存,然后取出并执行pushSprite()。
在考虑这种可移植性的同时编写代码是一种有趣的体验,这也是不以库为目标面向各种设备就无法做到的事情。创建独特的游戏库,同时利用 Arduino IDE 等通用开发环境和 Adafruit Arcada [^85] 或 LovyanGFX 等多设备兼容库,提供了独特的体验。与各种微控制器板打交道,相比面向 PC 或智能手机开发库,呈现出另一种不同的乐趣。如果感兴趣,不妨一试。
制作幻想主机
幻想主机 [^86] 体现了开发者一种异想天开的想法:"如果真有这样一台游戏主机就好了。"想象一下不存在的 Game Boy 或 Famicom 版本,在 PC 上实现它们,然后享受成果——这就是幻想主机。
幻想主机的典型代表无疑是 PICO-8。[^87] 128x128 像素的屏幕、四个音轨同时播放、256 个 8x8 像素的精灵图,以及包含 Lua 开发环境、像素画编辑器、音乐编辑器和地图编辑器的丰富内置工具——这是一款极具创新性的技术产品。
虽然名字叫"主机",[^88] 但许多幻想主机在内部集成了完整的开发环境。它们更像 MSX 或 Family BASIC 那样的微型计算机。
制作一台 PICO-8 水平的幻想主机是相当有挑战性的。然而,亲手打造自己幻想主机的愿望确实令人心动。要做到这一点,就必须刻意限制规格。以拥有极小屏幕、简单声音输出和基本输入方式的幻想主机为目标,我创作了 PEEKPOKE。[^89]
PEEKPOKE 可以在 PC 和智能手机浏览器上游玩(点击屏幕即可操作)。
BOMB SNAKE [41]
这是一款贪吃蛇游戏,用方向键(上下左右)或 WASD 键操控蛇去收集红色炸弹。在智能手机上,通过屏幕底部的虚拟方向键来操控。
在 PEEKPOKE 中,机器的控制完全通过 peek 和 poke 命令来读写内存实现。它采用内存映射 I/O [^90] 来操作有限的功能集:32x30 像素 8 色屏幕、8x5 文本屏幕、七个按键输入和一个单音蜂鸣器。没有内置开发环境;游戏可以用 JavaScript 编写脚本。[^91]
通过将所有主机特有功能委托给内存,并将开发环境交给 JavaScript,构建过程大大简化了。能制作的游戏相当基础,但勉强可以称之为一台幻想主机。在启动时添加一个启动画面,就能增添几分幻想主机的韵味。
没有开发环境,制作幻想主机的工作量大幅减少。幻想一台拥有有趣规格的主机并轻松地制作出来,是一件非常愉快的事情。这次制作的主机架构相当简单。不过,考虑设计具有更奇特功能的主机,或者致敬 Cassette Vision、ATARI 2600 等现有主机的设计,也会很有趣。
通过自动化提升开发效率
当想要以更少的精力进行游戏开发时,程序化生成 [^92] ——即通过编程来生成像素画、音效、背景音乐和关卡——是一个强大的工具。虽然生成质量可能不及手工制作的素材,但通过反复迭代生成过程直到获得满意的结果,就能以最小的精力获取必要的游戏素材。此外,通过使用随机关卡生成算法,玩家每次都能享受独特的游戏体验,从而提升游戏的重复游玩价值。
在这里,让我们探讨自动生成角色像素画、背景音乐、音效和益智游戏关卡等元素的方法。
自动像素画生成
被称为自动像素画生成器的工具有多种类型,常见的方法是将大量预设部件进行组合并改变其颜色来创建新的像素画。[^93] 这种方法常用于游戏头像创建,能够生成大量风格一致的角色及其动画。然而,这种方法只能创建特定角色的变体。如果没有与所需角色匹配的生成器,就无法获得想要的像素画。
一种稍微更灵活的方法是在基础像素画上添加随机开关的点,通过这些变化来创建各种图案。[^94] 使用这种方法,通过修改基础像素画,可以适应各种角色的生成。
我也按照随机点变化的方法制作了一个像素画创建库。[^95] 例如,使用这个库创建各种形状的宇宙飞船,结果如下(点击图片可跳转到演示页面)。
pixel-art-gen [42]
这种方法生成的产物随机性很高,擅长创建像宇宙飞船这样自由形态的角色。然而,对于有约束的角色,比如侧面视角下有明确眼睛、手臂和腿的怪物,就显得力不从心了。因此,像素画生成器本身就有固有的优势和劣势,不存在万能的解决方案。
近年来,生成式 AI 已经能够根据提示词创建图像,将此应用于像素画的方法也已出现。[^96] 然而,生成式 AI 擅长创建较大的图像,并不适合创建 16x16 像素这样的小图像。
不过,随着技术的进步,未来也许能够生成像像素画这样的小图像及其动画。例如,向搭载 DALL-E 3 模型的 Bing Image Creator [^97] 提供以下提示词,可以获得可用于射击游戏的宇宙飞船像素画:
创建一张展示一系列复古视频游戏风格宇宙飞船的图像,俯视视角。每艘宇宙飞船应在 32x32 像素网格内设计,使用 16 色调色板。将这些像素化宇宙飞船以视觉上美观的方式排列。
按照提示词在 32x32 像素网格内创建图像的指令尚未被准确执行。不过,这类问题预计会随着未来生成模型的发展而逐步解决。
背景音乐和音效的自动生成
什么样的背景音乐(BGM)适合小游戏?首先想到的是老式街机游戏中的 BGM。所谓"老",指的是 20 世纪 80 年代初期的《Xevious》或《Dig Dug》之类的游戏。那个时代的复古街机游戏通常使用大约 4 到 8 小节的短乐句作为 BGM,不断循环播放。
自动生成此类 BGM 的技术有多种。其中之一是 WolframTones。[^98] 看起来很方便。不过它似乎有一个限制:无法重现老游戏中常见的乐句,比如贝斯线以十六分音符在纯五度间交替。
在最新技术中,有 OpenAI 的 Jukebox;[^99] 但它生成的是音乐波形而非乐谱,因此不适合复古游戏。类似的技术 MusicLM [^100] 有一个 8 位采样,似乎能够创建类似芯片音乐的音轨,但仍然显得过于丰富。
这就引出了 Magenta,[^101] 这是 Google 的一个研究项目,将机器学习应用于音乐和艺术。Magenta.js [^102] 是其在浏览器中运行的实现版本。
Magenta.js 在给定一段乐谱后,利用 MusicRNN [^103] 自动生成后续乐句。如果给它一段复古游戏的短乐谱,它就能产生具有类似风格的另一首曲子。我创建了一个简单的演示程序来测试这一点(点击图片跳转到演示页面)。[^104]
点击屏幕中央的"Generate"按钮后,会基于左侧的乐句生成新的乐句并显示出来,在右侧播放。它生成仅包含旋律和贝斯音轨的简单乐句,但能产生相当有复古游戏音乐韵味的曲调。对于多个音轨,每个乐句分别创建,如果贝斯与旋律不和谐(确保频率比约为 1:4),会进行调整。取消选中中间下方复选框可禁用此调整,从而生成更自由的乐句。
至于音效的自动生成,针对旋律的 MusicRNN 似乎难以胜任。相反,有许多基于波形的解决方案,其中很多基于 sfxr。[^105] 这些工具可以用来为动作游戏添加简单的音效。
益智游戏关卡自动生成
本节将探讨关卡自动生成,换言之就是益智游戏谜面的自动生成。虽然像 Game & Watch 这样的游戏在单一画面上游玩,但许多游戏有多个关卡或随滚动出现的地形,因此需要生成关卡。
关卡制作的质量直接影响游戏体验,尤其是在益智游戏中。特别是在像《推箱子》[^106] 这样的非动作益智游戏中,创建令人享受解谜过程的关卡至关重要。
目前已经存在多种《推箱子》关卡生成器。典型的创建方法包括:
- 1. 创建一个没有放置箱子的空房间。
- 2. 将箱子放置在正确的目标位置。
- 3. 反向模拟游戏来分散箱子。
第三步本质上确保了如果玩家"拉"并移动箱子,箱子确实可以被移动到正确的位置。
一种基于上述方法的生成器实现,[^107] 在玩家卡住时会回溯搜索其他排列方式。关于生成方法的论文 [^108] 引入了诸如玩家沿直线推箱子的次数或去推另一个箱子的次数等指标,旨在创建箱子尽可能远离正确位置的关卡,从而增加玩家需要执行的操作。
还有一篇论文旨在使用被称为 PuzzleScript [^110] 的通用益智游戏创建语言,为任何益智游戏生成关卡。[^109] 通过将 PuzzleScript 规则分析器中的游戏对象特性传递给关卡生成器和评估器来创建关卡。这种方法由评估器判断生成的关卡是否可解、是否有趣,与前述的反向模拟方法不同。
虽然现有方法多种多样,让我们尝试为自己定制的益智游戏进行关卡生成。
我尝试创建了一款名为 slickslack [^111] 的益智游戏,类似于《推箱子》和《Pengo》[^112] 的混合体。游戏目标是将显示为蓝色方块的箱子弹到正确的黄色位置(点击图片游玩)。
slickslack_screenshot [44]
采用的关卡自动生成方法与其他《推箱子》生成器类似,从正确答案反向模拟游戏。不过,并非先创建空房间,而是创建一个全是墙壁的房间,在反向滑箱子的同时挖掘墙壁。
slickslack_screenshot_generating
- 1. 创建一个任意大小的、全部由墙壁组成的房间(或由可以是墙壁或空地的格子组成)。
- 2. 将箱子放置在正确的目标位置。
- 3. 沿任意方向滑动箱子任意距离。
- 4. 在滑动方向的起始位置的对面放置墙壁,确保箱子在那里停下。
- 5. 将滑动过的区域确认为空地(挖掘墙壁)。
执行上述滑动操作任意次数来创建关卡。然而,这样不加考虑地创建关卡并不能保证关卡有趣,所以需要进行一些调整。
由于这个益智游戏没有玩家角色,箱子可以相当自由地滑动。因此,为了营造益智感,需要考虑滑动箱子的顺序、如何通过撞击其他箱子让箱子停在正确位置,以及箱子之间的交互。此外,过多的墙壁会减少游戏约束,降低益智感。考虑到这些,做了以下调整:
- • 优先选择能让箱子被现有墙壁或其他箱子挡住的滑动方向,避免创建新墙壁。
- • 旨在使箱子滑动后与其他箱子相邻。
我还创建了另一款自动生成关卡的益智游戏 HAKOSAN。[^113] 目标是使用方向键同时滑动三个角色到达红色终点(点击图片游玩)。
HAKOSAN [45]
同样,关卡是通过从终点反向滑动角色来生成的。
因此,这种从正确答案反向操作谜题来自动生成问题的方法,在许多场景中都适用。如果加入像 PuzzleScript 论文中提到的评估器,来判断生成关卡的趣味性并进行筛选,可以进一步提升此方法。该论文使用各种指标评估关卡:箱子与正确位置之间的距离、玩家的移动次数、应用规则的次数等。虽然不能确定这些指标是否准确反映了解谜的乐趣,但它们对于过滤掉明显无趣的关卡似乎很有用。在资源充足的情况下,融入此类改进可以实现更好的关卡生成。
小游戏能否自动生成?
我渴望拥有一台能自动生成小游戏的机器。开发者只需游玩这台机器生成的游戏,保留有趣的、丢弃无趣的,仅凭这一过程就能创造出游戏。这简直是一台梦想机器。
前提是人类之后会进行审查和筛选,因此大多数产出不有趣也没关系。更关键的是确保游戏在生成时拥有足够丰富的机制变化。
让 AI 创造游戏的努力已经持续了数年。ANGELINA 项目 [^114] 提出了一种通过随机组合机制来生成新游戏的方法——比如在按下按钮时,将玩家的位置或重力等变量进行翻倍、减半或正负号切换。[^115] 按下按钮后切换变量状态的机制被称为"可切换游戏机制"(Toggleable Game Mechanics, TGM),该研究将其应用于从始至终的跳跃解谜游戏中,旨在探索各种 TGM 的应用方式。
研究采用遗传算法从随机组合中筛选出合适的 TGM 组合。选择的适应度取决于玩家在到达终点前在关卡中移动的范围有多广。
然而,通过这种方法创造的游戏变化范围仍然有限,能否称之为"新游戏"仍是一个模糊地带。发明新游戏对人类来说都很困难,对计算机来说更是巨大的挑战。
最近,有潜力突破这些限制的技术出现了。以 ChatGPT 为代表,这些技术体现在搭载了大型语言模型(LLM)的 AI 聊天机器人中。
用 AI 聊天机器人创造解谜游戏
文章《ChatGPT 发明了自己的解谜游戏》[^116] 讨论了一个场景:让 ChatGPT 设计一种新的逻辑谜题,结果它提出了一个名为 Sumplete 的游戏。在这个游戏中,数字被放置在二维网格上,每行和每列的数字之和分别标注在网格的右侧和底边。玩家通过划掉网格上的数字来匹配给定的总和。
然而,这款游戏实际上早已存在,名为 Summer,[^117] 是为智能手机设计的。无论人类还是 AI 都不可能了解所有已存在的游戏,因此创造出已经存在的游戏是常有的事。保证游戏的全新性是一件困难的事。
尽管如此,让 ChatGPT 参与头脑风暴新的逻辑谜题仍然是一项有趣的尝试。例如,当给出以下任务时,ChatGPT 能够提出多种谜题:
我希望你扮演一名逻辑谜题游戏设计师。设计 5 种全新的逻辑谜题。创建的规则要与现有的逻辑谜题(如数独)不同。谜题应由二维网格构成。部分网格可以被墙壁分隔。单元格的初始状态既包含含有数字或符号的格子,也包含空格子。玩家需要填入空白格并努力找到正确答案。
提示词要求提供五种基于二维网格的逻辑谜题,部分格子含有数字或符号,其余为空。网格可能被墙壁分隔。预计会出现类似 Heyawake [^118] 的谜题建议。
其中一个提案是名为"Magnet Blocks"(磁铁方块)的谜题:
在这个谜题中,网格包含极性相反的磁铁(北极和南极)。玩家必须在网格中填入正极和负极的方块,使每个方块根据极性吸引或排斥相邻的磁铁。只有当方块与周围磁铁兼容时才能放置,且相同极性的方块不能相邻接触。
以磁铁为主题的 Magnet Blocks 提出的规则有些模糊。不过,将其解读为"N 与 N、S 与 S 不能相邻接触"的磁铁游戏后,成功实现了可玩的版本(点击图片即可游玩)。
Magnet Blocks [46]
具体规则如下:
- • 网格初始包含条形磁铁和墙壁。
- • 条形磁铁必须放入空格中,使 N 与 N、S 与 S 不相邻接触。条形磁铁的长度为 3 格或以上。
- • 当所有空格都放有条形磁铁时,谜题通关。
尽管关卡生成逻辑不够出色,导致谜题缺乏深度,但它仍然算得上是一个谜题。
这个谜题真的是全新的吗?存在一款名为 Magnets [^119] 的类似游戏,虽然同样以磁铁为主题,但规则有很大不同:
- • 条形磁铁的放置位置和方向是预先确定的,固定长度为 2。
- • 网格边缘给出了每行和每列中 + 和 - 出现次数的约束条件。
- • 不需要填满所有空格。
到目前为止,尚未发现具有完全相同规则的谜题。然而,不能排除在非磁铁主题的谜题中存在类似规则集的可能性。
逻辑谜题通常有固定的风格范式,是 ChatGPT 围绕其头脑风暴新规则的不错主题。然而,正因为这些固定风格,被认为是"新的"想法很可能与已有游戏不谋而合。
此外,让 ChatGPT 生成足够精确以构成可玩谜题的规则并不容易;这需要人类介入,将模糊的提案精炼为具体的规则。将这些规则转化为可玩的程序代码仍然是一项困难的任务。
判断所创造的谜题是否有趣又是另一个挑战,因为这不仅取决于规则,还取决于关卡生成背后的逻辑。
通过用其他方法、程序或插件来补充 ChatGPT 不擅长的任务(如创建精确规则),AI 聊天机器人的应用范围有望进一步扩大。
教 AI 理解游戏机制
在上一节中,我将动作小游戏的机制以标签的形式列出。[^120] 我们展示了通过随机组合多个标签,可以构思出利用这些机制的游戏。如果把这项任务交给 ChatGPT,或许能够想出新的游戏创意。
我们向 ChatGPT 提供了以下提示词,让它扮演游戏设计师的角色:
我希望你扮演一名游戏设计师。请记住以下与游戏机制相关的标签。标签以"类别: 名称, "描述""的格式书写,每个标签占一行。随机组合这些标签,构思一个仅包含对应游戏机制的新游戏。将该游戏设计为仅需单个按键的动作小游戏。最多可组合 5 个标签。描述这是什么样的游戏以及所选的标签。尽量不重复使用相同的游戏机制标签,尝试构思 5 款不同的游戏。 player: rotate, "玩家角色旋转。" player: reciprocate, "玩家角色水平或垂直往复运动。" player: reflect, "玩家角色在碰到墙壁或物体时反弹。" ...
标签列表及其说明在标签列表文件 [^121] 中继续,完整的提示词包含所有这些标签。[^122]
游戏 1:Scaffold Jump(脚手架跳跃) 所选标签:player: scaffold, on pressed: jump 描述:在这款游戏中,玩家控制一个沿脚手架移动的角色。角色持续向前移动,玩家可以通过按下按钮让角色跳跃。目标是在收集硬币或道具的同时避免从脚手架坠落或撞到障碍物。随着玩家前进,游戏逐渐加速,难度也随之增加。 游戏 2:Pinball Panic(弹球恐慌) 所选标签:player: circle, weapon: bounce, field: pins, on pressed: shoot 描述:在这款游戏中,玩家控制一个在弹球台式场地中弹跳的圆形角色。按下按钮可以发射弹丸,弹丸会在钉子间弹射并消灭敌人。目标是尽可能长时间存活,同时通过消灭敌人和收集道具来获取高分。 游戏 3:Springy Strings(弹力绳) 所选标签:player: string, player: bounce, field: gravity, on pressed: jump 描述:在这款游戏中,玩家控制一个在零重力场中弹跳的弹簧角色。按下按钮可以让角色跳跃,弹得更高。目标是在收集道具和到达关卡终点的同时躲避障碍物和敌人。 游戏 4:Wipeout Warriors(冲刷战士) 所选标签:player: bar, field: water, obstacle: chase, weapon: wipe, on pressed: jump 描述:在这款游戏中,玩家控制一个在水上赛道中竞速的条形角色,赛道上充满了障碍物和敌人。角色自动向前移动,玩家可以通过按下按钮让角色跳跃。角色还可以使用冲刷武器来清除前方的障碍物和敌人。目标是以最短时间到达赛道终点。 游戏 5:Color Conundrum(色彩谜题) 所选标签:rule: match, rule: time limit, field: roughness, on pressed: turn 描述:在这款游戏中,玩家控制一个在崎岖地形中导航的角色,同时需要匹配颜色。角色自动向前移动,玩家可以通过按下按钮来左右转向。目标是在时间耗尽前尽可能多地匹配颜色,同时避开路上的障碍物和敌人。
有了游戏名称、所选标签和游戏描述,就可以挑选有趣的游戏并将其作为游戏创意。
以游戏 2 "Pinball Panic" 为例。在布满钉子和敌人的弹球台式场地中,玩家按下按钮发射弹丸,弹丸在钉子间弹射来消灭敌人。巧妙控制弹射球击中敌人可能很有趣,也许可以加入弹球翻板来发射球。
游戏 3 "Springy Strings" 如何?在无重力空间中,弹簧角色通过弹射障碍物和敌人来导航,或许是通过踢击或挥臂推进。
游戏 5 "Color Conundrum" 设想了一款俯视游戏,玩家角色在崎岖地形中导航,通过按下按钮左右转向来匹配颜色,同时收集同色道具,并避开障碍物和敌人。
如果 ChatGPT 还能实现游戏代码就太方便了,但目前这显然还不可行。虽然当提示"用 p5.js 实现游戏 1"时,它确实会输出一些代码,但无法准确反映游戏机制。
将游戏机制标签教给 ChatGPT 并让其进行组合,可以作为头脑风暴游戏创意基础的一个好方法。ChatGPT 似乎很适合这类头脑风暴应用。
AI 聊天机器人能创造新游戏吗?
搭载大型语言模型(LLM)的 AI 聊天机器人能够生成游戏创意并实现代码。然而,它们的能力仍在发展中,尚不能在没有人类干预的情况下创建平衡性良好的游戏。不过,最近 LLM 性能的提升使它们已经能够处理小游戏开发的许多方面。
GPT-3.5 时代
GPT-4 于 2023 年 3 月 14 日在 ChatGPT 上线,在此之前使用的是 GPT-3.5。虽然 GPT-3.5 在发布时是一款开创性的 LLM,但不可否认,与更新的高性能 LLM 相比,其输出质量有所不足。
使用 GPT-3.5 进行游戏开发面临以下挑战:
- • 难以构思出足够详细、可在算法层面实现的新游戏创意
- • 无法有效实现新算法的源代码
当被要求生成小游戏创意时,GPT-3.5 只会返回模糊的、泛泛的概念,缺乏实现所需的具体性。而且,即使给出了具体的创意,如果需要新算法,它也很难产出合适的代码。因此,将 LLM 作为小游戏生成器来使用面临很大挑战。
Claude 3.5 Sonnet 时代
OpenAI 逐步将 ChatGPT 的模型从 GPT-3.5 更新到 GPT-4 和 GPT-4o,显著提升了性能。OpenAI 的竞争对手 Anthropic 也更新了其 Claude LLM,于 2024 年 6 月 21 日发布了 Claude 3.5 Sonnet。[^123]
伴随 LLM 性能提升的还有将大型参考文档附加到提示词的能力,使 LLM 能够处理各种前置知识。这些在 LLM 性能和功能上的改进在一定程度上帮助克服了上述问题。
LLM 在生成新创意方面越来越强
LLM 性能的提升是否直接关联到创意生成能力的增强尚不清楚。但似乎确实有明显的改善。此外,通过参考文档向 LLM 提供关于创意构思方法和期望创意示例的前置知识也变得更加容易。
当使用 LLM 自动生成一键动作小游戏时,此语境下的"创意"指的是新颖有趣的游戏规则。为此,我向 LLM 提供了以下知识:
- • 生成游戏创意的头脑风暴方法 [^124]
- • 可分配给单个按钮的动作描述 [^125]
- • 现有自创游戏的规则 [^126]
结果,结合 Claude 3.5 Sonnet 的高性能,我们成功提高了生成独特游戏规则的概率。
LLM 可以通过逐步流程实现新算法
如上所述,LLM 已经能够生成合适的游戏规则。下一个挑战是将这些规则转化为正确的代码。
即使对于最新的高性能 LLM,将游戏规则直接转化为代码仍然困难。当从游戏规则开始逐步细化实现方法时,获得正确代码的可能性会提高。因此,我在提示词中指示 LLM 按以下步骤实现游戏:
- 1. 从游戏环境、核心机制、玩家交互和挑战等方面整理游戏规则。
- 2. 详细描述实现所整理游戏规则的游戏对象行为,考虑属性、初始状态、形状、颜色、运动方式和一键操控。
- 3. 给出实现游戏规则和对象的 JavaScript 骨架代码。
- 4. 使用库将骨架代码完善为可玩的游戏。
我还在提示词中提供了使用这些步骤实现自创游戏的示例。这种方法有助于向 LLM 传达我们的期望,进一步改善其输出质量。
LLM 难以调整游戏平衡
高性能 LLM 现在能够以一定的质量创建游戏主题、规则和相应的源代码。但它们仍然难以评估所创建游戏的质量并改进其不足之处。
这里的游戏质量指以下方面:
- • 它能作为一个游戏正常运行吗?是否存在不合理的游戏结束条件或无限循环模式?
- • 它有适当的风险与回报吗?分数和游戏时长是否随着玩家技能提升而增长?
- • 它有趣吗?游戏玩法是否直观并能带来畅快感?
针对这些问题的改进示例可能包括:
- • 规则优化:修改游戏结束条件或得分系统
- • 参数调整:改变速度或玩家角色和敌人出现的频率
- • 操控方式改进:修改操控使其更直观、对玩家压力更小
仅靠 LLM 似乎难以处理这些任务。要评判所创建游戏的质量,计算机需要亲自游玩实现的游戏并分析结果。虽然超出 LLM 范畴的能够玩游戏的 AI 已经存在,但计算机能在多大程度上理解人类诸如"畅快感"这类感受还不得而知。
让计算机改进游戏的弱点似乎非常具有挑战性。如果 AI 能够评判游戏质量,也许可以利用类似强化学习的方式将其作为奖励。然而,AI 能否适当地改进规则和操控方式,或调整游戏中各种各样的参数来提升游戏质量,仍然存疑。
因此,LLM 在小游戏创作中的使用范围似乎最好限制在 LLM 目前擅长做的方面。也就是说,LLM 仅被期望创建游戏创意和生成实现代码。生成的代码和游戏仍然不完美,因此以下任务需要手动完成:
- • 修复代码 bug 和不符合预期的规则
- • 改进规则和代码使游戏可玩
- • 添加考虑风险与回报的游戏结束条件和得分系统
- • 调整规则和参数使游戏更有趣
- • 实现难度递进并调整难度曲线
考虑到这一点,使用 LLM 似乎并没有显著减少工作量。然而,LLM 实现的代码偶尔会产生有趣的行为。因此,它仍然可以作为创建游戏创意基础的"玩具"来使用。
使用 LLM 的"生成重掷游戏开发"
通过这种方式使用 LLM,可以反复生成游戏,直到创建出符合你偏好的游戏,然后手动完善它。让我们将这个过程称为"生成重掷游戏开发"(Generative Reroll Game Development)。
以下是生成重掷游戏开发的一个例子。我们使用 Claude 3.5 Sonnet 作为 LLM,提示词和前置知识存储在仓库中。[^127]
当给定主题"脆弱的柱子"时,提示词建议了以下游戏:
Pillar Paraglider(柱间滑翔):控制一个在脆弱柱子间飞行的滑翔翼。滑翔翼持续下降。按下按钮可以上升,但每次按压也会发出可能损坏附近柱子的冲击波。核心机制:在上升与保护柱子之间取得平衡。
在细化和实现这个创意后,我们创建了游戏。[^128] 这是 Claude 的直接输出。
按下按钮后,红色玩家角色上升,同时发出圆形冲击波。冲击波会摧毁柱子。虽然看起来深受 Flappy Bird 的影响,但实现的行为相当有趣。
然而,这个游戏有几个明显的问题:
- • 太简单了。反复按下按钮可以用冲击波清除柱子。即使玩家角色到达屏幕顶部或底部也不会游戏结束。
- • 得分系统过于简单。分数仅基于飞行距离,因此冒险行为不会带来更高的分数。
- • 没有实现最初的核心机制。本意是在上升与保护柱子之间取得平衡,但没有这样实现。而且,忠实实现这一机制可能会导致冲击波碰撞检测范围过大的压力型游戏。
在生成重掷游戏开发中,关键过程是如何将这些具有有趣行为的游戏改进为真正有趣的游戏。
对于这个游戏,我做了以下改动:
- • 影响所有方向的圆形冲击波太过强大,因此我为玩家角色添加了方向性,将冲击波限制在其前方的一个窄角度内。此外,冲击波现在只摧毁直接命中的柱子部分,而不是整根柱子。我还实现了玩家角色触碰屏幕顶部或底部时的游戏结束条件。
- • 为摧毁柱子的每个部分给予分数。还实现了连续摧毁的分数倍增器,激励玩家冒险飞向柱子以获取更高分数。
- • 我放弃了原来的核心机制。一般来说,关于"破坏"的游戏比关于"避免破坏"的游戏更有趣。
改进后的游戏可以在 [^129] 中看到。
WAVY BIRD 截图
游戏演变为用冲击波在柱子上打洞来前进。虽然可能稍显困难,但它比初始版本实现了更好的风险与回报平衡,成为了一款更完整的游戏。
改进版本与原始代码之间的差异详见 [^130]。虽然看起来原始代码所剩无几,但原始框架为修改提供了有用的参考,比从零开始要轻松得多。
添加了音效和标题的完成版本可在 [^131] 中体验。仓库 [^127] 中包含大量通过类似流程开发的游戏,供参考。
这就是目前使用 LLM 的生成重掷游戏开发的现状。这个过程是否比人类自己构思创意并传统方式实现更容易,还有待讨论。然而,选择 LLM 建议的游戏并想方设法使其变得有趣的开发过程,与传统开发过程相比提供了不同类型的乐趣。在生成重掷游戏开发中,同时享受游戏开发和用于生成的提示词开发/改进的并行过程也很重要。
未来,我们或许只需告诉 LLM "创建一个有趣的游戏",它就能返回一个实现完善的好的游戏。目前,通常需要数十次"重掷"才能获得一个具有有趣行为的游戏,成功率相当低。然而,用以前的 LLM 几乎不可能获得任何有趣的产出,泛泛的、缺乏灵感的游戏是常态。得益于过去一年左右 LLM 的进化,我们现在能够生成至少感觉上有些新意的东西,这是一个积极的信号。
如果 LLM 继续以这种速度进化,创意的质量将会提高,它们也将能更准确地将这些创意实现为代码。而且,当我们指出上述问题时,LLM 也许能够相应地修改代码。这可能导致通过更少的重掷和更简单的改进就能获得可玩的游戏。然而,未来的 LLM 是否会稳步提升性能以达到这些能力,目前尚不确定。截至 2024 年,LLM 性能提升的速率似乎正在放缓。
利用 AI 聊天机器人的游戏开发未来
利用 AI 聊天机器人的游戏开发尚未成为完全自动化的过程,但它蕴含着新的可能性。目前,AI 聊天机器人有能力生成具有有趣行为的"玩具",有效的流程是由人类将这些"玩具"精炼为完整的游戏。
未来,如果 LLM 性能持续提升,有望生成更高质量的游戏创意和代码。然而,游戏平衡调整和趣味性评估等方面——这些创意性工作——在可预见的未来可能仍需人类介入。
"生成重掷游戏开发"提供了一种全新的、与众不同的游戏开发乐趣。基于 LLM 生成的创意和代码来构建游戏,结合人类的创造力,带来了新的发现和惊喜。
随着 LLM 的进化,我们可以期待这些开发方法进一步发展。对于小游戏开发者而言,AI 聊天机器人有望开启创造力的大门。
结语
我们围绕小游戏开发探讨了各种话题,从它带来的乐趣、创作方法,到利用 AI 进行自动生成的潜力。
创建和游玩小游戏都很简单。近年来,随着幻想主机(fantasy console)和游戏引擎的出现,游戏创作的环境变得越来越丰富。面向初学者的教程和文档也非常充足,入门之简单令人惊讶。
游戏创作完成后,将其发布到网上观察反应也是一种乐趣。参加 Game Jam 也很有意思。在这些场合中,分享自己创作的游戏并获取反馈,能够进一步提升你的游戏开发技能。
如果这篇文章激发了哪怕一丝兴趣,我鼓励你跟随突然闪现的灵感,试着做一款简单的游戏。新的发现和乐趣一定在等着你。
引用链接
[1]Joys of Small Game Development: https://abagames.github.io/joys-of-small-game-development-en/
[2]CC BY 4.0: https://creativecommons.org/licenses/by/4.0/deed.en
[3]joys-of-small-game-development-en: https://github.com/abagames/joys-of-small-game-development-en
[4]ABA Games: http://www.asahi-net.or.jp/~cs8k-cyu/
[5]: https://abagames.github.io/crisp-game-lib-11-games/?timbertest
[6]: https://abagames.github.io/crisp-game-lib-games/?cnodes
[7]: https://abagames.github.io/action-mini-game-mechanic-tags/index.html
[8]: https://abagames.github.io/crisp-game-lib-games/?thunder
[9]: https://abagames.github.io/crisp-game-lib-games/?cywall
[10]: https://abagames.github.io/crisp-game-lib-games/?divarr
[11]: https://abagames.github.io/crisp-game-lib-games/?jumpon
[12]: https://abagames.github.io/crisp-game-lib-games/?nsclimb
[13]: https://abagames.github.io/crisp-game-lib-games/?ladderdrop
[14]: https://abagames.github.io/crisp-game-lib-games/?numberline
[15]: https://abagames.github.io/crisp-game-lib-games/?numberball
[16]: https://abagames.github.io/crisp-game-lib-games/?froooog
[17]: https://abagames.github.io/crisp-game-lib-games/?pinclimb
[18]: https://abagames.github.io/crisp-game-lib-games/?squarebar
[19]: https://abagames.github.io/crisp-game-lib-games/?tapej
[20]: https://abagames.github.io/crisp-game-lib-games/?embattled
[21]: https://abagames.github.io/crisp-game-lib-games/?reflector
[22]: https://abagames.github.io/crisp-game-lib-games/?bamboo
[23]: https://abagames.github.io/crisp-game-lib-games/?chargebeam
[24]: https://abagames.github.io/crisp-game-lib-games/?laserfortress
[25]: https://abagames.github.io/crisp-game-lib-games/?shiny
[26]: https://abagames.github.io/crisp-game-lib-games/?scrambird
[27]: https://abagames.github.io/crisp-game-lib-games/?tilted
[28]: https://abagames.github.io/crisp-game-lib-games/?upshot
[29]: https://abagames.github.io/crisp-game-lib-games/?bombup
[30]: https://abagames.github.io/crisp-game-lib-games/?orbitman
[31]: https://abagames.github.io/crisp-game-lib-games/?arcfire
[32]: https://abagames.github.io/crisp-game-lib-games/?turbulent
[33]: https://abagames.github.io/crisp-game-lib-games/?subjump
[34]: https://abagames.github.io/crisp-game-lib-games/?mirrorfloor
[35]: https://abagames.github.io/crisp-game-lib-games/?liftup
[36]: https://abagames.github.io/crisp-game-lib-games/?rebirth
[37]: https://abagames.github.io/crisp-game-lib-games/?rwheel
[38]: https://abagames.github.io/jsgame256/springcar.html
[39]: https://abagames.github.io/diffi-tween/
[40]: https://abagames.github.io/crisp-game-lib-games/?ref_collision
[41]: https://abagames.github.io/peekpoke/bombsnake/
[42]: https://abagames.github.io/pixel-art-gen/index.html?ships
[43]: https://abagames.github.io/short-vgm-generator/build/
[44]: https://abagames.github.io/slickslack/index.html
[45]: https://abagames.github.io/hakosan/build/
[46]: https://abagames.github.io/crisp-game-lib-11-games/?magnetblocks
热门跟贴