2D particle physics and boids flocking for agent-based simulation — vector math, force fields, steering behaviors, and a simulation loop that ties it all together.
- Vector2D: full 2D vector math — add, sub, mul, dot, cross, rotate, magnitude, normalize, distance, angle between
- Particle2D: agents with position, velocity, acceleration, and steering behaviors (seek, flee, arrive)
- Force fields: attract, repel, vortex, and uniform fields with configurable radius and falloff
- Boids flocking: align, cohesion, separation, and orbit — classic Reynolds flocking with tunable weights
- Simulation: manages particles + fields in a bounded 2D space, runs timestep loop with optional flocking
use agent_field::{Simulation, Particle2D, Vector2D, Field, FieldKind, flocking};
// Create a simulation with flocking enabled
let mut sim = Simulation::new(200.0, 200.0).enable_flocking();
// Add particles
for i in 0..10 {
sim.add_particle(
Particle2D::new(i as f64 * 20.0, 100.0)
.with_velocity(1.0, 0.0)
);
}
// Add a force field
sim.add_field(Field::new(Vector2D::new(100.0, 100.0), FieldKind::Attract, 50.0));
// Run the simulation
sim.run(100);
println!("Center of mass: {}", sim.center_of_mass());
println!("Particle count: {}", sim.particle_count());impl Vector2D {
pub fn new(x: f64, y: f64) -> Self;
pub fn zero() -> Self;
pub fn magnitude(&self) -> f64;
pub fn normalize(&self) -> Self;
pub fn dot(&self, other: &Self) -> f64;
pub fn cross(&self, other: &Self) -> f64;
pub fn rotate(&self, angle: f64) -> Self;
pub fn distance_to(&self, other: &Self) -> f64;
pub fn angle_between(&self, other: &Self) -> f64;
// Add, Sub, Mul impls via operators
}impl Particle2D {
pub fn new(x: f64, y: f64) -> Self;
pub fn with_velocity(self, vx: f64, vy: f64) -> Self;
pub fn seek(&self, target: &Vector2D) -> Vector2D;
pub fn flee(&self, threat: &Vector2D) -> Vector2D;
pub fn arrive(&self, target: &Vector2D, slow_radius: f64) -> Vector2D;
}pub enum FieldKind { Attract, Repel, Vortex, Uniform }
impl Field {
pub fn new(position: Vector2D, kind: FieldKind, strength: f64) -> Self;
pub fn with_radius(self, radius: f64) -> Self;
pub fn force_at(&self, position: &Vector2D) -> Vector2D;
}pub fn align(particle: &Particle2D, neighbors: &[&Particle2D]) -> Vector2D;
pub fn cohesion(particle: &Particle2D, neighbors: &[&Particle2D]) -> Vector2D;
pub fn separation(particle: &Particle2D, neighbors: &[&Particle2D], min_dist: f64) -> Vector2D;
pub fn orbit(particle: &Particle2D, center: &Vector2D, radius: f64) -> Vector2D;
pub fn flocking(particle: &Particle2D, neighbors: &[&Particle2D], weights: FlockWeights) -> Vector2D;impl Simulation {
pub fn new(width: f64, height: f64) -> Self;
pub fn enable_flocking(self) -> Self;
pub fn add_particle(&mut self, p: Particle2D);
pub fn add_field(&mut self, f: Field);
pub fn run(&mut self, steps: usize);
pub fn center_of_mass(&self) -> Vector2D;
pub fn particle_count(&self) -> usize;
}Part of the SuperInstance OpenConstruct ecosystem. Rust port of the Python agent-field library.
- agent-rhythm-rs — temporal patterns for coordinating field agents
- agent-dna-rs — genetic traits can drive particle behavior parameters
- agent-shadow-rs — record and replay field agent movements
39 tests covering vector operations, particle steering, field forces, flocking behaviors, and full simulation runs with center-of-mass and boundary checks.
# Cargo.toml
[dependencies]
agent-field = { git = "https://github.com/SuperInstance/agent-field-rs" }Requires Rust 2021 edition. No external dependencies.