From 3d50dcdb9cca497c11868b36a609bd583150b623 Mon Sep 17 00:00:00 2001 From: Francois Belair Date: Sat, 21 Dec 2019 13:07:43 -0500 Subject: [PATCH] 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. --- .../demos/seek_and_flee/Agents/Coward.tscn | 13 --- project/demos/seek_and_flee/Coward.gd | 42 -------- project/demos/seek_and_flee/GUI.gd | 28 ++++++ project/demos/seek_and_flee/GUI.tscn | 95 +++++++++++++++++++ project/demos/seek_and_flee/SeekFlee.tscn | 19 ++-- project/demos/seek_and_flee/SeekFleeDemo.gd | 28 +++--- project/demos/seek_and_flee/Seeker.gd | 11 ++- .../seek_and_flee/{Agents => }/Seeker.tscn | 2 + 8 files changed, 159 insertions(+), 79 deletions(-) delete mode 100644 project/demos/seek_and_flee/Agents/Coward.tscn delete mode 100644 project/demos/seek_and_flee/Coward.gd create mode 100644 project/demos/seek_and_flee/GUI.gd create mode 100644 project/demos/seek_and_flee/GUI.tscn rename project/demos/seek_and_flee/{Agents => }/Seeker.tscn (99%) diff --git a/project/demos/seek_and_flee/Agents/Coward.tscn b/project/demos/seek_and_flee/Agents/Coward.tscn deleted file mode 100644 index b0a2c84..0000000 --- a/project/demos/seek_and_flee/Agents/Coward.tscn +++ /dev/null @@ -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 ) diff --git a/project/demos/seek_and_flee/Coward.gd b/project/demos/seek_and_flee/Coward.gd deleted file mode 100644 index 5434234..0000000 --- a/project/demos/seek_and_flee/Coward.gd +++ /dev/null @@ -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) diff --git a/project/demos/seek_and_flee/GUI.gd b/project/demos/seek_and_flee/GUI.gd new file mode 100644 index 0000000..ae83330 --- /dev/null +++ b/project/demos/seek_and_flee/GUI.gd @@ -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) diff --git a/project/demos/seek_and_flee/GUI.tscn b/project/demos/seek_and_flee/GUI.tscn new file mode 100644 index 0000000..9ad06ae --- /dev/null +++ b/project/demos/seek_and_flee/GUI.tscn @@ -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" diff --git a/project/demos/seek_and_flee/SeekFlee.tscn b/project/demos/seek_and_flee/SeekFlee.tscn index 5439a90..7183345 100644 --- a/project/demos/seek_and_flee/SeekFlee.tscn +++ b/project/demos/seek_and_flee/SeekFlee.tscn @@ -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/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/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/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] radius = 30.0 @@ -22,6 +22,12 @@ __meta__ = { "_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="."] current = true @@ -68,13 +74,6 @@ script = ExtResource( 5 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="BottomBoundary"] shape = SubResource( 3 ) -[node name="Spawners" type="Node2D" parent="."] - -[node name="SeekerSpawner" type="Node2D" parent="Spawners"] +[node name="Spawner" type="Node2D" parent="."] script = ExtResource( 2 ) Entity = ExtResource( 4 ) - -[node name="CowardSpawner" type="Node2D" parent="Spawners"] -script = ExtResource( 2 ) -Entity = ExtResource( 6 ) -entity_color = Color( 0, 1, 0.741176, 1 ) diff --git a/project/demos/seek_and_flee/SeekFleeDemo.gd b/project/demos/seek_and_flee/SeekFleeDemo.gd index 6f589cb..c1965f5 100644 --- a/project/demos/seek_and_flee/SeekFleeDemo.gd +++ b/project/demos/seek_and_flee/SeekFleeDemo.gd @@ -3,8 +3,10 @@ extends Node2D Access helper class for children to access window boundaries. """ + onready var player: KinematicBody2D = $Player -onready var spawners: Node2D = $Spawners +onready var spawner: Node2D = $Spawner +onready var _gui: = $GUI var camera_boundaries: Rect2 @@ -23,15 +25,15 @@ func _ready() -> void: var rng: = RandomNumberGenerator.new() rng.randomize() - for spawner in spawners.get_children(): - for i in range(spawner.entity_count): - var new_pos: = Vector2( - 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) - ) - var entity: KinematicBody2D = spawner.Entity.instance() - entity.global_position = new_pos - entity.player_agent = player.agent - entity.speed = rng.randf_range(spawner.min_speed, spawner.max_speed) - entity.color = spawner.entity_color - spawner.add_child(entity) + for i in range(spawner.entity_count): + var new_pos: = Vector2( + 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) + ) + var entity: KinematicBody2D = spawner.Entity.instance() + entity.global_position = new_pos + entity.player_agent = player.agent + entity.speed = rng.randf_range(spawner.min_speed, spawner.max_speed) + entity.color = spawner.entity_color + _gui.connect("mode_changed", entity, "_on_GUI_mode_changed") + spawner.add_child(entity) diff --git a/project/demos/seek_and_flee/Seeker.gd b/project/demos/seek_and_flee/Seeker.gd index 22598a3..8c8b2a0 100644 --- a/project/demos/seek_and_flee/Seeker.gd +++ b/project/demos/seek_and_flee/Seeker.gd @@ -9,6 +9,8 @@ onready var radius: = ($CollisionShape2D.shape as CircleShape2D).radius onready var agent: = GSTSteeringAgent.new() onready var accel: = GSTTargetAcceleration.new() 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 velocity: = Vector2.ZERO @@ -30,7 +32,7 @@ func _physics_process(delta: float) -> void: return _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 = move_and_slide(velocity) @@ -40,3 +42,10 @@ func _physics_process(delta: float) -> void: func _update_agent() -> void: 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 diff --git a/project/demos/seek_and_flee/Agents/Seeker.tscn b/project/demos/seek_and_flee/Seeker.tscn similarity index 99% rename from project/demos/seek_and_flee/Agents/Seeker.tscn rename to project/demos/seek_and_flee/Seeker.tscn index 511241e..804897a 100644 --- a/project/demos/seek_and_flee/Agents/Seeker.tscn +++ b/project/demos/seek_and_flee/Seeker.tscn @@ -2,6 +2,8 @@ [ext_resource path="res://demos/seek_and_flee/Seeker.gd" type="Script" id=1] + + [sub_resource type="CircleShape2D" id=1] [node name="Seeker" type="KinematicBody2D"]