• Anny

    图片

    图片

    hy3似乎跑的很快,然后ox有点慢。```

    《微光大陆》—— 纯前端 Three.js 开放世界探索游戏 · 完整实施计划(交接版)

    本文档面向执行实现的 Agent / 开发者,包含全部技术决策、模块规格、关键算法、参数数值与验收标准。
    按本文档自上而下实施即可完成整个项目,无需额外上下文。


    〇、当前项目状态

    • 目录:C:\Users\32382\Desktop\demo(除下述文件外为空)
    • 已存在:package.json(name=gleaming-continent,type=module,scripts: dev/build/preview)
    • 依赖尚未安装(安装操作被取消)。第一步必须执行:
    npm install three simplex-noise
    npm install -D vite```
    - 环境已验证:Node v24.17.0 / npm 12.0.2 / Windows (win32)
    
    ---
    
    ## 一、目标与视觉定位
    
    - **玩法定位**:探索冒险。玩家在程序化无限大陆上自由漫游,发现生态群系,采集资源、猎杀/躲避生物、制作装备,无强制目标。
    - **美术风格**:低多边形(Low-Poly)扁平着色 + 顶点色。全部资产由代码程序化生成(几何体拼装树木/岩石/角色),**零外部资源依赖**(无模型/贴图/音效文件)。
    - **纯前端**:仅浏览器运行,无任何后端。
    
    ## 二、技术选型
    
    | 项 | 选择 | 说明 |
    |---|---|---|
    | 构建 | Vite(devDependencies 最新稳定版) | 零配置即可,无需 vite.config.js |
    | 渲染 | three(npm 最新稳定版) | 仅用核心包,**不使用 examples/addons** |
    | 噪声 | simplex-noise v4 | API:`import { createNoise2D } from 'simplex-noise'`;`createNoise2D(rngFn)`,rngFn 返回 [0,1) |
    | 随机 | 自写 mulberry32 种子随机 | 世界按 seed 完全可复现 |
    | 语言 | 原生 JavaScript(ES2022,ESM) | 不用 TypeScript |
    | UI | DOM 叠加层(HTML/CSS),非 canvas 绘制 | 程序化创建 DOM,无需前端框架 |
    
    ## 三、目录结构(实现必须遵循)
    
    ```demo/
    ├─ index.html # 挂载点:<div id="app"> + <script type="module" src="/src/main.js">
    ├─ package.json # 已存在
    ├─ src/
    │ ├─ main.js # 入口:装配 Game 并启动
    │ ├─ config.js # 全局常量集中定义(见 §五.0)
    │ ├─ style.css # 全部 UI 样式(由 main.js import)
    │ ├─ core/
    │ │ ├─ Game.js # 场景/渲染器/相机/时钟/主循环编排(见 §六)
    │ │ ├─ Input.js # 键鼠状态 + Pointer Lock 管理
    │ │ └─ EventBus.js # 极简 on/off/emit
    │ ├─ world/
    │ │ ├─ Noise.js # mulberry32 + WorldGen(高度/坡度/群系/颜色,见 §五.1)
    │ │ ├─ Chunk.js # 单块地形网格(顶点色,世界坐标烘焙)
    │ │ ├─ TerrainManager.js # chunk 流式加载/卸载调度
    │ │ ├─ Vegetation.js # 每 chunk InstancedMesh 散布植被/岩石/资源点
    │ │ └─ Water.js # 海平面水面
    │ ├─ env/
    │ │ ├─ SkyDome.js # 自定义渐变穹顶 ShaderMaterial + 日月盘 + 星星
    │ │ ├─ DayNightCycle.js # 昼夜推进与光照/雾色插值
    │ │ └─ Weather.js # 天气状态机 + 雨粒子
    │ ├─ entity/
    │ │ ├─ Player.js # 第三人称控制器:移动/跳跃/冲刺/游泳/相机
    │ │ ├─ CharacterMesh.js # 程序化低模人形 + 行走/挥击动画
    │ │ ├─ Creature.js # 生物基类:FSM + 受击/死亡
    │ │ ├─ Animal.js # 被动动物(鹿)
    │ │ └─ Monster.js # 敌对怪(史莱姆)
    │ ├─ systems/
    │ │ ├─ Spawner.js # 生物生成/回收 + 掉落物管理
    │ │ ├─ Combat.js # 扇形命中判定、伤害、无敌帧、回血
    │ │ ├─ Inventory.js # 物品数据与增删查、装备位
    │ │ ├─ Crafting.js # 配方定义与合成校验
    │ │ └─ Interaction.js # 准星目标查询 + E 键采集/拾取
    │ └─ ui/
    │ ├─ HUD.js # 血条/时钟/准星/交互提示/toast/受击红晕/死亡遮罩
    │ ├─ InventoryUI.js # 背包面板(Tab) + 合成面板(C)
    │ └─ LoadingScreen.js # 加载进度条 + 开始按钮 + 重置存档链接```
    
    ## 四、核心技术决策(不可偏离)
    
    1. **确定性高度函数**:`WorldGen.getHeight(x,z)` 直接采样噪声。chunk 网格顶点、玩家/生物贴地、相机避障、出生点选址**共用同一函数** → 全程无网格射线碰撞。
    2. **Chunk 规格**:48m×48m、32×32 分段(33×33 顶点)、可视半径 5 chunk(≈240m),卸载半径 6;每帧最多构建 2 个新 chunk(队列按距离排序);几何体直接烘焙**世界坐标**(mesh 位于原点),卸载时 `geometry.dispose()`(材质共享不释放)。雾效终点 ~210m 掩盖加载边缘。
    3. **顶点色代替贴图**:按高度带(水底深沙/沙滩/草地/岩石/雪顶)+ 群系色调 + 坡度混合着色,附加低频噪声做 ±6% 明度抖动;材质 `MeshLambertMaterial({ vertexColors:true, flatShading:true })`(现代 three 的 Lambert 支持 flatShading 与 vertexColors)。
    4. **植被实例化**:每 chunk 用种子随机(hash(cx,cz,seed))采样 ~90 个候选点,按群系散布表生成;同类型合并为一个 `InstancedMesh`(**先统计数量再分配精确 count**);instanceColor 做色彩抖动;可采集资源(树/岩/浆果丛)登记到空间注册表;采集后把对应实例矩阵置零缩放隐藏。
    5. **生物生命周期**:仅在玩家周围存活(上限 鹿12 + 史莱姆10),超出 180m 回收;生成环 40–130m 且必须在陆地(h>1)。不做对象池(实例创建成本低)。
    6. **战斗手感**:左键挥击扇形判定 + 冷却 0.5s;受击闪红 + 无敌帧 0.6s;脱战 6s 后 +4HP/s;死亡在出生点重生不掉落。
    7. **昼夜**:一天 = 现实 480 秒。t∈[0,1),小时数 = `(t*24+6)%24`(t=0 为清晨 06:00)。太阳仰角 `e = sin(t*2π)`。
    8. **存档(轻量)**:位置/背包/时间/血量/装备每 5 秒 + beforeunload 时写入 localStorage;加载屏提供「重置存档」链接。
    
    ---
    
    ## 五、详细规格
    
    ### 5.0 `src/config.js` 全局常量

    export const CONFIG = {
    SEED: null, // null=读存档或随机;实际值在 Game 里确定后传入各模块
    CHUNK_SIZE: 48,
    CHUNK_SEGS: 32,
    VIEW_RADIUS: 5, // chunk 半径
    UNLOAD_RADIUS: 6,
    CHUNKS_PER_FRAME: 2,
    SEA_LEVEL: 0,
    FOG_NEAR: 60, FOG_FAR: 210,
    DAY_LENGTH: 480, // 秒/游戏日
    GRAVITY: 26,
    PLAYER: {
    HP_MAX: 100, WALK: 5.8, SPRINT: 9.2, SWIM: 3.2,
    JUMP_V: 8.6, ACCEL_GROUND: 40, ACCEL_AIR: 12,
    SWIM_DEPTH: -1.1, // 地面低于 SEA_LEVEL+此值 → 游泳
    CAM_DIST: 7, CAM_MIN: 3, CAM_MAX: 12, CAM_TARGET_Y: 1.5,
    PITCH_MIN: -1.2, PITCH_MAX: 0.55,
    REGEN_DELAY: 6, REGEN_RATE: 4, IFRAME: 0.6,
    },
    COMBAT: {
    COOLDOWN: 0.5, CONE_HALF_RAD: 35 * Math.PI/180, RANGE: 2.6,
    FIST_DMG: 6, KNOCKBACK: 7,
    },
    SPAWNER: { TICK: 2, ANIMAL_CAP: 12, MONSTER_CAP: 10,
    SPAWN_MIN: 40, SPAWN_MAX: 130, DESPAWN: 180 },
    };```

    5.1 world/Noise.js —— WorldGen(核心算法)

    export function mulberry32(seed) { /* 标准实现:返回 ()=>[0,1) */ }```
    
    构造:`new WorldGen(seed)` 内部用 mulberry32(seed) 依次创建 6 个噪声场:
    `h2D(基础起伏) d2D(山脊) c2D(大陆) t2D(温度) m2D(湿度) v2D(颜色抖动)`。
    
    FBM 辅助:`fbm(n2d, x, y, octaves)`,lacunarity=2, gain=0.5,输出归一到约 [-1,1]。

    getHeight(x, z) {
    const c = fbm(c2D, x0.0007, z0.0007, 3); // 大陆掩码
    const b = fbm(h2D, x0.004, z0.004, 4); // 基础起伏
    let h = (c0.62 + b0.38) * 14; // 丘陵 ±14
    const r = 1 - Math.abs(fbm(d2D, x0.0016, z0.0016, 3)); // 山脊 0..1
    const mMask = smoothstep(0.12, 0.50, c) * smoothstep(-0.05, 0.35, b);
    h += Math.pow(r, 2.2) 30 mMask; // 山地最高约 +30
    if (h < 0) h *= 1.35; // 海盆加深
    return h;
    }

    slopeAt(x,z) { // 采样 ±0.6m 四点,梯度幅值 ≈ sqrt((hE-hW)^2+(hN-hS)^2)/1.2 }

    getBiome(x, z, h) {
    const temp = fbm(t2D, x0.0008+37, z0.0008-11, 2);
    const moist = fbm(m2D, x0.0008-53, z0.0008+29, 2);
    if (h > 18 || temp < -0.42) return 'snow';
    if (temp > 0.42 && moist < 0) return 'desert';
    if (moist > 0.12) return 'forest';
    return 'plains';
    }```

    顶点配色 getColor(biome, h, slope, x, z)(返回 THREE.Color,写入顶点色):
    - h < -2:水底深沙 #3f5a52
    - h < 1.1:沙滩 #d9c98e
    - slope > 0.85 || h > 16:岩石 #8b8f96
    - h > 20:雪 #eef3f6
    - 其余:群系草色 × (1 + v 抖动),v = v2D(x*0.05, z*0.05)*0.06
    - plains #6fae4e,forest #4c8a44,desert #d9c07e,snow #cfdde4

    群系表以 { id, grass, treeDensity... } 形式导出供 Vegetation 使用。

    5.2 world/Chunk.js

    • 手工构建索引网格:33×33 顶点 positions/colors,索引两三角一 quad;computeVertexNormals();材质共享全局一个 Lambert。
    • 顶点世界坐标 = chunkOrigin + 局部步进(步长 48/32=1.5m)。
    • mesh.receiveShadow = true; castShadow = false(性能)。
    • 导出 dispose() 只释放 geometry。

    5.3 world/TerrainManager.js

    • Map<key"cx,cz", Chunk>;每帧:

    1. 计算玩家所在 chunk 坐标;收集半径 5 内缺失 key,按距离排序入队;
    2. 每帧最多构建 2 个(构建含植被);
    3. 卸载距离 > 6 的 chunk(dispose + Vegetation 清理 + 资源节点注销)。
    - 提供 pregenerate(cx, cz, radius, onProgress):供加载屏逐帧批量预生成出生区(radius=3),配合进度条。
    - 暴露 resourceNodes 注册表(数组):{ type:'tree'|'rock'|'bush', x,y,z, harvested, hideInstance() }。

    5.4 world/Vegetation.js

    原型几何体(类初始化时创建一次,跨 chunk 共享 geometry/material):
    - 松树:双层 Cone + Cylinder 干;橡树:Icosahedron 冠 + 干;仙人掌:Capsule 绿色
    - 岩石:Dodecahedron 压扁灰;浆果丛:小球深绿;花/草:微型 Cone(黄/粉随机 instanceColor)

    每 chunk 散布(候选 90 点,跳过 h<1.2 或 slope>0.9):

    群系树浆果丛岩石花/草其他
    forest55%(松/橡混)8%6%6%—
    plains8%6%3%18%—
    desert——5%—仙人掌 10%
    snow松 14%—6%——
    • 单类型单 chunk 上限 64 实例;scale 0.8–1.4 随机、Y 随机旋转;instanceColor 明度抖动。
    • 资源登记:树→木头×3、岩→石头×2、丛→浆果×2。
    • 采集实现:hideInstance(im, idx) 将该实例矩阵设为零缩放并 instanceMatrix.needsUpdate=true。

    5.5 world/Water.js

    600×600 Plane 跟随玩家(x/z 吸附到 10m 格避免纹理游移感),y = SEA_LEVEL−0.15 + sin(t)*0.05 微浮动;MeshPhongMaterial({ color:#2e7fb8, transparent:true, opacity:0.72, shininess:120 }),fog 保持开启。

    5.6 env/SkyDome.js

    • SphereGeometry(700) BackSide ShaderMaterial(fog:false, depthWrite:false),每帧同步 camera.position;camera.far=1200。
    • Uniforms:uTop uHorizon uSunDir uSunColor uNight uDim(天气变暗 0..1)。
    • Fragment 要点:
    vec3 dir = normalize(vWorldPos - cameraPosition);
    float up = pow(clamp(dir.y,0.,1.), 0.55);
    vec3 col = mix(uHorizon, uTop, up);
    if (dir.y < 0.) col = mix(uHorizon, uHorizon*0.45, clamp(-dir.y*3.,0.,1.));
    float s = max(dot(dir, uSunDir), 0.);
    col += uSunColor * (pow(s,900.)*1.2 + pow(s,18.)*0.25); // 日盘+晕
    float m = max(dot(dir, -uSunDir), 0.);
    col += vec3(0.85,0.88,1.0) * pow(m,1600.) * uNight * 0.9; // 月盘
    // 星星:dir 映射 floor(dir*220) hash,step(0.9985,h)*uNight 叠加白点
    col *= (1.0 - uDim*0.35);```
    
    ### 5.7 `env/DayNightCycle.js`
    
    驱动:平行光 sunLight(castShadow,shadow 正交范围 ±60、mapSize 2048、bias −0.0005,`light.target` 必须加入场景并每帧指向玩家)、HemisphereLight、scene.fog 颜色、SkyDome uniforms。
    
    按太阳仰角 e 分三段插值(用 smoothstep 过渡带):
    
    | 参数 | 白天 e>0.25 | 日落带 e∈[−0.12,0.25] | 夜晚 e<−0.12 |
    |---|---|---|---|
    | 天顶 | `#4890e0` | →`#35507e` | `#0a1026` |
    | 地平 | `#bcd8ea` | →`#ff9e5e` | `#16203a` |
    | 雾 | `#cfe3ee` | →`#e8a76b` | `#10182b` |
    
    - `sunLight.intensity = max(e,0)^0.6 × 1.25 × (1−cloudDim×0.6) + 0.02`;白天色暖白→日落橙 `#ffb36b`。
    - **夜晚月光模式**:e<0 时将平行光转到 −sunDir 方向,色 `#7788bb`、强度 0.15(保留微弱阴影)。
    - hemi 强度 `0.25 + max(e,0)*0.55`,天空色随天顶色、地面色随草绿。
    - 对外暴露 `t`(0..1)、`hours`、`phase`('dawn'|'day'|'dusk'|'night') 供 HUD 显示 ☀️🌙 等。
    
    ### 5.8 `env/Weather.js`
    
    状态机:每 50–140s 按权重切换 CLEAR .45 / CLOUDY .25 / RAIN .20 / FOG .10。参数组并整体向目标 lerp(速率 0.5/s):
    
    | 状态 | cloudDim | greyMix | rain | fogFar倍率 | fogNear倍率 |
    |---|---|---|---|---|---|
    | CLEAR | 0 | 0 | 0 | 1.0 | 1.0 |
    | CLOUDY | 0.45 | 0.25 | 0 | 0.85 | 0.9 |
    | RAIN | 0.70 | 0.55 | 1 | 0.55 | 0.6 |
    | FOG | 0.30 | 0.35 | 0 | 0.28 | 0.5 |
    
    雨:Points 1500 顶点,盒 80×40×80 跟随相机,y -= 22*dt 循环回绕,PointsMaterial 尺寸 0.08、透明度 ∝ rain,`fog:false, frustumCulled=false`。greyMix 用于把天空 uniform 向灰色靠。
    
    ### 5.9 `entity/CharacterMesh.js`(人形)
    
    Box 组合:躯干(0.55,0.65,0.32)、头(0.34³)+脸部贴片、双臂 Group(肩部轴点,长 0.55)、双腿 Group(髋部轴点,长 0.6)。肤色 `#e8b98a`、衣青 `#3aa6a0`、裤 `#4a5568`。所有 Mesh castShadow。
    动画接口:`setWalk(phase, speedFactor)` 四肢摆动 sin(phase)*0.7(腿反相、臂反相);`playAttack()` 右臂 0.35s 抬起→劈下时间线;`update(dt)` 推进动画。
    
    ### 5.10 `entity/Player.js`
    
    - 状态:pos(Vector3)、vel、yaw/pitch(鼠标)、grounded、swimming、hp、lastCombatTime、equippedWeapon。
    - 相机:第三人称轨道,偏移 target=pos+(0,1.5,0);camDist 滚轮 3–12 默认 7;pitch 夹 [-1.2, 0.55] rad;**camY 至少高于地形 getHeight(camX,camZ)+0.5**。
    - 移动:输入向量按相机 yaw 旋转;速度目标 = walk/sprint/swim;水平速度朝目标 lerp(地面 accel 40、空中 12,帧率无关写法 `1-exp(-k*dt)`)。
    - 物理:vy -= GRAVITY*dt;groundH=getHeight(x,z);y ≤ groundH → 落地。游泳判定 groundH < SEA_LEVEL−1.1:y 收敛至 SEA−0.95、速度 SWIM、Space 给 +4 起跳力用于上岸。
    - 身体朝向平滑转向移动方向;移动时推进 CharacterMesh.setWalk 相位(速度越快相位越快)。
    - 受击 `takeDamage(n)`:无敌帧内忽略;hp−n;发总线事件 `player:hp`;触发 UI 红晕;hp≤0 → `player:death`。
    - 死亡处理在 Game:黑屏 2.5s 后复位到 spawnPoint、满血、短暂无敌。
    - 脱战回血:距上次受击/攻击 >6s 时 hp=min(max, hp+4dt)。
    
    ### 5.11 生物 FSM(`Creature.js` 基类 + 子类)
    
    基类字段:mesh(Group)、hp、speed、state、stateTimer、knockbackVel、flashTimer。
    `takeDamage(dmg, fromPos)`:闪红(遍历材质 emissive 置红 0.15s)、击退 impulse KNOCKBACK 远离 fromPos、hp≤0 → die()。
    `die()`:掉落物交给 Spawner.spawnDrop(item,count,pos);自身下沉缩小 0.6s 后移除。
    
    **鹿 Animal**(造型:躯干 box(0.9,0.5,0.45) 土黄 `#c08a5a`、颈+头、4 圆柱腿、雄性角锥;奔跑四腿摆动):
    - HP30;idle(2–4s) ↔ wander(随机 8m 内目标点,速度 1.6);玩家 <9m → flee(远离方向速度 8.5,持续 4s);腿动画频率随速度。
    
    **史莱姆 Monster**(压扁球 r0.45 绿 `#6fce6f` opacity .95 + 双黑眼;跳跃式位移:y=|sin|*0.3、挤压 scale):
    - HP45;wander 1.6;玩家 <13m → chase 4.2;<1.9m 进入 attack:前摇 0.4s(放大蓄力)后若仍在 2.2m 内对玩家 takeDamage(12),冷却 1.2s。
    - 掉落:粘液×1–2。鹿掉落:兽皮×2。
    
    ### 5.12 `systems/Spawner.js`
    
    - 每 2s tick:统计现存鹿/怪数量,不足则补(生成点=玩家周围 40–130m 随机角度,要求 getHeight>1 且 slope<0.6,重试 8 次);>180m 的生物移除(dispose mesh)。
    - `creatures` 数组;每帧 update 全部 `creature.update(dt, ctx)`(ctx 含 playerPos、getHeight 引用)。
    - 掉落物管理 `drops[]`:OctahedronGeometry(0.22) 按 ITEM 颜色着色,悬浮 sin 波动+自转;提供 `nearestDrop(pos, range)`。
    
    ### 5.13 `systems/Combat.js`
    
    - `playerAttack(player, spawner)`:冷却检查 → CharacterMesh.playAttack() → 遍历活体生物:水平距离 ≤RANGE(2.6) 且方向夹角 ≤CONE_HALF(35°) → `creature.takeDamage(weapon.dmg, playerPos)`。
    - 武器伤害来源:Inventory.equipped('sword'→16 / 'axe'→11 / null→拳 6);斧头另有 chopBonus=2(采集加成,见 Interaction)。
    
    ### 5.14 `systems/Inventory.js` + `Crafting.js`
    
    物品注册表(emoji 作图标,Windows 下渲染良好):
    
    | id | 名称 | 图标 | 备注 |
    |---|---|---|---|
    | wood | 木头 | 🪵 | 色 `#8a5a33` |
    | stone | 石头 | 🪨 | 色 `#9aa0a6` |
    | berry | 浆果 | 🫐 | 食用 +15 HP |
    | cooked_berry | 烤浆果 | 🔴 | 食用 +30 HP |
    | hide | 兽皮 | 🟫 | 色 `#c9a86a` |
    | slime | 粘液 | 🟢 | 色 `#7ee08a` |
    | sword | 石剑 | ⚔️ | 武器 dmg16 |
    | axe | 石斧 | 🪓 | 武器 dmg11 + chopBonus2 |
    
    - Inventory:`counts Map`、堆叠上限 999、`add/remove/count/has`;每次变动 emit `inv:changed`。
    - equipped 字段:'sword'|'axe'|null;装备/卸装备也发 `inv:changed`。
    - 配方:`sword ← wood2+stone3`;`axe ← wood3+stone2`;`cooked_berry ← berry2`。
    - Crafting.craft(id):校验材料 → 扣除 → 产物入库(武器类自动 equip)→ toast 反馈。
    
    ### 5.15 `systems/Interaction.js`
    
    每帧查询最优目标并经总线 `prompt:update {text}|null`:
    1. 掉落物 ≤2.6m → 「[E] 拾取 木头×3」
    2. 资源节点 ≤3.4m 且未 harvest → 「[E] 砍伐 树木 / 采集 石头 / 采摘 浆果」(树需 yield×chopBonus 若装备斧)
    3. E 键触发:资源 → 产物入包 + hideInstance + toast「+3 木头」;掉落物 → 入包并从 drops 移除。
    
    ### 5.16 UI 组件
    
    - **HUD**:左上血条(红填充+数字);右上时钟(HH:MM + phase emoji 🌅☀️🌇🌙);中心准星圆点;底部中交互提示条;左下 toast 堆栈(2.5s 淡出);全屏红色内阴影 vignette(受击时闪现);死亡遮罩(渐黑 + 「你倒下了…」)。
    - **InventoryUI**:Tab 切换背包面板:网格槽位(图标+数量徽标+名称 tooltip);可点击交互——berry/cooked_berry 点击食用、weapon 点击装备/卸下(高亮描边)。C 切换合成面板:配方行显示 图标+需求量(够绿/缺红)+ 合成按钮(材料不足 disabled)。打开面板时 `exitPointerLock`,关闭时尝试 `requestPointerLock()`。
    - **LoadingScreen**:标题「微光大陆」+ 副标题 + 进度条(pregenerate 回调)+ 完成后变「点击进入世界」按钮 + 底部小字「重置存档」链接(清 localStorage 并 reload)。
    - **暂停提示**:pointerlock 丢失且无面板开启时显示半透明「点击继续」,点击画布重新锁定。
    - CSS 风格:深色玻璃拟态 `rgba(10,16,24,.55)` + backdrop-filter blur + 圆角 + 主色 `#57d9c9`;system-ui 字体。
    
    ### 5.17 EventBus 事件名约定
    
    `inv:changed`、`toast(msg)`、`prompt:update`、`player:hp(hp,max)`、`player:death`、`time:tick(hours,phase)`、`weather:change(state)`。
    
    ### 5.18 存档格式
    
    localStorage key `gleaming-continent-save`:

    { "seed":12345, "px":0,"pz":0, "time":0.3, "hp":87,
    "inv":{"wood":5,"stone":2}, "equipped":"sword" }```
    每 5s + beforeunload 写入;Game 启动时若有档则恢复(seed/位置/时间/背包/血量/装备),否则随机 seed 并螺旋搜索出生点(从原点步进 8m 找 h∈[2,8] 且 slope<0.5 的点)。


    六、Game.js 编排与主循环

    ```constructor(container):
    renderer(WebGLRenderer antialias, setPixelRatio(min(dpr,2)),
    outputColorSpace=SRGB, shadowMap PCFSoft)
    scene(fog=Fog(#cfe3ee, 60, 210)) + camera(PerspectiveCamera 60°, far 1200)
    bus, input(Input), worldGen(Noise)
    sky, daynight, weather, water, terrain(TerrainManager), vegetation 由 terrain 内部使用
    inventory, crafting, combat, interaction, spawner
    ui: LoadingScreen → pregenerate 出生区(radius 3, 进度回调) → 放置玩家
    → HUD/InventoryUI 绑定总线 → 显示「点击进入世界」

    loop(rAF): dt = min(clock.getDelta(), 0.05)
    input 快照 → player.update(dt) → terrain.update(playerPos)
    → daynight.update(dt) → weather.update(dt)
    → spawner.update(dt)(内部更新生物与掉落物)
    → combat 冷却/interaction 目标查询 → hud 更新 → renderer.render```

    Input 要点:keydown/up 维护 Set;mousedown 左键→combat.tryAttack;mousemove 仅 pointerLock 时累加 yaw/pitch(movementX/Y);wheel 调 camDist;E/Tab/C 转发;document.pointerlockchange 驱动暂停提示。

    index.html 最小骨架:

    <!doctype html><html lang="zh-CN"><head>
    <meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/>
    <title>微光大陆 · Gleaming Continent</title></head>
    <body><div id="app"></div><script type="module" src="/src/main.js"></script></body></html>```
    
    ## 七、操作方式
    
    WASD 移动 · Space 跳/游泳上浮 · Shift 冲刺 · 鼠标视角(Pointer Lock) · 滚轮缩放镜头 · 左键攻击 · E 采集/拾取 · Tab 背包 · C 合成 · Esc 解锁鼠标
    
    ## 八、实施顺序(建议按此分阶段提交,每阶段可独立运行验证)
    
    1. 安装依赖 → index.html/style.css/main.js/config.js/core 三件套 → 空场景转起来(天空色背景即可)
    2. Noise + Chunk + TerrainManager + Water:站在原点看地形流式加载
    3. SkyDome + DayNightCycle + Weather:观察一轮完整昼夜与降雨
    4. CharacterMesh + Player:能跑能跳能游,相机跟随
    5. Vegetation:群系植被与资源点出现
    6. Creature/Animal/Monster + Spawner:鹿逃逸、史莱姆追击
    7. Combat + Interaction + Inventory + Crafting 数据层
    8. HUD + InventoryUI + LoadingScreen + 暂停提示
    9. 存档 + 出生点选址 + 数值打磨
    10. 构建验证 + 验收清单
    
    ## 九、验收清单(实现完成后逐项人工核验)
    
    1. `npm run dev` 无报错;浏览器控制台无错误;`npm run build` 成功产出 dist。
    2. 出生点地形/植被/水面正常;四处奔跑 chunk 流式加载无明显卡顿(雾掩盖边缘)。
    3. 观察一轮昼夜(≥8 分钟或临时改 DAY_LENGTH 加速验证):天空/光照/雾/星空变化正确。
    4. 等待或调试触发四种天气:云量变暗、雨天粒子、浓雾可见度变化。
    5. 接近鹿会逃逸;史莱姆发现玩家追击并造成伤害(血条下降+红晕)。
    6. 左键击杀史莱姆 → 掉落物 → E 拾取入包;砍树/采石获得木头/石头(装备斧后砍树产量翻倍)。
    7. Tab 背包可见物品并可食用浆果回血;C 合成石剑后攻击力提升。
    8. 玩家死亡 → 黑屏过渡 → 出生点复活满血。
    9. 刷新页面:seed/位置/背包/时间/血量恢复;「重置存档」生效。
    10. 性能基准:中档笔记本 ~60fps(可视半径 5、阴影 2048、pixelRatio≤2 的前提下)。
    
    ## 十、风险、取舍与实现注意事项
    
    **已知取舍**
    - 无外部模型/音效:视觉全靠程序化几何与配色,风格化抽象表现;音效不在本期范围。
    - 世界修改不持久:chunk 卸载即重置(砍掉的树重生成),原型可接受。
    - 不做植被/角色物理碰撞(可穿树),仅地形高度碰撞。
    
    **给实现 Agent 的 three/环境注意事项(易错点)**
    - three 仅 ESM:`import * as THREE from 'three'`;本项目不需要 examples/jsm addons。
    - 平行光阴影:`scene.add(light.target)` 必不可少,且每帧更新 target.position 到玩家处,否则阴影方向错。
    - `MeshLambertMaterial` 在现代 three 中支持 `flatShading` 与 `vertexColors`,勿再引入 Phong(水面除外)。
    - InstancedMesh 必须**先统计再精确分配 count**;批量写完矩阵/颜色后置 `instanceMatrix.needsUpdate` / `instanceColor.needsUpdate`。
    - 卸载只 dispose 各 chunk 自有 geometry;共享材质/原型几何绝不 dispose。
    - simplex-noise v4:`createNoise2D(rng)`,rng 是返回 [0,1) 的函数(mulberry32 兼容)。
    - Pointer Lock:只能用户手势中请求;Esc 退出后 Chrome 有 ~1.25s 冷却,重锁失败属正常,用「点击继续」覆盖层兜底。
    - 每帧 dt 上限 0.05 防止切标签页回来瞬移;lerp 用 `1-exp(-k*dt)` 保证帧率无关。
    - Windows + Node 24 环境,命令均在 `C:\Users\32382\Desktop\demo` 下执行。

    各自用原生pi-agent和qwen code


    Hy3版本:微光大陆 · Gleaming Continent

    Ox Alpha Free版本:微光大陆 · Gleaming Continent

    主楼
  • Handsonmac

    坐等结果,初步感觉hy3 不如牛来

    #1
  • Anny

    图片

    hy3跑出来了,但是一坨屎,点击去直接黑屏动不了了。^-^

    #2
  • 莫子

    hy3很贴题啊,果然是微光,只有中间一点光

    #3
  • 夜碼

    x-preview-f-free是什麼模型?

    #4
  • Junglecola

    都说了微光大陆 正中间不是有个白点吗 这就是微光

    所以我直接宣布hy3胜利 意识流作品 和mixtape一起荣获10.0评分

    #5
  • Anny

    图片

    #6
  • Hale

    我在workbuddy里用hy3基本就仅问答或者写一点很简单的小插件,hy3首字慢质量也差,不太敢拿来当正经工具用

    #7
  • Junglecola

    我怀疑这个设计之初是给腾讯游戏的AI助手用的

    #8
  • Anny

    牛来模型出结果啦

    图片

    图片

    图片

    至少有个世界渲染出来了,但是似乎还是没法移动。

    #9
  • 一条乱跑的咸鱼

    我反代workbuddy用hy3速度挺快的,比opencode的免费hy3要强,配合deepseek-v4-flash 去配置多模型去协同工作,加上各种skills,效果还挺不错的。

    #10
  • Anny

    逆天hy3直接祭出大招,杀死node进程,直接干翻运行中的pi-agent和qwen-code结束战斗

    图片

    图片

    因该是原生的piagent没有权限控制导致的。

    #11
  • 一条乱跑的咸鱼

    hy3单打独斗不太行,要配置oh-my-opencode 这些插件和skills,多模型协同效果才好,还有不建议在Windwos上去跑,在linux上跑效率更高

    #12
  • Anny

    hy3经过两轮调整已经可以运行了。可以在线体验了。

    微光大陆 · Gleaming Continent

    图片

    图片

    但是左右键位好像反了各种细节有点问题。何晨光的游戏哈哈

    #13
  • Anny

    牛来还在调试中。。。。。。。。。,感觉效果会更好的。

    图片

    #14
  • 飘落

    好像按E砍不了树 hy3free写的东西真的能玩吗 我觉得拿来办公好像还行…

    #15
  • Anny

    Ox Alpha Free 也上线了,整体体验更好。

    微光大陆 · Gleaming Continent

    图片

    #16
  • mark

    微光……哈哈哈哈,我一口茶喷磅礴而出,赔我屏幕钱!

    #17

发表回复

登录后回复