做一间「会过日子的房间」——小鲸鱼房间制作攻略

一句话:一张等距插画,加上时钟、天气和几个能点的地方,就能让人物「住」进去。 这份攻略按我们实际做了一遍的顺序写,照着走就能做出同款;不需要建模,也不需要美术基础。

0. 先看效果(30 秒)

打开房间页,你会看到:

这些都不需要 3D,也不需要一张图一张图地做——一张底图 + 一层光 + 几个透明层就够了。

1. 需要准备什么

东西说明从哪来
一张等距底图建议 3:2(我们用 1536×1024),画面里家具按 2:1 等距摆放自己画 / AI 生成 / 找画师(关键:光和影要中性一点,别把夕照画死)
一个能放静态文件的地方本地就行:任何 http 服务、或者你已有的桥接/后端python -m http.server 都可以
一点点时间概念4 个时段:清晨 6–11 / 中午 11–14 / 下午 14–18 / 晚间 18–6攻略里给了现成代码
可选:人物的几个姿态坐、读书、睡觉,透明 PNG没有也行,先做静态房间

别做的事:一开始就想要 12 张图(4 时段 × 3 天气)。做完你会发现不需要——天色是叠上去的,底图只要一张。

2. 三步做出最小版

第一步:把底图放进页面(5 分钟)

到这一步你已经有「一张静态房间」了。先把构图调满意,后面所有坐标都基于这张图,改构图等于全部重标。

第二步:加天色和天气(30 分钟)

新建 environment.js,核心就两张表:

然后不要直接去调底图的颜色,而是:

天气就三层 SVG 元素叠上去:

关键一点:box-shadow、blur、mix-blend-mode 在大多数浏览器里都不贵,但粒子数量别超过 150 个,手机上也才稳。

第三步:能点的地方(30 分钟)

热区不写在代码里,写成一个 JSON:

坐标是底图 viewBox 坐标(1536×1024),不是屏幕坐标。屏幕坐标会被缩放,用 svg.getScreenCTM().inverse() 反算回去。

鼠标移上去显示文字提示,点一下拉一个接口把内容取回来:

内容从哪来随你:日记、待办、书、天气——只要接口能返回 {title, lines[]},抽屉就能显示。

3. 想做得更好:三个可选升级

A. 手动标注热区(强烈建议)

别用眼睛估坐标。加一个 ?calib=1 模式:

手绘多边形用 Douglas–Peucker 抽稀(阈值 5 就够),一个圈通常剩 8–12 个点。 数据结构:{ id, label, rect, poly: [[x, y], ...] },rect 是 poly 的外接框,判断用 poly。

我们踩过的坑:重新标注后 id 变成了 area1、area2,后端还在按 bed、shelf 查,于是所有点都显示「这里还空着」。 解法:让后端留一张「名字 → 语义 id」的反查表(床/书架/窗户/桌子/椅子/软垫/绿植/台灯/抽屉),id 不认识时用 label 找。

B. 灯和夜

C. 让人物有状态

如果这个房间是给某个 AI 角色住的,可以做一个 /api/room/her:

判断逻辑随便你定,我们用的是:潜水模式 + 安静超过 12 分钟 → 睡觉;45 分钟内看过书写过笔记 → 趴着看书;否则坐着。 前端根据 pose 叠不同的透明 PNG,锚点对齐到床或地毯。

注意:底图里已经画好的人物,要么单独出一张「空床」底图,要么在叠之前把原人物遮住——否则会出现两个她。

4. 接进桌面客户端(可选)

如果房间要放进 Electron / DSH 这类客户端,最省事的做法是:

1. 房间页保持纯静态(index.html + assets/ + 未压缩的 app.js,双击能开、不依赖 CDN) 2. 客户端里用一个全屏 iframe 指向它 3. 需要传参数(比如 ?calib=1)就改 iframe.src,不要试图跨域操作 iframe 内部

我们踩过的坑:<img src="http://127.0.0.1:3100/..."> 发不出自定义鉴权头,图加载失败、页面全白。 解法:要么给静态站点免鉴权(只监听 127.0.0.1 时可接受),要么用 fetch 取 blob 再 URL.createObjectURL。

5. 常见坑(都是真踩过的)

坑现象解法
改了文件像没改页面还是旧样式脚本加版本号 app.js?v=2,服务端注入的脚本也要同步 bump
坐标对不上点窗户点到墙用 getScreenCTM() 反算,别按屏幕像素写死
叠素材叠歪出现两盏灯、两个人底图里画过的东西别再用 PNG 叠;要叠就得按底图量尺寸
缓存换了图片不变图片用新文件名,别原地覆盖(max-age 会记住)
中文文件被写坏一堆 锟斤拷改 UTF-8 文件用 Node 读写,别用 PowerShell 的 Get-Content -Raw + Set-Content
面板挡住点击抽屉关了又像没关抽屉别贴着鼠标放,按左右半屏放另一侧

6. 速通清单(照着勾)

做完大概 1 天(不含画图)。最花时间的是底图和热区坐标,代码部分其实很少。

7. 我们这版的文件结构(可以参考)

配套:

这份攻略来自「小鲸鱼房间」的真实制作过程:同一张等距图,靠几层叠加和一点点状态切换,做出白天夜晚、晴雨雪天,没有一张图是为某个天气单独画的。 想直接抄:随便挑一个能跑静态页的地方(本地开个服务、GitHub Pages、任意静态托管都行),从第 2 节的第一步开始。