blockmap是附屬在map data裡面的一個資料結構,blockmap存放的位置和長度都是紀錄在WAD最前面的lump目錄裡。他和碰撞檢測相關,概念是用grid(網格)把地圖切割成小block,只有在同一個block的物體和牆壁會進行檢測。根據1994釋出的一份unofficial doom spec文件block上限是113*113個,在遊戲的automap模式開啟grid,可以看到實際被分割的樣子。
blockmap結構分三塊:header、offset、blocklist,數值格式都是 I16 (int short),可以在doom wiki找到的表格就不放,僅紀錄我的筆記。
header是第0~7byte, 0~3紀錄的是grid起點座標,通常是負值,如果使用的系統只能繪製在第一象限就要作平移,這在所有automap繪製相關的座標都要注意。4~7是blockmap的水平和垂直格數,相乘即總block (N),所以doom1的E1M1有36*23=824個block。
Offset是第8~8+2*(N-1) byte,紀錄每個block在blockmap資料結構裡的位置(byte offset)。每兩個byte是一個block的起始位置,例如E1M1的第一個block位置(也就是blocklist的起點)在第832byte。
blocklist存放N個block的資訊,block的資料結構有兩種,Tool格式開頭是兩個0x00 (int short 0)結尾是兩個0xFF (int short -1),executable格式少了開頭兩個0x00,直接從wad解出來的是前者。所以直接搜尋blocklist資料裡-1的數量會等於block數量。0和-1之間會存放block內包含的line,並不是直接紀錄相關資訊,而是每2byte對應linedef裡的一筆資料,像E1M1最後一個linedef編號474,blocklist能找到的最大編號也是474。
#Blockmap structure#
###header###
x coordinate of grid origin
y coordinate of grid origin
Number of columns
Number of rows
###offsets###
Offset to block 0
...
Offset to block N - 1
###blocklist###
#block 0
0, line_a0, ..., line_an, -1
#block 1
0, line_b0, ..., line_bn, -1
... ... ...
#block n-1
0, line_x0, ..., line_xn, -1
#########
Block裡面有可能不含任何linedef,E1M1一開始的十幾個block都在地圖外,資料解出來是一串連續的0,-1,以為是blocklist資料格式弄錯,多花了好幾天查資料。所以特別把彙整所有資料的結果記錄下來。