feat(jogo): expediente dos mortos, jogo de zumbis em primeira pessoa
CI / audit (push) Successful in 10m48s
CI / verify (push) Successful in 19m2s
CI / deploy (push) Successful in 2m14s
CI / e2e (push) Failing after 36m15s

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:
evandro committed 2026-11-10 19:37:10 -03:00
1 parent c7d09d63d4
commit 67b32fcab3
118 files changed
+16730

No files matched your search

+131
View File
@@ -0,0 +1,131 @@
import { campoDeFluxo, direcaoNoCampo, lerMapa } from "../mapa";
import { AMBIENTES, ESCRITORIO, PORTAS } from "./escritorio";
const MAPA = lerMapa(ESCRITORIO);
const { largura, altura } = MAPA;
const andavel = (bloqueio: Uint8Array, x: number, z: number) =>
x >= 0 &&
z >= 0 &&
x < largura &&
z < altura &&
bloqueio[z * largura + x] === 0;
/** Quantas células andáveis a busca em largura alcança a partir do início. */
function alcancaveis(bloqueio: Uint8Array): number {
const inicio =
Math.floor(MAPA.inicio[1]) * largura + Math.floor(MAPA.inicio[0]);
const visto = new Uint8Array(largura * altura);
const fila = [inicio];
visto[inicio] = 1;
for (let k = 0; k < fila.length; k++) {
const x = fila[k] % largura;
const z = Math.floor(fila[k] / largura);
for (const [dx, dz] of [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
]) {
const i = (z + dz) * largura + x + dx;
if (andavel(bloqueio, x + dx, z + dz) && !visto[i]) {
visto[i] = 1;
fila.push(i);
}
}
}
return fila.length;
}
const totalAndavel = MAPA.solido.filter((c) => c === 0).length;
describe("mapa do escritório", () => {
it("tem pelo menos 40 × 28 células e é lido por lerMapa", () => {
expect(largura).toBeGreaterThanOrEqual(40);
expect(altura).toBeGreaterThanOrEqual(28);
expect(() => lerMapa(ESCRITORIO)).not.toThrow();
});
it("tem os 7 ambientes com nome", () => {
const nomes = AMBIENTES.map((a) => a.nome);
for (const nome of [
"recepção",
"área de mesas",
"sala de reunião",
"copa",
"sala do servidor",
"diretoria",
"almoxarifado",
]) {
expect(nomes).toContain(nome);
}
});
it("tem 6 ou mais nascedouros, todos a 8 m ou mais do início", () => {
expect(MAPA.nascedouros.length).toBeGreaterThanOrEqual(6);
for (const [x, z] of MAPA.nascedouros) {
expect(
Math.hypot(x - MAPA.inicio[0], z - MAPA.inicio[1]),
).toBeGreaterThanOrEqual(8);
}
});
it("alcança todo o chão a partir do início", () => {
expect(alcancaveis(MAPA.solido)).toBe(totalAndavel);
});
it("continua alcançando todo o chão sem qualquer uma das portas", () => {
expect(PORTAS.length).toBeGreaterThan(0);
for (const porta of PORTAS) {
const bloqueio = MAPA.solido.slice();
for (let z = porta.z; z < porta.z + porta.altura; z++) {
for (let x = porta.x; x < porta.x + porta.largura; x++) {
expect(andavel(bloqueio, x, z)).toBe(true);
bloqueio[z * largura + x] = 1;
}
}
expect(alcancaveis(bloqueio)).toBe(
totalAndavel - porta.largura * porta.altura,
);
}
});
it("não tem passagem com menos de 2 células: toda célula andável está num 2 × 2 andável", () => {
const livre = (x: number, z: number) => andavel(MAPA.solido, x, z);
for (let z = 0; z < altura; z++) {
for (let x = 0; x < largura; x++) {
if (!livre(x, z)) continue;
const emQuadrado = [
[-1, -1],
[-1, 0],
[0, -1],
[0, 0],
].some(
([ox, oz]) =>
livre(x + ox, z + oz) &&
livre(x + ox + 1, z + oz) &&
livre(x + ox, z + oz + 1) &&
livre(x + ox + 1, z + oz + 1),
);
expect([x, z, emQuadrado]).toEqual([x, z, true]);
}
}
});
it("o campo de fluxo leva cada nascedouro ao início em menos de 400 passos", () => {
const campo = campoDeFluxo(MAPA, MAPA.inicio[0], MAPA.inicio[1]);
const alvo = [Math.floor(MAPA.inicio[0]), Math.floor(MAPA.inicio[1])];
for (const [nx, nz] of MAPA.nascedouros) {
let x = Math.floor(nx);
let z = Math.floor(nz);
let passos = 0;
while ((x !== alvo[0] || z !== alvo[1]) && passos < 400) {
const [dx, dz] = direcaoNoCampo(MAPA, campo, x + 0.5, z + 0.5);
x += Math.round(dx);
z += Math.round(dz);
passos++;
}
expect([x, z]).toEqual(alvo);
expect(passos).toBeLessThan(400);
}
});
});