A Boids Flocking simulation implemented in Godot Engine.
- Introduction
- Update: Made a Game with Boids
- What is Boids Flocking?
- Implementation
- Conclusion
- References
Introduction
I implemented Boids Flocking in the Godot Engine.
It's so fun to watch how cutely the boids move, especially when they're chasing food.
This post is a memo on how I implemented it.
Note: This article was translated from my original post.
Update: Made a Game with Boids
Based on the Boids Flocking I implemented, I created a small game where you dodge the Boids.
You can play it in your browser, so try it out!
What is Boids Flocking?
First, a quick overview of the Boids Flocking algorithm.
Boids is an artificial life simulation that models the flocking behavior of birds. "Boid" comes from "Bird-oid", meaning "bird-like".
It was developed by Craig Reynolds and published in this paper in 1987.

The Boids algorithm simulates flocking using three simple rules:
- Separation
- Alignment
- Cohesion
Separation is the force that prevents boids from getting too close to each other.

Alignment is the tendency to align movement direction with nearby boids.

Cohesion is the force pulling the boid toward the center of its neighbors.

By combining these three forces, the group of boids behaves like a flock of birds.
It's fascinating how complex behavior emerges from such simple rules.
Let’s look at how this simulation is implemented in Godot Engine.
Implementation
The full source code is available on GitHub. In the following sections, I’ll break down the implementation of each part.
Separation
Here’s how Separation is implemented using GDScript, the scripting language in Godot Engine.
func process_seperation(neighbors):
var vector = Vector2()
var close_neighbors = []
for boid in neighbors:
if position.distance_to(boid.position) < perception_radius / 2:
close_neighbors.push_back(boid)
if close_neighbors.empty():
return vector
for boid in close_neighbors:
var difference = position - boid.position
vector += difference.normalized() / difference.length()
vector /= close_neighbors.size()
return steer(vector.normalized() * move_speed)
There are two main parts:
1. Finding nearby boids
2. Calculating the Separation force from them
The code below identifies boids within a closer range:
var close_neighbors = []
for boid in neighbors:
if position.distance_to(boid.position) < perception_radius / 2:
close_neighbors.push_back(boid)
The neighbors list passed to this function is already filtered by a perception_radius.
For Separation, we narrow it down further to those within perception_radius / 2.
The Separation force is calculated like this:
for boid in close_neighbors: var difference = position - boid.position vector += difference.normalized() / difference.length() vector /= close_neighbors.size()
Finally, this vector is added to the boid’s movement vector.
Alignment
Now for Alignment:
func process_alignments(neighbors):
var vector = Vector2()
if neighbors.empty():
return vector
for boid in neighbors:
vector += boid.velocity
vector /= neighbors.size()
return steer(vector.normalized() * move_speed)
This one’s straightforward. We calculate the average direction of nearby boids and steer toward it.
Cohesion
And Cohesion:
func process_cohesion(neighbors):
var vector = Vector2()
if neighbors.empty():
return vector
for boid in neighbors:
vector += boid.position
vector /= neighbors.size()
return steer((vector - position).normalized() * move_speed)
Also simple: we find the average position of nearby boids and steer toward it.
That covers the Separation / Alignment / Cohesion part of the Boids model.
Next, we’ll look at how boids chase food.
Chasing Food
To make boids chase a point (like food), we apply a force toward that point:
func process_centralization(center: Vector2):
if position.distance_to(center) < centralization_force_radius:
return Vector2()
return steer((center - position).normalized() * move_speed)
We pass the food's coordinates as center, and this function returns the vector to steer toward it.
If the boid is already close enough, it returns an empty vector to avoid clustering.
Each of these forces is calculated per frame and combined like this:
func _process(delta):
var neighbors = get_neighbors(perception_radius)
acceleration += process_alignments(neighbors) * alignment_force
acceleration += process_cohesion(neighbors) * cohesion_force
acceleration += process_seperation(neighbors) * seperation_force
acceleration += process_centralization(prey_position) * centralization_force
velocity += acceleration * delta
velocity = velocity.clamped(move_speed)
rotation = velocity.angle()
translate(velocity * delta)
Conclusion
That was a breakdown of my implementation of Boids Flocking in Godot Engine.
This isn’t optimized for performance, so it’s not suited for heavy use. But it was exciting to see the boids come to life.
Boids Flocking is a simple but well-known artificial life model. I’m looking forward to working on more complex simulations in the future.
[Related Article]
References
- Flocks, Herds, and Schools: A Distributed Behavioral Model, Craig W. Reynolds, 1987 - Google Scholar
- GitHub - codatproduction/Boids-simulation: A flocking simulation with obstacle avoidance made in Godot!
- Code That: Boids - YouTube
- Boids - Wikipedia
- GitHub - alifelab/alife_book_src: 「作って動かすALife - 実装を通した人工生命モデル理論入門」サンプルコード