godot-steering-ai-framework/godot/Demos/AvoidCollisions/Avoider.gd

92 lines
2.5 KiB
GDScript3
Raw Normal View History

extends KinematicBody2D
var draw_proximity: bool
var _boundary_right: float
var _boundary_bottom: float
var _radius: float
var _accel := GSAITargetAcceleration.new()
var _velocity := Vector2.ZERO
var _direction := Vector2()
var _drag := 0.1
var _color := Color(0.4, 1.0, 0.89, 0.3)
onready var collision := $CollisionShape2D
onready var agent := GSAIKinematicBody2DAgent.new(self)
onready var proximity := GSAIRadiusProximity.new(agent, [], 140)
onready var avoid := GSAIAvoidCollisions.new(agent, proximity)
onready var target := GSAIAgentLocation.new()
onready var seek := GSAISeek.new(agent, target)
onready var priority := GSAIPriority.new(agent, 0.0001)
func _draw() -> void:
if draw_proximity:
draw_circle(Vector2.ZERO, proximity.radius, _color)
func _physics_process(delta: float) -> void:
target.position.x = agent.position.x + _direction.x * _radius
target.position.y = agent.position.y + _direction.y * _radius
priority.calculate_steering(_accel)
agent._apply_steering(_accel, delta)
func setup(
linear_speed_max: float,
linear_accel_max: float,
proximity_radius: float,
boundary_right: float,
boundary_bottom: float,
_draw_proximity: bool,
rng: RandomNumberGenerator
) -> void:
rng.randomize()
_direction = Vector2(rng.randf_range(-1, 1), rng.randf_range(-1, 1)).normalized()
agent.linear_speed_max = linear_speed_max
agent.linear_acceleration_max = linear_accel_max
proximity.radius = proximity_radius
_boundary_bottom = boundary_bottom
_boundary_right = boundary_right
_radius = collision.shape.radius
agent.bounding_radius = _radius
agent.linear_drag_percentage = _drag
self.draw_proximity = _draw_proximity
priority.add(avoid)
priority.add(seek)
func set_proximity_agents(agents: Array) -> void:
proximity.agents = agents
func set_random_nonoverlapping_position(others: Array, distance_from_boundary_min: float) -> void:
var rng := RandomNumberGenerator.new()
rng.randomize()
var tries_max := max(100, others.size() * others.size())
while tries_max > 0:
tries_max -= 1
global_position.x = rng.randf_range(
distance_from_boundary_min, _boundary_right - distance_from_boundary_min
)
global_position.y = rng.randf_range(
distance_from_boundary_min, _boundary_bottom - distance_from_boundary_min
)
var done := true
for i in range(others.size()):
var other: Node2D = others[i]
if (
other.global_position.distance_to(position)
<= _radius * 2 + distance_from_boundary_min
):
done = false
if done:
break