Estrutura geral do sistema
O sistema é composto por duas partes principais que trabalham em conjunto:
- O jogo Flappy Bird: Implementado em Python com a biblioteca
pygame. Ele gerencia toda a mecânica do jogo, incluindo movimentação do pássaro, geração de canos, colisões e pontuação.- O pássaro segue regras de física simplificadas: gravidade constante, impulso ao pular e rotação da imagem baseada no movimento vertical.
- O chão e o plano de fundo são renderizados continuamente, criando a sensação de movimento infinito.
- Os canos são gerados com alturas aleatórias e espaçamento progressivo, aumentando a dificuldade conforme a pontuação cresce.
- Colisões são detectadas com precisão usando máscaras de pixel (
pygame.mask), garantindo que o pássaro só “morre” quando realmente toca os obstáculos. - Sons de pulo e pontuação proporcionam feedback auditivo, tornando a experiência mais imersiva.
- A IA que joga automaticamente: Cada pássaro é controlado por uma rede neural criada e treinada pelo algoritmo NEAT. A IA decide quando pular com base em entradas do ambiente.
- Cada geração possui dezenas ou centenas de pássaros, representando indivíduos distintos na população do NEAT.
- Os inputs da rede neural incluem: posição vertical do pássaro e distância até a parte superior e inferior do próximo cano.
- A saída da rede neural indica se o pássaro deve saltar ou permanecer no curso atual.
- O NEAT ajusta tanto os pesos quanto a topologia da rede ao longo de várias gerações, maximizando a aptidão (fitness), baseada em distância percorrida e pontuação acumulada.
- Indivíduos com melhor desempenho sobrevivem e se reproduzem, permitindo evolução progressiva e adaptação ao ambiente.
O objetivo final é que a IA aprenda a voar o mais longe possível sem colidir, enquanto o jogo simula física realista e aumenta a dificuldade gradualmente.
O código define parâmetros dinâmicos para controlar dificuldade e evolução, como:
- Velocidade dos canos que aumenta conforme a pontuação (
Pipe.SPEED). - Espaçamento entre os canos ajustado dinamicamente para desafios mais difíceis à medida que o jogo avança.
- Sistema de pontuação e fitness que influencia diretamente a evolução da rede neural.
Inputs da Rede Neural
Para tomar decisões, cada rede neural precisa “enxergar” o ambiente ao redor. Os inputs funcionam como sensores do pássaro, fornecendo informações essenciais para que a IA escolha a ação adequada a cada instante.
- Altura do pássaro (bird.y) — posição vertical atual do pássaro na tela. Permite avaliar se ele está alto ou baixo em relação ao próximo obstáculo.
- Distância até o topo do próximo cano (abs(bird.y - pipe.height)) — mede o espaço vertical entre o pássaro e a parte superior do cano. Indica se precisa subir para evitar colisão.
- Distância até a base do próximo cano (abs(bird.y - pipe.bottom_pos)) — mede a distância até a extremidade inferior do cano, ajudando a prevenir quedas ou saltos desnecessários.
Esses três inputs fornecem informações detalhadas sobre:
- Posição relativa do pássaro em relação ao obstáculo seguinte.
- Necessidade de saltar ou manter a trajetória atual.
- Como ajustar o movimento vertical para percorrer a maior distância possível.
Estrutura da Rede Neural
A rede neural é organizada em camadas que processam os inputs e decidem a ação do pássaro:
- Camada de entrada: recebe os 3 inputs do jogo, que funcionam como sensores do ambiente.
- Camadas ocultas: presentes ou não dependendo da configuração do NEAT. Permitem à rede aprender padrões complexos, como prever movimentos futuros ou calcular trajetórias seguras.
- Camada de saída: possui um único neurônio que gera um valor contínuo, interpretado como:
- Output maior que 0.5 → Pular
- Output ≤ 0.5 → Não pular
Como a decisão é calculada:
Cada input é multiplicado por seu peso correspondente, somado a um bias e processado por uma função de ativação (tanh). Sem o bias, a saída seria sempre zero se todas as entradas forem zero (dependendo da função de ativação). O bias desloca a função para cima ou para baixo, dando mais flexibilidade à rede para aprender padrões. O resultado contínuo é convertido em ação:
input_y = 30
input_cano_sup = 4
input_cano_inf = -7
pesos = [0.5, 2, 1.3]
bias = -5
soma = 30*0.5 + 4*2 + (-7*1.3) + (-5) = 8.9
output = tanh(soma) ≈ 0.999
Se output > 0.5 → PULA
Se output ≤ 0.5 → NÃO PULA
O NEAT permite que a topologia da rede evolua: adicionar ou remover nós e conexões, ajustando pesos e biases para aumentar a eficiência e maximizar a pontuação.
Resumindo, a rede neural transforma informações do ambiente em decisões concretas (pular ou não) e sua estrutura evolui automaticamente para melhorar a performance da IA ao longo do tempo.
Algoritmo Evolutivo (NEAT)
A IA aprende usando o NEAT (NeuroEvolution of Augmenting Topologies), um algoritmo genético especializado em redes neurais, que simula evolução biológica para melhorar o desempenho ao longo das gerações.
- População: dezenas ou centenas de pássaros são criados, cada um com uma rede neural única. Pesos e biases iniciais são aleatórios.
- Fitness: pontuação baseada no desempenho (distância percorrida, canos ultrapassados, tempo de sobrevivência), indicando aptidão para reprodução.
- Seleção: apenas os pássaros com maior fitness têm maior chance de transmitir genes à próxima geração, mas pode selecionar os 20% melhores para a recombinação genética.
- Crossover: mistura de genes de 2 indivíduos selecionados, combinando características (média dos pesos) de ambos.
- Mutação: pequenas alterações aleatórias nos pesos, 80% das conexões sofrem uma mutação, a variação média no valor do peso é ±0.5 e 10% das conexões têm o peso totalmente substituído por um novo valor aleatório.
Diferente de algoritmos genéticos tradicionais, o NEAT também evolui a topologia da rede:
- Adiciona novos neurônios ou conexões entre eles.
- Mantém histórico de inovações para preservar estruturas vantajosas durante crossover.
- Permite aumentar a complexidade gradualmente, aprendendo estratégias mais sofisticadas.
Analogia: Algoritmo Genético clássico altera apenas atributos; NEAT altera atributos e estrutura interna, como adicionar asas ou mudar conexões internas do organismo.
Fluxo do NEAT no jogo:
- Criar população inicial de redes neurais aleatórias.
- Cada pássaro joga, calculando fitness em tempo real.
- Selecionar indivíduos de maior performance para reprodução.
- Aplicar crossover e mutação, incluindo novos nós ou conexões.
- Repetir por várias gerações até obter redes eficientes.
No código, classes como Population, Genome e o método pop.run(main, 100) controlam o processo, executando o jogo por 100 gerações ou até atingir fitness máximo.
Como executar localmente
- Pré-requisitos: Python 3.8 ou superior.
python -m venv venv
source venv/bin/activate # macOS/Linux
venv\Scripts\activate # Windows
Cria e ativa um ambiente virtual, isolando as dependências do sistema.
- Instalar dependências:
pip install -r requirements.txt
O arquivo requirements.txt contém todas as bibliotecas necessárias, incluindopygame (motor gráfico) e neat-python (algoritmo evolutivo).
- Estrutura mínima do projeto:
/assets
/src
└── /game
└── FlappyBird.py
└── configs.txt
requirements.txtA pasta /assets contém as imagens e sons do jogo, enquanto /config define os parâmetros de evolução usados pelo NEAT.
- Executar o jogo:
python src/game/FlappyBird.py
Durante a execução, o terminal exibirá informações como:
- Média de fitness da população
- Melhor fitness da geração
- Quantidade de espécies e progresso evolutivo
Esses dados permitem acompanhar a evolução da IA em tempo real.
Dicas e experimentos
- Aumente
pop_size no arquivo de configuração para ampliar a diversidade genética e acelerar o aprendizado. - Teste funções de ativação diferentes (
sigmoid, relu, etc.) para observar mudanças no comportamento da IA. - Ajuste a função de fitness para enfatizar critérios específicos, como distância percorrida ou estabilidade de voo.
- Salve o melhor genoma usando
pickle para reutilização posterior sem reiniciar a evolução. - Observe o terminal para métricas avançadas como tempo por geração e divergência genética (mean genetic distance), úteis na análise de performance.
Seguindo essas etapas, você poderá executar o Flappy Bird AI localmente, testar modificações e explorar a evolução do aprendizado em tempo real.