Source code for core.components.steering

from __future__ import annotations

from core.ecs import Component
from core.vector import Vector2


[docs] class SteeringAgentComponent(Component): """Core steering agent. Accumulates forces from behaviour components and applies the resulting velocity to the entity's Transform each frame.""" def __init__( self, max_speed: float = 150.0, max_force: float = 300.0, mass: float = 1.0, drag: float = 0.0, ): self.entity = None self.max_speed = max(0.0, float(max_speed)) self.max_force = max(0.0, float(max_force)) self.mass = max(0.01, float(mass)) self.drag = max(0.0, float(drag)) # Runtime (not serialized) self._velocity = Vector2.zero() @property def velocity(self) -> Vector2: return self._velocity @velocity.setter def velocity(self, value: Vector2): self._velocity = value
# --------------------------------------------------------------------------- # Individual behaviour components – all are optional and composable. # The SteeringSystem iterates over whichever behaviours are present. # ---------------------------------------------------------------------------
[docs] class SeekBehavior(Component): """Steer towards a target position.""" def __init__(self, target_x: float = 0.0, target_y: float = 0.0, weight: float = 1.0): self.entity = None self.target_x = float(target_x) self.target_y = float(target_y) self.weight = max(0.0, float(weight)) self.enabled = True @property def target(self) -> Vector2: return Vector2(self.target_x, self.target_y) @target.setter def target(self, value: Vector2): self.target_x = float(value.x) self.target_y = float(value.y)
[docs] class FleeBehavior(Component): """Steer away from a target position.""" def __init__(self, target_x: float = 0.0, target_y: float = 0.0, weight: float = 1.0, panic_distance: float = 200.0): self.entity = None self.target_x = float(target_x) self.target_y = float(target_y) self.weight = max(0.0, float(weight)) self.panic_distance = max(0.0, float(panic_distance)) self.enabled = True @property def target(self) -> Vector2: return Vector2(self.target_x, self.target_y) @target.setter def target(self, value: Vector2): self.target_x = float(value.x) self.target_y = float(value.y)
[docs] class ArriveBehavior(Component): """Steer towards a target, decelerating smoothly within *slow_radius*.""" def __init__(self, target_x: float = 0.0, target_y: float = 0.0, weight: float = 1.0, slow_radius: float = 100.0): self.entity = None self.target_x = float(target_x) self.target_y = float(target_y) self.weight = max(0.0, float(weight)) self.slow_radius = max(1.0, float(slow_radius)) self.enabled = True @property def target(self) -> Vector2: return Vector2(self.target_x, self.target_y) @target.setter def target(self, value: Vector2): self.target_x = float(value.x) self.target_y = float(value.y)
[docs] class WanderBehavior(Component): """Produces a gentle, random meandering force.""" def __init__(self, weight: float = 1.0, circle_distance: float = 60.0, circle_radius: float = 30.0, angle_change: float = 30.0): self.entity = None self.weight = max(0.0, float(weight)) self.circle_distance = max(0.0, float(circle_distance)) self.circle_radius = max(0.0, float(circle_radius)) self.angle_change = max(0.0, float(angle_change)) self.enabled = True # Runtime self._wander_angle = 0.0
[docs] class SeparationBehavior(Component): """Steer to avoid crowding neighbours within *neighbor_radius*.""" def __init__(self, weight: float = 1.0, neighbor_radius: float = 50.0): self.entity = None self.weight = max(0.0, float(weight)) self.neighbor_radius = max(0.0, float(neighbor_radius)) self.enabled = True
[docs] class CohesionBehavior(Component): """Steer towards the average position of neighbours.""" def __init__(self, weight: float = 1.0, neighbor_radius: float = 100.0): self.entity = None self.weight = max(0.0, float(weight)) self.neighbor_radius = max(0.0, float(neighbor_radius)) self.enabled = True
[docs] class AlignmentBehavior(Component): """Steer to match the average heading of neighbours.""" def __init__(self, weight: float = 1.0, neighbor_radius: float = 100.0): self.entity = None self.weight = max(0.0, float(weight)) self.neighbor_radius = max(0.0, float(neighbor_radius)) self.enabled = True