Este é um jogo de Tower Defense 3D com Rodadas Ilimitadas (Endless Mode) rodando diretamente no navegador, desenvolvido como trabalho final para a disciplina de Computação Visual da UFRJ. O projeto utiliza a biblioteca p5.js em modo WEBGL e implementa diversos conceitos teóricos ensinados nas aulas em WebGL 1.0 (GLSL ES 1.0).
O jogo possui um modo infinito de rodadas. Ao iniciar, o jogador passa pelas 5 ondas iniciais do balanceamento clássico de forma contínua. Após a 5ª onda, o jogo continua gerando rodadas procedurais indefinidamente com dificuldade escalonada matematicamente:
- Quantidade de Inimigos: Aumenta progressivamente (+4 inimigos por onda).
- Tempo de Spawn: Inimigos nascem em intervalos cada vez menores (reduzindo até o limite de 0.35 segundos).
- Vida (HP) dos Inimigos: Aumenta em +3 pontos por onda de forma constante, exigindo upgrades e novas defesas.
-
Velocidade dos Inimigos: Se elevam gradualmente até o limite de
$0.65$ para manter o desafio sem desequilibrar a simulação visual.
Dessa forma, o jogador pode testar suas estratégias de defesa até o limite de sobrevivência do núcleo!
Devido a restrições de segurança do navegador (CORS) com carregamento local de scripts e recursos do WebGL, o projeto precisa ser servido através de um servidor local.
- Abra o terminal na pasta raiz deste projeto.
- Inicie um servidor HTTP local de sua preferência. Por exemplo, usando Python (nativo na maioria dos sistemas):
Ou, caso prefira o NodeJS/NPM:
python3 -m http.server 8000
npx serve . - Acesse o navegador no endereço correspondente:
| Tecla / Ação | Função no Jogo | Conceito Gráfico Associado |
|---|---|---|
| Clique Esquerdo | Constrói a torre do tipo selecionado na célula sob o mouse | Interseção Raio-Plano (Picking / Unprojection) |
| Q | Seleciona a torre Básica (custo: 50g) | Transformações Hierárquicas |
| W | Seleciona a torre Sniper (custo: 120g) | Transformações Hierárquicas |
| E | Seleciona a torre Rápida (custo: 30g) | Transformações Hierárquicas |
| ENTER | Inicia a próxima onda de inimigos | Lógica de Gameplay |
| F | Alterna velocidade do jogo acelerado (1x ↔ 2x ↔ 3x ↔ 5x ↔ 10x) | Simulação Temporal Independente |
| P | Alterna entre Projeção Ortográfica e Perspectiva | Matrizes de Projeção |
| R | Ativa / Desativa o indicador de alcance das torres | Shaders GLSL + SDF (Aula 7) |
| B | Ativa / Desativa o relevo (Bump Mapping) no terreno | Perturbação de Normais / Gradiente (Aula 9) |
| T | Ativa / Desativa a textura procedural das superfícies | Texturas |
| C | Ativa / Desativa o desenho da spline do caminho | Curvas de Catmull-Rom (Aula 12) |
| X | Ativa / Desativa os eixos XYZ do mundo | Sistema de coordenadas (Aula 3) |
| M | Ativa / Desativa o wireframe das primitivas | Malhas de triângulos (Aula 14) |
| 1 | Ativa / Desativa Luz Ambiente | Phong — Componente Ambiente ( |
| 2 | Ativa / Desativa Luz Direcional (Sol) | Phong — Componente Difusa ( |
| 3 | Ativa / Desativa Luz Pontual (Lâmpada) | Phong — Componente Especular ( |
O código é modularizado para manter responsabilidades separadas e facilitar a explicação técnica na arguição:
├── index.html # Carrega o p5.js local e orquestra a inclusão dos módulos
├── lib/
│ └── p5.min.js # Biblioteca p5.js local (requisito obrigatório)
├── src/
│ ├── main.js # Setup, loop de draw, lógica de eventos do teclado e mouse
│ ├── camera.js # Configuração da câmera isométrica e projeção perspectiva
│ ├── mundo.js # Definição do terreno, grid, anéis de preview e picking
│ ├── texturas.js # Geradores de texturas procedurais e shader de Bump Mapping
│ ├── iluminacao.js # Modelo de Phong completo (ambiente, difuso, especular, emissivo)
│ ├── caminho.js # Cálculo e amostragem de curva spline Catmull-Rom
│ ├── inimigos.js # Comportamento, renderização e brilho dos inimigos
│ ├── torres.js # Comportamento das torres e shader GLSL de alcance (SDF)
│ ├── projeteis.js # Movimentação e normalização vetorial de projéteis
│ ├── jogo.js # Controle econômico (gold), ondas de inimigos e HP
│ ├── ui.js # Renderização do HUD overlay 2D (painel "Conceitos visuais")
│ └── visualizacao.js # Toggles de conceito para a arguição (T/C/X/M) e helpers
Durante as sessões de arguição, os seguintes tópicos baseados nos slides do curso são demonstrados no código:
-
Transformações Hierárquicas (Aula 4):
- Implementado através do uso de pilhas de matrizes (
push()epop()). - Usado para montar as torres: a base é fixa, enquanto a cabeça (torreta) rotaciona em torno do eixo Y local herdando a posição global da base. O cano translada para a frente em relação à cabeça rotacionada, operando como um braço robótico articulado.
- Usado para os inimigos, onde o nariz está hierarquicamente ligado ao corpo em movimento.
- Implementado através do uso de pilhas de matrizes (
-
Geometria de Terreno Assada / "Baked" (Aula 5):
- Uso de
beginGeometry()eendGeometry()para criar um objetop5.Geometryestático contendo os cubos do terreno. Enviado à GPU apenas uma vez no setup, reduzindo drasticamente o consumo de CPU.
- Uso de
-
Matemática Vetorial (Aula 5):
- Projéteis rastreiam os inimigos normalizando o vetor diferença
$\vec{d} = \text{alvo} - \text{projétil}$ para que a velocidade linear permaneça constante independentemente da distância.
- Projéteis rastreiam os inimigos normalizando o vetor diferença
-
Projeções e Câmeras (Aula 6):
-
Isométrica: Câmera posicionada em
$(d, -d, d)$ olhando para a origem usando projeção ortográfica paralela (ortho), garantindo que os três eixos tenham escalas aparentes idênticas. -
Perspectiva: Transição ao vivo com a tecla
Paplicandoperspective(), onde as linhas paralelas convergem em pontos de fuga. -
Unprojection (Picking): Conversão de coordenadas de tela 2D
$(x,y)$ para raio no espaço do mundo 3D intersectando com o plano$Y=0$ para identificar sob qual célula o mouse está flutuando.
-
Isométrica: Câmera posicionada em
-
Shaders customizados e SDF (Aula 7):
- Indicador de alcance circular permanente no chão das torres desenhado via fragment shader em GLSL.
- Calcula a SDF de anel clássica (
$d = ||\vec{uv}| - 1.0| \cdot R$ ) e aplicasmoothsteppara suavizar e antialiasar as bordas físicas do indicador de forma limpa.
-
Modelo de Iluminação de Phong Completo (Aula 8):
-
Ambiente (
$I_a$ ): Luz indireta vinda de todos os ângulos (ambientLight). -
Difuso (
$I_d$ ): Resposta lambertiana ao sol direcional ($\max(0, \hat{n} \cdot \hat{l})$). -
Especular (
$I_s$ ): Brilho reflexivo na fonte de luz pontual com expoente de brilho metálico concentrado (specularMaterial+shininess). -
Emissivo (
$I_e$ ): Luz interna constante que brilha sem depender do ambiente. Aplicada de forma incandescente nos inimigos e nas partes texturizadas das torres.
-
Ambiente (
-
Texturas Procedurais
$C(s,t)$ (Aula 9):- Geradas em tempo de execução com
p5.Graphics(sem arquivos externos): pedra e terra para o terreno, chapas com rebites para as torres (texMetal) e placas de armadura para os inimigos (texInimigo).textureMode(NORMAL)mapeia o UV em$[0,1]$ . -
Bump Mapping: shader que perturba a normal usando o gradiente de um mapa de altura procedural (diferenças finitas em UV), num frame tangente (T,B) construído a partir da normal em espaço de mundo — simula relevo nas pedras do terreno sem vértices extras. A cor base é
mix(corLisa, textura, [T]), entãoBmuda só o relevo eTliga/desliga a cor de forma independente, evidenciando que textura (cor) e bump (normal) são conceitos separados. -
Desempenho: o terreno com bump é desenhado reaproveitando a geometria baked (Aula 5) num único
model()(1 draw call), em vez de redesenhar cada tile em modo imediato — mantém o FPS alto mesmo com o relevo ligado.
- Geradas em tempo de execução com
-
Splines de Catmull-Rom (Aula 12):
- Spline cúbica interpoladora contínua de classe
$C^1$ que conecta os pontos de controle (waypoints). - Derivada analítica calculada diretamente no script de caminhos para obter o vetor tangente de forma exata, rotacionando o inimigo no eixo Y para orientá-lo na direção real de locomoção.
- O toggle
Cliga/desliga o desenho da curva e dos waypoints para comparar a trajetória suave com os pontos de controle.
- Spline cúbica interpoladora contínua de classe
-
Malhas de triângulos (Aula 14):
- O toggle
Mativa o wireframe (stroke) das primitivas em modo imediato (torres, inimigos, projéteis), expondo a malha de triângulos (representação de fronteira / B-Rep) que compõe cada objeto.
- O toggle
-
Geometria e sistema de coordenadas (Aula 3):
- O toggle
Xdesenha os eixos X, Y, Z a partir da origem, materializando a base ortonormal e a orientação dos eixos do mundo (em p5 WEBGL, +Y aponta para baixo).
Para entender a evolução e o mapeamento de notas do projeto:
PLANO.md— Arquitetura de arquivos, metas e ordem de desenvolvimento.CONCEITOS.md— O guia definitivo para a arguição, listando onde cada conceito está no código, qual slide de referência do professor e a explicação oral recomendada.ESTADO.md— Registro atual de progresso, diário de bordo e metas concluídas.