fix(d2map): 修正空单元格阻挡掩码与玩家出生点虚空悬空问题 #114

Closed
opened 2026-09-18 14:13:50 +00:00 by troytt · 1 comment
Owner

背景与问题描述

在 #111 全地图走查中,发现部分关卡玩家出生点直接悬挂在无边纯黑虚空中,无法正常移动或探索:

  • 典型案例:Act 1 遗忘之塔外景(Tower 2)、Act 2 皇宫地下、Act 2 秘密避难所等。

根因剖析 (1.13c 对比)

  1. 虚空未标记阻挡:
    src/game/d2map.ts 的 buildIsoMapScene 中:
    const blocked = new Uint8Array(gridWidth * gridHeight) 初始化全为 0。只有放置了瓦片且具有阻挡属性的格子才被赋值为 1。未放置任何瓦片的纯黑虚空格从未被标记,被系统误判为“可通行的平地”。
  2. 出生点盲选几何中心:
    src/game/level-links.ts 中的 findIsoSpawn 算法直接从画布的几何中心 (cellsX / 2, cellsY / 2) 开始向外扩散搜寻第一个 blocked === 0 的单元格。在异形地图中,画布中心常常落在黑色虚空里,由于虚空格被误判为可通行,算法在半径 0 处直接返回虚空坐标!
  3. 1.13c 原版机制:
    在 D2Common.dll 中:
    • 空单元格必须打上 COLLIDE_BLANK(0x0001)与 COLLIDE_WALL 掩码,属于不可通行的无效区域(COLLIDE_MASK_INVALID);
    • 关卡玩家出生点严格绑定于 LvlWarp.txt、传送阵预设件(Waypoint Token)或房间内部起点 Token,绝不允许落在未放置房间的空区域。

修复要求

  1. 在 src/game/d2map.ts 中:
    • 修正未填充单元格的碰撞掩码与阻挡网格:未放置任何地表/建筑瓦片的空单元格默认标记为阻挡,并赋予 COLLIDE_BLANK | COLLIDE_WALL;
  2. 在 findIsoSpawn(及关卡出生点选择逻辑)中:
    • 优先查找场景内真实的入口标记(Warp / Waypoint / 场景核心房间内部),若无则必须在至少有一层有效地表瓦片(floor 存在且非 hidden)的通行格内搜寻;
    • 严禁将没有地表瓦片的空单元格选为出生点。
  3. 增加单元测试 tests/iso-spawn-void-guard.test.ts,验证异形关卡(Tower 2 等)出生点绝对不落在虚空中。
  4. 门禁通过:npm run typecheck、npx vitest run。

关联主 Issue: #111

## 背景与问题描述 在 #111 全地图走查中,发现部分关卡玩家出生点直接悬挂在无边纯黑虚空中,无法正常移动或探索: - 典型案例:Act 1 遗忘之塔外景(Tower 2)、Act 2 皇宫地下、Act 2 秘密避难所等。 ## 根因剖析 (1.13c 对比) 1. **虚空未标记阻挡**: `src/game/d2map.ts` 的 `buildIsoMapScene` 中: `const blocked = new Uint8Array(gridWidth * gridHeight)` 初始化全为 0。只有放置了瓦片且具有阻挡属性的格子才被赋值为 1。未放置任何瓦片的纯黑虚空格从未被标记,被系统误判为“可通行的平地”。 2. **出生点盲选几何中心**: `src/game/level-links.ts` 中的 `findIsoSpawn` 算法直接从画布的几何中心 `(cellsX / 2, cellsY / 2)` 开始向外扩散搜寻第一个 `blocked === 0` 的单元格。在异形地图中,画布中心常常落在黑色虚空里,由于虚空格被误判为可通行,算法在半径 0 处直接返回虚空坐标! 3. **1.13c 原版机制**: 在 `D2Common.dll` 中: - 空单元格必须打上 `COLLIDE_BLANK`(`0x0001`)与 `COLLIDE_WALL` 掩码,属于不可通行的无效区域(`COLLIDE_MASK_INVALID`); - 关卡玩家出生点严格绑定于 `LvlWarp.txt`、传送阵预设件(Waypoint Token)或房间内部起点 Token,绝不允许落在未放置房间的空区域。 ## 修复要求 1. 在 `src/game/d2map.ts` 中: - 修正未填充单元格的碰撞掩码与阻挡网格:未放置任何地表/建筑瓦片的空单元格默认标记为阻挡,并赋予 `COLLIDE_BLANK | COLLIDE_WALL`; 2. 在 `findIsoSpawn`(及关卡出生点选择逻辑)中: - 优先查找场景内真实的入口标记(Warp / Waypoint / 场景核心房间内部),若无则必须在至少有一层有效地表瓦片(floor 存在且非 hidden)的通行格内搜寻; - 严禁将没有地表瓦片的空单元格选为出生点。 3. 增加单元测试 `tests/iso-spawn-void-guard.test.ts`,验证异形关卡(Tower 2 等)出生点绝对不落在虚空中。 4. 门禁通过:`npm run typecheck`、`npx vitest run`。 关联主 Issue: #111
Author
Owner

修复完成并已合并至 main

  • Commit: fd67de7b1bafb3c019b92351890ec8cbe7dec5a8 (Merge: ad822bf)
  • 变更摘要:
    1. 在 src/game/d2map.ts buildIsoMapScene 中对没有非隐藏有效地面瓦片的纯黑虚空单元格,严格将 25 个子格子打上 blocked[idx] = 1 并设置 COLLIDE_MASK_INVALID(包含 COLLIDE_BLANK 与 COLLIDE_WALL)。
    2. 在 src/game/level-links.ts findIsoSpawn 中寻找玩家出生点时强制要求所在单元格拥有有效地面且处于连通可行走区域,杜绝玩家在遗忘之塔外景、皇宫、秘密避难所等不规则地图中心出生在纯黑虚空的问题。
    3. 新增单元测试 tests/iso-spawn-void-guard.test.ts 进行隔离保障验证。
  • 验证结果: npm run typecheck 0 errors,全量 vitest run 测试通过。
### 修复完成并已合并至 main - **Commit**: `fd67de7b1bafb3c019b92351890ec8cbe7dec5a8` (Merge: `ad822bf`) - **变更摘要**: 1. 在 `src/game/d2map.ts` `buildIsoMapScene` 中对没有非隐藏有效地面瓦片的纯黑虚空单元格,严格将 25 个子格子打上 `blocked[idx] = 1` 并设置 `COLLIDE_MASK_INVALID`(包含 `COLLIDE_BLANK` 与 `COLLIDE_WALL`)。 2. 在 `src/game/level-links.ts` `findIsoSpawn` 中寻找玩家出生点时强制要求所在单元格拥有有效地面且处于连通可行走区域,杜绝玩家在遗忘之塔外景、皇宫、秘密避难所等不规则地图中心出生在纯黑虚空的问题。 3. 新增单元测试 `tests/iso-spawn-void-guard.test.ts` 进行隔离保障验证。 - **验证结果**: `npm run typecheck` 0 errors,全量 `vitest run` 测试通过。
Sign in to join this conversation.
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: troytt/diablo2-web#114
No description provided.