尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证REA City — 浏览器里 1:1 新加坡市中心开放世界生活模拟(Three.js + 真实开放数据)
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗浏览器里跑的开放世界:以 1:1 真实比例还原新加坡市中心约 4.8 × 2.8 km 的切片——滨海湾、莱佛士坊、牛车水、丹戎巴葛、中峇鲁、红山。路网、建筑足迹与高度、红绿灯、路灯、巴士站、MRT 出口、小贩中心都来自公开数据(OpenStreetMap、LTA DataMall、URA、HDB、NEA),离线烘焙成分块数据后流式加载。
玩法是生活模拟 + 四种身份:吃饭睡觉、上班打工、开车坐地铁,昼夜更替、雷雨天气、靠左行驶、交通罚单与警察追捕。默认身份是黑帮成员(唯一能开枪的身份),也可以在建角色界面选金领、白领、蓝领。
技术栈:Three.js 0.186 · Vite 8 · TypeScript(严格模式)。没有游戏引擎与后端,存档在浏览器 localStorage。
需要 Node ≥ 22(数据脚本直接运行 .ts)。
npm install
npm run dev # http://127.0.0.1:5173
npm run build # tsc 检查 + 打包到 dist/(多页:游戏 + dev/ 下三个工具页)
npm run check # 仅 TypeScript 类型检查
npm run preview # 预览构建产物(端口 4173)
node --test scripts/test/*.test.ts # 单元测试(碰撞、分块编解码)
public/world/sg/(约 11 MB 分块世界)与 public/assets/characters/(约 4.5 MB 角色库)已随仓库提供,不跑数据流水线也能直接玩。
| 参数 | 作用 |
|---|---|
world=grid | 改用程序生成的方格城(旧原型,回归测试基线);默认 sg 真实新加坡 |
role=gang|gold|white|blue | 临时指定身份(覆盖建角色结果,便于测试) |
fresh=1 | 忽略存档开新局,并打开建角色界面 |
creator=1 | 打开建角色界面(以已保存的角色为初值) |
chars=box | 用方块人代替骨骼角色(低配 / 排错) |
shadows=0 | 关闭实时阴影 |
music=0 | 关闭背景音乐(手机设置页也可开关;步行为轻柔氛围乐,驾车切换为车载电台) |
law=relaxed / law=real | 执法松紧。默认 casual 畅玩:只有撞人、枪击行人、攻击警察、开枪打车会招来警察,闯红灯 / 超速 / 碰撞 / 抢车 / 酒驾 / 街头赛都不追究。relaxed 恢复交通罚单(闯红灯宽限/冷却、扣 6 分,小额碰撞不立即出警,警察更慢、被捕需贴住 4 s);real 接近原版严格度。只认 URL,不存进本地设置 |
signs=0 | 关闭文字街景(路名牌、招牌、站牌等) |
props=proc | 行道树改回程序化圆锥树(默认用 threejsassets 低模阔叶树,低配可用此项省约 30 万三角面) |
fx=high|low|off | 画质:high 默认(pmndrs/postprocessing 管线:AgX + N8AO + 泛光 + 调色/颗粒/暗角/色差;物理天空 + 高度雾 + 三级联阴影 CSM 约 350 m;电影化:丁达尔光束、太阳鬼影、胶片 LUT、手持晃动、开车速度 FOV 与边缘速度模糊);low 关 AO/天空/CSM/电影化、半分辨率泛光、高分屏后期封顶 1.25 倍;off 直出(仍保留 AgX 与环境光)。街景细节(P14):high/low 用程序化外墙(凹窗、室内映射夜窗、HDB 走廊/店屋五脚基/玻璃幕墙风格)、沥青/地砖/路缘着色器、Standard 道具与树叶透光,玩家周围 3×3 块加女儿墙/檐口/檐篷柱廊/屋顶设备/空调外机/楼前铺装;off 退回平涂窗格。手机设置页「画质」可切换 |
detail=0 | 关闭 P14.2 建筑几何细节件(对比开销用) |
facdetail=0 | 关闭 P14.6 近处外墙照片扫描细节(fx=high 才有;前后对比用) |
cine=0 | 关闭 high 档的电影化效果(光束/鬼影/LUT/手持/速度 FOV/速度模糊),便于对比与排查;控制台 __game.fx.cine 可单项调强度 |
lang=zh|en | 界面语言(默认跟浏览器语言;开局右上角或手机设置「语言 / Language」可切换,切换后页面重载、存档保留)。新增界面文字一律写 t('中文') 并在 src/i18n/en/ 补英文,npm run i18n:check 检查 |
timeSpeed=N | 游戏时钟倍速 |
bright=0.7–1.6 | 画面亮度倍率(默认 1,乘到曝光上;夜里嫌暗可以调高,例如 ?bright=1.2)。手机设置页的「亮度」滑杆(70–160%)是同一个设置 |
air=0 | 不加载滨海南机场(填海岛、堤道、航空插件都不出现;排查或对比开销用) |
invertPitch=1 | 飞行俯仰反转(默认 W = 推杆、机头向下) |
story=0 | 关闭漫画剧情过场(剧情图在 public/assets/story/,缺图时也会自动跳过) |
racedbg=1 | 赛车 AI 调试:每帧记录 AI 决策文字(__game.plug.race.state().ai[i].dbg) |
线上地址 https://rea.alextang.dev。配置在 wrangler.jsonc:目前没有 main,dist/ 全部作为静态资源上传,请求不经过 Worker 代码,免费且不限流量。缓存头在 public/_headers:assets/*.js|css 带 hash,长期缓存;角色、道具、LUT、world/ 文件名固定,缓存 1 天;index.html 不缓存。
npx wrangler login # 首次:浏览器登录 Cloudflare
npm run deploy:cf # 构建 + 上传;自定义域 rea.alextang.dev 由 routes.custom_domain 自动建 DNS 与证书
部署前先跑 npm run promo:build:宣传图与剧情过场图不入库(见下方「宣传素材」),只随 dist/ 上传;本地没有 public/assets/promo/、public/assets/story/ 时线上就会缺 OG 图、标题背景与剧情图(游戏会自动降级,但分享卡片会没图)。
限制(免费版):每个版本最多 20,000 个文件、单文件不超过 25 MiB,目前 dist 约 250 个文件、最大 3.7 MB。账号与云存档的后端设计(同一 Worker + D1)和各云平台费用对比见 docs/ACCOUNTS.md。
| 按键 | 作用 |
|---|---|
| W A S D / 方向键 | 步行移动 / 驾驶 |
| Shift | 奔跑 |
| Space | 跳跃(步行) / 手刹漂移(驾驶) |
| F | 上车 / 下车(可抢 NPC 车);开的士时接招手乘客 |
| E | 进入附近地点(小贩中心、商店、MRT、住家、办公楼、工地、的士站…) |
| Tab | 手机:状态、工作、地图、角色(衣柜)、设置、存档 / 读档 / 重新开始 |
| H | 鸣喇叭(驾驶时) |
| M | 当前任务提示 |
| Enter | 切换全屏 |
| 鼠标 | 转动视角(点击画面锁定指针,Esc 解锁) |
| 鼠标左键 / 左 Ctrl | 手枪射击(仅黑帮身份;锁定指针时自动过肩瞄准) |
| Esc | 关闭面板 / 解锁鼠标;建角色界面中返回 |
开飞机(Phase AIR):机库或停机位旁按 F 登机。W / S 俯仰(W 推杆机头向下,?invertPitch=1 反转),A / D 横滚(地面兼作前轮转向),Q / E 方向舵,Shift / Ctrl 加减油门,Space 刹车(任务中为拍照 / 投放),V 追尾 / 座舱视角,T 定高定向(装了航电,手动操作即断开)。地面且速度 < 3 m/s 时按 F 下机。
触屏手机(自动识别粗指针设备;桌面可用 ?touch=1 强制开启):左半屏浮动摇杆移动 / 驾驶(推到底奔跑),右半屏拖动转视角;右下角「上车/下车」「交互」「跳/手刹」「跑」「开火」(黑帮,按住时过肩瞄准)「喇叭」(驾驶时);顶部「手机」「任务」「全屏」。手机抽屉右上角 × 关闭。竞技场 FPS 暂不支持触屏。
| 身份 | 出生 / 住家 | 初始现金 | 特点 | 工作 |
|---|---|---|---|---|
| 黑帮成员(默认) | 牛车水 52 Pagoda Street | $500 | 可开枪;犯罪累积通缉星、警察追捕 | 偷车交货、收保护费、街头破坏,及三条主线任务 |
| 金领 | 滨海湾 The Sail | $20,000 | 奢侈消费线 | 赶会议、投资(定存/指数/加密,每天 07:00 结算)、上班 |
| 白领 | 中峇鲁 78 Moh Guan Terrace | $2,000 | 房租压力 | 上班打卡(09:00–18:00)、加班(18:00–22:00) |
| 蓝领 | 红山 131 Jalan Bukit Merah | $300 | 房租压力,需求消耗 ×1.3 | 租的士载客、外卖、工地搬运 |
非黑帮身份的犯罪会降级为交通执法(罚单 + 扣分),不会触发通缉。每个身份开局都有一条新手引导任务。
饥饿与精力两条需求随游戏时间下降;偏低时减速、屏幕出现暗角,精力归零会昏倒。小贩中心(海南鸡饭、叻沙、Kopi…)和商店补饥饿,回家睡觉恢复精力。
?law=relaxed / ?law=real 下:超速、闯红灯、撞车会开罚单(扣钱 + 扣分),扣满 24 分吊销驾照一天;警署可查记录。npm run econ:sim 检查(含心情倍率和每晚娱乐花费模型);赌场 RTP 用 npm run casino:sim 检查。四个场馆在小地图上是不透明大点,离得远时钉在小地图边缘指示方向;手机「赛车 / 竞技 / 赌场 / 联系人」页顶部有场馆卡(营业时间、距离、【导航】),点导航后小地图和 HUD 指向场馆门口,走到 15 m 内自动取消。门口按 E 打开面板。打烊时面板只剩少数全天按钮(如赛道日)。
| 场馆 | 位置(sg 门口坐标) | 营业 | 玩法 |
|---|---|---|---|
| 滨海湾金沙赌场 | 滨海湾 (1319, 145) | 24 小时 | 21 点、轮盘、骰宝、百家乐、老虎机 |
| 克拉码头夜店 | 克拉码头 (66, −704) | 21:00–04:00 | 门票、点酒、节奏舞蹈、VIP 卡座、搭讪 / 约会 |
| 滨海湾赛道 | 摩天轮旁维修区 (1825, −790) | 20:00–04:00(赛道日 08:00–18:00) | 街头赛、合法赛道日 |
| 丹戎巴葛射击俱乐部 | 丹戎巴葛 (27, 563) | 24 小时 | 5v5 爆破、天梯、职业联赛、1v1、死斗 |
方格城(?world=grid)也有这四个场馆。
?law=relaxed|real 下醉驾被 40 m 内看得见你的警车(包括路边设卡的警车)发现:罚款 $2,000、扣 12 分、通缉 1 星;默认畅玩档不查酒驾。舞蹈是 124 BPM 四轨节奏游戏,用 ←↓↑→ 或 A S W D 按键,判定窗口 Perfect ±60 ms / Good ±130 ms;每晚前两曲加心情,跳得好会吸引 NPC 过来搭话。VIP 卡座需要 Lv3,最低消费 $300,全额转成当晚的酒水额度。?law=relaxed|real 下非黑帮身份跑街头赛被巡警看到会得 1 星(默认畅玩档不会)。白天的合法赛道日会封路清场,没有通缉风险,奖金较低。滨海湾大奖赛需要 Lv6。报名面板可选对手水平(见下)。| 竞技场按键 | 作用 |
|---|---|
| W A S D | 移动 |
| 鼠标 | 瞄准(点击画面锁定指针) |
| 鼠标左键 | 开火;拿着手雷时松开左键投出;拿着 C4 时按住左键下包 |
| 鼠标右键 | 开镜(AWP 两档)/ 刀重击 |
| Space | 跳 |
| C | 蹲(不用 Ctrl,避免 Ctrl+W 关掉标签页) |
| Shift | 静步(没有脚步声) |
| 1 / 2 / 3 / 4 / 5 | 主武器 / 副武器 / 刀 / 手雷(再按一次换下一种雷)/ C4 |
| 滚轮 | 依次切换武器 |
| Q | 切回上一把武器 |
| R | 换弹 |
| B | 购买菜单(数字键选类别和物品) |
| E | 下包 / 拆包(按住) |
| Tab | 计分板(按住) |
| Z | 给队友下指令:自由行动 / 跟我 / 守住这里 |
| Esc | 暂停菜单(可以投降退出) |
?bright=1.2(范围 0.7–1.6),或者在手机设置页拖「亮度」滑杆。城市南边海上的虚构填海机场「滨海南机场」(跑道 09/27,长 1200 m),从 Marina Coastal Drive 南端走堤道上岛,叫车「出行」页可以直接去。航站楼、机库、塔台都是 airport 类 POI。
law=relaxed|real 下低空(< 120 m)飞越 CBD、降落在马路上会记通缉热度;默认畅玩档不管。在家睡觉会自动存档,住家面板也可手动存档;手机里有「存档 / 读档 / 重新开始」。存档、角色外观、设置分别保存在 localStorage。
脚本在 scripts/geo/,原始数据与中间产物在 data/(已 gitignore),最终产物写到 public/world/sg/。需要 GDAL(ogr2ogr)。详细说明见 scripts/geo/README.md。
| 命令 | 步骤 |
|---|---|
npm run geo:download | 00 下载原始数据到 data/geo/raw/ |
npm run geo:extract | 01 用 ogr2ogr 按切片范围提取为 GeoJSON |
npm run geo:project | 02 投影到本地米制坐标(原点 103.8465E, 1.2825N)并裁剪 |
npm run geo:all | 依次运行下面 7 步(不含 00–02) |
geo:roads | 03 车行道路网图(车道数、单行、信号灯路口、强连通裁剪;丢弃有盖/地下/停车场通道等 service 路及穿楼 service 边) |
geo:buildings | 04 建筑足迹与高度(OSM height/levels → HDB 层数 → URA GPR → 默认值)及分类;跳过悬空/屋顶/天桥/地下体,压车行道的剔除或裁剪 |
geo:landuse | 05 土地用途栅格 → 地面贴图 |
geo:props | 06 LTA 道具点位(路灯、红绿灯、巴士站、的士站、ERP、MRT 出口、有盖走廊、天桥) |
geo:pois | 07 POI(住家、办公楼、小贩中心、MRT、警署、医院、地标、商店) |
geo:roadmesh | 08 路面网格 |
geo:chunks | 09 按 256 m 分块打包 → public/world/sg/(分块、天际线、小地图、manifest) |
geo:check | 净空检查:压车行道的建筑、地铁出口、穿楼车道边(--list 列明细,--strict 不为 0 时退出码非 0) |
原始数据来源:
角色资产:npm run char:build 把 Quaternius Ultimate Modular Men / Women(放在 data/assets-eval/)打包成 public/assets/characters/characters.glb + catalog.json(46 个部件、24 段动画、14 个预设),说明见 scripts/char/README.md。
机场模型:npm run airfield:build 把 threejsassets「Airfield — Small Airport Kit」的 22 个免费 GLB(放在 data/assets-eval/threejsassets/airfield/,需登录下载)打包成 public/assets/airfield/airfield.glb(meshopt 压缩,约 1.2 MB;--inspect 打印各模型尺寸)。
外墙细节贴图:npm run facade:build 从 ambientCG(CC0)下载 4 种照片扫描材质(缓存在 data/assets-eval/ambientcg/),处理成亮度细节 + 法线拼成 public/assets/facade/detail.webp(需系统 unzip、cwebp)。只在 fx=high 加载,?facdetail=0 关闭。
宣传素材:npm run promo:build(需系统 cwebp,用 Playwright 无头 Chromium 在 canvas 上合成)。源图是用 どこでもロケハン 把真实新加坡街区渲染成的黑白漫画线稿 + 网点 PNG:public/assets/promo/src/skyline_dusk.png、skyline_night.png(滨海湾远景)、chinatown.png、raffles.png,以及剧情过场图 public/assets/story/*.png。脚本输出 public/assets/promo/ 下的 banner.webp(README 头图 1600×500)、og.png(分享卡片 1200×630)、cover.png(itch 封面 630×500)、title-bg.webp(开始 / 加载画面背景,≤ 400 KB),并把 story/*.png 转成同名 .webp(宽 1600,已是最新则跳过);源图缺失只提示并跳过。该工具条款禁止再分发原始导出文件,所以源图和合成结果都 gitignore、不入库,只随部署上传;合成时会重新写上「© OpenStreetMap contributors · © OpenMapTiles · Terrain Tiles」署名(原图右下角的署名常被裁掉)。开始画面缺 title-bg.webp 时保持原来的纯色遮罩。源图的拍摄地点、机位和重拍脚本(node scripts/story-art/shots.mjs scripts/story-art/shots.json)见 docs/STORY-ART.md。
道具模型:npm run props:build 把 threejsassets.com 免费模型(Draco GLB,放在 data/assets-eval/threejsassets/,需登录下载)解压合并成 public/assets/props/props.glb(运行时不需要 Draco 解码器)。
src/
main.ts, config.ts 入口;全局参数(车辆手感、尺寸、NPC 上限)
core/ Game(主调度、状态机、window.__game)、Camera(追尾/过肩相机)、Input、Context(共享上下文与事件总线)、Settings(URL/本地设置)
world/ WorldSource(世界数据源接口)
SgWorld、ChunkManager、ChunkFormat、BuildingMesh、PropMeshes、RoadMarkings、Landmarks、Signage、TextAtlas 真实新加坡
GridWorld、CityGenerator、GridGraph 方格城
Airfield、AirfieldMesh、AirfieldModels、RunwayShader、HeightField 滨海南机场
RoadGraph、Pathfinder、Colliders(多边形 + 空间哈希 + 射线)、PoiMarkers、Marker
physics/ ArcadeVehicle(街机车辆)、ArcadeFlight(街机固定翼)、Collision
entities/ Player、Aircraft、Vehicle(轿车/MPV/SUV/跑车/巴士)、Pedestrians、TrafficAI、PoliceAI
characters/ CharacterLibrary、CharacterInstance、CharacterSpec、presets 骨骼角色运行时
systems/ Clock、DayNight、Weather、Signals、Law、Needs、Poi、Interactions、Jobs、Quests、Save、Spawner、Weapon、Audio、Wallet、NightLights
activities/ Plugin(娱乐插件接口)+ casino / club / race / arena / aviation 五个玩法插件
data/ roles、jobs、quests、menus、venues、casino、dates、races、arena、mood 身份、工作、任务、菜单、场馆、娱乐与经济参数
ui/ Hud、Minimap、Phone、Panels、Creator(建角色界面)、Activity(娱乐小游戏的全屏宿主)
dev/ worldViewer、charsViewer、creatorViewer 开发工具页脚本
scripts/
geo/ 数据流水线 00–09 + lib/
char/ 角色资产打包
test/ node --test 单元测试
public/world/sg/ 烘焙好的世界数据
public/assets/characters/ 角色库
launcher/ macOS 桌面启动器
npm run dev 后打开:
/dev/world.html — 新加坡世界查看器。WASD 平移、Shift 加速、鼠标拖拽环绕、T 顶视图;1–4 四个住家,5 MBS,6 Raffles Place,7 鱼尾狮,8 滨海艺术中心,9 摩天轮,0 老巴刹,G 超级树,P 达士岭,M 马里安曼庙。参数 hour=、x=&z=、shadows=0、signs=0。/dev/chars.html — 角色库与预设查看器。/dev/creator.html — 建角色界面独立测试页。window.__game浏览器控制台可用,主要供自动化测试:
stats(fps / draw calls / 三角形 / NPC 数)、world(加载耗时、区块统计)、player、role、wanted、cars、peds、policeteleport(x, z)、teleportTo(poiId)、pois.list()clock.set(hour)、clock.skip(h)、weather.set('clear'|'cloudy'|'storm')、dayNightneeds.set(h, e)、interact(poiId)、panel.choose(i)、phone.show('work')、jobs.start(id) / jobs.state、quests.*、save() / load()law.crime() / law.traffic()、signals.*plug.aviation.rent() / board() / place(x, y, z, spd, hdg) / autopilot(...) / state / jobs / start(id) / autofly() / own(id) / lineUp();window.__airfield(机场网格统计)camShot([dx,dy,dz,lx,ly,lz])(相对玩家的相机位置与注视点)、gatherPeds(r)、creator.state()launcher/make-app.sh launcher/icon-mac-1024.png # 生成 ~/Desktop/REA City.app
launcher/make-app.sh launcher/icon-mac-1024.png /Applications
双击 REA City.app:源码有改动时自动构建,启动 vite preview(127.0.0.1:4173),并用 Chrome 独立窗口打开。构建日志 /tmp/rea-build.log,服务日志 /tmp/rea-preview.log。
public/assets/characters/LICENSE-quaternius.txt)。public/assets/promo/、public/assets/story/ 已 gitignore,只随线上部署)。npm run facade:build 生成 public/assets/facade/detail.webp,随仓库提交)。public/assets/props/、public/assets/airfield/ 已 gitignore)。克隆后直接运行时会自动退回程序化行道树、机场占位与程序化 Cessna,控制台只有 [props] / [airfield] / [aircraft] 降级 warning。要用真模型:到 threejsassets.com 登录下载对应免费模型放进 data/assets-eval/threejsassets/,再跑 scripts/props/build.ts 与 npm run airfield:build。