BLOCKMAP
Mais ações
O propósito do BLOCKMAP é detecção de colisão. Ou seja: o blockmap é usado para calcular quando um thing em movimento bate numa parede, ou quando dois things (um ou ambos em movimento) colidem. O blockmap é basicamente uma grade de “blocos”, cada um com 128×128 unidades (o dobro do tamanho da grade do chão). Se você quiser “ver” o blockmap, abra o automapa e habilite a grade.
Assim como NODES são usados para calcular quando uma linha deve ou não ser desenhada, o lump BLOCKMAP é usado para calcular colisão thing/parede. Cada bloco contém zero ou mais linedefs, normalmente poucos (certamente não tantos quanto o mapa inteiro). Então, ao detectar colisões de um thing em movimento, o engine só precisa rodar cálculos nas linedefs que estão no mesmo bloco do thing (em vez de testar o mapa inteiro).
Internamente, o blockmap também é usado para colisões thing/thing: cada bloco mantém uma lista dinâmica de todos os things contidos nele. Pelo mesmo princípio, o engine só precisa checar possíveis colisões com os things que compartilham o mesmo bloco do thing em movimento.
Curiosidade: remover o blockmap de um nível (o que hoje é praticamente impossível em ports modernos, já que eles constroem um blockmap em memória se ele não existir) mantém o comportamento geral igual (exibição do mapa, linha de visão dos inimigos, etc.), mas tudo pode atravessar linhas “impassíveis” e nada consegue acertar nada.
Também vale notar que, por causa de como o engine original fazia os cálculos, se o centro de um thing estivesse bem na borda de um bloco e o centro de outro thing na borda do bloco adjacente, a colisão podia “passar batido”, já que os centros caíam em blocos diferentes. Esse bug acontece porque o exe original (e muitos ports) usava apenas o centro do thing para determinar em qual bloco ele estava, ignorando o raio inteiro. No ZDoom isso foi corrigido. Há um artigo excelente do Colin Phipps em doom2.net sobre isso.
Estrutura do BLOCKMAP
Blockmaps são compostos por três partes: header, offsets e blocklist.
Header
bytes:
2: coordenada X da origem da grade
2: coordenada Y da origem da grade
2: número de colunas
2: número de linhas
Offsets
bytes:
2: offset para o bloco 0
2: offset para o bloco 1
.
.
.
2: offset para o bloco (N - 1)
Note que existem N blocos, onde N = colunas * linhas (do header). Todos os offsets são relativos ao início do lump BLOCKMAP. Esses offsets são unsigned, então podem ir até 65536 em vez de 32767 (como várias outras estruturas de WAD).
Nota: No código-fonte de Doom, esses offsets eram tratados como “shorts” (em unidades de 2 bytes). Então, se você estiver lendo byte-a-byte, o offset real é 2 * offset.
Blocklists
bytes:
2: 0x0000
2: linedef 0 dentro do bloco
2: linedef 1 dentro do bloco
.
.
.
2: 0xFFFF
A blocklist sempre começa com 0 e termina com -1. No meio fica a lista de todas as linedefs que têm qualquer porção dentro do bloco. Qualquer linedef na borda entre dois blocos vai ser colocada apenas no bloco à direita da linha (para linhas verticais) e apenas no bloco acima da linha (para linhas horizontais).
