统一跳一跳三维地块与落点判定
修正跳一跳长按起跳预测为真实脚点指向下一块顶面中心 统一前端指示器飞行动画与后端顶面 footprint 判定 调整 Three.js 方块贴图与角色顶面投影表现 补充跳一跳 UV 图集切片与运行态规则文档
This commit is contained in:
@@ -96,6 +96,14 @@
|
||||
- 验证:`cargo test -p platform-image --manifest-path server-rs/Cargo.toml vector_engine_send_retry_policy -- --nocapture`、`cargo test -p platform-image --manifest-path server-rs/Cargo.toml vector_engine_image_edit_retries_send_timeout_once_and_succeeds`、`cargo check -p api-server --manifest-path server-rs/Cargo.toml`;查询 `tracking_event` 时失败记录应能看到触发者 `user_id` 和可用的 `profile_id`。
|
||||
- 关联:`server-rs/crates/platform-image/src/vector_engine/client.rs`、`server-rs/crates/api-server/src/external_api_audit.rs`、`server-rs/crates/api-server/src/openai_image_generation.rs`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
||||
|
||||
## 跳一跳 Three.js 地块 UV 顶面要映射到 Z 轴
|
||||
|
||||
- 现象:跳一跳地块使用六面 UV 贴图后,看起来像贴图位置贴歪,顶面显示侧面纹理,或者旧单张地块图被拉到立方体多个面上。
|
||||
- 原因:运行态以 `z` 作为立方体竖直高度和相机下压方向,但 Three.js `BoxGeometry` / `RoundedBoxGeometry` 的默认材质 group 顺序把 `+Y` 当 top;如果直接按 `right / left / top / bottom / front / back` 写材质,玩法逻辑的 `top` 会贴到侧面。旧作品没有完整 `faceAssets` 时,把单张旧贴图强行作为 3D 六面 fallback 也会被误认为 UV 贴歪。
|
||||
- 处理:Three 平台层只在 `tileAssets[].faceAssets` 六面完整时启用;材质数组按 Three group 顺序写入 `right / left / back / front / top / bottom`,把逻辑 `top` 映射到 `+Z` 顶面,并按每面 UV 方向做翻转校正;旧单图作品继续走 DOM 图片 / 原型兜底层。
|
||||
- 验证:`npm run test -- src/components/jump-hop-runtime/JumpHopRuntimeShell.test.tsx` 应覆盖材质顺序、UV 翻转和旧单图不启用 Three 贴面;`cargo test -p api-server jump_hop_tile_atlas_slicing --manifest-path server-rs/Cargo.toml -- --nocapture` 应覆盖 UV 安全边裁切。
|
||||
- 关联:`src/components/jump-hop-runtime/JumpHopRuntimeShell.tsx`、`server-rs/crates/api-server/src/jump_hop.rs`、`docs/prd/【玩法创作】跳一跳俯视角玩法模板PRD-2026-05-19.md`、`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`。
|
||||
|
||||
## “我的”页每日任务卡不要硬编码进度,也不要跨日保留旧状态
|
||||
|
||||
- 现象:用户完成或领取每日任务后,任务中心弹窗里的任务状态已经变化,但“我的”页卡片仍显示 `0 / 1` 和“去完成”。
|
||||
@@ -1800,10 +1808,10 @@
|
||||
|
||||
## 跳一跳落点辅助标识不要再用舞台高度常量拍脑袋投影
|
||||
|
||||
- 现象:拖拽时落点辅助标识虽然会动,但看起来像静态点位漂移,和真实可落地的位置对不上。
|
||||
- 现象:按住蓄力时落点辅助标识虽然会动,但看起来像静态点位漂移,和真实可落地的位置对不上。
|
||||
- 原因:辅助标识如果只按 `stageSize.height` 和一个固定比例估算投影距离,再去跟拖拽向量合成,就会和当前地块到目标地块的真实屏幕跨度脱节;三维场景层级过高时还会把辅助点直接盖住。
|
||||
- 处理:辅助标识必须使用当前地块与目标地块之间的真实屏幕距离和后端 `chargeToDistanceRatio` 做投影,再映射到屏幕坐标;同时把辅助层 z-index 放到三维角色层之上,避免被场景层遮挡。
|
||||
- 验证:拖拽半程时辅助点应落在当前地块和目标地块之间,完整拖拽时应逼近目标地块中心;运行态截图里辅助点必须始终压在地块与角色之上。
|
||||
- 处理:辅助标识必须使用当前地块与目标地块之间的真实屏幕距离和后端 `chargeToDistanceRatio` 做投影,再映射到屏幕坐标;它只作为调参验证层随按下显示、松手或取消隐藏,不参与后端裁决和作品配置;同时把辅助层 z-index 放到三维角色层之上,避免被场景层遮挡。
|
||||
- 验证:半程蓄力时辅助点应落在当前地块和目标地块之间,完整蓄力时应逼近目标地块中心;运行态截图里辅助点必须始终压在地块与角色之上。
|
||||
- 关联:`src/services/jump-hop/jumpHopRuntimeModel.ts`、`src/components/jump-hop-runtime/JumpHopRuntimeShell.tsx`。
|
||||
|
||||
## 跳一跳长按蓄力不能再消费拖拽方向
|
||||
@@ -2089,8 +2097,8 @@
|
||||
|
||||
- 现象:跳一跳松手后如果后端很快返回下一帧 run,地块窗口会立刻前移,角色翻腾动画看起来像没播放;若同时刷新图片资产,还可能被误认为地块频闪。
|
||||
- 原因:后端 run 是规则真相,前端 runtime 又需要低延迟表现。如果 DOM 平台层直接用最新 `run.currentPlatformIndex` 渲染,后端回包会抢在动画前完成视觉切换。
|
||||
- 处理:前端保留独立 `displayRun`,松手后先进入 `isJumpAnimating=true`,角色在当前显示窗口内飞向前端预测真实落点;视觉预测必须用当前显示窗口的 current/next 地块作为方向来源,不能拿已经提前返回的后端新 run 目标配旧窗口角色,否则下一跳会朝实际目标反方向飞。飞行动画完成后再把 `displayRun` 切到最新后端 run,并进入约 `1440ms` 的 `platformAdvancing` 表现态。成功后的角色显示必须使用 `lastJump.landedX/landedY` 映射出的真实偏移,不要吸附到目标地块中心。推进期间地块 DOM 层和 DOM 角色层必须统一包在同一个 camera layer 下移动,旧当前地块先跟随相机偏移离开主视野,之后只保留在屏幕后方;不要给旧地块加独立向上 / 向下飞走 keyframes,也不要因为旧地块还在保留列表里阻塞下一跳。玩家继续向前跳时,已完成旧地块继续被新的相机推进自然带离屏幕,超过离屏阈值后销毁。相机层必须同时设置 `--jump-hop-camera-shift-x` 与 `--jump-hop-camera-shift-y`,并以旧窗口真实落点和新窗口真实落点为锚点,避免先横向瞬切居中再纵向推进;运行态相机层当前为约 `1.3x` 近距缩放。地块保留当前 / 目标 / 预览的深度尺寸差异,但深度差异必须用固定宽高 + CSS transform scale 缓动实现,不能直接改宽高瞬切;当前态不要额外叠 CSS scale。相机推进期间角色自身也不能保留 `left/top` transition,否则 `displayRun` 切换造成的角色局部坐标变更会和父级 camera layer 位移叠加,视觉上像落地后又从屏幕外飞回;角色推进期只允许 transform / opacity transition。正式胜负、成功跳跃次数、时长和排行榜仍以后端 run 为准,前端只延迟显示态。
|
||||
- 验证:`npm test -- src/services/jump-hop/jumpHopRuntimeModel.test.ts src/components/jump-hop-runtime/JumpHopRuntimeShell.test.tsx` 应覆盖动画期间平台仍停在旧窗口,成功落地保留真实落点偏移,动画结束后进入 `data-platform-advancing=true`,DOM 角色层与地块层同在 `jump-hop-camera-layer` 内,通过 `--jump-hop-camera-shift-x` 和 `--jump-hop-camera-shift-y` 完成相机斜向推进,并校验可见地块按深度保留不同视觉尺寸、运行态平台宽高使用固定基准值、推进态 transform transition 为 `1440ms`、推进态角色 transition 不包含 `left/top`、旧地块没有独立 `jump-hop-platform-exit-drift` keyframes 且下一跳不会被旧地块保留态阻塞。
|
||||
- 处理:前端保留独立 `displayRun`,松手后先进入 `isJumpAnimating=true`,角色在当前显示窗口内飞向前端预测真实落点;视觉预测必须用当前显示窗口的 current/next 地块作为方向来源,不能拿已经提前返回的后端新 run 目标配旧窗口角色,否则下一跳会朝实际目标反方向飞。飞行动画完成后再把 `displayRun` 切到最新后端 run,并进入约 `1440ms` 的 `platformAdvancing` 表现态。成功后的角色显示必须使用 `lastJump.landedX/landedY` 映射出的真实偏移,不要吸附到目标地块中心。推进期间地块层和角色层必须统一包在同一个 camera layer 下移动,旧当前地块先跟随相机偏移离开主视野,之后只保留在屏幕后方;不要给旧地块加独立向上 / 向下飞走 keyframes,也不要因为旧地块还在保留列表里阻塞下一跳。玩家继续向前跳时,已完成旧地块继续被新的相机推进自然带离屏幕,超过离屏阈值后销毁。相机层必须同时设置 `--jump-hop-camera-shift-x` 与 `--jump-hop-camera-shift-y`,并以旧窗口真实落点和新窗口真实落点为锚点,避免先横向瞬切居中再纵向推进;运行态相机层当前为约 `1.3x` 近距缩放。地块保留当前 / 目标 / 预览的深度尺寸差异,但深度差异必须用固定宽高 + CSS transform scale 缓动实现,不能直接改宽高瞬切;当前态不要额外叠 CSS scale。Three.js Sprite 角色与平台共用同一套屏幕坐标投影,DOM 角色只作为 WebGL 或贴图加载失败 fallback;DOM fallback 在相机推进期间自身不能保留 `left/top` transition,否则 `displayRun` 切换造成的角色局部坐标变更会和父级 camera layer 位移叠加,视觉上像落地后又从屏幕外飞回。正式胜负、成功跳跃次数、时长和排行榜仍以后端 run 为准,前端只延迟显示态。
|
||||
- 验证:`npm test -- src/services/jump-hop/jumpHopRuntimeModel.test.ts src/components/jump-hop-runtime/JumpHopRuntimeShell.test.tsx` 应覆盖动画期间平台仍停在旧窗口,成功落地保留真实落点偏移,动画结束后进入 `data-platform-advancing=true`,角色 Three 帧沿真实预测落点插值并保留飞行弧线,DOM fallback 角色与地块层同在 `jump-hop-camera-layer` 内,通过 `--jump-hop-camera-shift-x` 和 `--jump-hop-camera-shift-y` 完成相机斜向推进,并校验可见地块按深度保留不同视觉尺寸、运行态平台宽高使用固定基准值、推进态 transform transition 为 `1440ms`、推进态 DOM fallback 角色 transition 不包含 `left/top`、旧地块没有独立 `jump-hop-platform-exit-drift` keyframes 且下一跳不会被旧地块保留态阻塞。
|
||||
- 关联:`src/components/jump-hop-runtime/JumpHopRuntimeShell.tsx`、`src/services/jump-hop/jumpHopRuntimeModel.ts`、`server-rs/crates/module-jump-hop/src/application.rs`。
|
||||
|
||||
## 跳一跳相机推进不要让地块图片回退到原型方块
|
||||
@@ -2104,19 +2112,43 @@
|
||||
## 跳一跳 Three.js 平台层不能左右镜像 DOM 坐标
|
||||
|
||||
- 现象:视觉上下一块地块在角色右侧,但蓄力引导和角色飞行动画朝左侧;后端回包后地块窗口又闪现摆回正确位置,像是先按反方向飞、再由快照刷新纠正。
|
||||
- 原因:Three.js 平台层如果把相机 `up` 设置成反向,或在 Three 容器上做左右镜像,会让 WebGL 地块的屏幕 X 轴和 DOM 角色 / 落点预测的屏幕 X 轴相反。规则层仍沿当前地块中心到下一块中心裁决,所以后端快照会把状态纠正回来,表现为跳后刷新。
|
||||
- 处理:Three 相机保持 `up=(0, 1, 0)`,再用内部投影公式抵消 45° 下压导致的 Y 轴压缩;不要通过反向 `camera.up` 解决上下方向。DOM 角色、蓄力引导、落点预测和 Three 平台层必须共用同向屏幕坐标。
|
||||
- 原因:Three.js 平台层如果把相机 `up` 设置成反向,或在 Three 容器上做左右镜像,会让 WebGL 地块的屏幕 X 轴和角色 / 落点预测的屏幕 X 轴相反。规则层仍沿当前地块中心到下一块中心裁决,所以后端快照会把状态纠正回来,表现为跳后刷新。
|
||||
- 处理:Three 相机保持 `up=(0, 1, 0)`,再用内部投影公式抵消 45° 下压导致的 Y 轴压缩;不要通过反向 `camera.up` 解决上下方向。Three.js Sprite 角色、DOM fallback 角色、蓄力引导、落点预测和 Three 平台层必须共用同向屏幕坐标。
|
||||
- 验证:`npm run test -- src/components/jump-hop-runtime/JumpHopRuntimeShell.test.tsx src/services/jump-hop/jumpHopRuntimeModel.test.ts` 应覆盖 `JUMP_HOP_THREE_CAMERA_UP_Y=1`,并断言 Three 投影与 DOM 屏幕坐标同向。
|
||||
- 关联:`src/components/jump-hop-runtime/JumpHopRuntimeShell.tsx`、`src/components/jump-hop-runtime/JumpHopRuntimeShell.test.tsx`。
|
||||
|
||||
## 跳一跳 Three.js 角色不要被地块透明排序压住
|
||||
|
||||
- 现象:角色已经进 Three.js 场景后,看起来像落在地块内部或只露出头,角色没有站在方块顶面上。
|
||||
- 原因:地块材质如果设置 `transparent=true` 会进入 Three.js 透明物体排序队列,可能在 Sprite 角色之后绘制;同时角色脚点如果仍用固定 Z 高度,遇到标准 `1x1x1` 方块放大后的当前块时会落到顶面后方或方块体内。
|
||||
- 处理:地块贴图材质只使用 `alphaTest` 裁掉透明边,不放入透明材质队列;角色 Sprite 的 `renderOrder` 必须高于平台 mesh,脚点 Z 高度按最近方块半高加顶面偏移计算,确保角色站在当前方块顶面上方。
|
||||
- 验证:`npm run test -- src/components/jump-hop-runtime/JumpHopRuntimeShell.test.tsx` 应覆盖平台材质不透明队列、角色 renderOrder 高于地块、角色脚点高度高于方块顶面。
|
||||
- 关联:`src/components/jump-hop-runtime/JumpHopRuntimeShell.tsx`、`docs/prd/【玩法创作】跳一跳俯视角玩法模板PRD-2026-05-19.md`。
|
||||
|
||||
## 跳一跳立方体贴图不要走透明主体切片
|
||||
|
||||
- 现象:水果等主题生成成功后,运行态地块看起来像薄的纯水果 PNG、果切贴纸、透明 cutout;或者反过来六个面都是同一张平铺果皮 / 果肉材质,无法组合成方块苹果 / 方块香蕉这类完整主题对象表达。
|
||||
- 原因:跳一跳地板已经改为 Three.js 标准 `1x1x1` 等比极小倒角立方体复用几何体,运行态视角固定为近距相机和 45° 下压视角;image2 应生成 `1024x1536` 的 18 个 cube object UV unwrap,每个大单元内的 top/front/right/back/left/bottom 六面要共同包装同一个主题物体。只强调 full-bleed 容易让水果主题退化成果皮、果肉、叶脉等表面纹理;如果仍把一张图贴给六个面,模型也不需要理解正反和跨面连续特征。旧切图链路若把洋红 key 转 alpha、裁边、只保留最大 alpha 连通主体并补透明安全边,会把整格贴图重新抠成苹果 / 香蕉 / 果切等居中主体,贴到立方体上后四角和侧面都变透明。
|
||||
- 处理:跳一跳地板图集 prompt 固定要求 `cube object UV unwrap atlas / 立方体主题物体六面展开图集`,一张图只生成 18 个大单元,每个大单元固定 `4列*3行` UV 网:第 1 行第 2 列 top,第 2 行 left/front/right/back,第 3 行第 2 列 bottom;水果主题要明确生成能一眼说出名称的方块苹果、方块香蕉、方块橙子、方块西瓜等可识别对象,并要求果柄叶片、剥皮条带、放射切面、红瓤黑籽等身份特征跨面连续。禁止自然圆形水果、自然长条香蕉、非方块化完整水果、果切小贴纸、居中小物体、透明背景和留白,同时也禁止“单纯平铺材质 / 抽象纹理 / 只铺主题颜色 / 纯果皮材质 / 纯果肉纹理 / 纯叶脉纹理”。后端按 3x6 大单元和 4x3 UV 网切出 108 张 `256x256` 不透明面贴图,不再调用透明化、最大 alpha 连通主体保留或透明补边。洋红 `#FF00FF` 只作为图集安全缝 / UV 空位 / 外圈 key 色,裁切后若仍有极少残留则转成不透明材质底色;绿色、白色、雪地、云朵、草地、花朵、果肉粉色和浅黄色等主题颜色必须完整保留。
|
||||
- 处理:跳一跳地板图集 prompt 固定要求 `cube object UV unwrap atlas / 立方体主题物体六面展开图集`,一张图只生成 18 个大单元,每个大单元固定 `4列*3行` UV 网:第 1 行第 2 列 top,第 2 行 left/front/right/back,第 3 行第 2 列 bottom;水果主题要明确生成能一眼说出名称的方块苹果、方块香蕉、方块橙子、方块西瓜等可识别对象,并要求果柄叶片、剥皮条带、放射切面、红瓤黑籽等身份特征跨面连续。禁止自然圆形水果、自然长条香蕉、非方块化完整水果、果切小贴纸、居中小物体、透明背景和留白,同时也禁止“单纯平铺材质 / 抽象纹理 / 只铺主题颜色 / 纯果皮材质 / 纯果肉纹理 / 纯叶脉纹理”。后端先对图集做洋红去背,再以 `jump_hop_atlas_slicing.rs` 的自适应 blob+gradient 算法检测 3x6 大单元和单元内六面区域,输出 108 张 `256x256` 不透明面贴图;固定 3x6 / 4x3 切片只作为测试对照和必要 fallback 参考,不作为优先生图切图路径。洋红 `#FF00FF` 只作为图集安全缝 / UV 空位 / 外圈 key 色;绿色、白色、雪地、云朵、草地、花朵、果肉粉色和浅黄色等主题颜色必须完整保留。
|
||||
- 验证:`cargo test -p api-server jump_hop --manifest-path server-rs/Cargo.toml -- --nocapture` 覆盖跳一跳 UV unwrap prompt、18 个大单元、108 张不透明面贴图、绿色 / 白色材质不被透明化、洋红 key 残留不作为透明洞;前端 `JumpHopRuntimeShell` 测试覆盖新 UV 资产会解析六张面贴图,旧单贴图资产仍可 fallback。
|
||||
- 关联:`server-rs/crates/platform-image/src/generated_asset_sheets/alpha.rs`、`server-rs/crates/platform-image/src/generated_asset_sheets/sheet.rs`、`server-rs/crates/api-server/src/jump_hop.rs`。
|
||||
|
||||
## 跳一跳 UV 图集切片要防贴边矩形 u32 中间溢出
|
||||
|
||||
- 现象:跳一跳草稿在背景、返回按钮和地板图集 image2 都生成成功后,前端报“执行跳一跳共创操作失败”,Vite 代理日志出现 `socket hang up`,后端日志出现 `jump_hop_atlas_slicing.rs` 内 `attempt to subtract with overflow`。
|
||||
- 原因:blob gradient 切片的 histogram 最大不透明矩形在计算顶部坐标时写成 `by0 + ly - sh + 1`。当模型输出的 UV 面内容刚好贴到 cell 顶边,数学结果本应是 0,但 `u32` 会先执行中间步骤 `0 - 1` 并在 debug 运行时 panic。
|
||||
- 处理:顶部坐标先在局部坐标内用 `ly.saturating_add(1).saturating_sub(sh)` 计算,再加 block 偏移;不要恢复成连写减法。补充贴顶两行不透明矩形回归测试,保证贴边 UV 面不会打崩共创接口。
|
||||
- 验证:`RUSTC_WRAPPER= cargo test -p api-server --manifest-path server-rs/Cargo.toml jump_hop_atlas_slicing::tests::max_opaque_rect_handles_content_touching_top_edge`;整组再跑 `RUSTC_WRAPPER= cargo test -p api-server --manifest-path server-rs/Cargo.toml jump_hop`。
|
||||
- 关联:`server-rs/crates/api-server/src/jump_hop_atlas_slicing.rs`、`server-rs/crates/api-server/src/jump_hop.rs`。
|
||||
|
||||
## 跳一跳生图切图主路径不要绕过自适应图集切片
|
||||
|
||||
- 现象:拉取 `fix/jump-hop-image-gen` 后,如果又把生成链路切回旧固定坐标裁切,容易和该分支解决的 AI 图集偏移、间距不均、UV 面位置漂移问题互相抵消,导致新生图链路的实际收益无法验证。
|
||||
- 原因:当前跳一跳 image2 prompt 仍要求 3x6 大单元和 4x3 UV 子网格,这是给模型和算法的结构约束;真实生产切图由自适应 `SeedRefinement + blob + gradient + max opaque rectangle` 链路消化 AI 输出偏差。固定网格切片只能验证理想图集,不适合覆盖新分支的主修复。
|
||||
- 处理:生产生成链路优先调用 `slice_tile_atlas_adaptive(...)`;旧固定 `slice_jump_hop_tile_atlas(...)` 只保留为对照测试、实验和必要 fallback 参考。若自适应切图出现具体误切,应优先修正自适应模块的边界检测、主 blob、透明/安全色处理和回归测试,而不是直接全局切回固定坐标。
|
||||
- 验证:新生成作品下载 `tile-01-top/front/right` 等面贴图时,单图应基本充满对应主题面内容,不应出现大块空背景、相邻面混入或纯色原型 cube;同时执行 `RUSTC_WRAPPER= cargo test -p api-server --manifest-path server-rs/Cargo.toml jump_hop_atlas_slicing -- --nocapture`。
|
||||
- 关联:`server-rs/crates/api-server/src/jump_hop.rs`、`server-rs/crates/api-server/src/jump_hop_atlas_slicing.rs`、`docs/prd/【玩法创作】跳一跳俯视角玩法模板PRD-2026-05-19.md`。
|
||||
|
||||
## 含中文 image2 live 验证不要用 PowerShell 管道喂 Node 源码
|
||||
|
||||
- 现象:本地用 `@'...'@ | node -` 跑 VectorEngine / gpt-image-2 live 验证时,`request.json` 里的中文 prompt 可能全部变成 `????`,生成图会变成完全不相关的 UI、建筑海报或其它随机内容,容易误判为模型不服从提示词。
|
||||
|
||||
Reference in New Issue
Block a user