12.26

2025-12-27

周五

更改

从今天开始,日记的第一级标题将使用一个井号而不是两个

游戏开发日志

Why 推箱子?

首先,推箱子非常离散,相比连续时空中基于平台跳跃的解谜游戏(如时空幻境)甚至 3D 解谜游戏(传送门),从游戏规则和代码实现上看,离散游戏要简单得多,也更难出现 bug。从关卡设计上看,玩家行为更可控,因此更容易卡掉非预期解。当然,很重要的是,美术也简单多了!

其次,推箱子是 PSPACE 完全问题,我还没有读过证明1,但它应该是对的。所以如果你的解谜游戏玩法是推箱子的超集,它的上限不会太低,你总可以设计出足够难的关卡,方式是从推箱子难题集中抄袭。当然,这只是提供了一个真空中的球形鸡式的理论保证,因为实际上,要在关卡中足够好地融入游戏独有元素才行

Remark:我的游戏允许玩家同时推动多个箱子,实际上它不是推箱子的超集,所以它并不自动成为 PSPACE 完全问题。ChatGPT 说此时仍然是 PSPACE 完全的,因为证明过程并不强依赖玩家只能推动一个箱子。我不是很信任它,有空(寒假!)一定要读一下原始证明,搞明白这个问题

关卡规划

原本前三关不涉及活塞,完全是推箱子,我把它们从游戏中删除了,因为这不够开门见山,甚至可能让玩家厌倦。原来放这三关是想各自教玩家:

  1. 这是一个推箱子游戏
  2. 游戏中有多格的箱子,以及多目标点逻辑
  3. 和 Sokoban 不同,玩家可以同时推动多个箱子,就像在 Patrick’s Barabox 那样

现在我发现第一件事不需要开一关教学,任何一关都能告诉玩家这个显然的事实;第二件事,我认为玩家能自己感悟出来;第三件事,我修改了游戏的第二关,强迫玩家在第一步只能同时推两个箱子,这就完成了教学

现有的所有关卡都放在第一章 Pistons。先说说对游戏的预期:第二章计划依次引入粘性活塞和风扇,粘性活塞能拉回方块,扩展了活塞的种类,风扇引入 “超距作用”,并且让计时的实现更简单高效(目前用活塞能用 的空间模拟 tick 倒计时器,如果有风扇,只需要 ),而两者又可以产生化学反应:粘性活塞能粘住方块,防止被风扇吹走。

说回第一章,我把它分为三个部分:

  1. 基础推动规则,包括活塞推动和被推动的规则(1-9 关)
  2. 堵塞规则,包括活塞因末端有不可移动物体而无法推出的 “末端堵塞” 以及多个活塞冲突的 “并发冲突”(目前只做了第 10 关,计划 10-15 关)
  3. 综合谜题(16-25 关)

接下来就是如何设计一个关卡的问题

关卡设计

逻辑解谜游戏需要尤里卡时刻(Eureka Moment),它也叫顿悟时刻,说的是玩家在解决难题时的顿悟瞬间。一个常见的技巧是引导玩家往错误的方向思考,这样能够增加玩家发现正确做法时顿悟的程度

由于现在游戏只有活塞一个关键元素,不需要考虑多元素交互问题,只需要关心如何围绕活塞设计出合格的关卡

level editor

这是我的关卡编辑器,在经过几轮迭代后,已经比较易用,可以实时地添加和删除方块、电路,然后开始测试。可以随时扩展地图空间。还有一些高级功能:可以高亮一次关卡游玩中涉及的格子,以便在需要的时候用墙填充这些不需要用到的格子

上图是第 10 关,“堵塞” 的第一关,我设计关卡的过程是这样的:

  1. 这是关于堵塞的,我想在关卡里融合两个关于堵塞的谜题,让玩家分别解除堵塞和产生堵塞
  2. 基于这一点,在编辑器中摆放好必要的物体,让玩家能够做出这一系列动作
  3. 摆放墙壁,把上一步的场景围起来,留出合适的空间
  4. 确定正解,我希望玩家先解除堵塞,再产生堵塞
  5. 如何约束玩家必须走正解:产生堵塞所用的物体就是从解除堵塞中解放出来的
  6. 根据这一约束调整关卡布局
  7. 细化正解:我希望玩家必须从上往下推箱子解除堵塞
  8. 随机调整关卡布局,直到看起来能卡掉玩家从下往上推箱子的情况
  9. 叫室友来测试(serendipity_lin)
  10. 发现室友是天才,从下往上推箱子过了
  11. 尝试卡掉非预期解,方法是跑一遍正解,把没用到的一个格子用墙填上
  12. 再叫室友来测试
  13. 室友找到了新的非预期解
  14. 尝试卡掉非预期解,方法是增加一个新的目标点

核心就是不断迭代,让一个 idea 自己长成一个完整的关卡!


Patrick’s Barabox 的作者 Patrick Traynor 在博客上总结了一些关卡设计技巧:Puzzle Level Idea Strategies,我在设计关卡的过程中总结出的经验和其中的一部分不谋而合,他提到的其中一个策略是 :Create a possible level, then make it impossible

Start with a level that’s possible to solve, and keep making changes until it’s impossible, then undo your last change.

另一个对偶的策略是:Create an impossible level, then make it possible

Create a level that is obviously impossible to solve. Then, using that as a starting point, keep making adjustments to make it possible, and see where you end up. Or, come up with a loophole to solve a paradoxical situation, and then camoflage the loophole.

这两个方法 work 的直觉是,最后的情况在 possible 和 impossible 的交界处,距离不可解的情况只差了一个细节,这会保证过关方法不会太多

在第 10 关的设计中,第 6 步和第 8 步的迭代就是通过这两个方法的混合完成的!我让关卡反复在 possible 和 impossible 之间变化,直到找到一个平衡点,这样就能产生一个还不错的结果,最终只有两种非预期解,都能以容易的方式卡掉,得到了一个完美的关卡

Footnotes

  1. 很遗憾,在 TCS 导论的海报展示环节,做 reduction 的同学没有研究推箱子问题

最新评论

--