光线投射器

概念

Raycasting(光线追踪)通过发射“光线”来测量最近墙壁的距离,因此被称为“光线追踪器”。程序从玩家开始向前发送光线,直到撞上物体,然后根据行进的距离着色像素。光线以不同的方向发送。所有光线都被发送后,完整的图像将会出现。

基于精灵、基于列表和基于 SDF 的技术比较

本页介绍了两种可以编程的光线追踪器:基于精灵的方法,基于列表的方法和基于SDF的方法。每种方法都有其优点和缺点:

本页介绍两种可以编程的光线投射器:基于精灵的方法、基于列表的方法和基于 SDF 的方法。每个都有自己的优点和缺点:

基于精灵基于列表基于SDF
难度容易
帧率
所需知识基本临时编程划痕编程;三角法;数组划痕编程;三角法
地图的存储方式作为精灵;每个地图/世界都是一个服装作为数组(数字网格);每个映射都是一个单独的数组作为一组“我的块”
需要精灵1 个或更多,具体取决于设置至少 1(渲染器)至少 1(渲染器)
其他优势可用于制作具有曲面壁的世界可以轻松生成随机世界可以轻松生成球体、圆环和圆锥体等形状

对于初学者,建议从制作基于精灵的方法开始,因为它简单而不复杂。对于更高级的程序员和已经制作过基于精灵的光线追踪器的人,建议制作基于数组的光线追踪器,它速度更快但更复杂,或基于SDF的光线追踪器,它速度更慢、更复杂,但更灵活。

基于精灵的射线投射器

光线追踪器所需的组件包括:

“地图”

地图显示级别的布局。

“传感器”

传感器将计算从玩家到每堵墙的距离。

“渲染器”

根据“传感器”给出的距离绘制每堵墙。

本教程将使用四个精灵来实现这些三个要求。如果有人卡住了,这里有一个完成的例子。

地图

创建一个墙壁地图精灵,大小为480x360,最好有一个“空白”颜色的地板。然后,将以下脚本添加到精灵中:

【图1】

【图2】

人物

接下来,将创建一个可以在地图上行走的人物精灵。创建一个有一个像素的造型的人物精灵。该造型应该居中于像素。这很重要。在深入了解精灵脚本之前,请注意所有“应该被替换为玩家需要移动的速度”。【图3】

将以下脚本放在“person”精灵中:

【图4】

4(1).png

4(2).png

现在已经创建了一个可以在其中漫步的地图。

距离感知

这是构建 3D 光线追踪的起点。

在现实世界中,物体离得越远,它就越小。

下面是一个慢动作展示“距离感知”的 GIF 动画。橙色的“斑点”是人物精灵。 你将制作一个感知脚本,测量玩家到周围墙壁的距离。你需要为 96 个不同的角度做到这一点。所有这些都将在“sense”广播被调用时发生。

制作一个“距离感知”精灵,它具有一个一像素乘一像素的造型。造型应该在像素中心对齐。

然后,添加以下脚本:

【图5】

5(1).png

绘制

现在需要将“距离传感”收集的信息进行绘制。请记住,物体距离越远,它就越小。

创建一个“绘制”角色,加入以下脚本:

【图6】

6(1).png

这个项目现在已经完成。不幸的是,在Scratch中运行时会比较慢。

跳跃(可选)

虽然无法为项目添加真正的垂直移动,但是可以创建跳跃的视觉效果。它的工作原理是在玩家跳跃时以更低的高度绘制墙壁。更接近玩家的墙壁会向下移动更多,以模拟视差。要添加跳跃选项,首先将以下脚本添加到任何角色或背景:

【图7】

7(1).png

现在,将绘制墙壁的脚本修改为以下内容:

8.png

8(1).png

速度优化

有几种方法可以减少卡顿:

  • 将“人物”角色的旋转样式设置为“不旋转”。
  • 在“距离传感”角色中,每2步检查一次墙壁,而不是每1步。
  • 绘制较少的列,而不是96列。假设在“距离传感”中,精灵旋转2度而不是1度,笔的大小为8,则60列是一个不错的数量。
  • 将“Player”角色中的无限循环中的代码替换为以下内容:

【图9】

  • 使传感同时感知和绘制
  • 将所有的 替换为 ,并使传感和绘制始终感知和绘制【图10】

【图11】

基于精灵的射线追踪器的主要速度瓶颈是“距离传感”精灵必须进行大量的传感。

基于列表的射线投射器

基于列表的射线投射器使用一个存储在列表中的地图和存储在变量中的坐标(例如玩家和射线的坐标)来进行操作。这种射线投射方法是非常虚拟的,所有数据都存储为数字,没有实际的精灵造型使用。唯一需要的精灵是一个移动笔来画墙壁。如果你需要一个示例地图,可以在这里下载。示例可以在这里找到。

本教程将教你如何制作一个简单的基于列表的射线投射器。它使用自定义块使编辑更容易。请确保勾选“无屏幕刷新运行”框。

【图12】

所需变量

需要以下变量进行本教程:

【图13】

13(1).png

13(2).png

13(3).png

13(4).png

所需列表

以下是本教程中所需的列表:

【图14】

变量设置

下面的代码用于设置变量:

【图15】

设置列表

列表应包含n个数字,每个数字都是0或1,其中n是列表表示的网格每边的距离。应用填充的正方形应表示为1,未填充的正方形应表示为0。以下是一个10x10世界地图的示例。【图16】

【图17】

画笔阴影替换

这段代码用于替换“着色”块:【图18】

【图19】

主循环

这是启动所有其他脚本的绿旗脚本。

【图20】

Raycasting脚本

接下来是主要的Raycasting脚本。该块控制大部分自定义块。确保它是一个“不需要屏幕刷新”块。

【图21】

21(1).png

控制

“raycast”脚本中的自定义块之一是“Read Keys”自定义块。在这里,我们将重点介绍该脚本。

【图22】

22(1).png

计算墙壁

本节介绍计算墙壁的块。不幸的是,未包括墙壁触摸检测。

【图23】

23(1).png

23(2).png

绘制墙壁

本教程中的最后一部分是绘制墙壁的笔脚本。它是一个非常简单的脚本。

【图24】

现在,您的基于列表的光线跟踪器已经准备就绪!

基于SDF的射线投射器

一个基于SDF(Signed Distance Functions,符号距离函数)的射线追踪器使用SDF来判断射线是否触碰到一个对象。这是一种绘制单个像素而不是列的特殊方法,可以轻松绘制不同高度的对象。

需要的变量

【图25】

25(1).png

主循环

这个脚本启动了所有其他脚本。

【图26】

26(1).png

射线追踪脚本

这个脚本是用来发射射线的。

【图27】

27(1).png

移动射线

28.png

检查射线是否碰撞

这是用来获取任意点到射线位置距离的距离函数。

【图29】

这个块检查是否与球体发生碰撞。

【图30】

这个块包含所有SDF,并检查与所有对象的碰撞。

【图31】

移动相机

【图32】

你的基于SDF的射线追踪器现在已经准备好了!

标签: Scratch, Scratch编程, Scratch中国, 少儿编程, Scratch社区, Scratch编程社区, Scratch编程课程, Scratch编程教程