mirror of
https://github.com/Relintai/godot-steering-ai-framework.git
synced 2024-11-14 04:57:19 +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/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 )
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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"]
|
Loading…
Reference in New Issue
Block a user