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.
206 lines
6.9 KiB
TypeScript
206 lines
6.9 KiB
TypeScript
/** Números do jogo em um lugar só. São valores iniciais: mudam jogando, nunca espalhados pelo código. */
|
|
|
|
import GOLPE from "./golpe.json";
|
|
import type { Dificuldade, TipoItem, TipoZumbi } from "./tipos";
|
|
|
|
/** Duração de um passo da lógica, em segundos. */
|
|
export const PASSO = 1 / 60;
|
|
export const PASSOS_POR_SEGUNDO = 60;
|
|
|
|
export const JOGADOR = {
|
|
vida: 100,
|
|
/** m/s */
|
|
velocidade: 4.2,
|
|
raio: 0.35,
|
|
/** Altura dos olhos, de onde sai o tiro. */
|
|
olhos: 1.6,
|
|
/** Limite da inclinação, para cima e para baixo. */
|
|
inclinacaoMax: 1.2,
|
|
/** Vida devolvida quando uma horda cai. */
|
|
curaPorHorda: 25,
|
|
} as const;
|
|
|
|
export const ZUMBIS: Record<
|
|
TipoZumbi,
|
|
{
|
|
vida: number;
|
|
velocidade: number;
|
|
dano: number;
|
|
raio: number;
|
|
altura: number;
|
|
}
|
|
> = {
|
|
comum: { vida: 100, velocidade: 1.2, dano: 10, raio: 0.35, altura: 1.8 },
|
|
rapido: { vida: 50, velocidade: 2.4, dano: 6, raio: 0.3, altura: 1.7 },
|
|
blindado: { vida: 250, velocidade: 0.9, dano: 15, raio: 0.4, altura: 1.9 },
|
|
chefao: { vida: 1500, velocidade: 1.0, dano: 25, raio: 0.6, altura: 2.4 },
|
|
};
|
|
|
|
/** Passos de um golpe inteiro (preparo, impacto e volta): 0,8 s. */
|
|
const PASSOS_DO_GOLPE = 48;
|
|
|
|
export const ATAQUE_DO_ZUMBI = {
|
|
/** Distância entre as bordas do zumbi e do jogador para o ataque começar. */
|
|
alcance: 1.0,
|
|
/** Folga máxima, no passo do impacto, para o golpe acertar. Acima disso o golpe pega o ar. */
|
|
alcanceDoGolpe: 1.4,
|
|
/** Passos entre um golpe e o próximo. Etapa 2: passa a `PASSOS_DO_GOLPE`. */
|
|
intervalo: 60,
|
|
/**
|
|
* Passo do ciclo em que a mão bate. Vem do clipe `atacar` medido no Blender
|
|
* (`golpe.json`, gravado por `3d/jogo.py`): a tela toca o clipe no tempo do ciclo,
|
|
* então o impacto do clipe e o da lógica caem no mesmo passo.
|
|
*/
|
|
passoDoGolpe: Math.round((GOLPE.impacto / GOLPE.duracao) * PASSOS_DO_GOLPE),
|
|
/** Passos da animação de morte, até o zumbi sair da lista. */
|
|
passosMorrendo: 90,
|
|
} as const;
|
|
|
|
/** Acima desta fração da altura do zumbi o acerto é na cabeça e dobra o dano. */
|
|
export const FRACAO_DA_CABECA = 0.86;
|
|
export const MULTIPLICADOR_DA_CABECA = 2;
|
|
|
|
export const ARMAS = [
|
|
{ nome: "Pistola", dano: 34, intervalo: 20, alcance: 40, gasta: false },
|
|
{ nome: "Automática", dano: 20, intervalo: 6, alcance: 40, gasta: true },
|
|
{ nome: "Faca", dano: 100, intervalo: 30, alcance: 1.5, gasta: false },
|
|
] as const;
|
|
|
|
/** Meio ângulo do arco da faca, em radianos. */
|
|
export const ARCO_DA_FACA = Math.PI / 4;
|
|
|
|
export const MUNICAO = {
|
|
inicial: 90,
|
|
porCaixa: 30,
|
|
/** Chance de um zumbi morto largar uma caixa. */
|
|
chanceDeCaixa: 0.25,
|
|
/** Distância para o jogador recolher a caixa. */
|
|
raioDeColeta: 0.9,
|
|
} as const;
|
|
|
|
/** O que os zumbis largam ao morrer. */
|
|
export const ITENS = {
|
|
/** Chance de um zumbi morto largar um item. O chefão não larga. */
|
|
chance: 0.3,
|
|
/** Peso de cada tipo no sorteio. */
|
|
pesos: { municao: 45, kit: 25, cafe: 15, bateria: 15 } as Record<
|
|
TipoItem,
|
|
number
|
|
>,
|
|
/** Abaixo desta vida o peso do kit dobra. */
|
|
vidaBaixa: 40,
|
|
/** Itens no chão ao mesmo tempo; com o teto cheio, o mais antigo some. */
|
|
teto: 10,
|
|
/** Passos até o item sumir (20 s). */
|
|
duracao: 1200,
|
|
/** Distância para o jogador recolher. */
|
|
raioDeColeta: 0.9,
|
|
/** Balas da automática por item de munição. */
|
|
balas: 30,
|
|
/** Vida devolvida pelo kit. */
|
|
vida: 25,
|
|
/** Café: fator da velocidade de andar e passos que dura (8 s). */
|
|
cafe: { fator: 1.3, duracao: 480 },
|
|
/** Bateria: fator da cadência dos drones e passos que dura (10 s). */
|
|
bateria: { fator: 2, duracao: 600 },
|
|
} as const;
|
|
|
|
export const DRONE = {
|
|
dano: 25,
|
|
intervalo: 30,
|
|
alcance: 15,
|
|
/** m/s */
|
|
velocidade: 5,
|
|
/** Distância que o drone mantém do jogador. */
|
|
distancia: 2,
|
|
} as const;
|
|
|
|
export const HORDAS = {
|
|
/** Zumbis das três hordas, antes do multiplicador da dificuldade. */
|
|
tamanhos: [12, 16, 20],
|
|
/** Comuns que acompanham o chefão. */
|
|
escoltaDoChefao: 6,
|
|
/** Passos da pausa entre hordas. */
|
|
pausa: 300,
|
|
/** Passos da fase "inicio", antes da primeira horda. */
|
|
preparo: 120,
|
|
/** Passos entre dois nascimentos, por horda (a 4ª é a do chefão). */
|
|
nascerACada: [90, 50, 30, 30],
|
|
/** Fator da velocidade dos zumbis, por horda. */
|
|
velocidade: [0.8, 1, 1.15, 1.15],
|
|
} as const;
|
|
|
|
/** Quantas linhas o feed guarda. */
|
|
export const LINHAS_DO_FEED = 5;
|
|
|
|
export const TETO_A_VISTA = 16;
|
|
|
|
export const DIFICULDADES: Record<
|
|
Dificuldade,
|
|
{ velocidade: number; dano: number; quantidade: number }
|
|
> = {
|
|
facil: { velocidade: 0.6, dano: 0.4, quantidade: 0.7 },
|
|
normal: { velocidade: 1, dano: 1, quantidade: 1 },
|
|
dificil: { velocidade: 1.3, dano: 1.5, quantidade: 1.3 },
|
|
};
|
|
|
|
/**
|
|
* O escritório, em células de 1 m. `#` parede, `M` mesa (não dá para andar, o tiro passa),
|
|
* `J` onde o jogador começa, `N` onde os zumbis nascem, `.` chão.
|
|
*/
|
|
export const ESCRITORIO = [
|
|
"############################",
|
|
"#N.........#......#.......N#",
|
|
"#..MM..MM..#......#..MM....#",
|
|
"#..MM..MM.........#..MM....#",
|
|
"#..........#...............#",
|
|
"#..MM..MM..#......#..MM....#",
|
|
"#..MM..MM..###..###........#",
|
|
"#..........................#",
|
|
"#............J.............#",
|
|
"#..........................#",
|
|
"#..MM..MM..###..###..MM....#",
|
|
"#..MM..MM..#......#..MM....#",
|
|
"#..........#......#........#",
|
|
"#..MM..MM.........#..MM....#",
|
|
"#..MM..MM..#...............#",
|
|
"#N.........#......#.......N#",
|
|
"############################",
|
|
] as const;
|
|
|
|
/** Degraus de qualidade da tela, do melhor para o mais leve. Desce na ordem: resolução, sombras, zumbis à vista. */
|
|
export const NIVEIS = [
|
|
{ pixelRatio: 2, sombras: true, teto: 16 },
|
|
{ pixelRatio: 1.5, sombras: true, teto: 16 },
|
|
{ pixelRatio: 1, sombras: true, teto: 16 },
|
|
{ pixelRatio: 1, sombras: false, teto: 16 },
|
|
{ pixelRatio: 1, sombras: false, teto: 12 },
|
|
{ pixelRatio: 1, sombras: false, teto: 8 },
|
|
] as const;
|
|
|
|
/** Tempos em milissegundos. */
|
|
export const REGULADOR = {
|
|
/** Tamanho da janela em que o p95 do intervalo entre quadros e o do trabalho são medidos. */
|
|
janela: 2000,
|
|
/** p95 do intervalo acima disto na janela: desce um degrau. */
|
|
limite: 20,
|
|
/** Janela sem descida e com p95 do trabalho de JS abaixo disto conta como folga. */
|
|
folgaDeTrabalho: 6,
|
|
/** Tempo seguido de folga para subir um degrau. */
|
|
subida: 10000,
|
|
/** Quadro mais longo que isto é pausa da aba, não lentidão: não entra na conta. */
|
|
ignorar: 250,
|
|
/** Se descer de novo antes disto depois de subir, não sobe mais. */
|
|
trava: 20000,
|
|
/** Fração mínima em que o p95 do intervalo cai na janela seguinte a uma descida para ela contar como ganho. */
|
|
ganho: 0.1,
|
|
/** Descidas seguidas sem ganho que fazem o regulador voltar esses degraus e travar. */
|
|
descidasSemGanho: 2,
|
|
} as const;
|
|
|
|
/**
|
|
* Raio máximo usado para andar e desviar de parede. O chefão é mais largo que meia célula (0,6 m): com o raio inteiro
|
|
* ele nasce encostado na parede e não sai do lugar. Para levar tiro, vale o raio do tipo.
|
|
*/
|
|
export const RAIO_DE_PASSAGEM = 0.45;
|