木匣子

Web/Game/Programming/Life etc.

动森图鉴+开发笔记

这两个月受到疫情影响,从四月中开始在家办公,四月底开始降薪,并且到五月初的这两个多星期进入了做三休四的节奏,每周强制休二天年假,不知何时是头。

由于在家工作,有更多的时间做自己想做的事。为了给自己减压,于是入了动物之森 Switch 版开始捡树枝。玩了几个星期发现其实自己并不是很喜欢联机,硬是把一个休闲社交游戏玩成了单机游戏。

不过动森的探索性还是挺强的,光是收集小动物就可以折腾很久。而且游戏时间与现实同步,每过一个月就会有新的物种出现。有时候需要查一下攻略才知道最近新出了啥动物。

在网上浏览这些攻略的时候就想,为啥大家都把数据做成表格的形式,非常不直观,不如做成像游戏中的图鉴,还可以加上自己的改进。例如其它网站上对鱼的影子的描述,只是用文字写着 “Smallest (1)”、“Small (2)”…“Latest (6)” 这样让人摸不着头脑的表述。

我的第一反应就是:先做一个鱼影的预览效果吧,然后集成到动森图鉴里。于是开始想怎么实现一个会动的鱼影:鱼的头尽量保持不动,而尾部来回摇摆。可以抽象成两个函数叠加:

$$ f(x) = x^2 * sin(x * 2 * pi + t) $$

其中二次函数控制从鱼头到鱼尾的运动幅度;正弦函数负责鱼身的摆动,乘以 \(2pi\) 调整周期到单位 1 方便之后加入其它参数,再加以时间 \(t\) 改变相位。一个鱼的基本动画就出来了:我在 desmos 上创建了一个效果演示

接下来我需要把这个函数运用到一个鱼影贴图上,由于动森的鱼影非常简单,于是我用开源矢量软件 Inkscape 画了个多边形(顺便一提,最近 Inkscape 1.0 的正式版发布了,试用了一下,比五六年前好用太多。)

Fish Shadow

Fish Shadow with Fin

可是要怎么让它动起来呢?一开始我想直接以 svg 的方式,去操作顶点。但是多边形的效果并不好,而曲线又不容易控制。最后想到的方案还是用 Canvas 来做 Mesh 动画。于是找到 PIXI.js 这个优秀的前端动画库。翻了一下它的 API,发现了 SimpleRope 这个接口的 Demo,正好就是我需要的东西。于是实现了一个简单的 PoC ,效果还不错。我把这个 PoC 整理到 CodePen 上发表了:

在 PoC 中我用 dat.GUI 加入了一些参数,调整后可以保存下来,用于区别不同的鱼种。

在实际上项目中,由于需要仿真游戏界面,我还用 Inkscape 画了许多找不到的图标,例如鱼和虫的剪影、博物馆 Logo 等等。简直一画就上瘾。其它大部分界面图标则来自 FontAwesome 提供的 Svg 文件。素材准备花了一两个晚上,感觉万事具备,就差一个程序员了。

我的目标是做一个 Web APP,所以直接上我魔改后的 React Boilerplate /dev 分支上未发布的 v5 版本了。据说 React Boilerplate 准备用 Create-react-app 重构过。并且将 i18n 解决方案换成 i18next。真是深得我心,不过这次先用老版本吧。

数据方面,在 github 上发现了一个叫 acnhapi.com 的项目,可以直接调用他们的 restful 接口。唯一的缺点是不支持 https 。这些数据通常也不会变化,后期可以直接把数据下载到项目本地。

图鉴的最主要功能就是显示当前有什么动物可以在岛上获得,于是我在官方的图鉴界面上作了一些改动,用彩色表示当前活动的动物;用剪影表示在当月活动,但是当前不活跃的动物;至于其它当月不出现的动物,就用缺省图标表示。另外官方版本的捐赠图标只有当你把光标放在动物图标上时才会显示在名称边上。如果你想知道哪个动物未捐赠到博物馆,需要一个一个去查看,非常不方便。于是我将捐赠图标放在了左下角。

Critterpedia-plus-fish

用格子展示的方式没办法承载太多信息,玩家点击图标后,会展开详情界面查看细节信息。这个界面用 React 完美复刻了游戏界面,然后加入了一些功能,例如切换南北半球、显示一些额外的数据。这里还用红色问号图标引入了之前做的鱼影动画。

Critterpedia-plus-fish

为了方便批量标记捐赠,并且不在原来的图鉴上增加过多功能负担,又引入了收集模式(Collection Mode),在这个界面玩家可以选择动物进行标记。标记为捐赠的动物会变为彩色并加上博物馆图标。

此外在制作月份图表和 24 小时图表的时候,想到了可以设计成拖拽组件,让玩家通过选择不同的月份和时间来显示某一时刻下会出现的物种。这样玩家可以清楚了解到在接下来的时间会出现哪些动物可以收集。

在一周的业余时间慢慢完成了图鉴的开发工作,成就感满满。一开始的时候并没有特别在意手机用户,所以到快发布之前才想起需要稍微对手机做适配。于是又用了两个晚上在 iPhone 测试修改迭代。这个横版格子的设计对手机用户其实并不是很友好。但一开始就使用了支持横向滚动的 swiper 库,所以适配起来并不是很困难。(最后的数据显示有将近 40% 的手机用户,适配工作还是很值得的)。

项目快完成的时候,感觉心情不错,干脆就把项目开源好了,于是就把 GitHub 仓库标记为 Public 。有兴趣的朋友可以在这里获取源码

开源的另一个好处是可以直接使用 GitHub Actions + GitHub Pages 来部署项目。于是很顺利就把项目跑在了 GH-Pages 上了:Critterpedia Plus

之后如果想到什么有意思的功能,会满满往上面增加。喜欢这个图鉴的小伙伴欢迎分享给自己的朋友们。