游戏制作技巧
制作 LibGDX 游戏的小贴士
以下是我在游戏制作领域短暂涉足后学到的一些东西。
其中有些对你来说显而易见,有些则未必。
使用 Kotlin
Unciv 最初是 C# 的 Unity 项目,后来转向 Java 与 LibGDX,最终迁移到 Kotlin。
我后悔在 Java 中编写事件所花的每一分钟,这可能是你的应用能做出的最重要改变。
使用 Scene2d
除非你打算动态生成图片,否则你会使用预渲染资源。
手动摆放它们就像手动定位 HTML 标签,而不是利用 HTML 层级结构和 CSS 来引导布局。
Scene2d 也是如此——它是一个布局框架,相对容易理解,尤其是当……
忽略 Horizontal 和 Vertical group —— 使用 Table
我个人发现 Table 拥有以上两者的全部功能,甚至更多。
每个类都有不同的语法,所以我发现全都用 Table 反而更简单。
Table 几乎能做所有事情!它简直太棒了!
游戏变慢时,使用 Android Studio 的 Android profiler
自上而下的 CPU 图表是我见过最好的代码分析器,善加利用!
缓存一切
缓存是纯净、无状态代码与更高性能之间的权衡。 作为 PC 背景出身的人,我本能地认为任何低于 O(n^2) 的操作都不到一毫秒,因此不值得缓存。 但在移动开发中并非如此。
当你需要保存和加载包含大量关联部分的游戏数据时,这一点尤其重要——你必须避免循环引用、最小化存档体积,同时还要在加载时重建缺失的链接。
最小化字符串操作
你听过的所有关于最小化字符串操作的建议?用起来!
字符串常量应该是 const,使用 StringBuilder(或者用字符串的 ArrayList,最后 .joinToString())。
处处使用 Sequences!
我没想到的一个大问题是排序和映射时的中间列表。
显然,这些任务的内存分配是件大事。
所以尽可能在列表操作前调用 .asSequence()——这能节省大量时间和内存!
唯一不该这么做的情况是:你想缓存特定值以备将来使用——sequence 每次迭代都会重新走一遍完整流程,所以拿到最终结果后记得 .toList()!
制作开源游戏的一般建议
降低门槛——对程序员和玩家都是
我认为大多数开源游戏都受此困扰——圈内的人深入其中,而圈外想加入的人却要学习整套生态。
文档是个大问题,详细的指引也是——我指的是"手把手喂到嘴边"。
把新开发者当作从未用过 Git 的人来对待——他们可能真的没用过!
解释如何下载源代码、工具,如何让游戏在本地跑起来,如何修改以及如何提交。
对新玩家也一样——让游戏能跑起来应该尽可能简单——你想让人们玩你的游戏,不是吗?
包括:
- 源码到可执行文件的自动化——我用 Travis
- 应用商店等渠道
- 游戏内教程——玩家永远不会对最后这一点满意,但至少尽力去做
社区,社区,社区!
我个人在发布后大约一年里都低估了这一点。
我通过 Google Play 商店和 GitHub issues 与玩家交流,这似乎就够了。
直到玩家反复催促,我才开了 Discord 服务器——而这逐渐带来了巨大的改变!
你看,关键不在于程序员与玩家之间的互动。相对于庞大的玩家群体,核心开发者永远只是少数。
社区的关键是玩家与玩家之间的互动。解释、提问、点子、玩家之间互相碰撞的想法, 不仅让松散的社区变得更好,实际上还让游戏变得更好!
另外要记住,你周围还有更大的社区——开源社区、Linux 社区等等。
有很多人仅仅因为你的游戏是开源的就会去玩它,这也意味着他们没有太多其他选择。
例如……
- 成为最好的 4X 游戏意味着与最大的那些名字竞争
- 成为最好的 Linux 4X 游戏意味着竞争对手少得多,但如今"酷孩子们"都在跨平台,所以你仍然不占优
- 成为最好的开源 4X 游戏意味着大约 5 个竞争对手,而且没有金钱参与,所以平均水准没那么精良
- 成为最好的安卓开源 4X 游戏……意味着竞争对手少到完全可行
一切都是营销。
你的游戏名、图标、截图——玩家看到的关于你游戏的一切都是营销。
图标和标语尤其重要,因为它们是玩家最先看到的东西。
在几次实验后(Google Play 让你很容易做这些实验),我仅仅通过更换图标就看到了近 50%(!)的变化。
翻译是你源代码的一部分
这可能有点争议,容我解释。
在到达当前格式之前,我们在如何保存翻译上经历了好几轮迭代。
要点如下:
游戏翻译文件应该自动生成。这样你可以毫无顾虑地往游戏里添加新对象, 因为相应的词条会被自动加入翻译。
每种语言的翻译应分开存储——这样多个语言可以并行修改,互不冲突
翻译应该通过 PR 合入!这样其他语言使用者可以质疑或修改提出的翻译,你也可以对翻译运行测试。 如果你要求特定格式,这一点价值连城——坏翻译在门口就会被拒之门外。
开源问题需要开放的解决方案
简而言之,考虑使用免费(即使不是开源)的 API。
多人游戏需要在客户端之间同步游戏文件,即使其中一个玩家当前不在线。
'正确'的解决方式大概是有一个在线数据库和一个处理用户请求的服务。
由于这是开源游戏,我的预算是 0 美元,所以我们就简单地把所有文件存在 Dropbox 里,在那里上传/下载。
这安全吗?不安全,但需要吗?你需要权衡成本与价值。
模组也是一样。Steam 大而安全,所以它自己管理模组。
我们小而开放,所以只允许从 GitHub 下载,这让我们免费使用 GitHub 的所有内置功能(用户管理、readme、star、版本管理……)。
与基本算是滥用的 Dropbox 用法不同,GitHub 天生就是干这个的! 这正是他们当初设想的使用场景!
算总账的时刻
每个项目都会迎来这样一个时刻:酷炫的部分做完了。所有前沿的惊艳和算法的橡皮泥都玩完了,现在(哈)需要的只是打磨。
你知道谁喜欢打磨吗?玩家!当然,有些人会说"好游戏即使朴素也是好游戏",但他们心中对"朴素游戏"该有什么也是有标准的。
数字不会说谎。打磨好的游戏卖得更好,玩得人也更多。
你知道谁不喜欢打磨吗?开发者。
游戏相对简单时,打磨的选项有限,但游戏越复杂,可打磨的地方就越多。
而且这可能是个绝对的苦差事。又一个奇怪的使用场景、又一个游戏内选项、"更好的性能"(我肯定在各类性能相关的事情上花了几十个小时)。
最糟糕的是,所有人都注意到它缺席,却没人注意它存在。字面意义上的一百个打磨版本,而普通玩家可能只注意到一丝丝变化。
然后你会问自己:何必呢?我们到底在干什么?
对我来说,答案如下:
A. 要做出真正伟大的东西,你必须在它不再有趣之后继续坚持很久。
B. 有一群喜欢你正在做的事的人,他们希望有更多这样的东西 😃
C. 你知道自己想继续写代码,而且——怎么,你以为再开一个项目就能一样顺利?你已经试过好几次了,说实话,除非你投入和现在一样多的时间,否则做出第二个同样成功的游戏的几率真的很小,然后嘛,你又回到了这个位置。
这就是我过去一百来个版本所处的循环!解 bug、修边界情况、改进 AI、接收 PR。大量模组相关改动——既要阻止玩家在模组里做不该做的事导致游戏崩溃,又要给他们更多制作自由。
我不认为我真的会去把 G&K 做完,我绝对不打算实现 BNW 的机制,坦率说我觉得那些……不怎么样。
这就是我现在的状态。算是做完了这个游戏,但考虑到半年前我就这么想了,而发布仍然大约每周一次——所以也还算没做完。