From 9b02baaba652d678089a0f67f9c0a4f9966fc78b Mon Sep 17 00:00:00 2001 From: Francois Belair Date: Mon, 16 Dec 2019 16:14:46 -0500 Subject: [PATCH] Create a toy demo for Seek and Flee behaviors --- project.godot | 27 +++++++ src/Steering/Demos/SeekFlee/Boundary.gd | 13 ++++ src/Steering/Demos/SeekFlee/Coward.gd | 38 ++++++++++ src/Steering/Demos/SeekFlee/Coward.tscn | 13 ++++ src/Steering/Demos/SeekFlee/Player.gd | 26 +++++++ src/Steering/Demos/SeekFlee/SeekFlee.tscn | 80 +++++++++++++++++++++ src/Steering/Demos/SeekFlee/SeekFleeDemo.gd | 8 +++ src/Steering/Demos/SeekFlee/Seeker.gd | 38 ++++++++++ src/Steering/Demos/SeekFlee/Seeker.tscn | 13 ++++ src/Steering/Demos/SeekFlee/Spawner.gd | 28 ++++++++ 10 files changed, 284 insertions(+) create mode 100644 src/Steering/Demos/SeekFlee/Boundary.gd create mode 100644 src/Steering/Demos/SeekFlee/Coward.gd create mode 100644 src/Steering/Demos/SeekFlee/Coward.tscn create mode 100644 src/Steering/Demos/SeekFlee/Player.gd create mode 100644 src/Steering/Demos/SeekFlee/SeekFlee.tscn create mode 100644 src/Steering/Demos/SeekFlee/SeekFleeDemo.gd create mode 100644 src/Steering/Demos/SeekFlee/Seeker.gd create mode 100644 src/Steering/Demos/SeekFlee/Seeker.tscn create mode 100644 src/Steering/Demos/SeekFlee/Spawner.gd diff --git a/project.godot b/project.godot index ec6e359..29e0df1 100644 --- a/project.godot +++ b/project.godot @@ -83,6 +83,33 @@ _global_script_class_icons={ config/name="godot-steering-toolkit" config/icon="res://icon.png" +[input] + +sf_left={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null) + ] +} +sf_right={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null) + ] +} +sf_up={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null) + ] +} +sf_down={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null) + ] +} + [rendering] environment/default_environment="res://default_env.tres" diff --git a/src/Steering/Demos/SeekFlee/Boundary.gd b/src/Steering/Demos/SeekFlee/Boundary.gd new file mode 100644 index 0000000..a9439e5 --- /dev/null +++ b/src/Steering/Demos/SeekFlee/Boundary.gd @@ -0,0 +1,13 @@ +extends StaticBody2D + + +var rect: Rect2 + + +func _ready() -> void: + var extents: = ($CollisionShape2D.shape as RectangleShape2D).extents + rect = Rect2(-extents, extents*2) + + +func _draw() -> void: + draw_rect(rect, Color.yellowgreen) diff --git a/src/Steering/Demos/SeekFlee/Coward.gd b/src/Steering/Demos/SeekFlee/Coward.gd new file mode 100644 index 0000000..f623504 --- /dev/null +++ b/src/Steering/Demos/SeekFlee/Coward.gd @@ -0,0 +1,38 @@ +extends KinematicBody2D + + +onready var radius: = ($CollisionShape2D.shape as CircleShape2D).radius + +var agent: SteeringAgent +var player_agent: AgentLocation +var flee: Flee +var accel: = TargetAcceleration.new() +var velocity: = Vector2.ZERO +var speed: float +var color: Color + + +func _ready() -> void: + agent = SteeringAgent.new() + agent.max_linear_acceleration = speed/10 + agent.max_linear_speed = speed + + flee = Flee.new(agent, player_agent) + + +func _draw() -> void: + draw_circle(Vector2.ZERO, radius, color) + + +func _physics_process(delta: float) -> void: + _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/src/Steering/Demos/SeekFlee/Coward.tscn b/src/Steering/Demos/SeekFlee/Coward.tscn new file mode 100644 index 0000000..5240047 --- /dev/null +++ b/src/Steering/Demos/SeekFlee/Coward.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://src/Steering/Demos/SeekFlee/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/src/Steering/Demos/SeekFlee/Player.gd b/src/Steering/Demos/SeekFlee/Player.gd new file mode 100644 index 0000000..5a7ab70 --- /dev/null +++ b/src/Steering/Demos/SeekFlee/Player.gd @@ -0,0 +1,26 @@ +extends KinematicBody2D + + +onready var _radius: = ($CollisionShape2D.shape as CircleShape2D).radius + +export var speed: = 150.0 + +var player_agent: = AgentLocation.new() + + +func _draw() -> void: + draw_circle(Vector2.ZERO, _radius, Color.red) + + +func _get_movement() -> Vector2: + return Vector2(Input.get_action_strength("sf_right") - Input.get_action_strength("sf_left"), + Input.get_action_strength("sf_down") - Input.get_action_strength("sf_up")) + + +func _physics_process(delta: float) -> void: + var movement: = _get_movement() + if movement.length_squared() < 0.01: + return + + move_and_slide(movement * speed) + player_agent.position = Vector3(global_position.x, global_position.y, 0) diff --git a/src/Steering/Demos/SeekFlee/SeekFlee.tscn b/src/Steering/Demos/SeekFlee/SeekFlee.tscn new file mode 100644 index 0000000..d191561 --- /dev/null +++ b/src/Steering/Demos/SeekFlee/SeekFlee.tscn @@ -0,0 +1,80 @@ +[gd_scene load_steps=10 format=2] + +[ext_resource path="res://src/Steering/Demos/SeekFlee/Player.gd" type="Script" id=1] +[ext_resource path="res://src/Steering/Demos/SeekFlee/Spawner.gd" type="Script" id=2] +[ext_resource path="res://src/Steering/Demos/SeekFlee/SeekFleeDemo.gd" type="Script" id=3] +[ext_resource path="res://src/Steering/Demos/SeekFlee/Seeker.tscn" type="PackedScene" id=4] +[ext_resource path="res://src/Steering/Demos/SeekFlee/Boundary.gd" type="Script" id=5] +[ext_resource path="res://src/Steering/Demos/SeekFlee/Coward.tscn" type="PackedScene" id=6] + +[sub_resource type="CircleShape2D" id=1] +radius = 30.0 + +[sub_resource type="RectangleShape2D" id=2] +extents = Vector2( 10, 300 ) + +[sub_resource type="RectangleShape2D" id=3] +extents = Vector2( 512, 10 ) + +[node name="SeekFleeDemo" type="Node2D"] +script = ExtResource( 3 ) +__meta__ = { +"_editor_description_": "A toy demo to demonstrate the usage for the Seek and Flee steering behaviors." +} + +[node name="Camera2D" type="Camera2D" parent="."] +current = true + +[node name="Player" type="KinematicBody2D" parent="."] +collision_mask = 2 +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Player"] +shape = SubResource( 1 ) + +[node name="LeftBoundary" type="StaticBody2D" parent="."] +position = Vector2( -512, 0 ) +collision_layer = 2 +collision_mask = 5 +script = ExtResource( 5 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="LeftBoundary"] +shape = SubResource( 2 ) + +[node name="RightBoundary" type="StaticBody2D" parent="."] +position = Vector2( 512, 0 ) +collision_layer = 2 +collision_mask = 5 +script = ExtResource( 5 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="RightBoundary"] +shape = SubResource( 2 ) + +[node name="TopBoundary" type="StaticBody2D" parent="."] +position = Vector2( 0, -300 ) +collision_layer = 2 +collision_mask = 5 +script = ExtResource( 5 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="TopBoundary"] +shape = SubResource( 3 ) + +[node name="BottomBoundary" type="StaticBody2D" parent="."] +position = Vector2( 0, 300 ) +collision_layer = 2 +collision_mask = 5 +script = ExtResource( 5 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="BottomBoundary"] +shape = SubResource( 3 ) + +[node name="SeekerSpawner" type="Node2D" parent="."] +script = ExtResource( 2 ) +agent_scene = ExtResource( 4 ) +player = NodePath("../Player") + +[node name="FleeerSpawner" type="Node2D" parent="."] +script = ExtResource( 2 ) +agent_scene = ExtResource( 6 ) +player = NodePath("../Player") +agent_color = Color( 0.0980392, 0.886275, 0.517647, 1 ) diff --git a/src/Steering/Demos/SeekFlee/SeekFleeDemo.gd b/src/Steering/Demos/SeekFlee/SeekFleeDemo.gd new file mode 100644 index 0000000..f92ff1d --- /dev/null +++ b/src/Steering/Demos/SeekFlee/SeekFleeDemo.gd @@ -0,0 +1,8 @@ +extends Node2D + + +var camera_boundaries: Rect2 + + +func _init() -> void: + camera_boundaries = Rect2(Vector2.ZERO, Vector2(ProjectSettings["display/window/size/width"], ProjectSettings["display/window/size/height"])) diff --git a/src/Steering/Demos/SeekFlee/Seeker.gd b/src/Steering/Demos/SeekFlee/Seeker.gd new file mode 100644 index 0000000..759873f --- /dev/null +++ b/src/Steering/Demos/SeekFlee/Seeker.gd @@ -0,0 +1,38 @@ +extends KinematicBody2D + + +onready var radius: = ($CollisionShape2D.shape as CircleShape2D).radius + +var agent: SteeringAgent +var player_agent: AgentLocation +var seek: Seek +var accel: = TargetAcceleration.new() +var velocity: = Vector2.ZERO +var speed: float +var color: Color + + +func _ready() -> void: + agent = SteeringAgent.new() + agent.max_linear_acceleration = speed/10 + agent.max_linear_speed = speed + + seek = Seek.new(agent, player_agent) + + +func _draw() -> void: + draw_circle(Vector2.ZERO, radius, color) + + +func _physics_process(delta: float) -> void: + _update_agent() + accel = seek.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/src/Steering/Demos/SeekFlee/Seeker.tscn b/src/Steering/Demos/SeekFlee/Seeker.tscn new file mode 100644 index 0000000..4ea2577 --- /dev/null +++ b/src/Steering/Demos/SeekFlee/Seeker.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://src/Steering/Demos/SeekFlee/Seeker.gd" type="Script" id=1] + +[sub_resource type="CircleShape2D" id=1] + +[node name="Seeker" type="KinematicBody2D"] +collision_layer = 4 +collision_mask = 6 +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) diff --git a/src/Steering/Demos/SeekFlee/Spawner.gd b/src/Steering/Demos/SeekFlee/Spawner.gd new file mode 100644 index 0000000..afddacc --- /dev/null +++ b/src/Steering/Demos/SeekFlee/Spawner.gd @@ -0,0 +1,28 @@ +extends Node2D + + +onready var player_agent: AgentLocation = get_node(player).player_agent + + +export(PackedScene) var agent_scene: PackedScene +export var agent_count: = 10 +export var player: = NodePath() +export var min_speed: = 50.0 +export var max_speed: = 125.0 +export var agent_color: = Color.blue + + +func _ready() -> void: + var boundaries: Rect2 = owner.camera_boundaries + randomize() + for i in range(agent_count): + var new_pos: = Vector2( + rand_range(-boundaries.size.x/2, boundaries.size.x/2), + rand_range(-boundaries.size.y/2, boundaries.size.y/2) + ) + var agent: = agent_scene.instance() + agent.global_position = new_pos + agent.player_agent = player_agent + agent.speed = rand_range(min_speed, max_speed) + agent.color = agent_color + add_child(agent)