Deambular

Cada agente apunta a un punto que solo se desliza un poco alrededor de un círculo delante de él. Eso es lo que hace que deambular parezca intención y no ruido.

El editor de arriba está ejecutando este proyecto. Cambia una línea y se recarga.

Clases de Godot usadas

Node2DLine2DRandomNumberGenerator

El código

scripts/main.gd
extends Node

const COUNT: int = 18


func _ready() -> void:
	_add_background()

	var rng: RandomNumberGenerator = RandomNumberGenerator.new()
	rng.seed = 5507

	var view: Vector2 = get_viewport().get_visible_rect().size

	for i in COUNT:
		var agent: Node2D = Node2D.new()
		agent.set_script(Get.script('wanderer'))
		agent.position = view * 0.5 if i == 0 else Vector2(rng.randf_range(140, view.x - 140), rng.randf_range(140, view.y - 140))
		agent.velocity = Vector2.RIGHT.rotated(rng.randf_range(0, TAU)) * 160.0
		agent.rng.seed = rng.randi()
		agent.show_probe = i == 0
		agent.tint = Color('#8eef97') if i == 0 else Color('#8da5f3')
		add_child(agent)

	var note: Label = Label.new()
	note.text = 'the yellow square is what the green agent steers toward, it only slides a little around its circle each frame'
	note.position = Vector2(60, view.y - 56)
	note.add_theme_font_size_override('font_size', 19)
	note.add_theme_color_override('font_color', Color('#f3d48d'))
	add_child(note)

	print('%d agents steering toward a point that drifts around a circle in front of them' % COUNT)


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/wanderer.gd
extends Node2D

const MAX_SPEED: float = 170.0
const MAX_FORCE: float = 240.0
const WANDER_DISTANCE: float = 90.0
const WANDER_RADIUS: float = 55.0
const JITTER: float = 6.0
const TRAIL_POINTS: int = 90

var rng: RandomNumberGenerator = RandomNumberGenerator.new()
var velocity: Vector2 = Vector2(MAX_SPEED, 0)
var tint: Color = Color('#8da5f3')
var show_probe: bool = false

var wander_angle: float = 0.0
var hull: Polygon2D
var trail: Line2D
var ring: Line2D
var probe: Polygon2D


func _ready() -> void:
	trail = Line2D.new()
	trail.width = 3.0
	trail.default_color = Color(tint.r, tint.g, tint.b, 0.65)
	# top_level keeps the trail in world space instead of dragging its points along with the agent
	trail.top_level = true
	add_child(trail)

	if show_probe:
		ring = Line2D.new()
		ring.width = 2.0
		ring.default_color = Color('#f3d48d')
		ring.closed = true
		ring.top_level = true

		for i in 24:
			ring.add_point(Vector2(cos(TAU * i / 24.0), sin(TAU * i / 24.0)) * WANDER_RADIUS)

		add_child(ring)

		probe = Polygon2D.new()
		probe.polygon = PackedVector2Array([Vector2(-6, -6), Vector2(6, -6), Vector2(6, 6), Vector2(-6, 6)])
		probe.color = Color('#f3d48d')
		probe.top_level = true
		add_child(probe)

	hull = Polygon2D.new()
	hull.polygon = PackedVector2Array([Vector2(17, 0), Vector2(-12, 10), Vector2(-12, -10)])
	hull.color = tint
	add_child(hull)


func _process(delta: float) -> void:
	wander_angle += rng.randf_range(-JITTER, JITTER) * delta

	var heading: Vector2 = velocity.normalized() if velocity.length() > 1.0 else Vector2.RIGHT
	var center: Vector2 = position + heading * WANDER_DISTANCE
	var spot: Vector2 = center + Vector2(cos(wander_angle), sin(wander_angle)) * WANDER_RADIUS
	var desired: Vector2 = (spot - position).normalized() * MAX_SPEED

	velocity = (velocity + (desired - velocity).limit_length(MAX_FORCE) * delta).limit_length(MAX_SPEED)
	position += velocity * delta

	hull.rotation = velocity.angle()
	_wrap()

	trail.add_point(position)

	while trail.get_point_count() > TRAIL_POINTS:
		trail.remove_point(0)

	if show_probe:
		ring.position = center
		probe.position = spot


func _wrap() -> void:
	var view: Vector2 = get_viewport_rect().size

	if position.x < 0.0 or position.x > view.x or position.y < 0.0 or position.y > view.y:
		position = Vector2(fposmod(position.x, view.x), fposmod(position.y, view.y))
		trail.clear_points()

Más ejemplos de Navegación