Jogo 3D interativo feito do zero em Python, com toda a renderização 3D implementada à mão — matrizes próprias de transformação, projeção em perspectiva, câmera e rasterização — usando apenas Pygame + NumPy, sem nenhuma biblioteca de 3D (OpenGL, Panda3D, etc.).
Você controla um cubo que percorre uma arena coletando cristais, desviando de obstáculos e fugindo de inimigos com inteligência artificial de busca de caminho (A*). Começou como trabalho da disciplina de Computação Gráfica (UTFPR, Prof. Dr. Marlon Marcon) e virou um projeto pessoal de motor gráfico.
- Pipeline 3D próprio: mundo → visão → projeção em perspectiva → divisão
por w → viewport, tudo em matrizes 4x4 escritas à mão (
engine/math3d.py). - Câmera: terceira pessoa que segue o agente, com órbita livre por arraste do mouse e retorno suave à posição padrão.
- Iluminação: sombreamento difuso de Lambert com luz direcional.
- Algoritmo do pintor com renderização em camadas (céu → chão → sólidos) e ordenação por objeto para evitar z-fighting.
- Colisão:
- esfera × esfera (coleta de cristais, dano de inimigos);
- OBB × AABB via SAT (teorema dos eixos separadores) para o player girado contra obstáculos, com vetor de translação mínima.
- IA dos inimigos: busca de caminho A* sobre grade de navegação (8 direções, sem corte de quina), com interceptação (miram onde o jogador vai estar) e campo de custo que os atrai levemente para rotas com cristais. Recálculo controlado para manter performance.
- Geração procedural das fases: obstáculos e cristais posicionados por amostragem com rejeição (sem sobreposição, distância mínima entre cristais).
- Áudio: música por fase e efeitos (coleta, dano, colisão), com controle de volume e pause.
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
python main.pyÁudio é opcional. Para instalar a playlist padrão com dez faixas eletrônicas CC0 somente na sua máquina, execute
python -m scripts.baixar_musicas_livres. A opção recomendada é personalizarassets/musics/com arquivos.mp3,.oggou.wavque você tenha direito de usar. Sem músicas, o jogo continua funcionando normalmente.
| Tecla / Mouse | Ação |
|---|---|
| W / S | Avançar / recuar |
| A / D | Girar à esquerda / direita |
| Arrastar mouse | Orbitar a câmera |
- / = |
Volume da música |
[ / ] |
Volume dos efeitos |
| P | Pausar / continuar |
| ENTER | Iniciar / reiniciar |
| ESC | Sair |
Objetivo: colete todos os cristais de cada fase antes do tempo acabar, fugindo dos inimigos (encostar custa uma vida). As fases são infinitas e seguem uma curva de dificuldade progressiva; cair para fora do mapa também encerra o jogo.
.
├── main.py # composição da aplicação e ciclo de vida do Pygame
├── config.py # constantes e curva tipada de dificuldade
├── engine/ # motor gráfico independente das regras do jogo
│ ├── math3d.py # matrizes, perspectiva e look_at
│ ├── mesh.py # primitivas e dados geométricos
│ ├── camera.py # câmera em terceira pessoa
│ └── renderer.py # projeção, recorte, Lambert e rasterização
├── game/
│ ├── entities.py # Player, Cristal, Obstaculo e Inimigo
│ ├── collision.py # esfera, AABB e OBB/SAT
│ ├── level.py # geração procedural isolada
│ ├── pathfinding.py # grade de navegação, A* e campo de custo
│ ├── state.py # máquina de estados e transições válidas
│ ├── input.py # eventos traduzidos em ações do jogo
│ ├── update.py # regras de atualização da partida
│ ├── audio.py # música, efeitos e pulso rítmico
│ ├── hud.py # HUD, menu e overlays
│ ├── recorde.py # persistência local do recorde
│ ├── telemetria.py # coleta opcional de métricas
│ └── world.py # composição, renderização e game loop
├── scripts/ # análises opcionais de áudio e dificuldade
└── tests/ # testes da lógica pura
Jogo compõe os subsistemas, enquanto entrada, atualização e transições de
estado têm componentes próprios. As dependências podem ser injetadas, mantendo
o game loop desacoplado de áudio, telemetria, persistência, geração de fases e
Pygame durante os testes.
| Req. | Onde está |
|---|---|
| RT-01 | engine/mesh.py (primitivas: pontos, linhas, polígonos), cores RGB |
| RT-02 | engine/math3d.py + game/entities.py (matriz de modelo composta) |
| RT-03 | engine/math3d.perspectiva + divisão por w em engine/renderer.py |
| RT-04 | engine/camera.py + engine/math3d.look_at |
| RT-05 | game/world.Jogo.rodar (entrada → atualização → renderização) |
| RT-06 | game/collision.py (esferas, AABB e OBB/SAT) |
O projeto usa configuração centralizada em pyproject.toml, uma suíte
baseada na biblioteca padrão unittest e um piso inicial de 70% de cobertura
para engine/ e game/.
# ferramentas de desenvolvimento
python -m pip install -e ".[dev]"
# testes com o mesmo critério de cobertura usado pelo CI
coverage run -m unittest discover -v
coverage report
# análise estática e formatação
ruff check .
ruff format --check .O workflow do GitHub Actions executa esses controles em Python 3.9 e 3.12. Como este é um projeto mantido individualmente, o pull request serve também como histórico de auto-revisão: a integração só deve ocorrer depois dos testes locais e do CI aprovados.
Os utilitários não executam código durante importação:
python -m scripts.analisar_dificuldade
python -m scripts.analisar_musicaslibrosa faz parte da instalação padrão porque a análise de intensidade e a
sincronização visual com as batidas são recursos centrais do jogo.
Python · Pygame · NumPy
Este projeto é disponibilizado sob a licença MIT.