大篷车(商人的篷车)裂成两块:5 个碎片各自对齐到本格,接缝处约 32px 台阶 #1
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
现象
第一章罗格营地里,商人那辆带篷布的大篷车看起来被切成两半:前段篷布与后段篷布在中间对不上,接缝处有明显台阶/缺口。
复现:https://www.laiseek.xyz/diablo2/?act=1&level=1-act-1-town-townn1
(
第一幕 / 罗格营地 / 北,出生点右侧偏下那辆车;四个象限各有一处同样的道具)根因(已用数据定位)
这辆车不是一整张贴图,而是 5 块墙瓦片拼的:
data\global\tiles\Act1\Town\Objects.dt1style 0,sequence **q26–q30**,type 1TownN1.ds1的一条斜向连排 (31,18) (31,19) (31,20) (31,21) (31,22)#12 s0q26#11 s0q27#10 s0q28#9 s0q29#8 s0q30渲染规则(
src/game/d2map.ts的buildIsoMapScene墙分支):即每块碎片按自己那一格定位、并用各自的
minBlockY把内容底对齐到该格基线。相邻格之间屏幕步进是 (−80, +40),而q27的minBlockY = −224、q28/q29 = −256,正好差一个块高(32px)——于是两段篷布各自贴合自己那格,接缝处出现 ≈32px 台阶,看起来就是"车裂了"。已排除的原因(都做了测量)
#12/#11/#10/#9/#8,rarity 0),逐格随机不可能把它们配错。npm run verify:packs全绿(包 = 现读现解)。minBlockY与位图底部之间)。type 1墙,不涉及roofHeight。prop1全是0b10000001(bIsWall | bLayerAbove),wallLayer = 0,完全一致。尚未定死的一条:碎片的锚点规则
剩下两个具体怀疑点,都属于"碎片在格子里该往哪偏":
−80),不区分声明宽度(96/128/160)。引擎画墙是往一个固定 160 宽的面上画(OpenDiablo2tileSurfaceWidth = 160),碎片在面内的落点由块的 x 决定。已试过"窄瓦片右对齐(+(160−w))"这一种可能,并不能让篷布接上(更差),所以规则不是这么简单——可能要按块的最小 x 或(160−w)/2。minBlockY + 80(内容底对齐到基线+112)。对这几块 192–288px 高的碎片,如果引擎是按块网格而非minBlockY对齐,每块的位移就会不同,正好能解释那 32px 台阶。另外 DS1 packed 字段里有一个本项目完全没用到的位:
BIT(29) bObjectWall(D2MOO 注释:"wall tiles with props; may be block reverb / other sounds(箱子、桶、桌子之类)")——大篷车这种"带道具的墙"可能走的是另一条定位分支。建议的下一步(一步即可判定)
对五块碎片分别做 (dx, dy) 扫描,找出能让它们拼成一整辆车的位移,再把该位移反推成引擎公式(
160−w/ 块最小 x /bitmapHeight−|height|/−minBlockY哪个对得上)。与上次墙角修复(type 3必须连带画type 4)一样,一旦对上就写成verify:tiles的永久断言。地面对照(最快):如果手上有原版游戏里这辆车的截图,按同角度同缩放截一张本项目同位置的图对比即可判定"原版是整辆车"还是"原版也如此",从而决定是否要改锚点。
相关位置
src/game/d2map.ts(buildIsoMapScene的墙分支、TILE_ANCHOR_X、WALL_SURFACE_HEIGHT)type来自 orientation 层):src/formats/ds1.tsnpm run verify:tiles(槽位类型 / 位置公式 / 顶角配对)、npm run verify:alignment正常的大篷车截图如下
收到参考图,做了逐项比对。问题比"接缝"更大:我们这辆车的顶棚美术和原版不是同一种。
1. 我们画的是哪 5 块
Act1/Town/Objects.dt1、style 0、sequence **q26–q30**、type 1,被 DS1 放在TownN1的斜向连排(31,18) (31,19) (31,20) (31,21) (31,22)。渲染规则是每块贴合自己那一格:
x=(cx−cy)·80−80、y=(cx+cy)·40+minBlockY+80。而q27的minBlockY=−224与q28/q29的−256差一个块高(32px),于是两段篷布之间出现台阶 → 看起来像"裂成两块"。
2. 更关键:原版顶棚是条纹棚布,我们画的是素色帆布
我把经典版 MPQ 里全部 265 个 DT1 按"亮像素占比 + 宽条纹段"扫了一遍(Act 1 的 67 个也单独扫过):
找不到任何条纹棚布瓦片——最亮的是 Act 5 攻城场景的雪崖(Siege/cliff.dt1)。也就是说,
原版这辆车的条纹顶棚不是 DT1 瓦片。
3. 由此得到的判断
原版这辆车 = 瓦片(车斗/车轮,我们有)+ 对象美术(DCC)(条纹棚布、木架、柜台、木箱木桶等)。
本项目目前完全不画对象(只解析出位置与美术成员元数据,26 个对象:19 个火把、传送点、NPC、
TA/DC/B6等),所以营地里那些"该由对象提供"的部分本来就缺席:参考图里的火把、木箱、木桶、地毯、NPC 我们都没画,这也解释了为什么我们的营地比原版空旷。
4. 需要你确认一件事(能直接定死方向)
原版营地里是否同时存在两种情况:
① 这辆条纹棚布的车(商人的);
② 另一种素色帆布篷的车(例如栅栏边那辆)?
如果只有①:说明我们这条 5 格连排用错了瓦片(应解析到别的 style/sequence,或那些碎片本就属于被丢弃的另一层),需要改瓦片解析。
如果①②都有:那就是"我们漏画对象层(②其实是①的对象部分)"+"素色帆布车自身接缝"两个独立问题,后者继续按上面的 32px 台阶查锚点。
附:附件机制的实测
POST /repos/…/issues/1/assets)传上来的。https://www.laiseek.xyz/diablo2/assets/(或图库仓库troytt/diablo2-web-assets)。经过对暴雪原版资源数据(TownN1.ds1、Objects.dt1)、D2MOO 反编译源码以及 win_ds1edit(Paul Siramy)引擎的比对验证,该现象并非渲染错位 Bug,而是原版的美术设计(Works as Intended)。
1. 道具本体是一列“双节车队”,而非单一篷车
该道具并不是一辆被截断的大篷车,而是由两节车厢构成的车队:
因为后方拖车的货物箱上也盖有一层灰白色防雨布,容易从视觉上误以为那是“塌陷下去的后段车篷”。
2. 附件截图对象混淆
Issue 附件中的参考图
10mceml002at0.png实际上是营地西北侧基德(Gheed)的赌博货摊大篷车(带条纹遮阳篷和货架柜台),属于完全不同的另一个独立道具模型,并非南部的这列运输车队。3. 数据层面的硬编码铁证
在
Objects.dt1中,位于 (31, 21) 的seq 29瓦片内部:两者画在同一张 96×288 的 DT1 贴图内,其高低落差是暴雪美术在 1999 年渲染 3D 模型时固化在贴图中的,没有任何外部位移公式能够改变同一瓦片内部像素的相对位置。
4. 数学证明:
minBlockY并不导致 32px 错位虽然
q27的minBlockY = -224而q28/q29为-256,但在引擎渲染流水线中:yOffset = -minBlockY;draw.y = orthoY + minBlockY + 80;screen_y = draw.y + yOffset + block.y = orthoY + 80 + block.y。minBlockY在代数上被完全消去,实际像素的绝对行号完全取决于网格基线与 DT1 block 的原始相对高度,相邻瓦片之间不存在所谓的 32px 阶梯位移。实测q28与q29的接缝处像素颜色和线条均严格 100% 连续对齐。综上所述,当前
d2web的渲染算法与暗黑破坏神 II 原版完全一致,无需调整定位锚点。独立复核:结论正确,我按证据逐条确认(不改代码)
我用"只画这四块瓦片、背景全洋红"的离线合成做验证,两条硬证据都成立。
① 是"两节车队",不是一辆车被截断 —— 成立
去掉地板与所有其它道具后可以看清:右侧是一辆带圆拱高顶帆布篷的大货车(车斗、前后大木轮、牵引杆齐备),
左下方是挂在后面的低矮平板拖车(平板+木桶+盖布的板条箱)。拖车货物上的灰白防雨布确实容易被读成
"塌下去的后段车篷"。我此前把它当成"一辆车裂成两块"是误判。
② 同一张瓦片内部就画了两辆车的部件 —— 成立
Objects.dt1里 (31,21) 用的seq 29(96×288)单张内部上方是前车篷布的后翼、下方是拖车前部箱体;(31,22) 的
seq 30则是拖车尾部(木桶/板条箱)。也就是说两车的相对高低是 1999 年烘焙进同一张贴图的,不存在任何外部位移公式可以改变同一瓦片内的像素关系 —— 与你的判断一致。
③
minBlockY在代数上被消去 —— 成立,且与我的推导一致解码时
yOffset = -minBlockY、绘制时draw.y = orthoY + minBlockY + 80,屏幕行号screen_y = draw.y + yOffset + block.y = orthoY + 80 + block.y。我先前说的"32px 台阶"只是对美术内容的描述(
q27的minBlockY=-224与q28/q29的-256恰好差一个块高),不是位移错误的证据 —— 这点我认错误判。补充一个我做的接缝量化:把车队 4 块合成后做 3×3 闭运算找"内部 1px 空洞",共 186 个像素,但只有 27 个落在瓦片矩形边界 2px 内,
其余散布在绳结、轮辐、板条之间(属于美术自身的 1px 缝隙),没有形成沿接缝的连续缝线 → 与"相邻瓦片内容严格对齐"一致。
④ 附件那张参考图是另一个道具 —— 与我的实测自洽
我把经典版 MPQ 里全部 265 个 DT1 按"亮像素占比+宽条纹段"扫过:没有任何条纹棚布瓦片
(最亮的是 Act 5 攻城场景的雪崖)。所以参考图里的条纹遮阳篷不可能来自 DT1 —— 只能是对象(DCC)美术,
与你判断的"基德(Gheed)赌博货摊"属于另一个独立道具完全一致。
⑤ 由此得到的一条真实遗留项(与本 issue 无关,另记)
真正让我们营地和原版看起来不同的,是对象层整体没画:本项目只解析对象的位置与美术成员元数据
(营地 26 个对象:19 个火把、传送点、NPC、
TA/DC/B6),静态帧尚未接入。参考图里的条纹篷、火把、木箱、木桶、地毯、NPC 都属于这一层。建议单独开 issue 跟踪"对象静态帧渲染",本 issue 可按 Works as Intended 关闭。