1680 字
8 分钟
灵魂碎片 - 我是怎么做这款酒店恐怖迷宫的

灵魂碎片#

先玩再说#

又做了一款浏览器里就能开的 3D 游戏:灵魂碎片(副标题 Monkey Business)。

第一人称,酒店走廊迷宫,收集紫色灵魂碎片,躲开 Murder Monkey(血猴),再跑回电梯逃脱。有 3 条命,还有 NodeLoc 登录后的个人速通榜。

http://pacman.zard.loc.cc/

建议桌面端 Chrome / Edge,鼠标锁定视角后手感最完整。敏感者注意:有黑暗走廊、追逐惊吓,以及开局的光敏癫痫提示。

一开始不是酒店#

最早的计划其实是「中世纪地牢 + 火把 + 找出口」。文档里还写着 CDN 拉 Three.js、零构建、中文注释——方便自己和非技术朋友直接双击就能看懂。

后来越做越歪,最后对齐的是 Dark Deception 那一套节奏:

  1. 乘电梯进入窄走廊
  2. 在怪物巡逻下刮图收集
  3. 集齐后出口开启,回家路上再加码封锁
  4. 跑回电梯才算赢

舞台也就从地牢换成了维多利亚风酒店走廊:米色墙纸、深色木门、铜制房号、暖黄顶灯、黄铜电梯门。敌人定成血猴,名字直接叫 Murder Monkey。

玩法核心#

数值 / 说明
迷宫35×35,递归回溯生成,再打通环路 + 挖小广场
碎片110 颗紫色八面体,InstancedMesh 批量渲染
初始血猴6 只巡逻
逃脱封锁电梯开启后再刷 6 只,优先堵回家路线
生命3 次,被抓会有扑脸特写
宝石青宝石眩晕、橙宝石小地图显怪 30 秒

操作上:WASD + 鼠标,Shift 冲刺(体力无限,但脚步会暴露位置),V 是短时疾跑技能。空格掏出平板小地图,这点也是故意学 DD 的。

核心手感就一句话:跑得过猴子,但瞎冲会把自己喊死。 血猴追击速度大约 3.6,玩家跑步约 4.6;发现你时还会愣大概半秒咆哮,给你一次转身的窗口。

技术选型:故意零依赖#

整站没有打包器,没有 CDN,也没有外部贴图 / 音效 / 模型资源。

模块方案
渲染Three.js 放进本地 vendor/,ES Module 直接 import
贴图Canvas 像素画生成,NearestFilter,保留一点复古颗粒感
音效Web Audio API 振荡器 + 噪声,全程序化
模型BoxGeometry 拼体素(血猴、门、灯具全靠堆方块)
服务Node ≥18 内置 http,零 npm 依赖做静态站 + OAuth + 榜

这样做的好处很现实:分发简单、离线也能跑前端、部署时不用再管一堆静态资源 CDN 挂没挂。坏处也明显——美术上限被自己卡死了,只能靠灯光、雾、心跳和音效硬撑氛围。

本地启动:

Terminal window
npm start # http://127.0.0.1:8765/ ,会顺带起 OAuth / 速通 API

注意:不能双击 index.html。ES Module 在 file:// 下会跨域;纯 Python 静态服可以玩,但登录和排行榜要走 Node 那套。

几个我觉得值得写的点#

1. 迷宫不能是纯死胡同#

追逐游戏如果全是 DFS 死胡同,被咬住就只剩一条路等死。所以生成后会再打通一部分墙做环路,并挖几个 3×3 小广场,方便被追时变向、绕圈。

走廊也故意做得窄:格宽大约 2.35、墙高 3.25,逼近那种「酒店走廊贴着你跑」的压迫感,而不是开阔地牢。

2. 血猴 AI:巡逻 → 发现 → 追击 → 搜索#

状态机很经典:PATROL → SPOT → HUNT → SEARCH。寻路是网格四邻 BFS,追击时会节流重算路径,避免每帧全图搜。

听觉只吃冲刺脚步,视野大约十几格,还有视线遮挡。被抓时不做瞬间黑屏,而是 startFaceLunge 扑脸停在身前一小段时间——惊吓主要靠这一下。

3. 电梯是叙事,也是关卡边界#

开场不是直接扔进迷宫,而是走一轮过场:wait → ding → open → hold → walk → done。叮一声、门开、看一眼已点亮的走廊、自动走出、门再关上。

集齐碎片后门变绿、叮一声开启;同时 _spawnEscapeMonkeys 在靠电梯一侧刷封锁猴。出口和起点是同一个点——你要原路逃回去,这比「找到地图另一头的门」更折磨。

4. 点光太贵,所以装假灯#

Three.js 的 PointLight 一多就掉帧。走廊里灯具用 InstancedMesh 全量摆着好看,真正发光的点光只保留一个小池子(大约最多 10 盏)跟着玩家走。远景靠指数雾裁掉,抗锯齿也关了,pixelRatio 限到 1,整体偏性能优先的像素风。

墙体、碎片同样走实例化:几百格墙基本就是一次 draw call 的事。

5. 心跳是「距离感」的音画同步#

没有怪物 BGM 文件。靠近血猴时,程序化心跳会从大约 1.4 秒一次压到 0.35 秒,同时 HUD 红边强度跟着涨。威胁层还有一层锯齿波脉冲。氛围很大一块是靠这条链路撑起来的,而不是靠贴图精度。

6. NodeLoc 速通榜#

成绩只认 NodeLoc 账号,键是 nl:{id},游客能玩但不上榜。服务端用授权码 OAuth2 + 签名 Cookie,成绩落在本地 profiles.json,只保留个人最佳。

还做了很土但有效的防刷:通关时间短于 30 秒直接当异常拒收。

项目结构(人话版)#

js/
game.js 状态机、主循环、电梯过场、逃脱猴
maze.js 迷宫生成
world.js 酒店视觉 + 电梯
enemy.js 血猴 AI
shard.js 碎片
gem.js 技能宝石
player.js 第一人称与碰撞
audio.js 全程序化音效
auth.js 游客 / NodeLoc
ui.js 菜单、HUD、平板小地图
server/
oauth-nodeloc.js
leaderboard.js

没有物理引擎,碰撞就是网格判断;没有资源管线,纹理和声音都是代码里现画现响。整份工程更像「能跑通的游戏原型」,而不是引擎级框架。

写在最后#

这款游戏对我来说,更像一次约束条件下的完整闭环练习:从生成关卡、敌人 AI、演出过场,做到登录上榜和部署上线。美术全靠程序化硬撑,手感则一点点对着「窄走廊 + 收集 + 回家封锁」去磨。

如果你愿意试一把:先 NodeLoc 登录,再去刮那 110 颗碎片。跑回电梯的时候记得听脚步——有时候真正要命的不是眼前那只,而是你自己喊来的那几只。

下一篇如果有人催(游戏里第二关提示就是这么写的),可能会单独写血猴行为树怎么调,或者酒店材质/灯光是怎么从「地牢火把」改成现在这样的。

灵魂碎片 - 我是怎么做这款酒店恐怖迷宫的
http://blog.zard.loc.cc/posts/soul-shards-monkey-business/
作者
Zard
发布于
2026-07-22
许可协议
CC BY-NC-SA 4.0
评论