SDKs e revisões

Gerado em 22/10/2026 19:22 por docs/offline/ferramentas/docs_locais.py. Para atualizar, rode o script de novo.

Sumário

Documentação

SDK Câmera

Câmera de ombro, terceira pessoa e primeira pessoa para jogos em three.js. Não conhece nenhum jogo: recebe o alvo e uma função de colisão.

const rig = CameraModosSDK.criar(THREE, { chave: 'meu-jogo-camera', nomes: { ombro: 'ombro (Q troca)' } });
rig.seletor(document.querySelector('#menu'), 'Câmera');      // seletor pronto, opcional
// a cada quadro
rig.atualiza(camera, { x, y, z, yaw, pitch, mira, agachado }, dt,
  (ox, oy, oz, dx, dy, dz, max) => distanciaAteParede ?? null,  // colisão (opcional)
  (x, z, y) => alturaDoTeto);                                   // teto (opcional)
if (rig.primeiraPessoa()) { rig.viewmodel(grupoDaArma, camera); /* esconda o corpo do jogador */ }
rig.ciclar();  rig.trocaLado();  rig.setModo('terceira');  rig.aoMudar(m => ...);

Convenções: yaw 0 olha para -z; pitch positivo olha para baixo; a arma tem o cano em +z. Tudo que é número (distâncias, alturas, posição do viewmodel) se ajusta em criar(THREE, { ombro: {...}, terceira: {...}, primeira: {...}, viewmodel: {...} }).

No ZombiAdA o adaptador é implementacao/jogo-web/src/91-camera.js (tecla O, seletor no menu, esconde o corpo em primeira pessoa).

SDK Modo livre (ferramenta de teste)

Arquivo: modo-livre.js. Genérico, não conhece nenhum jogo. O build.py do jogo inclui tudo de sdk/*/*.js antes do src/.

const ML = ModoLivreSDK.criar(THREE, {
  chaveMarcas: 'meujogo-marcas', arquivo: 'marcas.txt', equipes: [['mapa','Mapa']],
  area: (x, z) => 'nome da área', hora: () => '12:00', msg: (texto, s) => {},
  pos: () => ({ x, y, z, yaw, pitch }), limites: { x: [-500, 500], y: [0.4, 260], z: [-500, 500] },
  pausa: aberto => {},          // true ao abrir painel (soltar mouse, pausar), false ao fechar
});
ML.chave('id', 'Rótulo', get, set)   // liga/desliga no painel (set devolve true para fechar o painel)
  .acao('id', 'Rótulo', fn)          // botão (fn devolve true para manter o painel aberto)
  .horasDoDia([['Manhã', 0.3]], setHora)
  .lugares(() => [['Grupo', [['Nome', ir]]]])
  .etiquetasDe(cam => [{ x, y, z, texto, cor }])
  .cenarios(lista, aplicar, checar);  // checar(c) -> { critério: { ok, nota } }
ML.irPara = (x, y, z, yaw, pitch) => {};
// a cada quadro: ML.voa(dt, yaw, pitch, { frente, lado, sobe, rapido }) e ML.cameraVoo(camera, yaw, pitch) quando ML.voo;
// ML.atualiza(dt, camera, visivel). Teclas ficam no jogo: ML.abre('form' | 'lista'), ML.fecha().
ML.expoe(); // window.__cenario, __cenCheck, __cenLista, __modoLivre para Playwright

Marcas: salvas no banco do artifact (db, coleção marcas) quando houver, senão no localStorage, com copiar e baixar. Exemplo de adaptador: implementacao/jogo-web/ferramentas/92-explorar.js (ZombiAdA).

PlantasSDK

SDK genérico, sem nada de jogo específico, para plantas de casas e lotes. As posições dos móveis são gravadas (slots) e os itens são sorteados nelas com semente, então nenhuma casa repete o mesmo padrão. JS puro, sem imports: plantas.js é um IIFE que define const PlantasSDK.

Coordenadas

  • u corre ao longo da fachada (0..w); v vai da rua para os fundos (0..d). A sala fica na frente.
  • Lote: v < 0 é o recuo frontal (jardim/garagem), v > d é o quintal, u < 0 e u > w são as laterais.
  • Retângulos são [u0, v0, u1, v1]. Nos móveis, x == u e z == v (centro). Medidas em metros.
  • A frente do móvel é o vetor (fu, fv). ry = atan2(fu, fv), igual ao olha(du, dv) do jogo com inw = 1. Se a rua do jogo estiver invertida, use ry = atan2(fu, inw * fv).

API

  • PlantasSDK.gerar(template, {w, d, semente, estilo, andar}) devolve {comodos, paredes, portas, janelas, moveis, fachada, lote, andares, faltando}. Mesmo template, medidas e semente dão o mesmo resultado.
    • moveis[]: {id, tipo, categoria, x, z, ry, w, d, h, y, fu, fv, comodo, andar, externo, slot, sobre, modo, aabb, liga?}. y é a altura da base (itens sobre outro). externo marca itens do lote (andar -1). liga marca a escada entre andares.
    • paredes[]: segmentos com lados (cômodo de cada lado ou 'fora'), ext, tipo (parede ou guardacorpo), andar. As portas já abrem o vão; a verga é do jogo.
    • portas[]: {u, v, eixo, larg, a, b, abre, ext, modelo: folha|dupla|aco, folhas, zonas}.
    • janelas[]: {u, v, eixo, larg, y0, y1, comodo, lado}.
    • fachada: {cor:{nome,hex}, acabamento: reboco|chapisco, grades, telhado: colonial|fibrocimento|laje, sacada, portaAco}.
    • lote: {rect, zonas, perimetro, portoes, caminhos, piscina}. Cada perimetro[] tem tipo (muro|cerca|grade), material, altura, topo (nada|caco|concertina|grade) e alturaTotal: é o que as regras de escalada usam. portoes[]: {tipo: social|garagem|carga, modelo: pedestre|basculante|correr, u, v, larg, altura, para}. caminhos[]: faixas reservadas do portão até a porta (pedestre) ou até a vaga/garagem (veículo).
    • faltando: slots obrigatórios que não coube colocar (deve vir vazio).
  • PlantasSDK.slots(template, {w, d}): as posições gravadas, para revisão. Cada slot tem x, z, w, d, aabb, fu, fv, ry, âncora, cats, obrigatorio, prob, folga, frente, grupo, requer, sobre, valido e motivo (quando inválido).
  • PlantasSDK.validar(res) devolve erros em português. listarTemplates(), catalogo, biblioteca, estilos, templates.
  • registrarTemplate(t), registrarItem(def), registrarBiblioteca(tipo, fnOuLista).

Muda alturas e topos dos muros, tipos de portão, paleta e materiais da fachada. O padrão vem do template. Tudo fica em PlantasSDK.estilos (dados). Popular: muro de bloco 1,8 m, portão de ferro, grades nas janelas. Nobre: muro 2,8 m com concertina ou grade. Comercial: porta de aço, sem jardim, fundos de serviço.

Regras de colocação

Nenhum móvel invade 0,9 m em frente a portas e portões; itens altos (h > 1,0) ou com janela:false nunca ficam em frente a janelas; sem sobreposição; há caminho em grade da porta (ou portão) ao centro do cômodo; frente voltada para dentro; folga na frente do móvel; piscina com aro livre de 1,2 m. Os caminhos reservados entre portão e porta ficam livres. Um slot de parede pode deslizar até 2 m ao longo da parede para escapar de porta e janela. tapete é plano e não colide.

Como adicionar

  • Item: PlantasSDK.registrarItem({tipo:'sofa4', categoria:'sofa', w:2.2, d:0.95, h:0.85, frente:'+z', janela:false, baixo:false}). O tipo é o que o jogo mapeia para a malha.
  • Slot: em Biblioteca[tipoDoComodo] (ou registrarBiblioteca), com os construtores: P(id, lado, pos, [w,d], {categoria:peso}, opções) parede (lado: esq|dir|frente|fundo|qualquer), C(id, 'fundo-esq', ...) canto (aceita qualquer), Z(id, fx, fz, ...) centro (fração do cômodo, com dx, dz em metros), J(id, ...) sob janela, SB(id, paiSlot, ...) sobre outro item, DT(...) dentro. Opções: obrigatorio, prob, folga, frente (centro, porta, alvo + alvo:'slot', ou u+ u- v+ v-), grupo (alternativas: só uma é usada), requer. O cômodo pode ajustar por ajustes:{slot:{...}} (ou null para remover), sem:[ids], extras:[...], lib:'outraBiblioteca'.
  • Template: registrarTemplate({id, nome, estilo, limites:{w:[a,b], d:[a,b]}, padrao:{w,d}, lote:(w,d)=>cfg|null, andares:[{nome, pe, abertos, comodos(w,d), portas(w,d), janelas(w,d)}]}). Cômodos: {id, tipo, nome, r:[u0,v0,u1,v1], partes:[...] (cômodo em L)}. Portas: {a, b:'fora'|id, lado, c, larg, abre, aco}; sem c, centraliza na parede comum. Janelas: {comodo, lado, c | n, larg, y0, y1}. lote devolve {rf, ml, mr, qf, vaga, garagem, social, carga, piscina, libs}.

Templates

casaA (4 cômodos), sobrado (2 andares, 13 cômodos), mercado (5), farmacia (5), apartamento (7, sem lote, andar opcional) e mansao (10, com piscina e jardim grande).

Como o jogo se pluga

  1. Concatene plantas.js no módulo e chame const r = PlantasSDK.gerar('casaA', {w: b.w, d: b.d, semente: b.id}).
  2. Converta (u, v) para o mundo: X = b.x + u, Z = front + inw * v. Para a frente use ry = Math.atan2(m.fu, inw * m.fv).
  3. Mapeie m.tipo para a sua malha (um mapa tipo -> fábrica). Use m.w, m.d, m.h como pegada, m.y para itens sobre outros e m.categoria para o loot.
  4. Monte paredes de r.paredes (altura do andar em r.andares[i].pe), vergas sobre r.portas, janelas de r.janelas, e o perímetro de r.lote.perimetro com altura/topo.
  5. Para revisar as posições gravadas use PlantasSDK.slots(...) ou o visor-plantas.html.

Arquivos

plantas.js (SDK), teste.mjs (node teste.mjs), visor-plantas.html (visor offline; node montar-visor.mjs reembute o plantas.js), shots.mjs (capturas com Playwright).

Revisão final ZombiAdA: checklist de consistência e orçamento de desempenho

Rascunho de trabalho da revisão final (22/10/2026). O relatório consolidado sai como página quando os times terminarem. Fontes lidas: briefs de zumbis (Bestiário v12), veículos, mapa (fatia Jardim Aurora), personagens, guia de estilo do corpo, sobreviventes/destino, VFX, explosões, Arsenal (página).

PC alvo: GTX 1060 6 GB / RX 580, Ryzen 5 2600 (6 núcleos/12 threads), 16 GB RAM, 1080p médio. Host é jogador e servidor ao mesmo tempo.


1. Inconsistências encontradas (primeira passada)

Bloqueadoras (precisam de uma decisão única antes de codar)
#TemaO que divergeProposta da revisãoDono
B1Pilha de redeZumbis: Netcode for Entities / Unity Transport. Veículos e personagens: Netcode for GameObjects. Mapa: NGO ou Mirror.Uma pilha só: Unity Transport com host autoritativo. Zumbis/multidão em Entities replicados por lote próprio (snapshot quantizado); jogador, NPC e veículo como entidades leves no mesmo transporte. Nada de Mirror.Revisão (decisão de engine com o usuário)
B2Modelo de danoTrês modelos diferentes: Bestiário (vida 100, multiplicadores por região, integridade de membro 40%/35%), Arsenal (vida 100, corredor 80, cabeça 40, braço 45, perna 55, PEN em pontos), Guia do corpo (segmentos 40/120/90/60/45/25/80/55; "zumbi só cai com a cabeça a 0"). Pela regra do Guia, tiro no tronco nunca mata, o que contradiz "Brutamonte cai no 4º tiro de 5.56 no tronco".Um modelo: vida total (Bestiário) decide a morte por tronco; segmentos (Guia) decidem desmembramento; penetração por pontos PEN (Arsenal) com custo por corpo e Brutamonte = 2 corpos. Arsenal é a fonte dos números das armas.Armas + Zumbis + Personagens
B3Números das armas5.56: 55 (Bestiário) × 45 (Arsenal). .308: 85 × 75. 9 mm: 35 × 30 (Guia). Machado: 50 × 85. 12 ga: 9×12 × 95.Arsenal vale para armas de fogo; o Bestiário recalcula o aceite do M2 (Brutamonte 220 cai em 5 tiros de 5.56 a 45, não 4). Armas brancas: abrir tabela única no Arsenal.Armas
B4Velocidades e perseguiçãoCorredor 5,5 m/s (Bestiário e mapa) × 6,0 (Personagens). Lento 1,4 × Andador 1,2 × andante 1,4. Jogador AGI 3 corre 5,56 m/s: mais rápido que o Corredor base de 5,5, então o aceite do M1 de Personagens ("corredor alcança em <15 s") só funciona por causa do fôlego (70 pontos, 12/s = 5,8 s).Bestiário é a fonte (Lento 1,4, Corredor 5,5 com modificadores até 6,5). Personagens reescreve o aceite do M1 contando o fôlego e o Corredor Fresco/Jovem.Personagens
B5Tempo de infecção e reanimaçãoPersonagens/Sobreviventes: morte em 48 h de jogo, reanima em 2–6 min. Bestiário: reanima em 2–4 min. Mapa (fatia): mordida mata e reanima em 120 s. Cena de teste v2: 30 s.48 h de jogo e 2–4 min. Fatia e cena de teste usam aceleração de debug, explícita no brief.Zumbis + Mapa
B6Tempo de jogo × tempo realDia de jogo = 60 min reais. "Corpos 15 min", "sangue seca em 10 min", "incêndio 10 min", "partes somem em 15 min de jogo" (Guia) × "60 s" (Arsenal). 15 min de jogo = 37 s reais.Toda duração ganha unidade: s_real para cosmético e desempenho (corpos, poças, detritos, partes), h_jogo para sistemas de mundo (infecção, fome, destino). Corpos e partes: 15 min reais.Todos
B7Número de jogadoresZumbis, mapa e veículos: 4. Personagens e sobreviventes: 2 a 8.Orçamento abaixo fecha com 8 na LAN se o teto global de zumbis materializados for respeitado. Aceite de cada time mede com 4 e com 8.Revisão
B8Banda de rede22–30 KB/s (teto 64), ≤64 KB/s, 256 kbps (=32 KB/s) por cliente.Típico ≤32 KB/s, pico ≤64 KB/s por cliente (seção 3).Todos
Importantes
#TemaDivergênciaProposta
I1LOD de simulaçãoZumbis L0 <35 m, L1 35–120, L2 120–400, L3 >400 (histerese 10 m). Mapa: navmesh individual <30 m, sync 10 Hz 16 bits/eixo. NPCs 80/300 m (histerese 20 m). Veículos dormem >60 m.Um único sistema de relevância (seção 4), com faixas por tipo de agente mas o mesmo cálculo de distância ao jogador mais próximo.
I2Taxa de replicação dos zumbisBestiário: 20 Hz em L0, 5 Hz em L1, delta 3–5 bytes. Mapa: 10 Hz para todos, 16 bits/eixo.Bestiário vale; o mapa remove a própria regra.
I3Triângulos do zumbiBestiário: 300–800. Guia do corpo: 2.500–5.000 com LOD 100/40/15%.LOD0 2.500 (só os ~40 mais perto), LOD1 1.000, LOD2 400, LOD3 impostor/150 (>120 m). Ver seção 2.
I4Animação2.000 por VAT, mas a "cascata" por junta (Animation Rigging) e o pêndulo do membro pendurado são por osso.Cascata e pêndulo no shader VAT como atraso por junta (amostra o clipe com offset por osso) para todos; Animation Rigging só para os ≤32 em L0 mais perto.
I5RagdollsBestiário 12 simultâneos, veículos pool de 24, explosões 12.Teto global 16, pool 24 (veículos herdam o pool global).
I6Partes soltasGuia: 40 no mapa, 15 min. Arsenal: 40 por jogador, 60 s.40 por jogador até 160, somem com o corpo (15 min reais) ou ao reciclar o mais antigo fora da vista.
I7Percepção e barulhoBestiário: raios por categoria (Lento ouve 40 m). Mapa: eventos com raio (pistola 60, espingarda 90). Veículos: eventos com raio. Arsenal: "ruído" qualitativo.Barulho é evento {posição, raio}; categoria aplica multiplicador de audição. Arsenal converte "médio/alto/extremo" em metros.
I8Porta e barricadaMapa: porta 300 de vida, 10 por golpe a cada 1,5 s. Bestiário: pressão por corpo (1 / 1,5 / 3) e Brutamonte 3× em porta.Golpe direto (mapa) para quem está na vaga de ataque + pressão da pilha (Bestiário) somada.
I9Nomes dos tiposLento / Andador / andante. 8 tipos na tabela 3.1 e 13 na rodada 4 do Bestiário."Lento" em todo lugar; Bestiário reescreve a 3.1 com os 13 tipos e a composição nova.
I10Nascimentos e histórias cruzadasSobreviventes só tem chegadas por reposição; não há nascimentos, casais, rivalidades nem efeito de uma base na outra.Em andamento no time de Sobreviventes. Orçamento da seção 5 vale para a versão nova.
I11População total do mundoNinguém definiu quantos zumbis existem no Vale (32×32 km) nem o teto de materializados com jogadores espalhados.Seção 4: população por bloco de 64 m em dados, teto global de 2.000 materializados, dividido entre jogadores.
I12Brief de zumbisDuas seções "12" e tabelas 3.1 e 12.1 que divergem.Renumerar e deixar só a tabela atual.

2. Orçamento por quadro (host, 60 FPS = 16,6 ms)

CPU (o host é servidor e cliente)
SistemaThread principalWorkers (Jobs/Burst)Observação
Zumbis: percepção, IA, flow field, multidão, pilha0,6 ms3,0 ms2.000 materializados; L0 a 20 Hz, L1 a 5 Hz, espalhados por quadro
Física (jogadores, ≤8 veículos, ≤16 ragdolls, detritos)1,5 ms—Detritos dormem em 2 s
Tiros e penetração (RaycastCommand em lote)0,3 ms0,3 msTeto de 64 disparos por quadro
NPCs (até 104, LOD completo ≤20)0,4 ms0,3 msUtilidade reavaliada a cada 0,5 s escalonada
Destino e histórias (tick diário)0,0 ms≤2 ms por dia, fatiadoFatiado em 0,1 ms por quadro, sem pico
Veículos0,5 ms—8 simulados
Rede (snapshot, compressão, envio a 7 clientes)1,0 ms0,5 ms30 Hz
Relevância/LOD e streaming de setor0,5 ms0,5 msSetores de 2 km, origem flutuante
Animação (rigs dos próximos)0,8 ms0,5 msVAT para o resto não custa CPU
VFX (eventos, pools)0,8 ms—Conforme Oficina
Áudio0,5 ms—24–32 vozes + multidão agregada
Mapa vivo (eventos, clima, animais)0,3 ms0,2 ms≤40 animais materializados
Jogabilidade, UI, outros1,5 ms—
Total principal8,7 msSobra ~3 ms; o render thread é separado
Render thread (submissão, culling)4,0 msSRP Batcher + GPU instancing
GPU (GTX 1060)
ItemTípico (60 FPS)Pior caso 2.000 zumbis (30 FPS)
Mundo (terreno, prédios, props, vegetação)5,0 ms6,0 ms
Sombras (direcional 2 cascatas + lanterna local)2,0 ms2,5 ms
Zumbis (VAT instanciado)1,5 ms6,0 ms
Jogadores, NPCs, veículos1,0 ms1,5 ms
VFX + decalques + fluidos (compute)2,5 ms4,0 ms
Pós (bloom, neblina, efeitos de tela)1,5 ms1,5 ms
UI0,3 ms0,3 ms
Total13,8 ms21,8 ms
Geometria e chamadas
ItemTeto
Triângulos na tela≤2,5 M típico, ≤3,5 M pior caso
Zumbis (2.000): 40×2.500 + 160×1.000 + 800×400 + 1.000×150≈ 0,73 M
Batches SRP≤1.500 (≤400 na rua, como pede o mapa)
Set pass≤150
Zumbis≤40 draw calls (malha × LOD × material de paleta 256²)
VRAM≤3,5 GB · RAM ≤6 GB

3. Orçamento de rede (por cliente, 30 Hz)

FluxoContaKB/s
Zumbis L0 (≤60 perto do cliente)60 × 20 Hz × 5 B6,0
Zumbis L1 (≤300)300 × 5 Hz × 4 B6,0
Grupos L2 (centróide)50 × 1 Hz × 8 B0,4
Jogadores (7 outros)7 × 30 Hz × 20 B4,2
NPCs completos (≤20)20 × 20 Hz × 8 B3,2
Veículos relevantes (≤8)8 × 30 Hz × 24 B5,8
Eventos (impacto 12 B, explosão 16 B, som)~100/s em combate1,2
Cabeçalhos UDP/transporte30 × 28 B0,8
Total≈ 27,6 KB/s (meta ≤32, teto 64)

Upload do host com 8 jogadores ≈ 190 KB/s (1,6 Mbps), sem problema em LAN. Cosmético nunca vai pela rede (semente).


4. Relevância única (mapa vivo + hordas)

FaixaDistância ao jogador mais próximoZumbisNPCsVeículosRede
R00–35 mIA completa 20 Hz, hitboxes, pilha, rig dos 32 mais pertocompleto (até 80 m)simulado20 Hz
R135–120 mflow field 5 Hz, 1 cápsulacompleto/simplificadodorme além de 60 m5 Hz
R2120–400 mgrupos de 8–32, 1 Hzsimplificado (até 300 m)dormecentróide 1 Hz
R3>400 mdados por bloco de 64 m, 0,2 Hzabstrato (tick por hora de jogo)dadosnada
  • Histerese de 10 m para zumbis e 20 m para NPCs, como nos briefs.
  • Teto global de materializados (R0–R1): 2.000 zumbis. Com jogadores espalhados, o teto se divide pela área de cada um; a horda que passa do teto fica em R2 como grupo e vai sendo materializada pela borda.
  • População do mundo em R3: dados por bloco (≈40 B por bloco, 250 mil blocos = 10 MB). A migração semanal de 1.000+ é um grupo R3 que só materializa perto de jogador.
  • Mapa vivo (eventos, clima, animais) roda no mesmo relógio: eventos são dados em R3 e só viram entidades em R0–R1.

5. NPCs vivos e histórias

  • Até 13 bases × 8 moradores = 104 NPCs, mais nascimentos (bebê é dado, não agente, até virar criança jogável fora do build).
  • Tick diário de destino (pontos de virada, risco, luto, relações cruzadas, nascimentos) ≤2 ms no total, fatiado em quadros.
  • LOD completo ≤20 NPCs ao mesmo tempo; o resto em simplificado (decisão a cada 2 s) ou abstrato.
  • Fofoca e memória: 30 entradas × 104 NPCs, cabe em memória sem custo.

6. Próximos passos

  1. Acompanhar os times que ainda trabalham (Zumbis, Mapa, Armas, Veículos, Personagens, Sobreviventes, Fluidos, Cena de teste) e revisar cada entrega no navegador.
  2. Mandar as correções B1–B8 e I1–I12 às threads donas.
  3. Relatório consolidado em página.
  4. Marco 1: teste de estresse de 2.000 zumbis + bloco do mapa vivo medindo FPS (protótipo three.js agora; engine depois da decisão).

7. Situação em 22/10, 06h

  • Relatório consolidado publicado como documento: ../jogo/revisao-final-fatia-jogavel.html
  • Fatia jogável na versão 7: ../jogo/zombiada-jardim-aurora.html
  • Mapa alinhou B1, B5, B7, I1, I2, I8, I9 e I11 (documento v8).
  • Abertos: 9 mm (30 × 35), Corredor 5,5 × 6,0 em Personagens e a folga do aceite M1 (14 m declarados, ~11 m na conta: 6,96 × 6,46 m/s por 7,7 s).

Regras de documentação e prévias do ZombiAdA

Regra pedida pelo Anderson em 22/10/2026: pode publicar online, mas sempre existe uma cópia local atualizada na pasta do projeto.

A regra

  1. Toda documentação, prévia, protótipo ou página publicada online (artifact do claude.ai, Claude Doc) tem uma cópia em docs/offline/, na pasta do time.
  2. A cópia é atualizada no mesmo turno em que a versão online muda. Publicou uma versão nova, regrave a cópia local logo em seguida.
  3. A cópia abre com dois cliques, sem internet, e não perde nada: 3D, animações, interações, sons e fontes.
    • three.js, addons (OrbitControls etc.), fontes e todo o código vão embutidos no próprio HTML. Nada de CDN, Google Fonts ou <script src> externo.
    • Páginas com <script type="module"> + importmap não carregam módulos externos em file://: o three.module.js vai embutido dentro do próprio módulo (o build_offline.py já faz isso).
    • Página com vários arquivos (ex.: Garagem) vira um HTML só.
    • Claude Docs são exportados para HTML.
  4. Links entre páginas apontam para as cópias locais, em caminho relativo. O link para a versão online fica só no índice.
  5. Toda página nova entra no índice docs/offline/index.html e no Portal das Equipes (portal/fonte/portal.html, entrada ["offline", "docs/offline/..."] em files, depois rodar python3 portal/fonte/build.py e republicar o portal).
  6. Antes de dar por pronto: abrir a cópia com a rede bloqueada e conferir que não há erro no console nem requisição externa.

Onde fica cada coisa

TimePasta local
Jogodocs/offline/jogo/
Mapadocs/offline/mapa/
Zumbis e personagensdocs/offline/zumbis-personagens/
Sobreviventes e facçõesdocs/offline/sobreviventes/
Armas e itensdocs/offline/armas-itens/
Veículosveiculos/garagem.html e veiculos/frota.html (mantidos pelo time de veículos)
Efeitosdocs/offline/efeitos/
Animaisdocs/offline/animais/
Arte geraldocs/offline/arte/

Como regenerar

docs/offline/ferramentas/build_offline.py converte a página publicada numa cópia offline:

  1. Baixe a versão publicada de cada página para ferramentas/raw/<nome>/index.html (o nome de cada pasta está na tabela PAGES do script).
  2. Rode python3 ferramentas/build_offline.py docs/offline (precisa de internet só para buscar as fontes do Google uma vez; o three.js está em ferramentas/lib/).
  3. Teste aberto sem rede.

Imagens da revisão

revisao/casa3-r6 4 imagens

par-S01.jpg
par-S02.jpg
par-S03.jpg
par-S07.jpg

revisao/plantas 8 imagens

tela-casaA-posicoes.png
tela-casaA-s1.png
tela-casaA-s7.png
tela-celular-mercado.png
tela-mansao-posicoes.png
tela-mansao-s1.png
tela-mansao-s4.png
tela-sobrado-andar2.png

revisao/plantas-jogo 3 imagens

aereo-quintais.png
mosaico.jpg
plano-casas.png

revisao/comparacoes 5 imagens

1-carros.jpg
2-sobreviventes.jpg
3-sangue.jpg
4-noite-rua.jpg
5-explosao.jpg