去年,当我获得PICO-8时,我做的第一件事是编写2D地形生成器。 我以前在Java和Android上都做过。 我已经学会了如何从Miners4k源代码(可通过Wayback Machine获得)生成地形,尽管它花了我几次尝试(以及阅读其他博客和Wikipedia)才能使其正常运行。 我选择了简化版的Diamond-Squared算法(用于生成2D等离子体),该算法创建了高度值的1D数组。
有关该算法的简介,请查看此博客。
从一个非常高的层次来看,您将获取一个数字数组,这些数字均已初始化为某个高度值,每个元素代表从0到地形宽度的某个x坐标处的高度值。 您选择数组的中间元素,并将其值设置为第一个和最后一个元素的平均值,再加上一个随机抖动值。 然后,您遍历数组的每一半,对每一半执行相同的操作,并减少随机性。 继续将数组分成两半,直到到达长度为1的数组(可以递归或迭代地完成),然后剩下的整个数组代表一系列的高度值,这些高度值在渲染时看起来像是类似于连绵起伏的丘陵。
我在PICO-8中的第一次尝试只是使用线条,从屏幕的底部绘制到for循环中数组每个元素的高度值。 非常简单,所有颜色均为单色。
我很快意识到,如果对每个垂直切片(数组的每个元素)使用多条线,我可以使它看起来就像是地形/岩石,上面放着一些草。 因此,现在循环画了三行,最后几个像素是单独的行,为“草”渲染了两种绿色。
在这一点上,我决定将其用于制作Worms-Clone,因为我意识到我可以通过编辑Terrain数组来模拟Terrain变形。 当我实施此方法时,它看起来很奇怪(而且我对这种方法的工作情况也没有很好的了解),因为草还留着。 在蠕虫中,当射弹击中景观时,会从风景中带走一小块,留下裸露的岩石。
我对此的解决方案是采用一维高度图数组,并使用它来构建一个稀疏的2D像素值数组来表示地形。 作为一个很好的副作用,这允许使用随机性创建更复杂的外观地形,以产生棕色和紫色像素的噪点,可以很好地代表土壤/岩石。 另一个不错的副作用是随机性,这意味着草不必再显得均匀了。 现在,当爆炸摧毁了某些地形时,可以很容易地算出爆炸半径中的哪些像素,然后将其消除。 它给了我想要的效果。
通过生成多个高度图,并将数据复制到2D数组时,将它们用作地形的上下边界,我进一步开发了此方法。 这允许洞穴和浮岛。 它开始看起来更像蠕虫。 通过在2D地形数组上进行迭代,检查元素是否不为零,然后将其值与pset()一起使用以绘制到屏幕上来绘制地形。
不幸的是,将pset()与用于整个屏幕的2D数组结合在一起并不快(至少,我无法使其快速)。 帧速率将在15-30FPS之间波动,而不是PICO-8上的标准稳定值30。 我还设法在这里进行了一堆碰撞检测,感到沮丧并离开了项目几个月。
在今年年初,我看到了来自@iLkKke和@kometbomb的这种酷似机器人的Worms / Scorched-Earth机器人,它激励了我,看看是否可以使我的地形渲染以30FPS的速度工作。 我为此做了几次尝试。 这些尝试包括:
- 通过将地形存储为x,y坐标和像素颜色打包为PICO-8浮点数的一维数组来删除零校验
- 将32×32大块地形数据写入Sprite存储器
- 将地形数据存储在用户存储器中并复制到屏幕存储器
尽管可能有些地方值得回顾,但这些都不是完全成功的。 我再次在场上脱颖而出,改为参加业余猫高五挑战赛,这对地形的关注较少。
当我接近该项目的结尾时,我正在考虑重新考虑几年前在Android上原型制作的游戏。 那时是侧面滚动射击游戏,您在游戏中扮演了一个巨大的魔法猪头,沿着(糟糕)的风景弹跳,射击了头骨。 (此处未显示图片:头骨,只是飞舞的岩石纹理)
我认为简单的基于行的地形演示可以很好地用作新版本的背景,因此我接受了该示例并尝试在每个垂直切片的高度值处渲染一个8×8的“草”精灵。 我没有这张照片,但是看起来不太好。 由于业余猫高五挑战赛让我大量使用sspr(),我决定可以使用1×32的sprite数据切片并将其渲染到我一直使用的行上方。 这很有趣,因为这意味着我不必使用三行就可以得到与我最早的努力相同的效果。 我意识到,通过使用较大的Sprite数据块,然后仅使用sspr()渲染1像素切片,我可以获得很好的效果。 根据x坐标的模数和“地形sprite”的宽度,使用x偏移量控制整个sprite数据的迭代。
我为地形精灵添加了细节,看起来更好。 我也在地面高度以下的32像素处剪切了纯色线。
在这一点上,我只是详细到镇上看它是否看起来不错,然后将纯色线条更改为PICO-8的深蓝色,以提供更好的对比度。 我发现通过在不同高度渲染切片的扭曲效果进一步改善了添加细节。
因此,最终结果是通过使用sspr()渲染地形精灵的切片以及使用line()调用在纹理区域下方渲染空间的单个for循环实现的。 很快 它的局限性来自它作为高度图的简单性,但是通过更改用于受损区域的地形精灵,仍可以在某种程度上实现类似蠕虫的地形变形之类的东西。 在我当前的版本中,terrain数据不再只是数字数组,而是Lua表,因此也可以存储其他数据,例如该位置是否有装饰。 (损坏可以用相同的方式完成)。
无论如何,感谢您阅读本文。 下次,我将进入Terrain生成代码,并发布一个演示购物车,以演示实现效果的方式。