Birds that teach themselves to eat food — through evolution, in your browser.
EvoFly is a Rust + WebAssembly simulation where a population of birds evolves over generations to navigate toward food. Each bird has a neural network brain wired to its field-of-view eye. The genetic algorithm selects the best-performing birds each generation, breeds them, and mutates their offspring — gradually producing smarter birds with no hand-coded rules.
Built by following the Learning to Fly series, and extended with a custom browser frontend (EvoFly).
Open http://localhost:8080 after following the setup guide.
┌──────────────────────────────────────────────────────┐
│ SIMULATION LOOP (per step) │
│ │
│ 👁 Eye sees nearby food → 9 numbers │
│ 🧠 Brain decides speed & turn → 2 numbers │
│ 🐦 Animal moves, eats food, ages │
│ │
│ Every 2500 steps → Evolution: │
│ 1. Fitness = foods eaten per bird │
│ 2. Roulette wheel selection of parents │
│ 3. Uniform crossover + Gaussian mutation │
│ 4. New generation of birds │
└──────────────────────────────────────────────────────┘
rust-genetic-algo/
├── Cargo.toml ← workspace root
├── README.md ← this file
│
├── genetic-algorithm/ ← lib-genetic-algorithm
│ └── src/lib.rs
│
└── libs/
├── neural-network/ ← lib-neural-network
│ └── src/lib.rs
├── simulation/ ← lib-simulation (core logic)
│ └── src/
│ ├── lib.rs (Simulation, Statistics)
│ ├── world.rs (World)
│ ├── animal.rs (Animal)
│ ├── eye.rs (Eye, process_vision)
│ ├── brain.rs (Brain)
│ ├── food.rs (Food)
│ └── animal_individual.rs (GA bridge)
├── simulation-wasm/ ← lib-simulation-wasm (WASM bridge)
│ └── src/lib.rs
└── web/ ← browser frontend (EvoFly)
├── index.html
├── index.js
├── package.json
└── pkg/ ← compiled WASM (generated)
Each bird has an eye with a 225° field of view divided into 9 cells. For each cell, the eye returns a float in [0.0, 1.0] — 0.0 means no food in that direction, 1.0 means food is right there.
A 3-layer neural network: 9 inputs → 18 hidden → 2 outputs.
- Output 0 → speed change
- Output 1 → rotation change
Every 2500 steps, the GA runs:
- Selection — Roulette wheel: birds that ate more food are more likely to be picked as parents
- Crossover — Each gene of the child is randomly taken from parent A or B
- Mutation — Each gene has a 1% chance of being nudged by a random Gaussian value
lib-simulation-wasm compiles to WebAssembly and exposes the simulation to JavaScript. The frontend reads position, rotation, and per-cell vision data every frame to render birds and their field of view.
| Technology | Use |
|---|---|
| Rust | All simulation logic, neural network, genetic algorithm |
nalgebra |
2D vector math (positions, rotations) |
rand |
Seeded RNG, weighted selection |
wasm-bindgen |
Rust ↔ JavaScript bridge |
wasm-pack |
Builds and packages the WASM module |
| Canvas 2D API | Renders simulation in the browser |
| Crate | Description |
|---|---|
lib-neural-network |
Feed-forward neural net with ReLU activation |
lib-genetic-algorithm |
Generic GA: selection, crossover, mutation |
lib-simulation |
World, animals, eye, brain, simulation loop |
lib-simulation-wasm |
WASM bindings for the browser |
# Run all tests
cargo test --workspace
# Build WASM
wasm-pack build libs/simulation-wasm/ --target web
# Copy WASM into web/
cp -r libs/simulation-wasm/pkg web/pkg
# Serve frontend
cd web && npx serve . --cors -p 8080Then open http://localhost:8080.
See /RUNNING.md for the full guide.
| Command | Effect |
|---|---|
t / train N |
Skip N generations |
animals N |
Respawn with N birds |
food N |
Respawn with N food items |
p / pause |
Toggle pause / resume |
r / reset |
Restart with current settings |
help |
Show all commands |
cargo test --workspacelib-genetic-algorithm 9 tests ✅
lib-neural-network 2 tests ✅
lib-simulation 3 tests ✅
Total: 14 / 14 pass