大家好!我们正在开发一个结合2048和蛇的可爱小益智游戏,名为204Snake。在这篇文章中,我们想谈谈开发这个游戏中最令人惊讶的挑战之一——蛇的设计。我们被许多人问到我们如何实现当前的蛇外观,所以我们想谈谈我们遇到的技术困难,以便让蛇看起来像它现在这样!
204Snake最初是一款游戏竞赛项目([game jam project](https://sodoj.itch.io/204snake)),而老版本的竞赛版蛇设计是可行的,但是我们想让新的艺术风格更具视觉吸引力。我们看了其他在正方形网格上移动的蛇游戏,受到Snakebird(Snakebird)的启发,感觉很流畅、生动和无缝的,所以我们决定开始工作!
从游戏和视觉角度来看,自然而然的选择是将蛇分成两个部分:头和尾。头部的技术细节是简单的,只需添加一个精灵即可完成。但是,尾部必须能够生长和收缩,弯曲在角落,保持蛇的感觉同时又保持尾部的实体感。它还需要提供在游戏中给玩家视觉反馈,同时指示蛇占据的网格空间和其长度。显然,仅使用精灵的老方法无法满足要求,所以我们需要新方法。显而易见的选择是使用线渲染器(Godot引擎的Line2D),但是最初看起来简单的方法却带来了自己的问题。
为了改善外观,我们尝试提高曲线的分辨率,添加更多的点,但是这只掩盖了问题,同时使动画变得几乎不可能。这个时候,我们知道我们需要自己的解决方案,所以下一步就是开发一个定制的线渲染器着色器,适合我们的需求。我们的想法是绘制一个覆盖在尾部曲线上的平铺纹理,通过将2D空间映射为一个轴沿着蛇的长度,另一个轴与曲线垂直的任何点。这样我们就可以轻松控制尾部的长度和宽度,并且可以很容易地动画化。但是,我们从未考虑到一个看似无关紧要的问题会出现,会颠覆我们的解决方案…
结果是,平滑的90度弯曲并不是我们所希望的。如果我们绘制一个穿过蛇尾的线,它就变得明显了,曲线上的一部分比直线段短,因为它可以被表示为一个直径为一个网格空间的四分之一圆弧。这样,尾部的长度就变得不均匀,和蛇的段数不同。显然,这个时候我们需要另一个解决方案,一个可以很好地适应曲线段的解决方案。既然曲线段本质上就是四分之一圆弧,那么我们为什么不直接绘制它们呢?这就带我们到了下一个解决方案:将尾部分成实际的段:直线和左、右曲线。我们可以保留原始映射(一个轴是长度,另一个轴是宽度)用于直线段,而对于曲线,我们可以使用极坐标系统,映射距离沿着四分之一圆弧曲线到长度,并表示宽度为距离圆心(内角)的距离。现在,如果我们将所有段的长度标准化为一个,稍微压缩曲线段,蛇的长度就变成了其段数。
这就带我们到了尾部实现的最终版本。它在两个部分中工作:首先,我们根据游戏板上的蛇段信息构造一个2D网格。它由四边形组成,每个四边形代表一个段。它们存储了关于每个段的信息,包括它是如何定向的,是否是曲线,和它在蛇身上的位置。每当玩家对蛇进行移动时,改变其形状,这个网格都会被重建和更新。第二部分,尾部着色器,可以使用这些信息,其他参数如尾部的总长度和宽度,来采样尾部纹理并绘制它。这种混合方法,既使用了分离的段,又将尾部当作一个实体来绘制,让我们既可以控制尾部的长度和宽度,又可以轻松地动画化。这样做,我们可以做出各种创造性的效果和动画。
到目前为止,动画蛇的运动仅仅是生成一个新段并平滑地移动尾部的位置,这里实际绘制的位置。这样做会带来一个奇怪的缺陷,需要在尾部的后面添加两个额外的“幽灵”段。这些段对玩家来说是不可见的,没有任何游戏功能,但仍然发挥着重要作用。第一个是用来保持尾部的最末端曲线的,否则尾部的尖端总是会指向后方。第二个是运动动画的遗留部分。保留它意味着我们不需要重建网格一次动画完成。
为了完成蛇的外观,只需将头部附加到尾部并同步它们的运动即可。匹配颜色和运动,让头部和尾部的过渡变得无缝,使头部看起来像蛇的一部分而不是一个独立的组件。然后,眼睛就可以动画化,以动态反应到可以被吃掉的方块的存在——但是这是一整个另一番故事。
另一个有趣的尾部动画是吃食物的动画,曾经在开发过程中出现过。我们想让吃食物和蛇生长有一个令人满意和有滋有味的感觉,看到食物沿着蛇移动之前被转化为新的生长段似乎是一个很好的想法。然而,它感觉太慢了,而且当玩家快速连续移动时,玩家就不知道蛇的长度了。我们不想阻碍玩家玩游戏,而且为了保持视觉清晰,我们决定放弃它。
蛇的尾部,尽管最初只是一个简单的想法,最后变成了我们有机会工作的最有趣的图形问题之一。我们很高兴当前在游戏中的外观和感觉,但是它需要大量的努力和迭代才能达到满意的结论,同时确保它对玩家的享受是优化和无Bug的。如果您有任何问题,欢迎在这里提问或留下评论,如果这篇文章引起了您的兴趣,您想从我们这里听到更多的话!
评论 (0)