An interactive, real-time flocking simulation built with Java 21 and LibGDX โ running both natively on desktop and directly in the browser via GWT. Boids Studio goes beyond the classic three-rule algorithm with a full Game Of Life ecosystem: predators that hunt, starve, and die; boids that sprint, exhaust, feed, and go hungry; emergent population dynamics; and a fully live-editable parameter set, all while sustaining 2,800+ boids at a steady 60 FPS in-browser.
Verified: 2,800+ boids at 60 FPS in the browser ๐
| Milestone | Status |
|---|---|
| Core physics & simulation (Vec2, Boid, spatial grid) | โ Complete |
| Desktop & web builds (LWJGL3 + GWT) | โ Complete |
| Interactive UI โ sliders, tools, presets, HUD | โ Complete |
| Visual polish โ HSL color, additive blending, motion trails | โ Complete |
| CI/CD pipeline โ GitHub Actions โ GitHub Pages auto-deploy | โ Complete |
| Automated versioning โ build-timestamped releases | โ Complete |
| Three-phase performance overhaul | โ Complete |
| Game Of Life Addition โ stamina, hunger, eating, starvation, statistics | โ Complete |
- Classic Boids โ Separation, Alignment, and Cohesion implemented as a single-pass, allocation-free hot loop
- Obstacle Avoidance โ Boids actively steer away from placed circular obstacles
- PredatorโPrey Dynamics โ Predators actively chase the nearest boid cluster; boids flee when a predator enters their perception radius using inverse-distance-squared panic forces
- Food Attractors โ Place attractor points that boids are drawn toward; hungry boids seek food up to 2.5ร more urgently
- Edge Wrapping โ The world is toroidal; boids seamlessly cross any edge and reappear on the opposite side
- Spatial Grid Acceleration โ An adaptive spatial hash grid ensures near-O(1) neighbor lookup, making large swarms feasible in real-time
A full ecological lifecycle layer sits on top of the classic flocking rules:
Boids
- Stamina โ Sprinting away from a nearby predator drains stamina. Exhausted boids can no longer sprint, making them vulnerable.
- Hunger โ Hunger drains slowly over time. Hungry boids seek food attractors with greater urgency. Eating near an attractor replenishes both hunger and stamina.
- Life bars โ A tiny stamina bar (cyan โ red) appears above a sprinting boid; a hunger bar (orange โ dark-red) appears when hunger drops below 75%.
Predators
- Hunger & starvation โ Predator hunger drains at 4/s. When hunger reaches zero the predator dies and disappears.
- Eating โ A predator within eat range has a ~70% per-second chance of consuming a boid, replenishing its hunger. Starving predators eat up to 2ร more frantically.
- Sprint โ Predators sprint toward nearby boids, consuming stamina. Chase force scales up to 3ร as a predator starves.
- Life bars โ Hunger (green โ red) and stamina (white โ dark) bars are always visible above each predator.
Statistics overlay (top-left HUD)
- Boids Created / Eaten
- Predators Created / Starved
Life bars toggle โ A "Life Bars: ON/OFF" button in the control panel instantly hides all life bars for a cleaner view.
- Dynamic HSL coloring โ Each boid's hue is derived from its heading angle, producing naturally shifting color gradients across the flock
- Additive blending โ Overlapping boids brighten rather than occlude, giving dense clusters a vibrant glow effect
- Motion trails โ A fading trail follows each boid, reinforcing the sense of speed and fluid motion
- Adaptive LOD โ Trail length, trail density, boid triangle size, and predator triangle size all scale down proportionally as the population grows to maintain framerate
- Desktop โ Native LWJGL3/OpenGL build with uncapped FPS
- Browser โ Full GWT compilation to JavaScript; no plugins, no download required
All parameters are adjustable in real-time via the collapsible right-side panel.
Select a tool from the toolbar, then left-click or drag anywhere on the simulation canvas:
| Tool | Action |
|---|---|
| Boids | Spawn boids at the cursor position. Hold and drag to paint a stream of boids. |
| Obs (Obstacles) | Place a solid circular obstacle (radius 30). Boids will actively steer around it. Right-click to remove. |
| Attr (Attractors) | Place a food attractor. Nearby boids are drawn toward it, forming feeding clusters. |
| Pred (Predators) | Place a predator that chases the nearest boid cluster at 1.5ร boid speed. Starts with full hunger and stamina; starves to death if it doesn't eat. Boids within perception range will flee in panic. |
| Slider | Range | Effect |
|---|---|---|
| Max Speed | 10 โ 400 | Top velocity of every boid. Higher values produce more energetic, fast-moving swarms. |
| Perception | 10 โ 300 | Radius within which each boid perceives its neighbors. Larger values create broader, slower flocks. |
| Separation | 0 โ 50 | Repulsion strength between boids. High values prevent crowding and break up tight groups. |
| Alignment | 0 โ 50 | How strongly boids match the direction of their neighbors. High values produce coordinated streams. |
| Cohesion | 0 โ 50 | Attraction toward the local group center. High values pull boids into dense formations. |
| Avoid Obstacles | 0 โ 100 | Obstacle repulsion multiplier. Higher values widen the avoidance margin around obstacles. |
One-click presets that instantly reconfigure all parameters for a specific emergent behavior:
| Preset | Behavior |
|---|---|
| Classic Boids | Balanced default parameters โ natural, free-form flocking as described by Craig Reynolds |
| Tight Flock | Elevated cohesion and alignment; boids snap into dense, fast-moving formations (180 px/s) |
| Chaotic Swarm | High separation, minimal alignment, high speed; produces erratic, turbulent swarm motion (250 px/s) |
| School of Fish | Strong alignment with a wide perception radius; smooth, coordinated stream behavior |
| Calm Birds | Slow, loosely distributed movement with a large perception horizon โ meditative and gentle (80 px/s) |
| Button | Action |
|---|---|
| Pause / Resume | Freeze or resume the simulation at any time |
| Clear All | Remove all boids, obstacles, attractors, and predators from the world |
| Life Bars: ON/OFF | Toggle the stamina and hunger bars above boids and predators |
| Input | Action |
|---|---|
| Left Click / Drag | Use the currently selected placement tool |
| Right Click | Remove the nearest obstacle |
| Scroll Wheel | Zoom in / out (range: 0.1ร โ 5ร) |
< button (panel edge) |
Collapse the control panel |
> button (screen edge) |
Expand the control panel |
Boids is an artificial-life simulation model created by Craig Reynolds in 1986 to reproduce emergent flocking behavior. Each agent follows only three local rules โ yet from these rules, complex coordinated swarm dynamics arise spontaneously.
The three rules:
- Separation โ Steer away from boids that are too close, preventing collisions
- Alignment โ Gradually match the heading and speed of nearby boids
- Cohesion โ Steer toward the average position of the local neighborhood
Boids Studio extends this foundation with:
- Obstacle repulsion fields
- Predator pursuit and inverse-distance-squared prey-fleeing instincts
- Food attractor gravity scaled by boid hunger
- Stamina, hunger, eating, and starvation โ a full ecological lifecycle
- Fully tunable weight parameters โ alter any rule weight at runtime to explore the phase space of emergent behavior
The project is a multi-module Gradle build:
core/ Shared simulation + UI logic (platform-independent Java)
โโโ model/ Vec2, Boid, Obstacle, Attractor, Predator
โโโ sim/ World, BoidRules, SpatialGrid
โโโ config/ SimulationConfig, Preset
โโโ render/ WorldRenderer, BoidRenderer, TrailRenderer
โโโ input/ InputHandler
โโโ ui/ ControlPanel, StatsOverlay, SkinFactory
lwjgl3/ Desktop launcher โ LWJGL3/OpenGL, native window
html/ Web launcher โ GWT compilation to JavaScript
Design principles:
- Simulation logic is fully decoupled from rendering and platform code
- Zero external dependencies beyond LibGDX itself
- All hot paths are allocation-free โ no per-frame heap objects on the critical loop
- Configurable and extensible: all tunable constants live in
SimulationConfig
- Java 21 (or latest LTS)
- Gradle (or use the included
./gradlewwrapper โ no installation needed)
./gradlew :lwjgl3:run# Compile GWT and package the dist folder
./gradlew :html:dist
# Serve locally with any static server
npx serve html/build/dist./gradlew :html:superDev
# Then open http://localhost:8080 in your browserUnit and integration tests cover the core simulation logic:
- Vec2 โ arithmetic correctness, magnitude, normalization, edge cases
- World โ boid lifecycle, obstacle and predator interactions, edge wrapping stability, NaN/explosion guards
- Game Of Life mechanics โ predator eating & counter increment, predator starvation death, boid stamina drain & sprint cutoff, flee force inverse-distance weighting, boid hunger drain & food regen, hunger-scaled food attraction force
Testing framework: JUnit 5
./gradlew testThree focused optimization passes were required to push beyond the ~600-boid browser ceiling and reach 2,800+ boids at 60 FPS.
| Optimization | Impact |
|---|---|
Spatial grid reuse โ SpatialGrid is cleared and reused each frame; recreated only when perception radius or world size changes |
Eliminates full HashMap re-allocation every frame |
Perception radius caching โ perceptionRadius and perceptionRadiusยฒ computed once per World.update, threaded through all rule calls |
Removes redundant sqrt calls at the top of each rule |
UI throttling โ ControlPanel and StatsOverlay label updates capped at ~8 Hz |
Eliminates ~52 string allocations per second per label |
| Optimization | Impact |
|---|---|
Single-pass flock rule โ BoidRules.flock() combines Separation, Alignment, and Cohesion in one neighbor loop |
Cuts loop overhead by 3ร |
Raw float accumulation โ inner loop uses float math; produces exactly one Vec2 per boid per frame |
Eliminates ~80,000 short-lived allocations/frame at 1,000 boids ร 20 neighbors |
No-sqrt separation โ diff * 500/dยฒ replaces diff.normalize().scale(500/d) |
Removes one Math.sqrt call per in-range neighbor |
Neighbor buffer reuse โ single pre-allocated ArrayList<Boid> cleared before each spatial query |
Eliminates 1,000+ ArrayList allocations per frame |
Predator proxy โ single pre-allocated proxy boid replaces per-predator-per-frame new Boid(...) |
Eliminates predator-count object allocations per frame |
| Index-based iteration โ all hot-path list traversals use index loops | Avoids Iterator allocation on every traversal |
| Optimization | Impact |
|---|---|
| Adaptive trail quality โ trail length reduces at 600+ boids, shortens again at 1,000+, disables entirely at 1,500+ | Largest single rendering win at high counts |
| Trail decimation โ at 1,000+ boids, every other trail segment is skipped | Halves line draw calls at high density |
Trail ring buffer โ LinkedList<Vec2> replaced with ArrayDeque<Vec2> |
Better cache locality, zero per-node allocation |
Shared LOD scale โ a single computeLodScale() factor drives both boid (6pxโ4pxโ3px) and predator (12pxโ8pxโ6px) triangle sizes at the same thresholds |
Predators always stay exactly 2ร boid size; no drift at any population level |
| FPS Target | Boid Count |
|---|---|
| 60 FPS (adaptive trails) | ~1,500 โ 2,800 |
| 60 FPS (trails disabled) | 2,000 โ 2,800+ |
| 30+ FPS | 2,800 โ 4,000+ |
Verified: 2,894 boids at a sustained 60 FPS in Chrome on standard consumer hardware.
This project was developed with the assistance of AI tools (Cursor / Claude) as a learning and exploration exercise in emergent systems, game-dev architecture, and browser performance optimization.
Boids Studio was built as:
- A deep dive into emergent behavior simulation
- A clean architecture exercise in Java game development
- An exploration of browser performance limits with GWT/WebGL
- A browser-deployable interactive experiment that anyone can run instantly
MIT โ see LICENSE
Eyal Shahaf โ GitHub



