feat(jogo): expediente dos mortos, jogo de zumbis em primeira pessoa
Etapa 1 inteira (logica com 100% de cobertura, cena 3D, toque, sons, bancada de desempenho, e2e) e a base da etapa 2 (mapa novo no Tiled, texturas, imagens dos itens, sons conferidos, golpe recortado e medido). Pagina /jogo fora do menu e do sitemap ate a medicao no celular.
This commit is contained in:
1 parent
c7d09d63d4
commit
67b32fcab3
118 files changed
+16730
No files matched your search
@@ -0,0 +1,176 @@
|
||||
# Jogo de zumbis do portfólio: etapa 1, trecho jogável
|
||||
**Autor:** Evandro · **Data:** 2026-11-10 · **Porte:** grande · **Status:** em execução
|
||||
|
||||
## 1. Objetivo
|
||||
Uma página `/jogo` com um jogo de tiro em primeira pessoa em que cada horda de zumbis é um problema de empresa que eu resolvo; horda eliminada vira um aliado com o nome da solução. A etapa 1 entrega um trecho jogável e medido no computador e no S26 Ultra, para decidir com número quanto o jogo pode crescer.
|
||||
|
||||
## 2. Escopo
|
||||
- Dentro: rota `/jogo` (tela inicial, partida, relatório final) e `/jogo/bancada` (medição); um mapa (escritório à noite); um modelo de zumbi realista com 3 variações de textura; 3 comportamentos (comum, rápido, blindado) e o chefão; pistola, automática e faca; 3 drones aliados; feed de eliminações; sangue; efeitos sonoros; controles de teclado e mouse e de toque; a lista dos 27 problemas; créditos dos arquivos.
|
||||
- Fora (não fazer): botão na entrada do site (etapa 2, depois da medição); outros mapas; comportamentos "divide", "invisível" e "atira de longe"; multiplayer e placar online; música; braços em primeira pessoa; opção sem sangue; arquivos que pedem login (Mixamo, Sketchfab); dependência nova; cartão que cite cliente.
|
||||
|
||||
## 3. Critérios de aceite
|
||||
- CA1 (laço): no Fácil, 3 hordas e o chefão. Ao cair cada horda aparece "Resolvido: <problema>", nasce um drone com o nome da solução e o feed mostra "<solução> eliminou <problema>". O relatório final mostra eliminações da pessoa e dos drones, o link do serviço de cada problema e o WhatsApp com mensagem que cita o problema escolhido → `pnpm test:e2e -- jogo` com piloto automático e semente fixa.
|
||||
- CA2 (dificuldade): a partida abre no Fácil; Fácil, Normal e Difícil aplicam a tabela da seção 5 → `pnpm test -- lib/jogo/dificuldade`.
|
||||
- CA3 (armas): pistola com munição infinita; automática gasta e recolhe munição caída; faca só acerta a até 1,5 m → `pnpm test -- lib/jogo/armas`.
|
||||
- CA4 (celular): em aparelho de toque aparecem direcional, área de mira, troca de arma e faca; a automática atira sozinha com a mira no zumbi; em retrato a página pede para virar o aparelho; nenhum controle fica fora da área visível em 915×412 e 640×360 → e2e com toque emulado e inspeção no S26 Ultra.
|
||||
- CA5 (desempenho no computador): bancada com 16 zumbis animados à vista, 3 drones e sangue: p95 do quadro ≤ 16,7 ms em 1440×900 no Chromium com GPU; com CPU 4× mais lenta, p95 ≤ 33 ms → `pnpm test:e2e -- jogo-bancada` (local, com GPU).
|
||||
- CA6 (desempenho no S26 Ultra): mesma bancada no aparelho: p95 ≤ 16,7 ms; em 5 minutos de partida, a média do último minuto fica em até 1,2× a do primeiro → a bancada mostra o resultado na tela e ele vai para o Registro. Bloqueada por P1.
|
||||
- CA7 (regulador): com p95 > 20 ms por 2 s o jogo reduz, nesta ordem, resolução, sombras e zumbis à vista (mínimo 8); com folga por 10 s, sobe um degrau → `pnpm test -- lib/jogo/regulador` e bancada com CPU lenta.
|
||||
- CA8 (peso): tudo que baixa antes de jogar soma ≤ 6 MB; cada modelo ≤ 1,5 MB; o zumbi tem ≤ 12 mil triângulos; texturas com lado ≤ 1024 px; abrir `/` não baixa nenhum arquivo de `/jogo` e o LCP da home continua sendo o h1 → `pnpm test -- lib/jogo/orcamento` e e2e de rede.
|
||||
- CA9 (memória): 3 partidas seguidas sem recarregar: geometrias e texturas vivas (`renderer.info.memory`) iguais às da primeira e heap JS em até 1,1× → e2e na bancada.
|
||||
- CA10 (caminhos): toda função de `lib/jogo/**` tem complexidade ciclomática ≤ 10 e a cobertura de linhas e de ramos de `lib/jogo/**` é 100% → `pnpm test -- lib/jogo --coverage`.
|
||||
- CA11 (acesso): sem JavaScript, sem WebGL ou com movimento reduzido a página mostra os 27 problemas em texto com link para o serviço (com movimento reduzido há também "jogar mesmo assim", sem tremor de câmera); aviso de sangue antes de começar; pausa no `Esc` e ao sair da aba; botão de mudo; axe sem violação na tela inicial e no relatório → e2e.
|
||||
- CA12 (conteúdo e licença): cada problema aponta para um serviço que existe; nenhum texto do jogo cita cliente; cada arquivo de `public/jogo/` consta em `public/jogo/CREDITOS.json` com origem, autor e licença (`CC0-1.0` para o que foi baixado, `propria` para o que foi gerado aqui) → `pnpm test -- lib/jogo/problemas lib/jogo/creditos`.
|
||||
- CA13: Biome, typecheck, `pnpm test`, build e e2e verdes; `/jogo` e `/jogo/bancada` com `noindex` e fora do sitemap nesta etapa.
|
||||
|
||||
## 4. Contexto verificado
|
||||
- Cena 3D carregada sob demanda: `app/components/cinematic/HeroField.tsx:109` (`await import("./BlocosScene")`). `GLTFLoader` vem de `three/examples/jsm` (`BlocosScene.tsx:25`); `SkeletonUtils`, `PointerLockControls`, `DRACOLoader` e `meshopt_decoder` existem na mesma pasta do three 0.182.
|
||||
- Orçamento de quadro que já existe: `createFrameBudget(limitMs = 28, frames = 60)` em `lib/blocos.ts:315`. Bloco da marca: `public/3d/bloco.glb` (2,7 KB).
|
||||
- WhatsApp: `buildWhatsAppUrl(message)` em `lib/whatsapp.ts:17`. Serviços e slugs: `lib/site-content.ts:120-613`. `noindex` de referência: `app/not-found.tsx:21`.
|
||||
- Jest: `roots` em `app` e `lib`, `coverageProvider: "v8"`, sem `coverageThreshold` (`jest.config.ts:4-6`). O Biome não tem regra de complexidade (`biome.json`). e2e em `e2e/`, sobre a porta 3001 (`playwright.config.ts:10`).
|
||||
- Blender 5.2.2 instalado; os scripts de modelo ficam em `3d/*.py`.
|
||||
- Zumbi candidato: "Male City Zombie", de Rikindle3D, CC0, 4,4 MB em `.7z`, baixa sem login (https://opengameart.org/content/male-city-zombie-ready-for-use-in-game-engines); a página lista andar, atacar, morrer, parado, correr e reação. Formato interno e triângulos não conferidos. Não foi achado outro zumbi realista com esqueleto que baixe sem login.
|
||||
- Texturas e sons CC0 sem conta: Poly Haven, ambientCG, Kenney, OpenGameArt (licenças lidas pelos agentes de pesquisa, não conferidas arquivo a arquivo).
|
||||
- Não há número medido de quantos personagens animados um celular aguenta no three.js; um relato viu queda acima de uns 20.
|
||||
|
||||
## 5. Desenho
|
||||
- **Lógica separada da tela.** `lib/jogo/` não importa three nem DOM, avança em passo fixo de 1/60 s e sorteia por semente; por isso é testável caminho a caminho e o piloto repete a mesma partida. Interface comum: `criarPartida({ semente, dificuldade, problemaId })`, `avancar(estado, entrada)` e `Entrada = { mover: [x, y], olhar: [dx, dy], atirar: boolean, arma: 0 | 1 | 2 }`.
|
||||
- **Módulos:** `tipos` e `valores` (contrato e números, abaixo), `mapa` (grade de 1 m escrita em texto, de onde saem as paredes da lógica e as da tela), `partida` (inicio → horda → pausa → chefão → vitória ou derrota), `hordas`, `zumbis` (campo de fluxo em grade, colisão por círculo), `armas` (tiro por raio contra cápsulas), `drones`, `feed`, `dificuldade`, `regulador`, `problemas`, `piloto`, `orcamento`, `creditos`.
|
||||
- **Contrato da lógica:** plano XZ em metros, Y para cima; `rumo` em radianos, com direção `(sin(rumo), cos(rumo))`. O estado é um objeto só, alterado no lugar por `avancar`; cada passo deixa em `eventos` o que a tela precisa desenhar (tiro, acerto, morte, drone novo, horda resolvida).
|
||||
- **Valores iniciais:** zumbi comum (vida 100, 1,2 m/s, dano 10), rápido (50, 2,4 m/s, 6), blindado (250, 0,9 m/s, 15), chefão (1500, 1,0 m/s, 25); ataque a 1 m, um por segundo. Pistola (dano 34, 3 tiros/s, munição infinita), automática (20, 10 tiros/s, 90 balas, caixa caída dá 30), faca (100, 2 golpes/s, 1,5 m). Acerto acima de 1,55 m de altura dobra o dano. Drone (dano 25, 2 tiros/s, 15 m, precisa de linha de visão). Pausa de 5 s entre hordas, com +25 de vida.
|
||||
- **Hordas:** a 1 só tem comuns; a 2, comuns e rápidos; a 3, comuns, rápidos e blindados; o chefão vem com 6 comuns. As três hordas levam o nome de três outros problemas da mesma área do problema escolhido.
|
||||
- **Feed:** só registra eliminação feita por drone e horda resolvida.
|
||||
- **Tela:** `app/jogo/` com o canvas three e a interface em HTML por cima. Sem motor de física e sem biblioteca nova.
|
||||
- **Zumbis:** um GLB clonado com `SkeletonUtils.clone`, com teto de zumbis à vista (16 no nível alto, 8 no baixo); o resto da horda espera na fila. Animação assada em textura com instâncias só entra se a bancada reprovar: não construir antes de medir.
|
||||
- **Drones:** blocos verdes da marca (`bloco.glb`) agrupados, com o nome da solução por cima. Sem esqueleto, custam pouco.
|
||||
- **Partida:** hordas de 12, 16 e 20 zumbis e o chefão; o problema escolhido é o chefão e a área dele dá os nomes das hordas. Vida 100.
|
||||
|
||||
| Dificuldade | Velocidade | Dano | Quantidade |
|
||||
|---|---|---|---|
|
||||
| Fácil (padrão) | 0,6× | 0,4× | 0,7× |
|
||||
| Normal | 1× | 1× | 1× |
|
||||
| Difícil | 1,3× | 1,5× | 1,3× |
|
||||
|
||||
- **Problemas (27) e o serviço de cada área:**
|
||||
- Vender e ser encontrado → `criacao-de-sites`: site que ninguém acha no Google; site que não abre direito no celular; site lento; catálogo desatualizado; pedido perdido no WhatsApp; pagamento que falha.
|
||||
- Atender → `atendimento-whatsapp-ia`: atraso no atendimento; mesma pergunta respondida cem vezes; agenda com horário duplicado; cliente sem retorno.
|
||||
- Operar → `engenharia-de-software`: planilha duplicada; digitar a mesma coisa em dois lugares; estoque furado; processo que só uma pessoa sabe fazer; controle no papel.
|
||||
- Fiscal e financeiro → `nota-fiscal-reforma-tributaria`: nota fiscal rejeitada; fechamento do mês que não bate; cobrança esquecida; relatório que demora dias.
|
||||
- Sistemas e integrações → `arquitetura-de-software` (a máquina vai para `integracao-hardware-software-iot`): sistemas que não conversam; máquina que não conversa com o sistema; sistema antigo em que ninguém mexe; sistema que cai na hora do pico.
|
||||
- Segurança e dados → `arquitetura-de-software` (o app vai para `/ia`): senha compartilhada; dados sem backup; acesso de ex-funcionário; app feito por IA cheio de falha.
|
||||
- **Arquivos 3D:** `3d/jogo.py` (Blender sem janela) baixa as fontes para `3d/fontes/` (fora do git), reduz, troca as texturas e exporta para `public/jogo/`. Compressão Draco só se o peso passar do CA8. Variações de textura do zumbi e cartazes do cenário saem da geração de imagem.
|
||||
- **Bancada:** `/jogo/bancada?zumbis=16&seg=20` roda o piloto, mostra na tela e expõe `window.__bancada = { p50, p95, max, quadros, chamadas, triangulos, heapMB }`.
|
||||
|
||||
## 6. Restrições, riscos, suposições
|
||||
- Restrições: sem dependência nova; nenhum byte do jogo na home; só arquivos CC0 que baixam sem login; sem commit nem push sem pedido.
|
||||
- R1: só há um zumbi realista sem login, de aparência mediana e formato não conferido. T1 abre e mede antes de tudo; se não servir, o trabalho para e a decisão volta ao Evandro (zumbi simplificado do Quaternius ou liberar login).
|
||||
- R2: o S26 Ultra é topo de linha; passar nele não garante aparelho médio. Por isso o CA5 mede com CPU 4× mais lenta e o CA7 exige o regulador.
|
||||
- R3: sangue e zumbi realista num site que vende para dono de empresa. O jogo fica em página própria, com aviso antes de começar e `noindex` nesta etapa.
|
||||
- R4: Safari no iPhone não será testado (sem aparelho).
|
||||
- Suposições: S1 no celular o jogo roda em paisagem; S2 nome provisório "Expediente dos Mortos"; S3 o CI não tem GPU, então a bancada roda só local e no aparelho; S4 "testes ciclomáticos" é o CA10; S5 valores da tabela e das hordas são iniciais e se ajustam jogando.
|
||||
- Perguntas abertas: P1: para o S26 Ultra abrir a bancada é preciso publicar a branch como prévia (push de `feat/jogo-zumbis`, que o CI publica fora de produção). Depende do ok do Evandro.
|
||||
|
||||
## 7. Microtasks
|
||||
### T1 · preparar o zumbi · sênior
|
||||
- Serve: CA8, CA12 · Depende de: nenhuma · Arquivos: criar `3d/jogo.py`, `public/jogo/zumbi.glb`, `public/jogo/CREDITOS.json`
|
||||
- Fazer: baixar o candidato, abrir no Blender, relatar formato, triângulos e clipes; reduzir para ≤ 12 mil triângulos e textura de 1024 px; exportar com os clipes `parado`, `andar`, `atacar`, `morrer`. Parar e relatar se o arquivo não servir (R1).
|
||||
- Pronto quando: `blender -b -P 3d/jogo.py` termina com `OK zumbi`; o GLB tem ≤ 1,5 MB; um render de frente e um de perto estão em `3d/out/`.
|
||||
- [x] feito
|
||||
### T2 · bancada de desempenho · sênior
|
||||
- Serve: CA5, CA6 · Depende de: T1 · Arquivos: criar `app/jogo/bancada/page.tsx`, `app/jogo/Bancada.tsx`, `e2e/jogo-bancada.spec.ts`
|
||||
- Fazer: cena com N zumbis clonados andando em círculo, 3 drones e luz do mapa; medir o tempo de quadro por `seg` segundos e publicar `window.__bancada`; `noindex`.
|
||||
- Pronto quando: o e2e lê `p95` com 16 zumbis; o resultado aparece na tela.
|
||||
- [x] feito
|
||||
### CP1 · após T1–T2 · direto
|
||||
- Verificar: CA5 no computador e, com P1 resolvida, CA6 no S26 Ultra. O teto de zumbis à vista sai desta medida e vai para o Registro. Reprovou: parar e rever o desenho com o Evandro.
|
||||
### T3 · partida, hordas e dificuldade · implementador
|
||||
- Serve: CA1, CA2 · Depende de: CP1 · Arquivos: criar `lib/jogo/partida.ts`, `lib/jogo/hordas.ts`, `lib/jogo/dificuldade.ts` e os testes
|
||||
- Fazer: teste primeiro; máquina de estados e tabela da seção 5; `criarPartida` e `avancar` com a interface da seção 5.
|
||||
- Pronto quando: `pnpm test -- lib/jogo/partida lib/jogo/hordas lib/jogo/dificuldade` verde, com um teste por caminho.
|
||||
- [x] feito
|
||||
### T4 · zumbis · implementador [P]
|
||||
- Serve: CA1 · Depende de: T3 · Arquivos: criar `lib/jogo/zumbis.ts` e o teste
|
||||
- Fazer: campo de fluxo em grade até o jogador, colisão por círculo, comportamentos comum, rápido, blindado e chefão, teto de zumbis à vista e fila.
|
||||
- Pronto quando: `pnpm test -- lib/jogo/zumbis` verde.
|
||||
- [x] feito
|
||||
### T5 · armas · implementador [P]
|
||||
- Serve: CA3 · Depende de: T3 · Arquivos: criar `lib/jogo/armas.ts` e o teste
|
||||
- Fazer: pistola, automática e faca; tiro por raio contra cápsula; munição caída e recolhida.
|
||||
- Pronto quando: `pnpm test -- lib/jogo/armas` verde.
|
||||
- [x] feito
|
||||
### T6 · drones e feed · implementador [P]
|
||||
- Serve: CA1 · Depende de: T3 · Arquivos: criar `lib/jogo/drones.ts`, `lib/jogo/feed.ts` e os testes
|
||||
- Fazer: drone nasce quando a horda cai, escolhe o alvo mais próximo, atira em ritmo fixo; o feed guarda as últimas 5 linhas "<solução> eliminou <problema>".
|
||||
- Pronto quando: `pnpm test -- lib/jogo/drones lib/jogo/feed` verde.
|
||||
- [x] feito
|
||||
### T7 · problemas e créditos · implementador [P]
|
||||
- Serve: CA12 · Depende de: nenhuma · Arquivos: criar `lib/jogo/problemas.ts`, `lib/jogo/creditos.ts` e os testes
|
||||
- Fazer: os 27 problemas com área, solução e serviço da seção 5; o teste confere cada slug em `lib/site-content.ts` e cada arquivo de `public/jogo/` no `CREDITOS.json`.
|
||||
- Pronto quando: `pnpm test -- lib/jogo/problemas lib/jogo/creditos` verde.
|
||||
- [x] feito
|
||||
### T8 · complexidade e cobertura · implementador
|
||||
- Serve: CA10 · Depende de: T3–T7 · Arquivos: criar `lib/jogo/complexidade.test.ts`; modificar `jest.config.ts`
|
||||
- Fazer: teste que percorre `lib/jogo/**` com a API do TypeScript e conta decisões por função (`if`, laços, `case`, `catch`, `?:`, `&&`, `||`, `??`), falhando acima de 10; `coverageThreshold` de 100% em linhas e ramos para `lib/jogo/**`.
|
||||
- Pronto quando: `pnpm test -- lib/jogo --coverage` verde; uma função de 11 decisões posta de propósito faz o teste falhar.
|
||||
- [x] feito
|
||||
### CP2 · após T3–T8 · direto
|
||||
- Verificar: Biome, typecheck e `pnpm test`; uma partida inteira do piloto termina em vitória no Fácil só com a lógica.
|
||||
### T9 · cena jogável no computador · sênior
|
||||
- Serve: CA1 · Depende de: CP2 · Arquivos: criar `app/jogo/page.tsx`, `app/jogo/Jogo.tsx`, `app/jogo/cena.ts`
|
||||
- Fazer: mapa do escritório, zumbis e drones ligados ao estado da lógica, arma na tela, mira, vida, munição, feed; mouse com `PointerLockControls`, `WASD`, `1 2 3`, `Esc` pausa.
|
||||
- Pronto quando: uma partida completa é jogável em 1440×900 sem erro no console.
|
||||
- [x] feito
|
||||
### T10 · controles de toque · sênior
|
||||
- Serve: CA4 · Depende de: T9 · Arquivos: criar `app/jogo/toque.ts`, `app/jogo/jogo.css`
|
||||
- Fazer: direcional à esquerda, arrastar à direita para mirar, tiro automático com a mira no zumbi, botões de arma e faca, aviso de virar o aparelho.
|
||||
- Pronto quando: o e2e com toque emulado elimina um zumbi; os controles cabem em 915×412 e 640×360.
|
||||
- [x] feito
|
||||
### T11 · telas de início e de fim · implementador
|
||||
- Serve: CA1, CA11 · Depende de: T9 · Arquivos: criar `app/jogo/Inicio.tsx`, `app/jogo/Relatorio.tsx`; modificar `app/jogo/page.tsx`
|
||||
- Fazer: escolha do problema e da dificuldade, aviso de sangue, mudo; cartão "Resolvido" entre hordas; relatório com links e WhatsApp por `buildWhatsAppUrl`; lista em texto para quem não tem JavaScript, WebGL ou pediu menos movimento.
|
||||
- Pronto quando: a mensagem do WhatsApp cita o problema escolhido; a lista em texto aparece sem JavaScript.
|
||||
- [x] feito
|
||||
### T12 · sangue, som e regulador · sênior
|
||||
- Serve: CA7, CA9 · Depende de: T9 · Arquivos: criar `lib/jogo/regulador.ts` e o teste; modificar `app/jogo/cena.ts`
|
||||
- Fazer: partículas e marcas de sangue com teto de 64; sons CC0 liberados no primeiro toque; regulador do CA7; descarte de geometrias e texturas ao fim da partida.
|
||||
- Pronto quando: `pnpm test -- lib/jogo/regulador` verde; a bancada com CPU lenta desce de nível sozinha.
|
||||
- [x] feito
|
||||
### T13 · testes de ponta a ponta · implementador
|
||||
- Serve: CA1, CA4, CA8, CA9, CA11, CA13 · Depende de: T10–T12 · Arquivos: criar `e2e/jogo.spec.ts`, `lib/jogo/orcamento.test.ts`; modificar `app/sitemap.test.ts`
|
||||
- Fazer: partida com piloto e semente fixa; toque; rede da home sem arquivo de `/jogo`; 3 partidas e memória; axe; pesos de `public/jogo/`; `/jogo` fora do sitemap.
|
||||
- Pronto quando: `pnpm test:e2e -- jogo` e `pnpm test -- lib/jogo/orcamento` verdes.
|
||||
- [x] feito
|
||||
### CP3 · após T9–T13 · direto
|
||||
- Verificar: todos os CAs; parecer do `fable-critico` sobre o laço de renderização e o descarte de memória; partida no S26 Ultra pelo Evandro.
|
||||
|
||||
## 8. Registro
|
||||
2026-11-10 — spec escrita a partir das decisões do Evandro: primeira pessoa, jogável no celular desde o início, zumbi realista com sangue, só arquivos sem login, drones como aliados, Fácil por padrão, chefão escolhido pela pessoa, S26 Ultra como aparelho de teste.
|
||||
2026-11-10 — a licença aceita em `CREDITOS.json` passou a ser `CC0-1.0` ou `propria`, porque texturas e cartazes gerados aqui não têm origem externa.
|
||||
2026-11-10 — aprovada pelo Evandro ("pode"), incluindo o push da branch como prévia quando a bancada estiver pronta (P1).
|
||||
2026-11-10 — ordem da lógica revista: ela não depende do resultado da bancada (se a medição reprovar, muda a tela, não as regras), então corre em paralelo com T1 e T2. O contrato (`lib/jogo/tipos.ts`, `lib/jogo/valores.ts`) foi escrito antes; a base (`mapa`, `rng`) e `hordas` com `feed` saem primeiro, depois `zumbis` com `dificuldade`, depois `armas` e `drones`, e por último `partida` com `piloto`. O nascimento dos zumbis fica em `zumbis`, não em `hordas`.
|
||||
2026-11-10 — T7 entregue: 27 problemas e a conferência de créditos, 17 testes, 100% de linhas e ramos. O teste roda no jsdom (o `jest.setup.ts` não carrega no ambiente node).
|
||||
2026-11-10 — T1 entregue: `public/jogo/zumbi.glb` com 11.950 triângulos, 1.459.472 bytes, 66 ossos, 1,80 m, clipes `parado`, `andar`, `atacar`, `morrer`, `correr`, `reacao`; texturas de cor e normal em JPEG 1024. Aparência (R1): proporção humana boa, mas a textura original é uma crosta ruidosa igual na pele e na roupa; não passa por realista de perto. Tentativa de conserto dentro do combinado: repintar com texturas geradas pela assinatura GPT (T1b), que também dá as 3 variações. Se não ficar bom, a decisão volta para o Evandro (liberar download com login ou trocar de estilo).
|
||||
2026-11-10 — os ossos do zumbi têm o prefixo `mixamorig:`, ou seja, o autor montou esqueleto e animações no Mixamo antes de publicar como CC0. A Adobe permite usar personagens e animações do Mixamo em projetos comerciais, jogos incluídos (helpx.adobe.com/creative-cloud/faq/mixamo-faq.html); o uso aqui (embutido no jogo, não redistribuído solto) cabe nisso. O arquivo foi baixado do OpenGameArt sem login.
|
||||
2026-11-10 — T4, T5, T6 e T8 entregues. `pnpm test:jogo` (script novo, com limite de 100% de cobertura) entrou no job `verify` do CI. O regulador de qualidade (parte de lógica da T12) saiu antes como `lib/jogo/regulador.ts`, com os degraus em `valores.ts`.
|
||||
2026-11-10 — a partida inteira do piloto pegou um defeito do desenho: a regra "com linha de visão o zumbi anda reto" prendia o zumbi atrás das mesas, que são sólidas mas deixam ver por cima. Correção: andar reto só com caminho livre de sólidos; senão, campo de fluxo mirando o centro da próxima célula, sem cortar quina.
|
||||
2026-11-10 — contrato da tela escrito em `app/jogo/contrato.ts` (`Escolha`, `Retrato`, `Resultado`, `Controle`); controles e telas correm em paralelo com a bancada. T10 ganhou `lib/jogo/alavanca.ts` e `alvoNaMira` em `armas.ts` (o tiro automático do toque do CA4 precisa saber se a mira está num zumbi). Nomes de arquivo mudaram em relação à seção 7: `app/jogo/controle.ts` e `Toque.tsx` no lugar de `toque.ts`; `Hud.tsx` e `ListaDeProblemas.tsx` a mais.
|
||||
2026-11-10 — causa real dos zumbis presos: seguindo o campo de fluxo, o corpo (raio 0,35) raspava a quina da mesa. `direcaoNoCampo` passou a mirar o centro da próxima célula e o zumbi só anda reto com `caminhoLivre`. Partida do piloto com semente 1 no Fácil: vitória no passo 6.703 (cerca de 1 min 52 s), placar 23 × 17, vida 100. O piloto mira sem errar, então uma pessoa leva mais tempo; a duração e o dano ficam para ajustar depois de jogar de verdade.
|
||||
2026-11-10 — o chefão (raio 0,6) nascia encostado na parede e não andava. Decisão: para andar, todo zumbi usa no máximo `RAIO_DE_PASSAGEM` (0,45 m); para levar tiro e atacar, vale o raio do tipo.
|
||||
2026-11-10 — a cena saiu em duas partes com interface fixa: T9a (`cena.ts`, `ambiente.ts`, `atores.ts`) e T9b (`page.tsx`, `Jogo.tsx`); a parte de sangue e som da T12 virou `efeitos.ts` e `som.ts`. Acréscimo ao desenho: cada zumbi leva o nome do problema acima da cabeça e cada drone o nome da solução, para a ideia ficar legível sem depender só do feed.
|
||||
2026-11-10 — T2 entregue. Bancada no computador (RTX 5060 Ti, `next dev`, 1440×900, Chromium com GPU): 16 zumbis p50/p95/máx 16,7/16,7/16,8 ms, 50 chamadas, 85 mil triângulos; 24 zumbis 16,7/16,7/16,8 ms; com CPU 4× mais lenta, 16 zumbis 16,7/16,8/33,4 ms e 24 zumbis 16,7/33,4/100 ms. CA5 atendido no computador. O tempo entre quadros trava nos 60 Hz do monitor e não mostra a folga; a bancada vai ganhar a medida do trabalho por quadro. Desvio: o Playwright não aceita `launchOptions` por bloco, então o caso com GPU abre o próprio Chromium.
|
||||
2026-11-10 — CP2: `pnpm test:jogo` com 253 testes, 100% de linhas e ramos, nenhuma função acima de 10 decisões. Piloto com semente 1: Fácil vitória no passo 5.988 (24 × 16), Normal 5.003 (37 × 18), Difícil 4.662 (46 × 24), sempre com vida 100. O piloto não erra e recua sempre; não serve de medida de dificuldade para gente.
|
||||
2026-11-10 — sons: 10 arquivos MP3 mono (1,7 a 18 KB cada) de pacotes CC0 da Kenney e do OpenGameArt (kurt, EZduzziteh, AntumDeluge), todos em `CREDITOS.json`. Um pacote foi recusado porque a página dizia CC0 e o zip trazia CC-BY. Ninguém ouviu os sons ainda: foram escolhidos por nome, duração e pico.
|
||||
2026-11-10 — `efeitos.ts` e `som.ts` entregues (22 testes): arma feita de caixas, clarão, traçantes, 64 gotas e 64 marcas de sangue em reserva fixa, 5 chamadas de desenho. `page.tsx` e `Jogo.tsx` entregues (16 testes), página sem h1 próprio (o h1 é da tela inicial e do relatório).
|
||||
2026-11-10 — a primeira versão da tela inicial ficou fraca (27 opções numa coluna só, botão "Começar" 1.600 px abaixo, sem imagem). Redesenho em andamento: duas colunas no computador, barra fixa com "Começar" no celular, imagem de abertura renderizada do próprio zumbi (`public/jogo/capa.jpg`).
|
||||
2026-11-10 — T1b entregue: cor refeita por bake no Blender com as 4 texturas geradas (pele, camisa, calça, máscara de sangue), normal original a 0,3, sem `KHR_materials_specular`, materiais `roupa`, `corpo`, `olhos`; três roupas (A no GLB, `roupa-b.jpg` 111 KB, `roupa-c.jpg` 64 KB); `capa.jpg` 83 KB. `zumbi.glb` com 1.465.268 bytes e 11.950 triângulos. Aparência: passa por zumbi crível a 2–3 m no escuro, não por fotorrealista; o molde original ainda aparece na calça curta, nos pés descalços, na barriga à mostra e na costura do ombro. R1 fica aberto para o Evandro decidir depois de ver no jogo.
|
||||
2026-11-10 — bancada com a medida de trabalho por quadro: 16 zumbis p95 2,8 ms (10,9 ms com CPU 4× mais lenta); 24 zumbis 4,5 ms (10,5 ms). Memória da bancada: geometrias 5 e texturas 55 iguais na 1ª e na 3ª medição. `capa.jpg` (1600 × 900) ficou fora do limite de 1024 px do CA8, que vale para textura; ganhou limite próprio de 1600 px e 220 KB.
|
||||
2026-11-10 — T9 entregue: `cena.ts`, `ambiente.ts`, `atores.ts`. No navegador com GPU, o piloto vence no Fácil (passo 5.988) sem erro no console; p95 de 16,7 ms e 26 chamadas de desenho no meio da horda (máximo medido 36 no Fácil e 49 no Difícil). Desvio da interface: `criarAmbiente` recebe `{ camera, movimentoReduzido }` e expõe `atualizar`. Conferência estática do conjunto: tsc rc=0, Biome limpo em 357 arquivos, 363 testes de `app/jogo` e `lib/jogo` passando.
|
||||
2026-11-10 — primeira olhada na cena: funciona, mas a arma é um bloco preto com faces brancas, os rótulos dos drones tomam a tela de perto, os dos zumbis se empilham e fora da lanterna fica escuro demais. Polimento em andamento, junto com o parecer do `fable-critico` e os testes de ponta a ponta.
|
||||
2026-11-10 — parecer do `fable-critico` (só leitura, CP3): sem vazamento achado em 3 partidas; passo fixo correto (teto de 5 passos, sem salto na volta da pausa). Um defeito que bloqueia: o regulador media o intervalo entre quadros, que a 60 Hz nunca fica abaixo de 16,7 ms, então nunca voltava a subir, e numa tela limitada a 30 quadros desceria até o fim sem ganho. Decisão: o regulador passa a receber também o tempo de trabalho do quadro; desce pelo intervalo (p95 > 20 ms, como no CA7), sobe quando o intervalo está dentro do limite e o trabalho tem p95 abaixo de 6 ms por 10 s, e duas descidas seguidas sem ganho de 10% fazem voltar e travar. Outros achados em conserto: perda de contexto WebGL sem tratamento, um esqueleto por malha em cada zumbi (3 vezes o custo de ossos), interpolação com 2 passos no mesmo quadro, som que não volta no iOS ao sair da aba, clique rápido perdido entre dois passos, alocação por quadro. O CA9 media `renderer.info.memory` entre renderers diferentes, o que não prova nada: a cena passa a publicar o que sobrou depois do descarte (esperado 0 geometrias e 0 texturas).
|
||||
2026-11-10 — consertos do parecer, parte 1: as 3 malhas de cada zumbi passaram a dividir um esqueleto (com 16 zumbis e CPU 4× mais lenta, o trabalho por quadro caiu de 20,9 para 12,4 ms no p95 e as texturas de 56 para 24); clone reaproveitado começa do zero; `liberar()` retoma o som sempre que o contexto não está rodando; clique ou toque inteiro entre dois passos vira um tiro. 106 testes de `app/jogo`, tsc e bancada (4 casos) verdes.
|
||||
2026-11-10 — polimento visual entregue e conferido nas capturas: armas refeitas (0,8% a 3,2% da tela), rótulos de tamanho fixo e só nos 3 zumbis mais próximos e no chefão, drones a 2,3 m, sala visível a 12 m, portas com luz vermelha nos nascedouros. Ainda feio: pilares lisos e armas feitas de caixas. Em 915 × 412 as eliminações cobrem os botões e o aviso cobre a mira (a corrigir no HUD).
|
||||
2026-11-10 — o Evandro pediu o refino (ferramentas abertas por CLI, mapa novo, itens, golpe sincronizado, ataque mais rápido): virou a spec `2026-11-10-jogo-zumbis-etapa-2-refino.md`, com execução autônoma. Esta etapa fecha antes de a lógica nova entrar.
|
||||
2026-11-10 — T13b entregue: `e2e/jogo.spec.ts` com 12 casos; 11 passam (CA1, CA4 em 915 × 412, 640 × 360 e retrato, CA8, CA11, CA13). O caso do CA9 falha por dois defeitos do jogo: heap em 1,113× e 1,117× entre a 1ª e a 3ª partida (limite 1,1×) e, com semente aleatória, o piloto fica mais de 5 minutos na horda 3 com "faltam 2". Os dois estão em conserto (o segundo com varredura de 300 sementes por dificuldade). Decisões do teste: no CA8, "arquivo do jogo" é o bloco que contém `__jogo` (a home já baixa o three pelo fundo 3D); no CA11 a pausa é conferida com `exitPointerLock`, porque o `Esc` simulado não solta a trava do mouse.
|
||||
2026-11-10 — Partida que empacava: achada e consertada. Causa: dois zumbis chegavam juntos a uma passagem de 1 m entre mesas e a separação empurrava cada um metade da sobreposição, um contra cada mesa; nenhum passava e o jogador, sem linha de visão, esperava (Fácil, semente 4, horda 3, "faltam 2" correto). Conserto em `separarPar` (`lib/jogo/zumbis.ts`): só o zumbi mais longe do jogador recua, e recua a sobreposição inteira. Varredura de 300 sementes × 3 dificuldades: 900 partidas terminam, todas em vitória, com vida média do piloto de 100 (o piloto não apanha; não diz nada sobre a dificuldade para uma pessoa, S5). Teste permanente novo com 40 sementes por dificuldade (leva de 19 a 23 s; reduzir na etapa 2). `pnpm test:jogo`: 277 testes, 100% nas quatro colunas.
|
||||
2026-11-10 — Consertos do parecer crítico, parte 2, feitos: regulador mede intervalo e trabalho (duas descidas sem ganho voltam os degraus e travam; nível inicial pelo `pixelRatio` do aparelho); contexto WebGL perdido pausa a partida e "Continuar" volta a valer depois de restaurar; `guardarPasso` a cada passo; sem vetor novo por passo; carga cancelada não cria renderer; `sobras` = 0 geometrias e 0 texturas nas 3 partidas (faltava soltar a textura `DFG_LUT`, que o three não liberava); "Continuar" chama `som.liberar()`. Heap entre a 1ª e a 3ª partida: 1,096× (limite 1,1×), medido com coleta forçada. Playwright: 16 passaram (bancada e jogo). Observado com CPU 4× mais lenta: o nível desceu, não houve ganho, voltou e travou, como desenhado; não foi visto subir de volta.
|
||||
2026-11-10 — Ponto de controle antes da lógica da etapa 2: Biome limpo (386 arquivos), typecheck rc=0, `pnpm test` 2071 testes, `pnpm test:jogo` 278 testes com 100% nas quatro colunas, build rc=0. Commit e push da prévia feitos neste estado. Desvio: o `impeccable critique` e o `audit` da etapa 1 passam para o fechamento da etapa 2, sobre a tela final, porque o refino já mudou HUD, sons e clipe de ataque.
|
||||
@@ -0,0 +1,182 @@
|
||||
# Jogo de zumbis do portfólio: etapa 2, refino (mapa, itens, golpe sincronizado)
|
||||
**Autor:** Evandro · **Data:** 2026-11-10 · **Porte:** grande · **Status:** em execução
|
||||
|
||||
Aprovação: o pedido foi "faça uma spec completa para esses passos e execute de maneira autônoma". Vale como ok antecipado; mudança de escopo ou de CA continua indo para o Registro e para o relato final.
|
||||
|
||||
## 1. Objetivo
|
||||
Refinar o jogo de `/jogo` com ferramentas abertas controladas por linha de comando: um mapa maior feito num editor de mapas, zumbis que começam devagar e largam itens com imagem própria, golpe do zumbi que só tira vida no instante em que a mão bate (com som no mesmo instante), ataque um pouco mais rápido e sons de tiro conferidos.
|
||||
|
||||
## 2. Escopo
|
||||
- Dentro: escolha e prova das ferramentas (mapa, modelo, som); mapa novo do escritório gerado por script, editável no Tiled e convertido para a grade da lógica e para o GLB da cena; 4 itens que caem dos zumbis (munição, kit médico, café, bateria) com imagens geradas pela assinatura do ChatGPT; ritmo crescente das hordas; golpe em três fases ligado ao clipe `atacar`; ciclo de ataque 25% mais rápido; sons de tiro, de dano, de item e de golpe no ar; zumbi novo a partir do MPFB2 se a prova passar (T2).
|
||||
- Fora (não fazer): botão na entrada do site (continua esperando a medição no S26 Ultra); segundo mapa; inventário com escolha de item; armas novas; multiplayer; música; dependência nova no `package.json`; servidor MCP do Blender (ver seção 5); instalar programa com sudo ou com login; mudar a interface fora do HUD dos itens.
|
||||
|
||||
## 3. Critérios de aceite
|
||||
- CA1 (ferramentas): `3d/FERRAMENTAS.md` lista cada programa usado, versão, licença lida no arquivo de licença dele e o comando exato; `bash 3d/mapa.sh` refaz o mapa inteiro sem abrir janela e, rodado duas vezes, não muda nenhum arquivo → `bash 3d/mapa.sh && git status --short lib/jogo/mapas public/jogo/mapa.glb` sem diferença na segunda vez.
|
||||
- CA2 (mapa): escritório com pelo menos 40 × 28 células, 6 ambientes com nome, 6 nascedouros e 2 caminhos entre quaisquer dois ambientes; toda célula de chão é alcançável do início; todo nascedouro fica a 8 m ou mais do início; nenhuma passagem tem menos de 2 células de largura; a grade da lógica e o GLB da cena saem do mesmo `3d/mapa/escritorio.tmx` → `pnpm test -- lib/jogo/mapas` e capturas da cena.
|
||||
- CA3 (ritmo): hordas de 8, 14 e 20 zumbis (antes do multiplicador); um zumbi nasce a cada 90, 50 e 30 passos; a velocidade deles é 0,8×, 1× e 1,15× → `pnpm test -- lib/jogo/hordas`.
|
||||
- CA4 (itens, lógica): zumbi morto larga item com chance de 30%, sorteado por peso (munição 45, kit 25, café 15, bateria 15; kit com peso dobrado se a vida está abaixo de 40; bateria só com drone vivo); munição dá 30 balas, kit dá 25 de vida, café dá 1,3× de velocidade por 8 s, bateria dobra a cadência dos drones por 10 s; item some em 20 s; no máximo 10 no chão; recolhe a 0,9 m; mesma semente, mesmos itens → `pnpm test -- lib/jogo/itens`.
|
||||
- CA5 (itens, tela): cada item no chão mostra a imagem gerada dele; ao recolher, o HUD mostra o nome e o tempo que resta do efeito e toca o som `item`; todos os itens juntos custam até 2 chamadas de desenho; o atlas das imagens tem até 512 px de lado e 120 KB → `pnpm test -- app/jogo/itens3d app/jogo/Hud` e e2e.
|
||||
- CA6 (golpe sincronizado): o golpe tem preparo, impacto e volta; a vida só cai no passo do impacto, e só se o jogador ainda está a até 1,4 m; fora disso sai `golpeNoAr`, sem dano; começado, o golpe vai até o fim. Na tela, o tempo do clipe `atacar` vem do tempo da lógica: em cada `golpe`, o clipe está a no máximo 34 ms do instante de impacto medido no Blender, e o som e o clarão vermelho saem no mesmo quadro → `pnpm test -- lib/jogo/zumbis app/jogo/efeitos` e e2e com GPU lendo `window.__jogo.golpes`.
|
||||
- CA7 (ataque mais rápido): o ciclo do ataque cai de 60 para 48 passos (de 1 para 1,25 golpe por segundo) → `pnpm test -- lib/jogo/valores`.
|
||||
- CA8 (sons): tiro de pistola, rajada, dano no jogador, item e golpe no ar em MP3 mono, com menos de 10 ms de silêncio no começo e pico até −1 dBFS; licença CC0 lida na página oficial do pacote e não contradita por arquivo dentro dele, sem login; o som do tiro sai no mesmo quadro do evento `tiro` → `pnpm test -- lib/jogo/creditos lib/jogo/orcamento app/jogo/efeitos`.
|
||||
- CA9 (zumbi novo, condicional): se T2 passar, o zumbi vem do MPFB2 com camisa, calça comprida e sapato de pacotes CC0, até 12 mil triângulos e 1,5 MB, com os mesmos 6 clipes, e entra no jogo só se o render lado a lado for melhor que o atual; se T2 não passar, fica o atual e o motivo vai para o Registro → renders em `3d/out/jogo/` e `pnpm test -- lib/jogo/orcamento`.
|
||||
- CA10 (desempenho e peso): com o mapa novo, 16 zumbis à vista, itens e drones: p95 do quadro ≤ 16,7 ms em 1440 × 900 e ≤ 33 ms com CPU 4× mais lenta; até 120 chamadas de desenho; `mapa.glb` ≤ 1,5 MB; `public/jogo` ≤ 6 MB; depois do descarte sobram 0 geometrias e 0 texturas → e2e da bancada e `pnpm test -- lib/jogo/orcamento`.
|
||||
- CA11 (qualidade): `pnpm test:jogo` com 100% nas quatro colunas e nenhuma função acima de 10 decisões; o piloto vence nas 3 dificuldades no mapa novo; Biome, typecheck, `pnpm test`, build e e2e verdes; os CAs da etapa 1 continuam valendo.
|
||||
- CA12 (conteúdo e licença): todo arquivo novo de `public/jogo/` está em `CREDITOS.json` (`CC0-1.0` ou `propria`); nenhum texto cita cliente.
|
||||
|
||||
## 4. Contexto verificado
|
||||
- Golpe hoje: `lib/jogo/zumbis.ts:113-120` tira vida quando `tempo % 60 === 20`, sem relação com o clipe; o clipe `atacar` do GLB dura 2,667 s; ao sair do alcance o zumbi troca de estado na hora (`zumbis.ts:156`).
|
||||
- Itens hoje: só a caixa de munição (`MUNICAO` em `lib/jogo/valores.ts:60-67`, 25% de chance, 30 balas, tipo `Caixa` em `tipos.ts:76`).
|
||||
- Hordas hoje: 12, 16 e 20 (`valores.ts:79-88`); nascimento a cada 20 passos (`zumbis.ts:16`).
|
||||
- Mapa hoje: grade de 28 colunas escrita à mão em `valores.ts:108-126`, lida por `lerMapa` (`lib/jogo/mapa.ts:38`), caracteres `# M . J N`.
|
||||
- Sons hoje: 10 MP3 em `public/jogo/sons/`, escolhidos sem ninguém ouvir; um pacote de tiros (Tabasco) foi recusado porque o zip traz CC-BY.
|
||||
- Na máquina: Blender 5.2.2, ffmpeg, ImageMagick e flatpak; não há Tiled, Godot, LDtk, TrenchBroom nem sox.
|
||||
- Pesquisa (em `~/tmp/jogo/pesquisa-ferramentas.md`, com as fontes): Tiled exporta sem janela com `tiled --export-map json entrada.tmx saida.json` e baixa sem login pelas releases do GitHub; MPFB2 é extensão de Blender (código GPLv3, saída sem restrição), com pacotes CC0 de pele, camisa, calça e sapato, e cria humano por Python (`HumanService.create_human`); a documentação cita um esqueleto "mixamo". Não confirmado: Tiled sem servidor gráfico nesta máquina, MPFB2 no Blender 5.2, triângulos do humano, nomes dos ossos.
|
||||
|
||||
## 5. Desenho
|
||||
- **Ferramentas escolhidas.** Mapa: Tiled (aberto, tem CLI, e o arquivo `.tmx` abre no editor para ajuste à mão). Modelos e cenário 3D: Blender por script, como na etapa 1. Humano: MPFB2 dentro do Blender. Imagens: geração de imagem do ChatGPT (`logo-gpt`). Som: ffmpeg. Descartados: Godot (é motor, o jogo roda em three.js), TrenchBroom e LDtk (sem CLI confirmada), Material Maker (CLI não confirmada; as texturas saem da geração de imagem), servidor MCP do Blender (exige o Blender aberto com janela; o script por CLI refaz tudo sozinho e fica no repositório).
|
||||
- **Instalação.** Programas baixados ficam em `3d/ferramentas/` (fora do git), sem sudo e sem login. O MPFB2 usa uma pasta de usuário do Blender separada (`BLENDER_USER_RESOURCES`), para não mexer no Blender do Evandro.
|
||||
- **Cadeia do mapa.** `3d/mapa.py gerar` (com semente, só sob `--gerar`) escreveu a primeira versão de `3d/mapa/escritorio.tmx`, que passa a ser a fonte → Tiled exporta `3d/mapa/escritorio.json` e uma imagem de conferência → `3d/mapa.py` converte para `lib/jogo/mapas/escritorio.ts` (a grade em texto que `lerMapa` já entende) → `blender -b -P 3d/mapa_3d.py` monta `public/jogo/mapa.glb` (paredes, piso, forro, móveis, luminárias) a partir do mesmo JSON. `3d/mapa.sh` roda tudo. Editou o `.tmx` no Tiled, rodou o script, o jogo muda.
|
||||
- **Golpe.** `3d/jogo.py` recorta o clipe `atacar` para um golpe só, mede o quadro em que a mão vai mais à frente e grava `lib/jogo/golpe.json` (`duracao` e `impacto`, em segundos). A lógica usa ciclo de 48 passos e `passoDoGolpe = round(impacto / duracao × 48)`. A tela não deixa a animação correr solta: a cada quadro põe o tempo do clipe em `(tempo do zumbi % 48) / 48 × duracao`. Sincronia por construção, e conferida por medida (CA6).
|
||||
- **Itens.** `lib/jogo/itens.ts` substitui a caixa: sorteio, queda, validade, coleta e efeitos, tudo pela semente. Na tela, um atlas 2 × 2 com as 4 imagens e um só desenho instanciado, mais um anel de luz no chão.
|
||||
- **Ritmo.** `HORDAS` ganha `nascerACada` e `velocidade` por horda; a tabela de dificuldade continua multiplicando por cima.
|
||||
- **Contrato.** Os tipos e valores novos entram em `lib/jogo/tipos.ts` e `valores.ts` antes das tarefas de lógica (T6), para elas rodarem em paralelo sem disputar esses dois arquivos.
|
||||
|
||||
## 6. Restrições, riscos, suposições
|
||||
- Restrições: as da etapa 1 (sem dependência nova no projeto, nenhum byte do jogo na home, só CC0 sem login, textos sem cliente). Commit na branch `feat/jogo-zumbis` e push dela como prévia já estão autorizados; nada vai para a `main`.
|
||||
- R1: o Tiled pode não rodar sem servidor gráfico aqui. Saída: `QT_QPA_PLATFORM=offscreen`, depois `flatpak --user`; se nada funcionar, o `.tmx` continua sendo a fonte e a conversão é feita pelo nosso script (registrar).
|
||||
- R2: o MPFB2 pode não rodar no Blender 5.2, passar de 12 mil triângulos ou não aceitar os clipes do zumbi atual. T2 mede antes; se falhar, fica o zumbi atual (CA9).
|
||||
- R3: mapa maior e itens custam quadro. CA10 mede de novo, com CPU 4× mais lenta.
|
||||
- R4: ninguém ouve os sons aqui. A conferência é por duração, pico e forma de onda; o ouvido do Evandro decide depois.
|
||||
- R5: golpe que vai até o fim e erra deixa o jogo mais fácil de esquivar; o ciclo 25% mais rápido compensa. Valores continuam iniciais (S5 da etapa 1).
|
||||
- Suposições: S1 "começar devagar" é o ritmo do CA3; S2 "itens" são os 4 do CA4; S3 "software para mapas com CLI" é atendido pelo Tiled mais o Blender; S4 a etapa 1 fecha (consertos do parecer, e2e, commit e prévia) antes de a lógica nova entrar.
|
||||
|
||||
## 7. Microtasks
|
||||
### T1 · provar o Tiled por linha de comando · sênior [P]
|
||||
- Serve: CA1 · Depende de: nenhuma · Arquivos: criar `3d/FERRAMENTAS.md`, `3d/mapa/prova.tmx`, `3d/mapa/prova.json`
|
||||
- Fazer: baixar o Tiled para `3d/ferramentas/`, exportar um mapa de prova para JSON e para imagem sem abrir janela, anotar versão, licença lida e comando.
|
||||
- Pronto quando: `prova.json` saiu do Tiled por CLI; `FERRAMENTAS.md` tem a linha do Tiled com a licença citada.
|
||||
- [x] feito
|
||||
|
||||
### T2 · provar o MPFB2 por linha de comando · sênior [P]
|
||||
- Serve: CA9 · Depende de: nenhuma · Arquivos: criar `3d/humano.py`; acrescentar em `3d/FERRAMENTAS.md`
|
||||
- Fazer: instalar a extensão em pasta de usuário separada, criar um humano com camisa, calça comprida e sapato de pacotes CC0, pôr esqueleto compatível com os clipes do zumbi atual, renderizar frente e perto. Parar e relatar se não der (R2).
|
||||
- Pronto quando: `blender -b -P 3d/humano.py` termina com `OK humano` e informa triângulos e ossos; renders em `3d/out/jogo/humano-*.png`; veredito escrito.
|
||||
- [x] feito
|
||||
|
||||
### T3 · recortar e medir o golpe · sênior [P]
|
||||
- Serve: CA6 · Depende de: nenhuma · Arquivos: modificar `3d/jogo.py`, `public/jogo/zumbi.glb`; criar `lib/jogo/golpe.json`
|
||||
- Fazer: deixar o clipe `atacar` com um golpe só (preparo, impacto, volta), medir o instante do impacto e gravar `duracao` e `impacto`.
|
||||
- Pronto quando: `blender -b -P 3d/jogo.py` termina com `OK zumbi`; `golpe.json` existe; `3d/out/jogo/golpe.png` mostra 5 quadros do golpe com o do impacto marcado.
|
||||
- [x] feito
|
||||
|
||||
### T4 · imagens dos itens · logo-gpt, depois impl [P]
|
||||
- Serve: CA5, CA12 · Depende de: nenhuma · Arquivos: criar `3d/itens/*.png`, `public/jogo/itens.webp`; modificar `public/jogo/CREDITOS.json`
|
||||
- Fazer: gerar munição, kit médico, café e bateria no mesmo estilo, fundo removível; montar o atlas 2 × 2 com transparência.
|
||||
- Pronto quando: atlas com 512 px e até 120 KB; as 4 imagens conferidas a olho; crédito `propria`.
|
||||
- [x] feito
|
||||
|
||||
### T5 · sons novos e tiros conferidos · sênior [P]
|
||||
- Serve: CA8, CA12 · Depende de: nenhuma · Arquivos: `public/jogo/sons/*.mp3`, `public/jogo/CREDITOS.json`
|
||||
- Fazer: conferir (e trocar se preciso) `pistola` e `automatica`; acrescentar `dano`, `item` e `golpe-no-ar`; licença lida dentro de cada pacote.
|
||||
- Pronto quando: `pnpm test -- lib/jogo/creditos lib/jogo/orcamento` verde; tabela com duração, pico e silêncio inicial de cada som.
|
||||
- [x] feito
|
||||
|
||||
### CP1 · após T1–T5 · direto
|
||||
- Ver os renders do humano e do golpe e as imagens dos itens; decidir CA9; registrar.
|
||||
- [x] feito
|
||||
|
||||
### T6 · contrato da lógica nova · direto
|
||||
- Serve: CA3, CA4, CA6, CA7 · Depende de: T3 e fim da etapa 1 · Arquivos: modificar `lib/jogo/tipos.ts`, `lib/jogo/valores.ts`
|
||||
- Fazer: tipos `Item`, `TipoItem`, eventos `golpeNoAr`, `itemCaiu`, `itemPego`; valores `ITENS`, `HORDAS.nascerACada`, `HORDAS.velocidade`, `ATAQUE_DO_ZUMBI` com ciclo de 48 e `alcanceDoGolpe`.
|
||||
- Pronto quando: `tsc` compila com os tipos novos; `pnpm test -- lib/jogo/valores` verde.
|
||||
- [ ] feito
|
||||
|
||||
### T7 · golpe em três fases · sênior [P]
|
||||
- Serve: CA6, CA7 · Depende de: T6 · Arquivos: modificar `lib/jogo/zumbis.ts`, `lib/jogo/zumbis.test.ts`
|
||||
- Fazer: preparo, impacto e volta; dano só no impacto e dentro do alcance; `golpeNoAr`; golpe começado vai até o fim.
|
||||
- Pronto quando: `pnpm test -- lib/jogo/zumbis` verde com 100% do arquivo.
|
||||
- [ ] feito
|
||||
|
||||
### T8 · itens na lógica · sênior [P]
|
||||
- Serve: CA4 · Depende de: T6 · Arquivos: criar `lib/jogo/itens.ts`, `lib/jogo/itens.test.ts`; modificar `lib/jogo/partida.ts`
|
||||
- Fazer: sorteio, queda, validade, coleta, efeitos de café e bateria; tirar a caixa antiga.
|
||||
- Pronto quando: `pnpm test -- lib/jogo/itens lib/jogo/partida` verde com 100%.
|
||||
- [ ] feito
|
||||
|
||||
### T9 · ritmo das hordas · impl [P]
|
||||
- Serve: CA3 · Depende de: T6 · Arquivos: modificar `lib/jogo/hordas.ts`, `lib/jogo/hordas.test.ts`
|
||||
- Fazer: tamanho, intervalo de nascimento e velocidade por horda.
|
||||
- Pronto quando: `pnpm test -- lib/jogo/hordas` verde com 100%.
|
||||
- [ ] feito
|
||||
|
||||
### T10 · gerar o mapa no Tiled · sênior [P]
|
||||
- Serve: CA1, CA2 · Depende de: T1 · Arquivos: criar `3d/mapa.py`, `3d/mapa.sh`, `3d/mapa/escritorio.tmx`, `lib/jogo/mapas/escritorio.ts`, `lib/jogo/mapas/escritorio.test.ts`
|
||||
- Fazer: gerador com semente, exportação pelo Tiled, conversão para a grade; testes do CA2.
|
||||
- Pronto quando: `bash 3d/mapa.sh` duas vezes sem diferença; `pnpm test -- lib/jogo/mapas` verde; imagem do mapa conferida.
|
||||
- [x] feito
|
||||
|
||||
### T11 · texturas do cenário · logo-gpt [P]
|
||||
- Serve: CA2, CA12 · Depende de: nenhuma · Arquivos: criar `3d/texturas/cenario-*.jpg`
|
||||
- Fazer: parede, carpete, forro, madeira de mesa e 4 cartazes de escritório, todas repetíveis sem emenda (menos os cartazes).
|
||||
- Pronto quando: 8 imagens conferidas a olho; nenhuma com marca, logotipo ou nome de empresa.
|
||||
- [x] feito
|
||||
|
||||
### T12 · montar o mapa em 3D · sênior
|
||||
- Serve: CA2, CA10 · Depende de: T10, T11 · Arquivos: criar `3d/mapa_3d.py`, `public/jogo/mapa.glb`; modificar `public/jogo/CREDITOS.json`
|
||||
- Fazer: paredes, piso, forro, móveis e luminárias a partir do JSON do Tiled, com poucas malhas e poucas texturas.
|
||||
- Pronto quando: `mapa.glb` ≤ 1,5 MB; 3 renders em `3d/out/jogo/mapa-*.png`; `pnpm test -- lib/jogo/orcamento` verde.
|
||||
- [ ] feito
|
||||
|
||||
### CP2 · após T7–T12 · direto
|
||||
- `pnpm test:jogo` com 100%; piloto vence nas 3 dificuldades no mapa novo; ver os renders do mapa.
|
||||
- [ ] feito
|
||||
|
||||
### T13 · cena com o mapa novo · sênior
|
||||
- Serve: CA2, CA10 · Depende de: T12 · Arquivos: modificar `app/jogo/ambiente.ts`, `app/jogo/ambiente.test.ts`, `app/jogo/cena.ts`
|
||||
- Fazer: carregar `mapa.glb` no lugar das caixas geradas; luzes nos pontos marcados; descarte completo.
|
||||
- Pronto quando: capturas da cena conferidas; `window.__jogo.sobras` 0 e 0; até 120 chamadas de desenho.
|
||||
- [ ] feito
|
||||
|
||||
### T14 · golpe na tela · sênior
|
||||
- Serve: CA6, CA8 · Depende de: T7, T13 · Arquivos: modificar `app/jogo/atores.ts`, `app/jogo/efeitos.ts`, `app/jogo/cena.ts`
|
||||
- Fazer: tempo do clipe vindo da lógica; som e clarão no quadro do evento; publicar `window.__jogo.golpes`.
|
||||
- Pronto quando: `pnpm test -- app/jogo` verde; no navegador com GPU, todo golpe com desvio até 34 ms.
|
||||
- [ ] feito
|
||||
|
||||
### T15 · itens na tela · sênior
|
||||
- Serve: CA5 · Depende de: T8, T4, T14 · Arquivos: criar `app/jogo/itens3d.ts`, `app/jogo/itens3d.test.ts`; modificar `app/jogo/Hud.tsx`
|
||||
- Fazer: itens instanciados com o atlas, anel no chão, piscar no fim da validade; HUD com nome e tempo do efeito.
|
||||
- Pronto quando: `pnpm test -- app/jogo/itens3d app/jogo/Hud` verde; captura com item no chão e efeito no HUD conferida.
|
||||
- [ ] feito
|
||||
|
||||
### T16 · zumbi novo no jogo · sênior (só se o CP1 aprovar)
|
||||
- Serve: CA9 · Depende de: T2, T3 · Arquivos: modificar `3d/jogo.py`, `public/jogo/zumbi.glb`, `public/jogo/roupa-*.jpg`
|
||||
- Fazer: trocar a base pelo humano do MPFB2, com as 3 roupas, o sangue e os 6 clipes.
|
||||
- Pronto quando: render lado a lado conferido; `pnpm test -- lib/jogo/orcamento` verde; bancada sem perda.
|
||||
- [ ] feito
|
||||
|
||||
### T17 · testes de ponta a ponta do refino · sênior
|
||||
- Serve: CA5, CA6, CA10, CA11 · Depende de: T13–T15 · Arquivos: modificar `e2e/jogo.spec.ts`, `e2e/jogo-bancada.spec.ts`, `lib/jogo/piloto.ts`
|
||||
- Fazer: casos de item, de golpe sincronizado e de desempenho no mapa novo; piloto ajustado se precisar.
|
||||
- Pronto quando: e2e verde com GPU; piloto vence nas 3 dificuldades.
|
||||
- [ ] feito
|
||||
|
||||
### CP3 · fechamento · direto
|
||||
- Rodar a verificação de cada CA; parecer do `fable-critico` sobre a sincronia e o descarte; `impeccable critique` e `audit`; commit e push da prévia; preencher CA → resultado.
|
||||
- [ ] feito
|
||||
|
||||
## 8. Registro
|
||||
2026-11-10 — spec escrita a partir do pedido do Evandro e da pesquisa de ferramentas. A etapa 1 ainda fecha em paralelo (consertos do parecer crítico, polimento visual e e2e); as tarefas de lógica desta etapa só entram depois dela (S4).
|
||||
2026-11-10 — T1 feita: Tiled 1.12.2. O AppImage só traz o plugin gráfico `xcb` e a máquina não tem `xvfb-run`, então o caminho sem janela é o Flatpak de usuário: `env -u DISPLAY -u WAYLAND_DISPLAY flatpak run --env=QT_QPA_PLATFORM=offscreen --command=tiled org.mapeditor.Tiled --export-map json entrada.tmx saida.json` (e `--command=tmxrasterizer` para imagem). Mapa de prova exportado para JSON (48 células, 1 ponto) e para PNG. Efeito colateral: o Flatpak ficou em `~/.local/share/flatpak` (não em `3d/ferramentas/`), instalou o KDE Platform 6.10 e atualizou o runtime `GL.nvidia` do Flatpak. R1 resolvido.
|
||||
2026-11-10 — T4 (imagens): 4 imagens dos itens geradas e conferidas a olho (caixa de balas com pente, estojo vermelho com cruz, copo de café, bateria com 4 luzes verdes), fundo preto liso. A bateria e o pente são quase pretos: o atlas remove o fundo por preenchimento a partir dos cantos, não por limiar. Falta montar o atlas.
|
||||
2026-11-10 — T11 feita: parede, carpete em placas, forro e madeira saíram repetíveis; os 4 cartazes saíram com o texto certo ("METAS DO MÊS", "BACKUP: TODA SEXTA", "NÃO DESLIGUE O SERVIDOR", "SENHA NÃO SE EMPRESTA"), sem marca nem nome.
|
||||
2026-11-10 — T5: nenhum pacote de tiro CC0 do OpenGameArt traz arquivo de licença dentro (nem os tiros que já estavam em uso). Regra ajustada (muda o texto do CA8): vale a licença escrita na página oficial do pacote, desde que nada dentro do arquivo a contradiga; pacote com arquivo dizendo outra licença continua recusado. O crédito guarda a página e a data da leitura.
|
||||
2026-11-10 — T5 feita: `automatica` trocada por um tiro de PPSh da Free Firearm Sound Library cortado em 180 ms (a antiga tinha cauda de 69 ms e corpo fraco); `pistola` mantida, com o pico corrigido (+0,17 → −1,07 dBFS); `caixa` com pico corrigido; `golpe` tinha 22 ms de ruído antes da pancada e agora começa em 0,5 ms; novos `dano` (gemido curto), `item` (arpejo) e `golpe-no-ar` (vush). Os 13 arquivos medidos: pico entre −1,83 e −1,07 dBFS, silêncio inicial até 0,2 ms. Ninguém ouviu: escolha por espectrograma e forma de onda (R4).
|
||||
2026-11-10 — T10 feita: mapa de 44 × 32 células, 11 ambientes (os 7 pedidos mais banheiros, hall dos elevadores, escada e área de serviço), 7 nascedouros, 22 portas, salão de 18 × 10 com 4 ilhas de mesas e corredor em anel. `bash 3d/mapa.sh` duas vezes com o mesmo `sha256sum`; 7 testes do mapa verdes; `pnpm test:jogo` 100% com 273 testes. Planta conferida a olho: parece um escritório. Desvio da seção 5: o `mapa.sh` rodava o gerador e apagaria edição feita à mão no Tiled; decisão: o `.tmx` é a fonte e o gerador só roda com `--gerar`. Não conferido: abrir o `.tmx` no Tiled com janela.
|
||||
2026-11-10 — T2 feita: MPFB 2.0.18 roda sem janela no Blender 5.2.2, instalado só em `3d/ferramentas/blender-user`. Humano com camisa polo, calça de lã e botina: 41.364 triângulos brutos, 11.634 depois de tirar as faces sob a roupa e reduzir; esqueleto `mixamo` com 52 ossos de mesmo nome dos do zumbi (faltam só 13 pontas que não deformam); os 6 clipes passaram. Recusados por licença: calça cargo e uma pele, cujos arquivos dizem AGPL apesar de o pacote se dizer CC0. Pendências medidas: GLB de 13,7 MB por causa das texturas (limite 1,5 MB); pele fura a camisa no ombro com o braço erguido; `morrer` ainda anda 1,2 m; não testado no three.js. R2 resolvido.
|
||||
2026-11-10 — CP1, decisão do CA9: aprovada a troca da base do zumbi. No render lado a lado o humano do MPFB2 tem proporção e rosto de gente e roupa de escritório; o zumbi atual tem tronco inchado, mangas soltas do corpo e barriga de fora. T16 entra, com estas condições: pele morta, sangue e olhos turvos; ombro sem furo; GLB ≤ 1,5 MB e ≤ 12 mil triângulos; `morrer` sem andar; conferido no three.js. A aparência final continua sendo decisão do Evandro (R1 da etapa 1).
|
||||
2026-11-10 — T4 feita: `public/jogo/itens.webp` com 512 × 512 e 32 KB, refeito por `bash 3d/itens.sh`; conferido sobre vermelho e sobre cinza: os 4 objetos inteiros (pente e bateria sem buraco), sem halo; o vapor do café sumiu, como previsto. Crédito `propria` e caso novo no teste de orçamento (17 testes verdes).
|
||||
2026-11-10 — T3 feita: `atacar` recortado para um golpe só (quadros 8 a 50 do original, com os 5 últimos voltando à pose do primeiro): duração 1,400 s, impacto em 0,833 s, mão direita, alcance 0,790 m à frente do quadril; `lib/jogo/golpe.json` gravado. Com o ciclo de 48 passos, `passoDoGolpe` = 29 (0,483 s depois do começo do golpe) e a tela toca o clipe 1,75× mais rápido. `zumbi.glb`: 11.950 triângulos, 1.455.084 B. Render `3d/out/jogo/golpe.png` conferido: preparo, mão estendida no impacto, volta. Desvio: o exportador começava os clipes em 1/30 s; o `atacar` passou a começar em 0 s. Não conferido: o golpe em movimento no navegador (T14).
|
||||
2026-11-10 — CP1 fechado: humano, golpe e imagens dos itens vistos; CA9 aprovado (acima).
|
||||
2026-11-10 — HUD em celular deitado (pendência da etapa 1, feita aqui): feed no canto de cima à direita com até 3 linhas, acima dos botões; cartão "Resolvido" no terço de cima, fora da mira; o feed fica transparente enquanto o cartão aparece. Capturas `3d/out/jogo/hud-915*.png` e `hud-640*.png` conferidas. Área segura só testada com valor 0.
|
||||
Reference in new issue
Block a user