做个 3D 游戏来纪念宝可梦 25 年小智的夺冠退场
2022 年,11 月 11 日,在这天,来自真新镇的小智终于成了宝可梦世界冠军!
那些年,在不同地区的遗憾:
- 1999年石英联盟16强
- 2002年城都联盟8强
- 2005年丰源联盟8强
- 2010年神奥联盟4强
- 2013年合众联盟8强
- 2016年卡洛斯联盟亚军
到现在,终有回响:
- 2019年阿罗拉联盟冠军
- 2022年世界锦标赛冠军
25 年的旅程,也终于迎来了终点,小智退场。
自己谈不上最喜欢的动漫是宝可梦,但宝可梦毕竟是从儿时就有的记忆,且一直延续至今,感情很是微妙的,所以打算写个东西来纪念下。或许游戏是最贴和的,可是我并未有任何游戏编程经验,一下就有点犯晕了……
思来想去,就做一个中国象棋吧,加点 AI,自己也就可以在 Linux 下玩玩了,反正 Linux 下没啥可玩的中国象棋。
说干就干,那就开始规划,首先是游戏所需:
- 玩法
- 规则
- 控制
- 人机
- 界面
- 图形库
- 模型
- 游戏引擎
但实际上对于大部分棋类,都是在 Board 和 Piece 这些基础物件间控制操作的,那么可以这样来划分包:
- stuff 基础包,提供控制和基础物件
- game 游戏包
- dark 暗棋规则
- classic 中象规则
- bot 提供规则
于是乎,就可以通过组合
我一直认为在画界面,写终端界面是相对容易的,所以觉得先出个 tui 界面的来测试游戏正确性,是比较有可行性的,于是有一个界面的包:
- appearance
- text 提供 tui 界面操作
- pokemon 提供宝可梦界面操作
结果发现 Java 的包 tui 库,可谓是惨不忍睹,由于我不是使用 Openjdk,而是 Graalvm,所以也试了 Nodejs 和 Python 的相关库,结果问题多多:
- Node.js 在 Graalvm 下是独立的应用,跟 Graaljs 并不一样,也并不支持 AOT,而 JavaScript 下的 tui,像 blessed 和 ink,全是需要 Node.js 的运行环境的,在 Graalvm 下,有一些兼容性问题,如颜色不能正确显示,而且在 Graalvm 的
--jvm
下卡顿严重,占用资源也高。 - Graalpython 支持 AOT,但是几个 tui 库都有问题,blessings 和 textual 都是缺少 Python 动态库,Graalpython 对于像 cursor 这种正常 Python 都会带的动态库都没有实现。pytermgui 虽然不需要额外动态库,但是却在 Graalvm 下有各种很基础的错误。
靠链接其他语言还是行不通,或者说比较折腾,后面发现 Java 下面有个叫 lanterm 的库,我其实不需要它提供的界面框架,只需要它的事件,在此过程有两个问题:
- 虽然是 tui 库,但是它却依赖 AWT,在当前的 Graalvm 17 下的需要配置相关选项的,如 https://github.com/oracle/graal/issues/1327 所描述的,配置加上
buildArgs.add('-Djava.awt.headless=false')
和agent = true
,然后再加上 Graalvm 关于反射的 json 配置文件。但即使这样后,在不同的 Linux 发行版下,有可能还会出现 gcc 在 ld 时出现错误,问题在 https://github.com/oracle/graal/issues/4594 还未解决,建议是使用 Graalvm 11,没有上述两个问题。 - 不同终端如 konsole 和 gnome-terminal,它们底层使用的库并不一样,lanterm 对他们的支持也是不一样的,如要保持都可以点击,那么 g 系软件正常,k 系软件则是会出现双击,不过这并不是什么大影响,只是文档很多没有说明,需要在源代码找,如上述所说的在 https://github.com/mabe02/lanterna/blob/master/src/main/java/com/googlecode/lanterna/terminal/MouseCaptureMode.java 。
搞完 tui 验证程序可行性后,就可以开始进行 3D 界面的编程了。一开始我想的方案是以前被吹得很厉害的 JavaFX,后面才发现真搞 3D 用它是根本不切实际的:
- 现在大多数 JDK 已经没有带上 JavaFX,要自己去折腾,如找 Gluon 家的。
- OpenJFX 对 3D 模型的支持也不够好,只有一个叫 interactivemesh 的闭源库,支持少,比较老,交互缺,只能作为 viewer 去操作动画。
所以最后找了 Java 下的游戏引擎 JmonkeyEngine,虽然使用者少,帮助不够多,但是起码是能正常工作的,在 Gradle 下加入依赖,就可以在 vim/emacs 或者 vscode 上面进行开发测试了。在游戏引擎的帮助下,3D 编程就显得特别容易,只剩下建模这块比较麻烦,在折腾了两天 blender,才对不同格式,和贴图什么的比较了解。
在快 10 年的低压商务本上开发完,最终只能开低渲染: