尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

用Scratch实现3D恐怖游戏:射线投射与迷宫渲染全解析

用Scratch实现3D恐怖游戏:射线投射与迷宫渲染全解析 在 Scratch 里做一款 3D 恐怖游戏听起来像是把 3D 建模、图形渲染和关卡设计全部塞进积木编程工具。实际做完后会发现Scratch 本身虽然是 2D 舞台引擎但只要理解一种叫“射线投射”的渲染思路完全可以在不加载任何外部素材的情况下渲染出第一人称 3D 迷宫。恐怖感的核心也不再是模型有多精细而是视野受限制、墙壁突然出现、声音突然变化。下文会以“迷宫探索恐怖游戏”为目标讲解从地图设计、摄像机移动、射线投射渲染到碰撞检测的完整实现并提供可以在 Scratch 中逐步复现的变量、函数结构和伪代码。这个项目适合已经熟悉 Scratch 基础积木、想挑战更高难度作品的读者也能作为理解 3D 图形原理的入门案例。1. 先搞清楚Scratch 的 2D 舞台如何呈现 3D 世界Scratch 的舞台本质是平面坐标系一个角色只有 x 坐标和 y 坐标没有 z 坐标。所谓“3D 游戏”并不是在 Scratch 内部真的创建了一个三维空间而是通过数学计算把三维世界里的位置投影到二维屏幕上。只要投影结果足够合理玩家就会产生“我在走 3D 迷宫”的错觉。1.1 Scratch 是 2D 引擎3D 要靠“视觉欺骗”做 3D 效果常见的方案有几种射线投射Raycasting从摄像机位置向屏幕的每一列发射一条射线射线碰到墙后就停止用墙的距离决定这一列墙画多高。经典游戏《德军总部 3D》就是这种思路。多边形投影把 3D 模型的顶点投影到 2D 平面上再用画笔把顶点连起来。适合做低多边形风格的 3D 模型。伪 3D 精灵用大小变化、位置偏移和遮挡关系模拟远近适合做赛车类或跑酷类小游戏。恐怖迷宫更适合射线投射。因为射线投射非常适合表现走廊、墙角、房间和转角而“转角遇到怪”正是恐怖游戏最常见的玩法。射线投射的实现不算复杂计算量也小在 Scratch 的积木循环里可以跑得动。1.2 射线投射的核心公式一列像素对应一条射线在射线投射中屏幕不是按“像素点”去画的而是按“竖线”去画。假设舞台宽 480 像素渲染分辨率设置成 120 列那么每列宽度就是 4 像素。每一列对应一条射线这条射线从摄像机位置出发插入迷宫地图中。射线投射的几个关键变量摄像机位置posX、posY。摄像机方向向量dirX、dirY。投影平面向量planeX、planeY。方向向量决定玩家朝哪个方向看投影平面向量决定视野宽度。对屏幕第 x 列可以算出这一列对应的射线方向cameraX (2 * x) / W - 1 rayDirX dirX planeX * cameraX rayDirY dirY planeY * cameraX射线进入地图后沿着网格一格一格前进直到撞到墙。撞墙后得到一个垂直距离 perpDist墙的高度就由这个距离决定lineHeight H / perpDist这里的 H 是屏幕高度。距离越远height 越小墙看起来就越矮距离越近墙越接近整个屏幕。这种“距离越远物体越小”的投影关系就是 3D 感的来源。特别要注意计算墙高时用的是“垂直距离”不是射线从摄像机到墙的直线距离。如果使用直线距离左右两侧的墙会向外膨胀画面出现明显的鱼眼变形。垂直距离可以消除这种变形。1.3 恐怖感从哪里来视野、明暗和声音才是重点很多初学者以为恐怖游戏必须有精细的贴图和复杂的 3D 模型。在 Scratch 项目里真正决定恐怖感的是三件事视野限制、明暗层次、声音节奏。设计元素实现方式效果第一人称视角射线投射画墙玩家直接代入角色视野限制超过一定距离不画墙玩家看不到远处被迫前进黑暗空间渲染后叠一层半透明黑色遮罩降低可见度制造压迫感惊吓点走到指定区域后广播事件突然出现怪物造型和声音音效节奏循环低频环境音持续制造紧张情绪在后续实现中渲染部分只负责“三维空间感”气氛部分靠黑幕、视野截断和广播事件完成。这样设计的好处是代码清晰玩家体验也不会因为缺少贴图而崩塌。2. 素材与地图准备把迷宫变成程序读得懂的数据做射线投射前必须先有一张“逻辑地图”。地图不是图片而是程序可以逐格读取的数据。用 Scratch 的列表保存地图是最直接的做法。2.1 环境准备哪套 Scratch 环境最适合做渲染实验建议使用 Scratch 3.0 官方在线编辑器或桌面版并手动添加“画笔”扩展。射线投射会大量使用画笔的“落笔”“抬笔”“移动”和“全部擦除”积木。项目建议推荐环境Scratch 3.0 网页版或桌面版舞台分辨率480 x 360渲染列数80 到 120 列所需扩展画笔扩展前置技能变量、列表、广播、自定义积木如果网络不稳定也可以使用 Scratch 桌面版。离线版和在线版在画笔积木上基本一致不会影响项目迁移。2.2 地图矩阵设计0 是路1 是墙2 是门地图可以用一个字符串列表表示。每一行是一个字符串每个字符代表一个格子。比如1111111111 1000000001 1011110101 1010000101 1010111101 1000000001 1010000001 1111111111在这个迷宫地图里“1”表示墙“0”表示可以走的空地。最外面一圈全是“1”保证玩家不会走出地图范围。在 Scratch 中可以把每一行作为列表mapRows的一项读取某个坐标的字符时用第 (mapC) 个字符第 (mapR) 项具体来说如果玩家位置是 posX、posY那么它对应的格子列号和行号可以这样计算mapX 向下取整 (posX) 1 mapY 向下取整 (posY) 1因为 Scratch 列表下标从 1 开始而 posX 从 0 开始所以计算时要加 1。下面示例地图中如果玩家初始位置是 (1.5, 1.5)对应的地图格子是第 2 行第 2 列字符是“0”玩家就能正常移动。地图设计要注意几点每行字符数必须一样否则读取会错位。边界必须是墙“1”。玩家出生点不能是墙。如果想做“门上锁”可以再加字符“2”在移动逻辑里单独判断。2.3 精灵与舞台设计只有一个观察者其余靠画笔这个项目里的“角色”不一定要是一个可见的小猫精灵。射线投射依靠画笔在舞台上画墙所以可以专门用一个画笔精灵负责绘制。项目结构可以设计成画笔精灵隐藏状态执行所有射线投射和画线操作。黑幕精灵一个全屏的黑色造型用“虚像”效果控制透明度用来压暗画面。怪物精灵平时隐藏广播“惊吓事件”后突然显示。舞台背景纯黑色。变量和列表统一放在画笔精灵中方便管理。隐藏画笔精灵后仍然可以使用画笔积木绘制内容这是 Scratch 画笔的常用技巧。为了避免玩家看到精灵自身建议所有绘制精灵都设为隐藏。主循环里也不需要真的“移动角色”只需要更新摄像机的变量值然后重新绘制一帧。3. 第一人称摄像机移动、旋转和碰撞检测“摄像机”在 Scratch 中不是一个精灵而是一组变量。玩家的移动、转身、渲染都在修改这些变量。理解了摄像机模型后面的渲染函数才会顺畅。3.1 摄像机变量位置、方向、投影平面一个完整的射线投射摄像机需要这些变量变量名含义初始值示例posX玩家在地图中的 x 坐标1.5posY玩家在地图中的 y 坐标1.5dirX摄像机方向向量的 x 分量1dirY摄像机方向向量的 y 分量0planeX投影平面向量的 x 分量0planeY投影平面向量的 y 分量0.66speed移动速度0.08rotSpeed旋转速度0.06方向向量指向玩家“正前方”投影平面向量定义了屏幕左右方向。当方向向量接近正 x 方向时投影平面接近正 y 方向两者保持垂直视野才不会变形。初始化伪代码定义 初始化摄像机 将 [posX v] 设为 (1.5) 将 [posY v] 设为 (1.5) 将 [dirX v] 设为 (1) 将 [dirY v] 设为 (0) 将 [planeX v] 设为 (0) 将 [planeY v] 设为 (0.66)这里 planeY 设置为 0.66对应大约 60 度到 70 度的水平视野。值越大画面越宽但边缘变形越明显值越小视野越窄越像“望远镜”效果。3.2 前后左右移动和旋转的数学公式移动很简单向前走就是把摄像机位置沿方向向量移动一小段距离。posX posX dirX * speed posY posY dirY * speed向后走就是用减号向左扫射可以用投影向量的反方向向右扫射可以用投影向量的正方向posX posX - planeX * speed posY posY - planeY * speed旋转比较复杂。旋转时方向向量 dir 和投影平面向量 plane 都要同时旋转。旋转公式如下oldDirX dirX dirX oldDirX * cos(角度) - dirY * sin(角度) dirY oldDirX * sin(角度) dirY * cos(角度) oldPlaneX planeX planeX oldPlaneX * cos(角度) - planeY * sin(角度) planeY oldPlaneX * sin(角度) planeY * cos(角度)Scratch 的三角函数积木使用角度制不需要手动转换弧度。左转和右转就是把“角度”传成正数或负数具体正负方向可以在测试时调整。定义 旋转摄像机 (旋转角度) 将 [oldDirX v]
返回列表