Versão simplificada de "Plants vs Zombies" em Python com pygame, para a disciplina de Análise, Projeto e Programação Orientada a Objetos. Grupo: Cecília, Giovana, Miguel, Teo.
uv run main.pyComo jogar: digite seu nome, escolha as plantas, clique numa carta do HUD
e depois numa célula do gramado para plantar (botão direito cancela a carta).
Sóis caem do céu e brotam dos girassóis — passe o mouse por cima para
coletá-los antes que sumam. Ervilheiro atira, Noz segura os zumbis. Sobreviva às 3
ondas para vencer; se um zumbi chegar à casa, é game over. P pausa,
ESC volta ao menu. O score vai para o ranking em scores.csv.
O código fica em src/, dividido em dois pacotes (cada classe em seu próprio
arquivo); main.py, na raiz, só importa Jogo de src.models e roda.
main.py # ponto de entrada (uv run main.py)
src/
config/
settings.py # constantes (tela, tabuleiro, cores, sol)
recursos.py # CONFIG dos sprites + carregar_imagens()
models/
sprite.py, animacao.py # primitivos compartilhados (ficam na raiz)
entidades/ # hierarquia Entidade (uma classe por arquivo)
entidade.py # Entidade (abstrata)
planta.py # Planta (abstrata)
girassol.py, ervilheiro.py, noz.py
zumbi.py # Zumbi (abstrata)
zumbi_basico.py, zumbi_cone.py
projetil.py, sol.py
nucleo/ # tabuleiro, gerenciadores, HUD, dados, laço
celula.py, tabuleiro.py
gerenciador_sol.py, gerenciador_ondas.py
carta.py # carta do HUD (cooldown)
banco_dados.py # BancoDeScores (CSV com pandas)
jogo.py # Jogo (janela, laço principal, troca de telas)
telas/ # views (fluxograma da entrega)
tela.py # Tela (abstrata)
tela_menu.py, tela_nome.py, tela_selecao.py, tela_jogo.py
tela_fim.py, tela_game_over.py, tela_vitoria.py
Cada __init__.py reexporta o conteúdo do pacote: src.config expõe
settings e carregar_imagens; src.models (e os subpacotes entidades,
nucleo, telas) expõem todas as classes (ex.: from src.models import Jogo). sprite.py e animacao.py ficam na raiz de models/ de propósito:
entidades depende deles e nucleo depende de entidades, então mantê-los
fora desses pacotes evita import circular.
Cada sprite é configurado em CONFIG, no topo de src/config/recursos.py:
nome -> (arquivo, lado_do_quadro_px, altura_na_tela_px, fps). As artes do
grupo ficam em assets/:
| sprite | arquivo | quadro | fps |
|---|---|---|---|
| girassol | sunflower.png |
32x32 | 10 |
| ervilheiro | peashooter.png |
32x32 | 15 |
| noz | wallnut.png |
32x32 | — (estágios) |
| zumbi básico | zumbibasico.png |
32x32 | 8 |
| zumbi com cone | zumbicone.png |
32x32 | 8 |
| tiro | tiro.png |
32x32 | 12 (recortado) |
| sol | sun.png |
16x16 | 7 |
Como funciona: o PNG é fatiado em grade de quadros (esquerda→direita,
cima→baixo); células vazias são ignoradas, e os quadros restantes formam a
animação em loop (classe Animacao). GIF animado não funciona no pygame —
por isso o formato é spritesheet PNG. Todos os arquivos listados em CONFIG
precisam existir em assets/; se algum faltar, o jogo encerra com um erro
indicando qual sprite está faltando.
Casos especiais já tratados no código:
- Ervilheiro: fica parado no 1º quadro enquanto não há zumbi na pista;
ao surgir um, a animação de ataque toca e o tiro sai exatamente no 15º
quadro (
FRAME_TIROemervilheiro.py). - Noz: o
wallnut.pngtem 5 quadros que viram estágios de dano (inteira → rachada), escolhidos pela vida restante. Com um quadro só, a noz escureceria conforme apanha (wallnut_estatica.pngé uma versão de um quadro guardada como alternativa). - Tiro: o quadro de 32px tem uma ervilha pequena no centro; o flag
recortaremCONFIGapara a borda transparente antes de escalar, para a ervilha aparecer num tamanho visível.
Para mudar tamanho na tela ou velocidade de uma animação, ajuste os números
em CONFIG — nenhuma outra parte do código precisa ser tocada.