mirror of
https://github.com/Relintai/godot-steering-ai-framework.git
synced 2025-01-09 22:09:37 +01:00
Add GUI controls to seek/flee demo
Being toy demos, they should be easily tweakable and modifiable by the user to get a feel for what the parameters of the behaviors do.
This commit is contained in:
parent
3e9ce641fb
commit
3d50dcdb9c
@ -1,13 +0,0 @@
|
|||||||
[gd_scene load_steps=3 format=2]
|
|
||||||
|
|
||||||
[ext_resource path="res://demos/seek_and_flee/Coward.gd" type="Script" id=1]
|
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id=1]
|
|
||||||
|
|
||||||
[node name="Coward" type="KinematicBody2D"]
|
|
||||||
collision_layer = 4
|
|
||||||
collision_mask = 6
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
|
|
||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
|
||||||
shape = SubResource( 1 )
|
|
@ -1,42 +0,0 @@
|
|||||||
extends KinematicBody2D
|
|
||||||
"""
|
|
||||||
AI agent that seeks to move away from the player's location as directly as possible.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
onready var radius: = ($CollisionShape2D.shape as CircleShape2D).radius
|
|
||||||
|
|
||||||
onready var agent: = GSTSteeringAgent.new()
|
|
||||||
onready var accel: = GSTTargetAcceleration.new()
|
|
||||||
onready var flee: = GSTFlee.new(agent, player_agent)
|
|
||||||
|
|
||||||
var player_agent: GSTAgentLocation
|
|
||||||
var velocity: = Vector2.ZERO
|
|
||||||
var speed: float
|
|
||||||
var color: Color
|
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
|
||||||
agent.max_linear_acceleration = speed/10
|
|
||||||
agent.max_linear_speed = speed
|
|
||||||
|
|
||||||
|
|
||||||
func _draw() -> void:
|
|
||||||
draw_circle(Vector2.ZERO, radius, color)
|
|
||||||
|
|
||||||
|
|
||||||
func _physics_process(delta: float) -> void:
|
|
||||||
if not player_agent:
|
|
||||||
return
|
|
||||||
|
|
||||||
_update_agent()
|
|
||||||
accel = flee.calculate_steering(accel)
|
|
||||||
|
|
||||||
velocity = (velocity + Vector2(accel.linear.x, accel.linear.y)).clamped(agent.max_linear_speed)
|
|
||||||
velocity = move_and_slide(velocity)
|
|
||||||
if velocity.length_squared() > 0:
|
|
||||||
update()
|
|
||||||
|
|
||||||
|
|
||||||
func _update_agent() -> void:
|
|
||||||
agent.position = Vector3(global_position.x, global_position.y, 0)
|
|
28
project/demos/seek_and_flee/GUI.gd
Normal file
28
project/demos/seek_and_flee/GUI.gd
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
extends MarginContainer
|
||||||
|
|
||||||
|
|
||||||
|
enum BehaviorMode { SEEK, FLEE }
|
||||||
|
|
||||||
|
signal mode_changed(behavior_mode)
|
||||||
|
|
||||||
|
onready var seek: CheckBox = $BehaviorControls/Seek
|
||||||
|
onready var flee: CheckBox = $BehaviorControls/Flee
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
seek.connect("pressed", self, "_on_Seek_pressed")
|
||||||
|
flee.connect("pressed", self, "_on_Flee_pressed")
|
||||||
|
|
||||||
|
|
||||||
|
func _on_Seek_pressed() -> void:
|
||||||
|
flee.pressed = false
|
||||||
|
flee.button_mask = BUTTON_MASK_LEFT
|
||||||
|
seek.button_mask = 0
|
||||||
|
emit_signal("mode_changed", BehaviorMode.SEEK)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_Flee_pressed() -> void:
|
||||||
|
seek.pressed = false
|
||||||
|
seek.button_mask = BUTTON_MASK_LEFT
|
||||||
|
flee.button_mask = 0
|
||||||
|
emit_signal("mode_changed", BehaviorMode.FLEE)
|
95
project/demos/seek_and_flee/GUI.tscn
Normal file
95
project/demos/seek_and_flee/GUI.tscn
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://demos/seek_and_flee/GUI.gd" type="Script" id=3]
|
||||||
|
|
||||||
|
[node name="GUI" type="MarginContainer"]
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
margin_right = 116.0
|
||||||
|
custom_constants/margin_right = 20
|
||||||
|
custom_constants/margin_top = 20
|
||||||
|
custom_constants/margin_left = 20
|
||||||
|
custom_constants/margin_bottom = 20
|
||||||
|
script = ExtResource( 3 )
|
||||||
|
__meta__ = {
|
||||||
|
"_edit_use_anchors_": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="BehaviorControls" type="VBoxContainer" parent="."]
|
||||||
|
margin_left = 20.0
|
||||||
|
margin_top = 20.0
|
||||||
|
margin_right = 102.0
|
||||||
|
margin_bottom = 580.0
|
||||||
|
|
||||||
|
[node name="Seek" type="CheckBox" parent="BehaviorControls"]
|
||||||
|
margin_right = 82.0
|
||||||
|
margin_bottom = 24.0
|
||||||
|
focus_mode = 0
|
||||||
|
pressed = true
|
||||||
|
enabled_focus_mode = 0
|
||||||
|
text = "Seek"
|
||||||
|
|
||||||
|
[node name="Flee" type="CheckBox" parent="BehaviorControls"]
|
||||||
|
margin_top = 28.0
|
||||||
|
margin_right = 82.0
|
||||||
|
margin_bottom = 52.0
|
||||||
|
focus_mode = 0
|
||||||
|
enabled_focus_mode = 0
|
||||||
|
text = "Flee"
|
||||||
|
|
||||||
|
[node name="Help" type="VBoxContainer" parent="BehaviorControls"]
|
||||||
|
margin_top = 56.0
|
||||||
|
margin_right = 82.0
|
||||||
|
margin_bottom = 108.0
|
||||||
|
|
||||||
|
[node name="Controls" type="Label" parent="BehaviorControls/Help"]
|
||||||
|
margin_right = 82.0
|
||||||
|
margin_bottom = 14.0
|
||||||
|
text = "Controls"
|
||||||
|
|
||||||
|
[node name="GridContainer" type="GridContainer" parent="BehaviorControls/Help"]
|
||||||
|
margin_top = 18.0
|
||||||
|
margin_right = 82.0
|
||||||
|
margin_bottom = 52.0
|
||||||
|
columns = 3
|
||||||
|
|
||||||
|
[node name="Sep" type="Control" parent="BehaviorControls/Help/GridContainer"]
|
||||||
|
margin_right = 15.0
|
||||||
|
margin_bottom = 15.0
|
||||||
|
rect_min_size = Vector2( 15, 15 )
|
||||||
|
|
||||||
|
[node name="W" type="Label" parent="BehaviorControls/Help/GridContainer"]
|
||||||
|
margin_left = 19.0
|
||||||
|
margin_top = -1.0
|
||||||
|
margin_right = 34.0
|
||||||
|
margin_bottom = 14.0
|
||||||
|
rect_min_size = Vector2( 15, 15 )
|
||||||
|
text = "W"
|
||||||
|
|
||||||
|
[node name="Sep2" type="Control" parent="BehaviorControls/Help/GridContainer"]
|
||||||
|
margin_left = 38.0
|
||||||
|
margin_right = 53.0
|
||||||
|
margin_bottom = 15.0
|
||||||
|
rect_min_size = Vector2( 15, 15 )
|
||||||
|
|
||||||
|
[node name="A" type="Label" parent="BehaviorControls/Help/GridContainer"]
|
||||||
|
margin_top = 18.0
|
||||||
|
margin_right = 15.0
|
||||||
|
margin_bottom = 33.0
|
||||||
|
rect_min_size = Vector2( 15, 15 )
|
||||||
|
text = "A"
|
||||||
|
|
||||||
|
[node name="S" type="Label" parent="BehaviorControls/Help/GridContainer"]
|
||||||
|
margin_left = 19.0
|
||||||
|
margin_top = 18.0
|
||||||
|
margin_right = 34.0
|
||||||
|
margin_bottom = 33.0
|
||||||
|
rect_min_size = Vector2( 15, 15 )
|
||||||
|
text = "S"
|
||||||
|
|
||||||
|
[node name="D" type="Label" parent="BehaviorControls/Help/GridContainer"]
|
||||||
|
margin_left = 38.0
|
||||||
|
margin_top = 18.0
|
||||||
|
margin_right = 53.0
|
||||||
|
margin_bottom = 33.0
|
||||||
|
rect_min_size = Vector2( 15, 15 )
|
||||||
|
text = "D"
|
@ -3,9 +3,9 @@
|
|||||||
[ext_resource path="res://demos/seek_and_flee/Player.gd" type="Script" id=1]
|
[ext_resource path="res://demos/seek_and_flee/Player.gd" type="Script" id=1]
|
||||||
[ext_resource path="res://demos/seek_and_flee/Spawner.gd" type="Script" id=2]
|
[ext_resource path="res://demos/seek_and_flee/Spawner.gd" type="Script" id=2]
|
||||||
[ext_resource path="res://demos/seek_and_flee/SeekFleeDemo.gd" type="Script" id=3]
|
[ext_resource path="res://demos/seek_and_flee/SeekFleeDemo.gd" type="Script" id=3]
|
||||||
[ext_resource path="res://demos/seek_and_flee/Agents/Seeker.tscn" type="PackedScene" id=4]
|
[ext_resource path="res://demos/seek_and_flee/Seeker.tscn" type="PackedScene" id=4]
|
||||||
[ext_resource path="res://demos/seek_and_flee/Boundary.gd" type="Script" id=5]
|
[ext_resource path="res://demos/seek_and_flee/Boundary.gd" type="Script" id=5]
|
||||||
[ext_resource path="res://demos/seek_and_flee/Agents/Coward.tscn" type="PackedScene" id=6]
|
[ext_resource path="res://demos/seek_and_flee/GUI.tscn" type="PackedScene" id=7]
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id=1]
|
[sub_resource type="CircleShape2D" id=1]
|
||||||
radius = 30.0
|
radius = 30.0
|
||||||
@ -22,6 +22,12 @@ __meta__ = {
|
|||||||
"_editor_description_": "A toy demo to demonstrate the usage for the Seek and Flee steering behaviors."
|
"_editor_description_": "A toy demo to demonstrate the usage for the Seek and Flee steering behaviors."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[node name="GUI" parent="." instance=ExtResource( 7 )]
|
||||||
|
margin_left = -512.0
|
||||||
|
margin_top = -300.0
|
||||||
|
margin_right = -414.0
|
||||||
|
margin_bottom = -208.0
|
||||||
|
|
||||||
[node name="Camera2D" type="Camera2D" parent="."]
|
[node name="Camera2D" type="Camera2D" parent="."]
|
||||||
current = true
|
current = true
|
||||||
|
|
||||||
@ -68,13 +74,6 @@ script = ExtResource( 5 )
|
|||||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="BottomBoundary"]
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="BottomBoundary"]
|
||||||
shape = SubResource( 3 )
|
shape = SubResource( 3 )
|
||||||
|
|
||||||
[node name="Spawners" type="Node2D" parent="."]
|
[node name="Spawner" type="Node2D" parent="."]
|
||||||
|
|
||||||
[node name="SeekerSpawner" type="Node2D" parent="Spawners"]
|
|
||||||
script = ExtResource( 2 )
|
script = ExtResource( 2 )
|
||||||
Entity = ExtResource( 4 )
|
Entity = ExtResource( 4 )
|
||||||
|
|
||||||
[node name="CowardSpawner" type="Node2D" parent="Spawners"]
|
|
||||||
script = ExtResource( 2 )
|
|
||||||
Entity = ExtResource( 6 )
|
|
||||||
entity_color = Color( 0, 1, 0.741176, 1 )
|
|
||||||
|
@ -3,8 +3,10 @@ extends Node2D
|
|||||||
Access helper class for children to access window boundaries.
|
Access helper class for children to access window boundaries.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
onready var player: KinematicBody2D = $Player
|
onready var player: KinematicBody2D = $Player
|
||||||
onready var spawners: Node2D = $Spawners
|
onready var spawner: Node2D = $Spawner
|
||||||
|
onready var _gui: = $GUI
|
||||||
|
|
||||||
var camera_boundaries: Rect2
|
var camera_boundaries: Rect2
|
||||||
|
|
||||||
@ -23,15 +25,15 @@ func _ready() -> void:
|
|||||||
var rng: = RandomNumberGenerator.new()
|
var rng: = RandomNumberGenerator.new()
|
||||||
rng.randomize()
|
rng.randomize()
|
||||||
|
|
||||||
for spawner in spawners.get_children():
|
for i in range(spawner.entity_count):
|
||||||
for i in range(spawner.entity_count):
|
var new_pos: = Vector2(
|
||||||
var new_pos: = Vector2(
|
rng.randf_range(-camera_boundaries.size.x/2, camera_boundaries.size.x/2),
|
||||||
rng.randf_range(-camera_boundaries.size.x/2, camera_boundaries.size.x/2),
|
rng.randf_range(-camera_boundaries.size.y/2, camera_boundaries.size.y/2)
|
||||||
rng.randf_range(-camera_boundaries.size.y/2, camera_boundaries.size.y/2)
|
)
|
||||||
)
|
var entity: KinematicBody2D = spawner.Entity.instance()
|
||||||
var entity: KinematicBody2D = spawner.Entity.instance()
|
entity.global_position = new_pos
|
||||||
entity.global_position = new_pos
|
entity.player_agent = player.agent
|
||||||
entity.player_agent = player.agent
|
entity.speed = rng.randf_range(spawner.min_speed, spawner.max_speed)
|
||||||
entity.speed = rng.randf_range(spawner.min_speed, spawner.max_speed)
|
entity.color = spawner.entity_color
|
||||||
entity.color = spawner.entity_color
|
_gui.connect("mode_changed", entity, "_on_GUI_mode_changed")
|
||||||
spawner.add_child(entity)
|
spawner.add_child(entity)
|
||||||
|
@ -9,6 +9,8 @@ onready var radius: = ($CollisionShape2D.shape as CircleShape2D).radius
|
|||||||
onready var agent: = GSTSteeringAgent.new()
|
onready var agent: = GSTSteeringAgent.new()
|
||||||
onready var accel: = GSTTargetAcceleration.new()
|
onready var accel: = GSTTargetAcceleration.new()
|
||||||
onready var seek: = GSTSeek.new(agent, player_agent)
|
onready var seek: = GSTSeek.new(agent, player_agent)
|
||||||
|
onready var flee: = GSTFlee.new(agent, player_agent)
|
||||||
|
onready var _active_behavior: = seek
|
||||||
|
|
||||||
var player_agent: GSTAgentLocation
|
var player_agent: GSTAgentLocation
|
||||||
var velocity: = Vector2.ZERO
|
var velocity: = Vector2.ZERO
|
||||||
@ -30,7 +32,7 @@ func _physics_process(delta: float) -> void:
|
|||||||
return
|
return
|
||||||
|
|
||||||
_update_agent()
|
_update_agent()
|
||||||
accel = seek.calculate_steering(accel)
|
accel = _active_behavior.calculate_steering(accel)
|
||||||
|
|
||||||
velocity = (velocity + Vector2(accel.linear.x, accel.linear.y)).clamped(agent.max_linear_speed)
|
velocity = (velocity + Vector2(accel.linear.x, accel.linear.y)).clamped(agent.max_linear_speed)
|
||||||
velocity = move_and_slide(velocity)
|
velocity = move_and_slide(velocity)
|
||||||
@ -40,3 +42,10 @@ func _physics_process(delta: float) -> void:
|
|||||||
|
|
||||||
func _update_agent() -> void:
|
func _update_agent() -> void:
|
||||||
agent.position = Vector3(global_position.x, global_position.y, 0)
|
agent.position = Vector3(global_position.x, global_position.y, 0)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_GUI_mode_changed(mode: int) -> void:
|
||||||
|
if mode == 0:
|
||||||
|
_active_behavior = seek
|
||||||
|
else:
|
||||||
|
_active_behavior = flee
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
[ext_resource path="res://demos/seek_and_flee/Seeker.gd" type="Script" id=1]
|
[ext_resource path="res://demos/seek_and_flee/Seeker.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[sub_resource type="CircleShape2D" id=1]
|
[sub_resource type="CircleShape2D" id=1]
|
||||||
|
|
||||||
[node name="Seeker" type="KinematicBody2D"]
|
[node name="Seeker" type="KinematicBody2D"]
|
Loading…
Reference in New Issue
Block a user