Buscar y huir
Buscar y huir son las mismas dos líneas con un signo cambiado. Los vectores dibujados son la velocidad deseada, la actual y la diferencia entre ambas.
El editor de arriba está ejecutando este proyecto. Cambia una línea y se recarga.
Clases de Godot usadas
Node2DPolygon2DLine2D
El código
scripts/main.gd
extends Node
const ORBIT_RADIUS: float = 185.0
const ORBIT_SPEED: float = 1.1
const PADDING: float = 70.0
var panels: Array[Rect2] = []
var agents: Array[Node2D] = []
var markers: Array[Polygon2D] = []
var elapsed: float = 0.0
func _ready() -> void:
_add_background()
var view: Vector2 = get_viewport().get_visible_rect().size
var half: float = view.x * 0.5
panels = [
Rect2(PADDING, PADDING + 40.0, half - PADDING * 1.5, view.y - PADDING * 2.0 - 40.0),
Rect2(half + PADDING * 0.5, PADDING + 40.0, half - PADDING * 1.5, view.y - PADDING * 2.0 - 40.0),
]
var divider: Line2D = Line2D.new()
divider.points = PackedVector2Array([Vector2(half, PADDING), Vector2(half, view.y - PADDING)])
divider.width = 2.0
divider.default_color = Color(0.55, 0.65, 0.95, 0.25)
add_child(divider)
for i in 2:
var frame: Polygon2D = Polygon2D.new()
frame.polygon = PackedVector2Array([panels[i].position, Vector2(panels[i].end.x, panels[i].position.y), panels[i].end, Vector2(panels[i].position.x, panels[i].end.y)])
frame.color = Color(0.55, 0.65, 0.95, 0.05)
add_child(frame)
var title: Label = Label.new()
title.text = 'seek' if i == 0 else 'flee'
title.position = Vector2(panels[i].position.x, PADDING - 10.0)
title.add_theme_font_size_override('font_size', 26)
title.add_theme_color_override('font_color', Color('#8eef97') if i == 0 else Color('#fc7f7f'))
add_child(title)
var marker: Polygon2D = _make_circle(14.0, Color('#f3d48d'))
add_child(marker)
markers.append(marker)
var agent: Node2D = Node2D.new()
agent.set_script(Get.script('agent'))
agent.flee = i == 1
agent.bounds = panels[i].grow(-80.0)
agent.position = panels[i].get_center() + Vector2(0, 120)
add_child(agent)
agents.append(agent)
var legend: Label = Label.new()
legend.text = 'yellow: desired velocity blue: current velocity green: desired minus current'
legend.position = Vector2(PADDING, view.y - PADDING + 14.0)
legend.add_theme_font_size_override('font_size', 18)
legend.add_theme_color_override('font_color', Color('#f3d48d'))
add_child(legend)
print('same two lines of math with one sign flipped, the left agent closes on the dot and the right one keeps away from it')
func _process(delta: float) -> void:
elapsed += delta
var angle: float = elapsed * ORBIT_SPEED
markers[0].position = panels[0].get_center() + Vector2(cos(angle), sin(angle * 0.7)) * ORBIT_RADIUS
agents[0].target = markers[0].position
markers[1].position = panels[1].get_center() + Vector2(cos(angle), sin(angle)) * panels[1].size * 0.44
agents[1].target = markers[1].position
func _make_circle(radius: float, color: Color) -> Polygon2D:
var points: PackedVector2Array = PackedVector2Array()
for i in 20:
points.append(Vector2(cos(TAU * i / 20.0), sin(TAU * i / 20.0)) * radius)
var circle: Polygon2D = Polygon2D.new()
circle.polygon = points
circle.color = color
return circle
func _add_background() -> void:
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
add_child(background)
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)scripts/agent.gd
extends Node2D
const MAX_SPEED: float = 260.0
const MAX_FORCE: float = 230.0
const DRAW_SCALE: float = 0.45
var flee: bool = false
var bounds: Rect2 = Rect2()
var target: Vector2 = Vector2.ZERO
var velocity: Vector2 = Vector2(MAX_SPEED, 0)
var hull: Polygon2D
var desired_line: Line2D
var velocity_line: Line2D
var steering_line: Line2D
func _ready() -> void:
desired_line = _make_line(Color('#f3d48d'))
velocity_line = _make_line(Color('#8da5f3'))
steering_line = _make_line(Color('#8eef97'))
hull = Polygon2D.new()
hull.polygon = PackedVector2Array([Vector2(26, 0), Vector2(-18, 15), Vector2(-18, -15)])
hull.color = Color('#fc7f7f') if flee else Color('#8eef97')
add_child(hull)
func _process(delta: float) -> void:
var to_target: Vector2 = target - position
var desired: Vector2 = (-to_target if flee else to_target).normalized() * MAX_SPEED
var steering: Vector2 = (desired - velocity).limit_length(MAX_FORCE)
velocity = (velocity + steering * delta).limit_length(MAX_SPEED)
position += velocity * delta
_stay_inside()
hull.rotation = velocity.angle()
desired_line.points = PackedVector2Array([Vector2.ZERO, desired * DRAW_SCALE])
velocity_line.points = PackedVector2Array([Vector2.ZERO, velocity * DRAW_SCALE])
steering_line.points = PackedVector2Array([velocity * DRAW_SCALE, desired * DRAW_SCALE])
func _stay_inside() -> void:
if (position.x < bounds.position.x and velocity.x < 0.0) or (position.x > bounds.end.x and velocity.x > 0.0):
velocity.x = -velocity.x
if (position.y < bounds.position.y and velocity.y < 0.0) or (position.y > bounds.end.y and velocity.y > 0.0):
velocity.y = -velocity.y
position = position.clamp(bounds.position, bounds.end)
func _make_line(color: Color) -> Line2D:
var line: Line2D = Line2D.new()
line.width = 4.0
line.default_color = color
add_child(line)
return line