Vector2 arrive(Vector2 target) const noexcept {
Vector2 toTarget = target - position;
float distance = Vector2Length(toTarget);
if (distance < 0.1f) return ZERO; // If already at target, no force needed
float speed = globalConfig.max_speed;
// Apply gradual deceleration within the arrive radius
if (distance < globalConfig.arrive_radius) {
speed = globalConfig.max_speed * (distance / globalConfig.arrive_radius);
}
Vector2 desiredVelocity = Vector2Normalize(toTarget) * speed;
return (desiredVelocity - velocity) * globalConfig.arrive_weight;
}
Vector2 pursuit(const Boid& target) const noexcept {
Vector2 toTarget = target.position - position;
float distance = Vector2Length(toTarget);
// Estimate time to intercept based on distance and relative speed
float lookAheadTime = distance / (globalConfig.max_speed + Vector2Length(target.velocity));
// Predict future target position
Vector2 futurePosition = target.position + (target.velocity * lookAheadTime);
// Seek the predicted position instead of current position
return seek(futurePosition);
}
Vector2 evade(const Boid& pursuer) const noexcept {
Vector2 toPursuer = pursuer.position - position;
float distance = Vector2Length(toPursuer);
// Compute lookahead time based on both speeds
float lookAheadTime = distance / (globalConfig.max_speed + Vector2Length(pursuer.velocity));
// Predict future position of the pursuer
Vector2 futurePosition = pursuer.position + (pursuer.velocity * lookAheadTime);
// Steer away from the predicted position
return flee(futurePosition);
}
struct Config {
float wander_distance = 50.0f; // Distance ahead of the boid to project the wander circle
float wander_radius = 25.0f; // Size of the wander circle
float wander_jitter = 0.2f; // How much the wander angle changes each frame
float wander_weight = 0.5f; // Steering force weight for wander behavior
};
float wanderAngle = 0.0f; // Persistent wandering angle
Vector2 wander() noexcept {
// Step 1: Project the wander circle ahead of the boid
Vector2 circleCenter = Vector2Normalize(velocity) * globalConfig.wander_distance;
// Step 2: Adjust the wander angle slightly
wanderAngle += unit_range() * globalConfig.wander_jitter; // Small random variation
// Step 3: Compute displacement on the wander circle (ensuring uniform distribution)
Vector2 displacement = {
cos(wanderAngle) * globalConfig.wander_radius,
sin(wanderAngle) * globalConfig.wander_radius
};
// Step 4: Calculate the final wander target
Vector2 wanderTarget = position + circleCenter + displacement;
// Step 5: Seek the wander target
return seek(wanderTarget) * globalConfig.wander_weight;
}
Comments
0 B
|0 👍
/0 👎
0 B
|👍
/👎