写在前面
之前已经发过了两个作品了:Taichi Voxel Challenge 2022
最近忙完手头的几个比较急的工作,又手痒想整点活了 hhh,本来有几个想法,但最后就先做了 PVZ 这个。
PVZ 目前还是 WIP,后面应该会再完善一下下,后面如果时间充裕还可以再来整几个,不过快要答辩了 555。
作品思路
PVZ 这个目前只做了一个最简单的豌豆射手,但其实在做的过程中也遇到很多的问题。首先,还是来分析一下豌豆射手的结构吧!
豌豆射手大概就是有以下几个结构:主体炮筒,眼睛,枝干,后面的芽和下方的叶片。
主体炮筒:这个炮筒其实我们还可以再来拆解一下,其实可以把他看成一个圆柱,但圆柱的壁变成曲线,看起来很简单对不对?我们直接用 SDF 表示几何体然后直接构建就好啦!但是我不会 SDF(x),其实这样也是有点问题的,因为炮口应该会比较靠下,所以我们干脆拆成一个球体 + 几个圆即可。
眼睛:这个没啥难度,直接从球体上扣掉一个矩形,安放一个黑矩形当眼睛,白矩形点高光即可。
|
|
枝干:这个枝干的曲线可是难倒我了,我并不会 bezier curve,所以我决定化繁为简,直接用正弦函数 hhh,由某条龙的作品启发 233,定义好振幅,我只选取了 [0, PI] 的参数范围。
|
|
后面的芽:直接也当成曲线画上即可
下面的叶子:原版的豌豆射手下方有 3 片叶子,2 大 1 小,但是太复杂了,这里也是简单表示,画 4 个方向的 4 片叶子。但是叶子这个又是个不规则的图形,好像又不好表示…我灵机一动,画了一片叶子(),这很像是两个对角的半圆拼接起来的重合区域,那就有了,指定一个起点和方向,然后左上右下或者右上左下作为圆心,判断重叠区域即可。但这样画出来是平的,没有关系,我们在 z 坐标还是用老方法,直接两个关于 x 和 y 的正弦函数相加就好了!(机智如我)
|
|
到此,豌豆射手就结束了。构建豌豆射手的代码如下:
|
|
剩下的就是草坪了。因为有格子数的限制,没法实现原版的 6 * 9 的设置,也没法画全四周的篱笆了,所以就直接画了 6 *6 的场景。画完以后差点味儿,再给草坪周围加上噪声即可。
|
|
最后做完了行数有点超,稍微压一下行就 99 行啦!
最后
有几个遇到的问题至今未解决 - -,首先一个就是我不知道怎么在 @ti.func
中交换 vec3
的维度,比如 vec3(x, y, z)
变成 vec3(z, y, x)
,不然在构建圆形的地方还能少几行,因为我是想着多方向的圆形,最后还是选择了最暴力的 if 算法。
还有一个小细节就是在圆形和球体的地方,为了让圆形更圆一下,就得给放宽一下边界条件,比如 x * x + y * y <= r * r + eps
。在球体的时候,有时候会是上面多一个点,这时候缩一下边界条件会比较好。