diff --git a/CHANGELOG.md b/CHANGELOG.md index 10bbfad..9a867c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ This document lists new features, improvements, changes, and bug fixes in every ## Master +- Removed the demos repository and brought demos back into main repo +- Added a repository with just the files for [submodule](https://github.com/GDQuest/godot-steering-ai-framework-submodule) usage. + ## Godot Steering AI Framework 3.0.0 ### Changes diff --git a/README.md b/README.md index e615538..f82e435 100644 --- a/README.md +++ b/README.md @@ -8,23 +8,21 @@ This project is a framework to code complex and smooth AI movement in the [Godot It supports all essential steering behaviors like flee, follow, look at, but also blended behaviors, group behaviors, avoiding neighbors, following a path, following the leader, and much more. - - -**Table of Contents** - -- [Introduction](#introduction) -- [The framework](#the-framework) -- [Installation](#installation) -- [Getting Started](#getting-started) - - [More information and resources](#more-information-and-resources) -- [Example usage](#example-usage) - +- [Godot Steering AI Framework](#godot-steering-ai-framework) + - [Getting the framework](#getting-the-framework) + - [Introduction](#introduction) + - [The framework](#the-framework) + - [How it works](#how-it-works) + - [Documentation](#documentation) + - [Contributing](#contributing) + - [Support us](#support-us) + - [Join the community](#join-the-community) ## Getting the framework -This repository contains just the framework to make it easy for you to install it. +This repository contains the framework and some demos for learning purposes. -You should also check out the [Steering AI Framework Demos](https://github.com/GDQuest/godot-steering-ai-framework-demos) repository! It contains many demos to learn to use the framework and see what you can achieve with it. +If you want just the framework with nothing else to get in the way or to create a Git submodule, use the [Godot Steering AI Framework Submodules](https://github.com/GDQuest/godot-steering-ai-framework-submodule) repository. ## Introduction diff --git a/godot/Demos/Arrive/ArriveDemo.gd b/godot/Demos/Arrive/ArriveDemo.gd new file mode 100644 index 0000000..c18049b --- /dev/null +++ b/godot/Demos/Arrive/ArriveDemo.gd @@ -0,0 +1,51 @@ +extends Node + +export (float, 0, 3200, 100) var linear_speed_max := 800.0 setget set_linear_speed_max +export (float, 0, 10000, 100) var linear_acceleration_max := 80.0 setget set_linear_acceleration_max +export (float, 0, 100, 0.1) var arrival_tolerance := 25.0 setget set_arrival_tolerance +export (float, 0, 500, 10) var deceleration_radius := 125.0 setget set_deceleration_radius + +onready var arriver := $Arriver +onready var target_drawer := $TargetDrawer + + +func _ready() -> void: + arriver.setup(linear_speed_max, linear_acceleration_max, arrival_tolerance, deceleration_radius) + + +func _unhandled_input(event: InputEvent) -> void: + if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.is_pressed(): + arriver.target.position = Vector3(event.position.x, event.position.y, 0) + target_drawer.update() + + +func set_arrival_tolerance(value: float) -> void: + arrival_tolerance = value + if not is_inside_tree(): + return + + arriver.arrive.arrival_tolerance = value + + +func set_deceleration_radius(value: float) -> void: + deceleration_radius = value + if not is_inside_tree(): + return + + arriver.arrive.deceleration_radius = value + + +func set_linear_speed_max(value: float) -> void: + linear_speed_max = value + if not is_inside_tree(): + return + + arriver.agent.linear_speed_max = value + + +func set_linear_acceleration_max(value: float) -> void: + linear_acceleration_max = value + if not is_inside_tree(): + return + + arriver.agent.linear_acceleration_max = value diff --git a/godot/Demos/Arrive/ArriveDemo.tscn b/godot/Demos/Arrive/ArriveDemo.tscn new file mode 100644 index 0000000..8b02e8e --- /dev/null +++ b/godot/Demos/Arrive/ArriveDemo.tscn @@ -0,0 +1,39 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://Demos/Arrive/Arriver.gd" type="Script" id=1] +[ext_resource path="res://Demos/Utils/DemoInterface.tscn" type="PackedScene" id=2] +[ext_resource path="res://Demos/Arrive/ArriveDemo.gd" type="Script" id=3] +[ext_resource path="res://Demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=4] +[ext_resource path="res://Demos/Arrive/TargetDrawer.gd" type="Script" id=5] +[ext_resource path="res://Demos/Utils/CircleDraw.gd" type="Script" id=6] + +[sub_resource type="CircleShape2D" id=1] +radius = 23.2163 + +[node name="ArriveDemo" type="Node"] +script = ExtResource( 3 ) +linear_speed_max = 1600.0 +linear_acceleration_max = 5000.0 +arrival_tolerance = 35.0 +deceleration_radius = 180.0 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 4 )] + +[node name="TargetDrawer" type="Node2D" parent="."] +script = ExtResource( 5 ) + +[node name="Arriver" type="KinematicBody2D" parent="."] +show_behind_parent = true +position = Vector2( 960, 540 ) +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Arriver"] +shape = SubResource( 1 ) +script = ExtResource( 6 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +stroke = 6.0 + +[node name="DemoInterface" parent="." instance=ExtResource( 2 )] +text_bbcode = "Arrive Demo +Mouse click to make the [color=lime]green \"Player\"[/color] move to the [color=fuchsia]purple target[/color]" diff --git a/godot/Demos/Arrive/ArriveDemo.tscn.bak b/godot/Demos/Arrive/ArriveDemo.tscn.bak new file mode 100644 index 0000000..ab7af6a --- /dev/null +++ b/godot/Demos/Arrive/ArriveDemo.tscn.bak @@ -0,0 +1,39 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://demos/Arrive/Arriver.gd" type="Script" id=1] +[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=2] +[ext_resource path="res://demos/Arrive/ArriveDemo.gd" type="Script" id=3] +[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=4] +[ext_resource path="res://demos/Arrive/TargetDrawer.gd" type="Script" id=5] +[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=6] + +[sub_resource type="CircleShape2D" id=1] +radius = 23.2163 + +[node name="ArriveDemo" type="Node"] +script = ExtResource( 3 ) +linear_speed_max = 1600.0 +linear_acceleration_max = 5000.0 +arrival_tolerance = 35.0 +deceleration_radius = 180.0 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 4 )] + +[node name="TargetDrawer" type="Node2D" parent="."] +script = ExtResource( 5 ) + +[node name="Arriver" type="KinematicBody2D" parent="."] +show_behind_parent = true +position = Vector2( 960, 540 ) +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Arriver"] +shape = SubResource( 1 ) +script = ExtResource( 6 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +stroke = 6.0 + +[node name="DemoInterface" parent="." instance=ExtResource( 2 )] +text_bbcode = "Arrive Demo +Mouse click to make the [color=lime]green \"Player\"[/color] move to the [color=fuchsia]purple target[/color]" diff --git a/godot/Demos/Arrive/Arriver.gd b/godot/Demos/Arrive/Arriver.gd new file mode 100644 index 0000000..8646b6b --- /dev/null +++ b/godot/Demos/Arrive/Arriver.gd @@ -0,0 +1,28 @@ +extends KinematicBody2D + +var agent := GSAIKinematicBody2DAgent.new(self) +var target := GSAIAgentLocation.new() +var arrive := GSAIArrive.new(agent, target) +var _accel := GSAITargetAcceleration.new() + +var _velocity := Vector2() +var _drag := 0.1 + + +func _physics_process(delta: float) -> void: + arrive.calculate_steering(_accel) + agent._apply_steering(_accel, delta) + + +func setup( + linear_speed_max: float, + linear_acceleration_max: float, + arrival_tolerance: float, + deceleration_radius: float +) -> void: + agent.linear_speed_max = linear_speed_max + agent.linear_acceleration_max = linear_acceleration_max + agent.linear_drag_percentage = _drag + arrive.deceleration_radius = deceleration_radius + arrive.arrival_tolerance = arrival_tolerance + target.position = agent.position diff --git a/godot/Demos/Arrive/TargetDrawer.gd b/godot/Demos/Arrive/TargetDrawer.gd new file mode 100644 index 0000000..3bdfc31 --- /dev/null +++ b/godot/Demos/Arrive/TargetDrawer.gd @@ -0,0 +1,19 @@ +extends Node2D + +const COLORS := { + deceleration_radius = Color(1.0, 0.419, 0.592, 0.5), + arrival_tolerance = Color(0.278, 0.231, 0.47, 0.3) +} + +var arriver: Node2D + + +func _ready() -> void: + yield(owner, "ready") + arriver = owner.arriver + + +func _draw(): + var target_position := GSAIUtils.to_vector2(arriver.target.position) + draw_circle(target_position, owner.deceleration_radius, COLORS.deceleration_radius) + draw_circle(target_position, owner.arrival_tolerance, COLORS.arrival_tolerance) diff --git a/godot/Demos/Arrive3d/Arrive3dDemo.tscn b/godot/Demos/Arrive3d/Arrive3dDemo.tscn new file mode 100644 index 0000000..8ffcc48 --- /dev/null +++ b/godot/Demos/Arrive3d/Arrive3dDemo.tscn @@ -0,0 +1,96 @@ +[gd_scene load_steps=14 format=2] + +[ext_resource path="res://Demos/Utils/DemoInterface.tscn" type="PackedScene" id=1] +[ext_resource path="res://Demos/Arrive3d/Camera.gd" type="Script" id=2] +[ext_resource path="res://Demos/Arrive3d/Seek3dDemo.gd" type="Script" id=3] +[ext_resource path="res://Demos/Arrive3d/Seeker.gd" type="Script" id=4] +[ext_resource path="res://Demos/Arrive3d/SeekerMat.tres" type="Material" id=5] + +[sub_resource type="CapsuleShape" id=1] + +[sub_resource type="CapsuleMesh" id=2] + +[sub_resource type="CubeMesh" id=3] +material = ExtResource( 5 ) +size = Vector3( 0.5, 0.5, 1 ) + +[sub_resource type="CylinderMesh" id=4] +top_radius = 2.0 +bottom_radius = 2.0 +height = 0.1 + +[sub_resource type="SpatialMaterial" id=5] +albedo_color = Color( 0.945098, 0.85098, 0.0745098, 1 ) + +[sub_resource type="BoxShape" id=6] +extents = Vector3( 1000, 0.1, 1000 ) + +[sub_resource type="PlaneMesh" id=7] +size = Vector2( 250, 250 ) + +[sub_resource type="SpatialMaterial" id=8] +albedo_color = Color( 0.0941176, 0.235294, 0.486275, 1 ) + +[node name="Arrive3dDemo" type="Node"] +script = ExtResource( 3 ) +linear_speed_max = 50.0 +linear_acceleration_max = 53.2 +deceleration_radius = 10.8 +angular_speed_max = 550 +angular_accel_max = 910 + +[node name="Arriver" type="KinematicBody" parent="."] +script = ExtResource( 4 ) + +[node name="CollisionShape" type="CollisionShape" parent="Arriver"] +transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 1.5, 0 ) +shape = SubResource( 1 ) + +[node name="Capsule" type="MeshInstance" parent="Arriver"] +transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 1.5, 0 ) +mesh = SubResource( 2 ) +material/0 = ExtResource( 5 ) + +[node name="Nose" type="MeshInstance" parent="Arriver"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 1.25 ) +mesh = SubResource( 3 ) +material/0 = null + +[node name="Camera" type="Camera" parent="."] +transform = Transform( 0.989952, 0.0720094, -0.121693, 0.0339305, 0.714503, 0.69881, 0.137271, -0.695917, 0.70488, -7.68317, 14.1265, 25.616 ) +current = true +script = ExtResource( 2 ) + +[node name="RayCast" type="RayCast" parent="Camera"] +enabled = true +cast_to = Vector3( -627, 200, -777 ) +collision_mask = 2 + +[node name="MouseTarget" type="Spatial" parent="."] +transform = Transform( 1, 0, 7.45058e-09, 0, 1, 0, 7.45058e-09, 0, 1, -4.76837e-07, 9.53674e-07, 1.90735e-06 ) + +[node name="MeshInstance" type="MeshInstance" parent="MouseTarget"] +mesh = SubResource( 4 ) +material/0 = SubResource( 5 ) + +[node name="StaticBody" type="StaticBody" parent="."] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.1, 0 ) +collision_layer = 2 +collision_mask = 2 + +[node name="CollisionShape" type="CollisionShape" parent="StaticBody"] +shape = SubResource( 6 ) + +[node name="Ground" type="MeshInstance" parent="."] +mesh = SubResource( 7 ) +material/0 = SubResource( 8 ) + +[node name="DirectionalLight" type="DirectionalLight" parent="."] +transform = Transform( -0.588165, 0.462179, -0.663666, -0.804031, -0.245728, 0.541436, 0.087159, 0.852061, 0.516134, -17.6076, 12.1748, 0 ) +light_energy = 0.5 +shadow_enabled = true + +[node name="DemoInterface" parent="." instance=ExtResource( 1 )] +mouse_filter = 2 +text_bbcode = "3D Arrive Demo +Move the mouse about the field to have the agent turn towards and smoothly arrive at the target marker." diff --git a/godot/Demos/Arrive3d/Arrive3dDemo.tscn.bak b/godot/Demos/Arrive3d/Arrive3dDemo.tscn.bak new file mode 100644 index 0000000..75f9899 --- /dev/null +++ b/godot/Demos/Arrive3d/Arrive3dDemo.tscn.bak @@ -0,0 +1,97 @@ +[gd_scene load_steps=14 format=2] + +[ext_resource path="res://src/Utils/DemoInterface.tscn" type="PackedScene" id=1] +[ext_resource path="res://demos/Arrive3d/Camera.gd" type="Script" id=2] +[ext_resource path="res://demos/Arrive3d/Seek3dDemo.gd" type="Script" id=3] +[ext_resource path="res://demos/Arrive3d/Seeker.gd" type="Script" id=4] +[ext_resource path="res://demos/Arrive3d/SeekerMat.tres" type="Material" id=5] + + +[sub_resource type="CapsuleShape" id=1] + +[sub_resource type="CapsuleMesh" id=2] + +[sub_resource type="CubeMesh" id=3] +material = ExtResource( 5 ) +size = Vector3( 0.5, 0.5, 1 ) + +[sub_resource type="CylinderMesh" id=4] +top_radius = 2.0 +bottom_radius = 2.0 +height = 0.1 + +[sub_resource type="SpatialMaterial" id=5] +albedo_color = Color( 0.945098, 0.85098, 0.0745098, 1 ) + +[sub_resource type="BoxShape" id=6] +extents = Vector3( 1000, 0.1, 1000 ) + +[sub_resource type="PlaneMesh" id=7] +size = Vector2( 250, 250 ) + +[sub_resource type="SpatialMaterial" id=8] +albedo_color = Color( 0.0941176, 0.235294, 0.486275, 1 ) + +[node name="Arrive3dDemo" type="Node"] +script = ExtResource( 3 ) +linear_speed_max = 50.0 +linear_acceleration_max = 53.2 +deceleration_radius = 10.8 +angular_speed_max = 550 +angular_accel_max = 910 + +[node name="Arriver" type="KinematicBody" parent="."] +script = ExtResource( 4 ) + +[node name="CollisionShape" type="CollisionShape" parent="Arriver"] +transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 1.5, 0 ) +shape = SubResource( 1 ) + +[node name="Capsule" type="MeshInstance" parent="Arriver"] +transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 1.5, 0 ) +mesh = SubResource( 2 ) +material/0 = ExtResource( 5 ) + +[node name="Nose" type="MeshInstance" parent="Arriver"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 1.25 ) +mesh = SubResource( 3 ) +material/0 = null + +[node name="Camera" type="Camera" parent="."] +transform = Transform( 0.989952, 0.0720094, -0.121693, 0.0339305, 0.714503, 0.69881, 0.137271, -0.695917, 0.70488, -7.68317, 14.1265, 25.616 ) +current = true +script = ExtResource( 2 ) + +[node name="RayCast" type="RayCast" parent="Camera"] +enabled = true +cast_to = Vector3( -627, 200, -777 ) +collision_mask = 2 + +[node name="MouseTarget" type="Spatial" parent="."] +transform = Transform( 1, 0, 7.45058e-09, 0, 1, 0, 7.45058e-09, 0, 1, -4.76837e-07, 9.53674e-07, 1.90735e-06 ) + +[node name="MeshInstance" type="MeshInstance" parent="MouseTarget"] +mesh = SubResource( 4 ) +material/0 = SubResource( 5 ) + +[node name="StaticBody" type="StaticBody" parent="."] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.1, 0 ) +collision_layer = 2 +collision_mask = 2 + +[node name="CollisionShape" type="CollisionShape" parent="StaticBody"] +shape = SubResource( 6 ) + +[node name="Ground" type="MeshInstance" parent="."] +mesh = SubResource( 7 ) +material/0 = SubResource( 8 ) + +[node name="DirectionalLight" type="DirectionalLight" parent="."] +transform = Transform( -0.588165, 0.462179, -0.663666, -0.804031, -0.245728, 0.541436, 0.087159, 0.852061, 0.516134, -17.6076, 12.1748, 0 ) +light_energy = 0.5 +shadow_enabled = true + +[node name="DemoInterface" parent="." instance=ExtResource( 1 )] +mouse_filter = 2 +text_bbcode = "3D Arrive Demo +Move the mouse about the field to have the agent turn towards and smoothly arrive at the target marker." diff --git a/godot/Demos/Arrive3d/Camera.gd b/godot/Demos/Arrive3d/Camera.gd new file mode 100644 index 0000000..4970295 --- /dev/null +++ b/godot/Demos/Arrive3d/Camera.gd @@ -0,0 +1,24 @@ +extends Camera + +var target: Spatial + +onready var ray := $RayCast + + +func _unhandled_input(event: InputEvent) -> void: + if event is InputEventMouseMotion: + _set_target_position(event.position) + + +func setup(_target: Spatial) -> void: + self.target = _target + _set_target_position(get_viewport().get_mouse_position()) + + +func _set_target_position(position: Vector2) -> void: + var to = project_local_ray_normal(position) * 10000 + ray.cast_to = to + ray.force_raycast_update() + if ray.is_colliding(): + var point = ray.get_collision_point() + target.transform.origin = point diff --git a/godot/Demos/Arrive3d/Seek3dDemo.gd b/godot/Demos/Arrive3d/Seek3dDemo.gd new file mode 100644 index 0000000..151ed7b --- /dev/null +++ b/godot/Demos/Arrive3d/Seek3dDemo.gd @@ -0,0 +1,92 @@ +extends Node + +export (float, 0, 100, 5) var linear_speed_max := 10.0 setget set_linear_speed_max +export (float, 0, 100, 0.1) var linear_acceleration_max := 1.0 setget set_linear_acceleration_max +export (float, 0, 50, 0.1) var arrival_tolerance := 0.5 setget set_arrival_tolerance +export (float, 0, 50, 0.1) var deceleration_radius := 5.0 setget set_deceleration_radius +export (int, 0, 1080, 10) var angular_speed_max := 270 setget set_angular_speed_max +export (int, 0, 2048, 10) var angular_accel_max := 45 setget set_angular_accel_max +export (int, 0, 178, 2) var align_tolerance := 5 setget set_align_tolerance +export (int, 0, 180, 2) var angular_deceleration_radius := 45 setget set_angular_deceleration_radius + +onready var target := $MouseTarget +onready var arriver := $Arriver + + +func _ready() -> void: + arriver.setup( + deg2rad(align_tolerance), + deg2rad(angular_deceleration_radius), + deg2rad(angular_accel_max), + deg2rad(angular_speed_max), + deceleration_radius, + arrival_tolerance, + linear_acceleration_max, + linear_speed_max, + target + ) + $Camera.setup(target) + + +func set_align_tolerance(value: int) -> void: + align_tolerance = value + if not is_inside_tree(): + return + + arriver.face.alignment_tolerance = deg2rad(value) + + +func set_angular_deceleration_radius(value: int) -> void: + deceleration_radius = value + if not is_inside_tree(): + return + + arriver.face.deceleration_radius = deg2rad(value) + + +func set_angular_accel_max(value: int) -> void: + angular_accel_max = value + if not is_inside_tree(): + return + + arriver.agent.angular_acceleration_max = deg2rad(value) + + +func set_angular_speed_max(value: int) -> void: + angular_speed_max = value + if not is_inside_tree(): + return + + arriver.agent.angular_speed_max = deg2rad(value) + + +func set_arrival_tolerance(value: float) -> void: + arrival_tolerance = value + if not is_inside_tree(): + return + + arriver.arrive.arrival_tolerance = value + + +func set_deceleration_radius(value: float) -> void: + deceleration_radius = value + if not is_inside_tree(): + return + + arriver.arrive.deceleration_radius = value + + +func set_linear_speed_max(value: float) -> void: + linear_speed_max = value + if not is_inside_tree(): + return + + arriver.agent.linear_speed_max = value + + +func set_linear_acceleration_max(value: float) -> void: + linear_acceleration_max = value + if not is_inside_tree(): + return + + arriver.agent.linear_acceleration_max = value diff --git a/godot/Demos/Arrive3d/Seeker.gd b/godot/Demos/Arrive3d/Seeker.gd new file mode 100644 index 0000000..ad4be91 --- /dev/null +++ b/godot/Demos/Arrive3d/Seeker.gd @@ -0,0 +1,47 @@ +extends KinematicBody + +var target_node: Spatial + +onready var agent := GSAIKinematicBody3DAgent.new(self) +onready var target := GSAIAgentLocation.new() +onready var accel := GSAITargetAcceleration.new() +onready var blend := GSAIBlend.new(agent) +onready var face := GSAIFace.new(agent, target, true) +onready var arrive := GSAIArrive.new(agent, target) + + +func _physics_process(delta: float) -> void: + target.position = target_node.transform.origin + target.position.y = transform.origin.y + blend.calculate_steering(accel) + agent._apply_steering(accel, delta) + + +func setup( + align_tolerance: float, + angular_deceleration_radius: float, + angular_accel_max: float, + angular_speed_max: float, + deceleration_radius: float, + arrival_tolerance: float, + linear_acceleration_max: float, + linear_speed_max: float, + _target: Spatial +) -> void: + agent.linear_speed_max = linear_speed_max + agent.linear_acceleration_max = linear_acceleration_max + agent.linear_drag_percentage = 0.05 + agent.angular_acceleration_max = angular_accel_max + agent.angular_speed_max = angular_speed_max + agent.angular_drag_percentage = 0.1 + + arrive.arrival_tolerance = arrival_tolerance + arrive.deceleration_radius = deceleration_radius + + face.alignment_tolerance = align_tolerance + face.deceleration_radius = angular_deceleration_radius + + target_node = _target + self.target.position = target_node.transform.origin + blend.add(arrive, 1) + blend.add(face, 1) diff --git a/godot/Demos/Arrive3d/SeekerMat.tres b/godot/Demos/Arrive3d/SeekerMat.tres new file mode 100644 index 0000000..8a9f1f9 --- /dev/null +++ b/godot/Demos/Arrive3d/SeekerMat.tres @@ -0,0 +1,4 @@ +[gd_resource type="SpatialMaterial" format=2] + +[resource] +albedo_color = Color( 0.152941, 0.764706, 0.247059, 1 ) diff --git a/godot/Demos/AvoidCollisions/AvoidCollisionsDemo.gd b/godot/Demos/AvoidCollisions/AvoidCollisionsDemo.gd new file mode 100644 index 0000000..f82b2a1 --- /dev/null +++ b/godot/Demos/AvoidCollisions/AvoidCollisionsDemo.gd @@ -0,0 +1,40 @@ +extends Node + +export (float, 0, 1000, 40) var linear_speed_max := 350.0 setget set_linear_speed_max +export (float, 0, 4000, 2) var linear_acceleration_max := 40.0 setget set_linear_accel_max +export (float, 0, 500, 10) var proximity_radius := 140.0 setget set_proximity_radius +export var draw_proximity := true setget set_draw_proximity + +onready var spawner := $Spawner + + +func set_linear_speed_max(value: float) -> void: + linear_speed_max = value + if not is_inside_tree(): + return + + spawner.set_linear_speed_max(value) + + +func set_linear_accel_max(value: float) -> void: + linear_acceleration_max = value + if not is_inside_tree(): + return + + spawner.set_linear_accel_max(value) + + +func set_proximity_radius(value: float) -> void: + proximity_radius = value + if not is_inside_tree(): + return + + spawner.set_proximity_radius(value) + + +func set_draw_proximity(value: bool) -> void: + draw_proximity = value + if not is_inside_tree(): + return + + spawner.set_draw_proximity(value) diff --git a/godot/Demos/AvoidCollisions/AvoidCollisionsDemo.tscn b/godot/Demos/AvoidCollisions/AvoidCollisionsDemo.tscn new file mode 100644 index 0000000..8dfadb0 --- /dev/null +++ b/godot/Demos/AvoidCollisions/AvoidCollisionsDemo.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://Demos/AvoidCollisions/Spawner.gd" type="Script" id=1] +[ext_resource path="res://Demos/AvoidCollisions/AvoidCollisionsDemo.gd" type="Script" id=2] +[ext_resource path="res://Demos/AvoidCollisions/Avoider.tscn" type="PackedScene" id=3] +[ext_resource path="res://Demos/Utils/DemoInterface.tscn" type="PackedScene" id=4] +[ext_resource path="res://Demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5] + +[node name="AvoidCollisionsDemo" type="Node"] +script = ExtResource( 2 ) +linear_speed_max = 520.0 +linear_acceleration_max = 2250.0 +proximity_radius = 100.0 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )] + +[node name="Spawner" type="Node2D" parent="."] +script = ExtResource( 1 ) +avoider_template = ExtResource( 3 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +agent_count = 80 + +[node name="DemoInterface" parent="." instance=ExtResource( 4 )] +text_bbcode = "Avoid Collisions Demo +Watch each agent try to keep traveling in a particular direction, but prioritize avoiding collisions with other agents." diff --git a/godot/Demos/AvoidCollisions/AvoidCollisionsDemo.tscn.bak b/godot/Demos/AvoidCollisions/AvoidCollisionsDemo.tscn.bak new file mode 100644 index 0000000..5bf239e --- /dev/null +++ b/godot/Demos/AvoidCollisions/AvoidCollisionsDemo.tscn.bak @@ -0,0 +1,26 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://demos/AvoidCollisions/Spawner.gd" type="Script" id=1] +[ext_resource path="res://demos/AvoidCollisions/AvoidCollisionsDemo.gd" type="Script" id=2] +[ext_resource path="res://demos/AvoidCollisions/Avoider.tscn" type="PackedScene" id=3] +[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=4] +[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5] + +[node name="AvoidCollisionsDemo" type="Node"] +script = ExtResource( 2 ) +linear_speed_max = 520.0 +linear_acceleration_max = 2250.0 +proximity_radius = 100.0 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )] + +[node name="Spawner" type="Node2D" parent="."] +script = ExtResource( 1 ) +avoider_template = ExtResource( 3 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +agent_count = 80 + +[node name="DemoInterface" parent="." instance=ExtResource( 4 )] +text_bbcode = "Avoid Collisions Demo +Watch each agent try to keep traveling in a particular direction, but prioritize avoiding collisions with other agents." diff --git a/godot/Demos/AvoidCollisions/Avoider.gd b/godot/Demos/AvoidCollisions/Avoider.gd new file mode 100644 index 0000000..7fcfb17 --- /dev/null +++ b/godot/Demos/AvoidCollisions/Avoider.gd @@ -0,0 +1,91 @@ +extends KinematicBody2D + +var draw_proximity: bool + +var _boundary_right: float +var _boundary_bottom: float +var _radius: float +var _accel := GSAITargetAcceleration.new() +var _velocity := Vector2.ZERO +var _direction := Vector2() +var _drag := 0.1 +var _color := Color(0.4, 1.0, 0.89, 0.3) + +onready var collision := $CollisionShape2D +onready var agent := GSAIKinematicBody2DAgent.new(self) +onready var proximity := GSAIRadiusProximity.new(agent, [], 140) +onready var avoid := GSAIAvoidCollisions.new(agent, proximity) +onready var target := GSAIAgentLocation.new() +onready var seek := GSAISeek.new(agent, target) +onready var priority := GSAIPriority.new(agent, 0.0001) + + +func _draw() -> void: + if draw_proximity: + draw_circle(Vector2.ZERO, proximity.radius, _color) + + +func _physics_process(delta: float) -> void: + target.position.x = agent.position.x + _direction.x * _radius + target.position.y = agent.position.y + _direction.y * _radius + + priority.calculate_steering(_accel) + agent._apply_steering(_accel, delta) + + +func setup( + linear_speed_max: float, + linear_accel_max: float, + proximity_radius: float, + boundary_right: float, + boundary_bottom: float, + _draw_proximity: bool, + rng: RandomNumberGenerator +) -> void: + rng.randomize() + _direction = Vector2(rng.randf_range(-1, 1), rng.randf_range(-1, 1)).normalized() + + agent.linear_speed_max = linear_speed_max + agent.linear_acceleration_max = linear_accel_max + + proximity.radius = proximity_radius + _boundary_bottom = boundary_bottom + _boundary_right = boundary_right + + _radius = collision.shape.radius + agent.bounding_radius = _radius + + agent.linear_drag_percentage = _drag + + self.draw_proximity = _draw_proximity + + priority.add(avoid) + priority.add(seek) + + +func set_proximity_agents(agents: Array) -> void: + proximity.agents = agents + + +func set_random_nonoverlapping_position(others: Array, distance_from_boundary_min: float) -> void: + var rng := RandomNumberGenerator.new() + rng.randomize() + var tries_max := max(100, others.size() * others.size()) + while tries_max > 0: + tries_max -= 1 + global_position.x = rng.randf_range( + distance_from_boundary_min, _boundary_right - distance_from_boundary_min + ) + global_position.y = rng.randf_range( + distance_from_boundary_min, _boundary_bottom - distance_from_boundary_min + ) + var done := true + for i in range(others.size()): + var other: Node2D = others[i] + if ( + other.global_position.distance_to(position) + <= _radius * 2 + distance_from_boundary_min + ): + done = false + if done: + break diff --git a/godot/Demos/AvoidCollisions/Avoider.tscn b/godot/Demos/AvoidCollisions/Avoider.tscn new file mode 100644 index 0000000..97f32cc --- /dev/null +++ b/godot/Demos/AvoidCollisions/Avoider.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://Demos/Utils/CircleDraw.gd" type="Script" id=1] +[ext_resource path="res://Demos/AvoidCollisions/Avoider.gd" type="Script" id=2] + +[sub_resource type="CircleShape2D" id=1] +radius = 21.3503 + +[node name="Avoider" type="KinematicBody2D"] +script = ExtResource( 2 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) +script = ExtResource( 1 ) +inner_color = Color( 0.890196, 0.411765, 0.337255, 1 ) +outer_color = Color( 1, 0.709804, 0.439216, 1 ) +stroke = 5.0 diff --git a/godot/Demos/AvoidCollisions/Avoider.tscn.bak b/godot/Demos/AvoidCollisions/Avoider.tscn.bak new file mode 100644 index 0000000..044f107 --- /dev/null +++ b/godot/Demos/AvoidCollisions/Avoider.tscn.bak @@ -0,0 +1,17 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=1] +[ext_resource path="res://demos/AvoidCollisions/Avoider.gd" type="Script" id=2] + +[sub_resource type="CircleShape2D" id=1] +radius = 21.3503 + +[node name="Avoider" type="KinematicBody2D"] +script = ExtResource( 2 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) +script = ExtResource( 1 ) +inner_color = Color( 0.890196, 0.411765, 0.337255, 1 ) +outer_color = Color( 1, 0.709804, 0.439216, 1 ) +stroke = 5.0 diff --git a/godot/Demos/AvoidCollisions/Spawner.gd b/godot/Demos/AvoidCollisions/Spawner.gd new file mode 100644 index 0000000..fedb269 --- /dev/null +++ b/godot/Demos/AvoidCollisions/Spawner.gd @@ -0,0 +1,66 @@ +extends Node2D + +export var avoider_template: PackedScene +export var inner_color := Color() +export var outer_color := Color() +export var agent_count := 60 + +var boundaries: Vector2 + + +func _ready() -> void: + boundaries = Vector2( + ProjectSettings["display/window/size/width"], ProjectSettings["display/window/size/height"] + ) + var rng := RandomNumberGenerator.new() + var avoiders := [] + var avoider_agents := [] + for i in range(agent_count): + var avoider := avoider_template.instance() + add_child(avoider) + avoider.setup( + owner.linear_speed_max, + owner.linear_acceleration_max, + owner.proximity_radius, + boundaries.x, + boundaries.y, + true if i == 0 and owner.draw_proximity else false, + rng + ) + avoider_agents.append(avoider.agent) + avoider.set_random_nonoverlapping_position(avoiders, 16) + if i == 0: + avoider.collision.inner_color = inner_color + avoider.collision.outer_color = outer_color + avoiders.append(avoider) + if i % 10 == 0: + yield(get_tree(), "idle_frame") + for child in get_children(): + child.set_proximity_agents(avoider_agents) + + +func _physics_process(_delta: float) -> void: + for child in get_children(): + child.global_position = child.global_position.posmodv(boundaries) + + +func set_linear_speed_max(value: float) -> void: + for child in get_children(): + child.agent.linear_speed_max = value + + +func set_linear_accel_max(value: float) -> void: + for child in get_children(): + child.agent.linear_acceleration_max = value + + +func set_proximity_radius(value: float) -> void: + for child in get_children(): + child.proximity.radius = value + get_child(0).update() + + +func set_draw_proximity(value: bool) -> void: + var child := get_child(0) + child.draw_proximity = value + child.update() diff --git a/godot/Demos/DemoPickerUI.gd b/godot/Demos/DemoPickerUI.gd new file mode 100644 index 0000000..657d5cc --- /dev/null +++ b/godot/Demos/DemoPickerUI.gd @@ -0,0 +1,28 @@ +class_name DemoPickerUI +extends Control + +# warning-ignore:unused_signal +signal demo_requested + +var demo_path := "" setget set_demo_path + +onready var list: ItemList = $VBoxContainer/ItemList +onready var button: Button = $VBoxContainer/Button + + +func _ready() -> void: + # warning-ignore:return_value_discarded + list.connect("demo_selected", self, "set_demo_path") + # warning-ignore:return_value_discarded + list.connect("item_activated", self, "_on_ItemList_item_activated") + # warning-ignore:return_value_discarded + button.connect("pressed", self, "emit_signal", ["demo_requested"]) + demo_path = list.file_paths[0] + + +func set_demo_path(value: String) -> void: + demo_path = value + + +func _on_ItemList_item_activated(_index: int) -> void: + emit_signal("demo_requested") diff --git a/godot/Demos/DemoPlayer.gd b/godot/Demos/DemoPlayer.gd new file mode 100644 index 0000000..cfcfa9f --- /dev/null +++ b/godot/Demos/DemoPlayer.gd @@ -0,0 +1,16 @@ +extends Node2D + + +func load_demo(scene_path: String) -> void: + if not scene_path: + return + + var demo = load(scene_path) + if demo: + add_child(demo.instance()) + + +func unload() -> void: + for node in get_children(): + call_deferred("remove_child", node) + node.queue_free() diff --git a/godot/Demos/DemoSelector.tscn b/godot/Demos/DemoSelector.tscn new file mode 100644 index 0000000..12d8cf2 --- /dev/null +++ b/godot/Demos/DemoSelector.tscn @@ -0,0 +1,84 @@ +[gd_scene load_steps=7 format=2] + +[ext_resource path="res://Demos/PopulateItemList.gd" type="Script" id=1] +[ext_resource path="res://assets/theme/gdquest.theme" type="Theme" id=2] +[ext_resource path="res://assets/sprites/background.png" type="Texture" id=3] +[ext_resource path="res://Demos/DemoPickerUI.gd" type="Script" id=4] +[ext_resource path="res://Demos/DemoPlayer.gd" type="Script" id=5] +[ext_resource path="res://Demos/Demos.gd" type="Script" id=6] + +[node name="Demos" type="Node"] +script = ExtResource( 6 ) + +[node name="DemoPlayer" type="Node2D" parent="."] +script = ExtResource( 5 ) + +[node name="DemoPickerUI" type="Control" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +theme = ExtResource( 2 ) +script = ExtResource( 4 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="TextureRect" type="TextureRect" parent="DemoPickerUI"] +anchor_right = 1.0 +anchor_bottom = 1.0 +rect_min_size = Vector2( 1024, 600 ) +size_flags_horizontal = 3 +size_flags_vertical = 3 +texture = ExtResource( 3 ) +expand = true +stretch_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="DemoPickerUI"] +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -341.0 +margin_top = -290.0 +margin_right = 341.0 +margin_bottom = 290.0 +rect_min_size = Vector2( 682, 0 ) +size_flags_horizontal = 3 +size_flags_vertical = 3 +alignment = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ItemList" type="ItemList" parent="DemoPickerUI/VBoxContainer"] +margin_top = 231.0 +margin_right = 682.0 +margin_bottom = 240.0 +auto_height = true +script = ExtResource( 1 ) + +[node name="Button" type="Button" parent="DemoPickerUI/VBoxContainer"] +margin_left = 201.0 +margin_top = 248.0 +margin_right = 481.0 +margin_bottom = 348.0 +rect_min_size = Vector2( 280, 100 ) +size_flags_horizontal = 4 +size_flags_vertical = 13 +text = "Load scene" + +[node name="ButtonGoBack" type="Button" parent="."] +visible = false +anchor_top = 1.0 +anchor_bottom = 1.0 +margin_left = 48.0 +margin_top = -156.0 +margin_right = 328.0 +margin_bottom = -56.0 +rect_min_size = Vector2( 280, 100 ) +size_flags_horizontal = 4 +size_flags_vertical = 13 +theme = ExtResource( 2 ) +text = "Go back" +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/godot/Demos/Demos.gd b/godot/Demos/Demos.gd new file mode 100644 index 0000000..e8a9150 --- /dev/null +++ b/godot/Demos/Demos.gd @@ -0,0 +1,30 @@ +extends Node + +onready var demo_picker: DemoPickerUI = $DemoPickerUI +onready var demo_player := $DemoPlayer +onready var button_go_back: Button = $ButtonGoBack + + +func _ready() -> void: + # warning-ignore:return_value_discarded + demo_picker.connect("demo_requested", self, "_on_DemoPickerUI_demo_requested") + # warning-ignore:return_value_discarded + button_go_back.connect("pressed", self, "_on_ButtonGoBack_pressed") + + +func _input(event: InputEvent) -> void: + if event.is_action_pressed("toggle_fullscreen"): + OS.window_fullscreen = not OS.window_fullscreen + get_tree().set_input_as_handled() + + +func _on_DemoPickerUI_demo_requested() -> void: + demo_player.load_demo(demo_picker.demo_path) + demo_picker.hide() + button_go_back.show() + + +func _on_ButtonGoBack_pressed() -> void: + demo_player.unload() + button_go_back.hide() + demo_picker.show() diff --git a/godot/Demos/Face/FaceDemo.gd b/godot/Demos/Face/FaceDemo.gd new file mode 100644 index 0000000..282d941 --- /dev/null +++ b/godot/Demos/Face/FaceDemo.gd @@ -0,0 +1,61 @@ +extends Node + +export (int, 0, 1080, 2) var angular_speed_max := 120 setget set_angular_speed_max +export (int, 0, 2048, 2) var angular_accel_max := 10 setget set_angular_accel_max +export (int, 0, 180, 2) var align_tolerance := 5 setget set_align_tolerance +export (int, 0, 359, 2) var deceleration_radius := 45 setget set_deceleration_radius +export (float, 0, 1000, 40) var player_speed := 600.0 setget set_player_speed + +onready var player := $Player +onready var turret := $Turret + + +func _ready() -> void: + player.speed = player_speed + turret.setup( + player.agent, + deg2rad(align_tolerance), + deg2rad(deceleration_radius), + deg2rad(angular_accel_max), + deg2rad(angular_speed_max) + ) + + +func set_align_tolerance(value: int) -> void: + align_tolerance = value + if not is_inside_tree(): + return + + turret.face.alignment_tolerance = deg2rad(value) + + +func set_deceleration_radius(value: int) -> void: + deceleration_radius = value + if not is_inside_tree(): + return + + turret.face.deceleration_radius = deg2rad(value) + + +func set_angular_accel_max(value: int) -> void: + angular_accel_max = value + if not is_inside_tree(): + return + + turret.agent.angular_acceleration_max = deg2rad(value) + + +func set_angular_speed_max(value: int) -> void: + angular_speed_max = value + if not is_inside_tree(): + return + + turret.agent.angular_speed_max = deg2rad(value) + + +func set_player_speed(value: float) -> void: + player_speed = value + if not is_inside_tree(): + return + + player.speed = player_speed diff --git a/godot/Demos/Face/FaceDemo.tscn b/godot/Demos/Face/FaceDemo.tscn new file mode 100644 index 0000000..8115e44 --- /dev/null +++ b/godot/Demos/Face/FaceDemo.tscn @@ -0,0 +1,48 @@ +[gd_scene load_steps=9 format=2] + +[ext_resource path="res://Demos/Face/Turret.gd" type="Script" id=1] +[ext_resource path="res://Demos/Face/FaceDemo.gd" type="Script" id=2] +[ext_resource path="res://Demos/Face/Player.gd" type="Script" id=3] +[ext_resource path="res://Demos/Utils/DemoInterface.tscn" type="PackedScene" id=4] +[ext_resource path="res://Demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5] +[ext_resource path="res://Demos/Utils/CircleDraw.gd" type="Script" id=8] + +[sub_resource type="CircleShape2D" id=1] +radius = 20.2633 + +[sub_resource type="CircleShape2D" id=2] +radius = 37.1052 + +[node name="FaceDemo" type="Node"] +script = ExtResource( 2 ) +angular_speed_max = 662 +angular_accel_max = 924 +deceleration_radius = 136 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )] + +[node name="Player" type="KinematicBody2D" parent="."] +position = Vector2( 687.363, 351.005 ) +script = ExtResource( 3 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Player"] +shape = SubResource( 1 ) +script = ExtResource( 8 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +stroke = 6.0 + +[node name="Turret" type="KinematicBody2D" parent="."] +position = Vector2( 984.348, 571.959 ) +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Turret"] +shape = SubResource( 2 ) +script = ExtResource( 8 ) +inner_color = Color( 0.890196, 0.411765, 0.337255, 1 ) +outer_color = Color( 1, 0.709804, 0.439216, 1 ) +stroke = 8.0 + +[node name="DemoInterface" parent="." instance=ExtResource( 4 )] +text_bbcode = "Face Demo +Move the [color=lime]green player[/color] around with WASD and notice the [color=#ffb570]orange turret[/color] orient itself" diff --git a/godot/Demos/Face/FaceDemo.tscn.bak b/godot/Demos/Face/FaceDemo.tscn.bak new file mode 100644 index 0000000..348b293 --- /dev/null +++ b/godot/Demos/Face/FaceDemo.tscn.bak @@ -0,0 +1,48 @@ +[gd_scene load_steps=9 format=2] + +[ext_resource path="res://demos/Face/Turret.gd" type="Script" id=1] +[ext_resource path="res://demos/Face/FaceDemo.gd" type="Script" id=2] +[ext_resource path="res://demos/Face/Player.gd" type="Script" id=3] +[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=4] +[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5] +[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=8] + +[sub_resource type="CircleShape2D" id=1] +radius = 20.2633 + +[sub_resource type="CircleShape2D" id=2] +radius = 37.1052 + +[node name="FaceDemo" type="Node"] +script = ExtResource( 2 ) +angular_speed_max = 662 +angular_accel_max = 924 +deceleration_radius = 136 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )] + +[node name="Player" type="KinematicBody2D" parent="."] +position = Vector2( 687.363, 351.005 ) +script = ExtResource( 3 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Player"] +shape = SubResource( 1 ) +script = ExtResource( 8 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +stroke = 6.0 + +[node name="Turret" type="KinematicBody2D" parent="."] +position = Vector2( 984.348, 571.959 ) +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Turret"] +shape = SubResource( 2 ) +script = ExtResource( 8 ) +inner_color = Color( 0.890196, 0.411765, 0.337255, 1 ) +outer_color = Color( 1, 0.709804, 0.439216, 1 ) +stroke = 8.0 + +[node name="DemoInterface" parent="." instance=ExtResource( 4 )] +text_bbcode = "Face Demo +Move the [color=lime]green player[/color] around with WASD and notice the [color=#ffb570]orange turret[/color] orient itself" diff --git a/godot/Demos/Face/Player.gd b/godot/Demos/Face/Player.gd new file mode 100644 index 0000000..d37cc17 --- /dev/null +++ b/godot/Demos/Face/Player.gd @@ -0,0 +1,18 @@ +extends KinematicBody2D + +var speed: float + +onready var agent := GSAIAgentLocation.new() + + +func _physics_process(_delta: float) -> void: + var movement := _get_movement() + move_and_slide(movement * speed) + agent.position = Vector3(global_position.x, global_position.y, 0) + + +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") + ) diff --git a/godot/Demos/Face/Turret.gd b/godot/Demos/Face/Turret.gd new file mode 100644 index 0000000..1657316 --- /dev/null +++ b/godot/Demos/Face/Turret.gd @@ -0,0 +1,43 @@ +extends KinematicBody2D + +var face: GSAIFace +var agent := GSAIKinematicBody2DAgent.new(self) + +var _accel := GSAITargetAcceleration.new() +var _angular_drag := 0.1 +var _cannon: Rect2 +var _color: Color + +onready var collision_shape := $CollisionShape2D + + +func _ready() -> void: + var radius = collision_shape.shape.radius + _cannon = Rect2(Vector2(-5, 0), Vector2(10, -radius * 2)) + _color = collision_shape.outer_color + + +func _physics_process(delta: float) -> void: + face.calculate_steering(_accel) + agent._apply_steering(_accel, delta) + + +func _draw() -> void: + draw_rect(_cannon, _color) + + +func setup( + player_agent: GSAIAgentLocation, + align_tolerance: float, + deceleration_radius: float, + angular_accel_max: float, + angular_speed_max: float +) -> void: + face = GSAIFace.new(agent, player_agent) + + face.alignment_tolerance = align_tolerance + face.deceleration_radius = deceleration_radius + + agent.angular_acceleration_max = angular_accel_max + agent.angular_speed_max = angular_speed_max + agent.angular_drag_percentage = _angular_drag diff --git a/godot/Demos/FollowPath/Drawer.gd b/godot/Demos/FollowPath/Drawer.gd new file mode 100644 index 0000000..fcecf1d --- /dev/null +++ b/godot/Demos/FollowPath/Drawer.gd @@ -0,0 +1,53 @@ +extends Node2D + +signal path_established(points) + +var active_points := [] +var is_drawing := false +var distance_threshold := 100.0 + + +func _unhandled_input(event: InputEvent) -> void: + if event is InputEventMouseMotion: + if is_drawing: + active_points.append(event.position) + update() + elif event is InputEventMouseButton: + if event.pressed and event.button_index == BUTTON_LEFT: + active_points.clear() + active_points.append(event.position) + is_drawing = true + update() + elif not event.pressed: + is_drawing = false + if active_points.size() >= 2: + _simplify() + + +func _draw() -> void: + if is_drawing: + for point in active_points: + draw_circle(point, 2, Color.red) + else: + if active_points.size() > 0: + draw_circle(active_points.front(), 2, Color.red) + draw_circle(active_points.back(), 2, Color.yellow) + draw_polyline(active_points, Color.skyblue, 1.0) + + +func _simplify() -> void: + var first: Vector2 = active_points.front() + var last: Vector2 = active_points.back() + var key := first + var simplified_path := [first] + for i in range(1, active_points.size()): + var point: Vector2 = active_points[i] + var distance := point.distance_to(key) + if distance > distance_threshold: + key = point + simplified_path.append(key) + active_points = simplified_path + if active_points.back() != last: + active_points.append(last) + update() + emit_signal("path_established", active_points) diff --git a/godot/Demos/FollowPath/FollowPathDemo.gd b/godot/Demos/FollowPath/FollowPathDemo.gd new file mode 100644 index 0000000..cc26ce3 --- /dev/null +++ b/godot/Demos/FollowPath/FollowPathDemo.gd @@ -0,0 +1,70 @@ +extends Node + +export (float, 0, 2000, 40) var linear_speed_max := 600.0 setget set_linear_speed_max +export (float, 0, 9000, 10.0) var linear_acceleration_max := 40.0 setget set_linear_acceleration_max +export (float, 0, 100, 0.1) var arrival_tolerance := 10.0 setget set_arrival_tolerance +export (float, 0, 500, 10) var deceleration_radius := 100.0 setget set_deceleration_radius +export (float, 0, 5, 0.1) var predict_time := 0.3 setget set_predict_time +export (float, 0, 200, 10.0) var path_offset := 20.0 setget set_path_offset + +onready var drawer := $Drawer +onready var follower := $PathFollower + + +func _ready() -> void: + follower.setup( + path_offset, + predict_time, + linear_acceleration_max, + linear_speed_max, + deceleration_radius, + arrival_tolerance + ) + + +func set_linear_speed_max(value: float) -> void: + linear_speed_max = value + if not is_inside_tree(): + return + + follower.agent.linear_speed_max = value + + +func set_linear_acceleration_max(value: float) -> void: + linear_acceleration_max = value + if not is_inside_tree(): + return + + follower.agent.linear_acceleration_max = value + + +func set_arrival_tolerance(value: float) -> void: + arrival_tolerance = value + if not is_inside_tree(): + return + + follower.follow.arrival_tolerance = value + + +func set_deceleration_radius(value: float) -> void: + deceleration_radius = value + if not is_inside_tree(): + return + + follower.follow.deceleration_radius = value + + +func set_predict_time(value: float) -> void: + predict_time = value + if not is_inside_tree(): + return + + follower.follow.prediction_time = value + + +func set_path_offset(value: float) -> void: + path_offset = value + if not is_inside_tree(): + return + + follower.follow.path_offset = value diff --git a/godot/Demos/FollowPath/FollowPathDemo.tscn b/godot/Demos/FollowPath/FollowPathDemo.tscn new file mode 100644 index 0000000..9614780 --- /dev/null +++ b/godot/Demos/FollowPath/FollowPathDemo.tscn @@ -0,0 +1,37 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://Demos/FollowPath/Drawer.gd" type="Script" id=1] +[ext_resource path="res://Demos/Utils/DemoInterface.tscn" type="PackedScene" id=2] +[ext_resource path="res://Demos/FollowPath/PathFollower.gd" type="Script" id=3] +[ext_resource path="res://Demos/FollowPath/FollowPathDemo.gd" type="Script" id=4] +[ext_resource path="res://Demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5] +[ext_resource path="res://Demos/Utils/CircleDraw.gd" type="Script" id=6] + +[sub_resource type="CircleShape2D" id=1] +radius = 24.1954 + +[node name="FollowPathDemo" type="Node"] +script = ExtResource( 4 ) +linear_speed_max = 920.0 +linear_acceleration_max = 3740.0 +deceleration_radius = 200.0 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )] + +[node name="Drawer" type="Node2D" parent="."] +script = ExtResource( 1 ) + +[node name="PathFollower" type="KinematicBody2D" parent="."] +position = Vector2( 960, 540 ) +script = ExtResource( 3 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="PathFollower"] +shape = SubResource( 1 ) +script = ExtResource( 6 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +stroke = 6.0 + +[node name="DemoInterface" parent="." instance=ExtResource( 2 )] +text_bbcode = "Follow Path Demo +Use the mouse to draw a path on screen and watch the [color=lime]green \"Agent\"[/color] follow it to the end." diff --git a/godot/Demos/FollowPath/FollowPathDemo.tscn.bak b/godot/Demos/FollowPath/FollowPathDemo.tscn.bak new file mode 100644 index 0000000..3935b61 --- /dev/null +++ b/godot/Demos/FollowPath/FollowPathDemo.tscn.bak @@ -0,0 +1,37 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://demos/FollowPath/Drawer.gd" type="Script" id=1] +[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=2] +[ext_resource path="res://demos/FollowPath/PathFollower.gd" type="Script" id=3] +[ext_resource path="res://demos/FollowPath/FollowPathDemo.gd" type="Script" id=4] +[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5] +[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=6] + +[sub_resource type="CircleShape2D" id=1] +radius = 24.1954 + +[node name="FollowPathDemo" type="Node"] +script = ExtResource( 4 ) +linear_speed_max = 920.0 +linear_acceleration_max = 3740.0 +deceleration_radius = 200.0 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )] + +[node name="Drawer" type="Node2D" parent="."] +script = ExtResource( 1 ) + +[node name="PathFollower" type="KinematicBody2D" parent="."] +position = Vector2( 960, 540 ) +script = ExtResource( 3 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="PathFollower"] +shape = SubResource( 1 ) +script = ExtResource( 6 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +stroke = 6.0 + +[node name="DemoInterface" parent="." instance=ExtResource( 2 )] +text_bbcode = "Follow Path Demo +Use the mouse to draw a path on screen and watch the [color=lime]green \"Agent\"[/color] follow it to the end." diff --git a/godot/Demos/FollowPath/PathFollower.gd b/godot/Demos/FollowPath/PathFollower.gd new file mode 100644 index 0000000..4429248 --- /dev/null +++ b/godot/Demos/FollowPath/PathFollower.gd @@ -0,0 +1,49 @@ +extends KinematicBody2D + +var _velocity := Vector2.ZERO +var _accel := GSAITargetAcceleration.new() +var _valid := false +var _drag := 0.1 + +onready var agent := GSAIKinematicBody2DAgent.new(self) +onready var path := GSAIPath.new( + [ + Vector3(global_position.x, global_position.y, 0), + Vector3(global_position.x, global_position.y, 0) + ], + true +) +onready var follow := GSAIFollowPath.new(agent, path, 0, 0) + + +func setup( + path_offset: float, + predict_time: float, + accel_max: float, + speed_max: float, + decel_radius: float, + arrival_tolerance: float +) -> void: + owner.drawer.connect("path_established", self, "_on_Drawer_path_established") + follow.path_offset = path_offset + follow.prediction_time = predict_time + follow.deceleration_radius = decel_radius + follow.arrival_tolerance = arrival_tolerance + + agent.linear_acceleration_max = accel_max + agent.linear_speed_max = speed_max + agent.linear_drag_percentage = _drag + + +func _physics_process(delta: float) -> void: + if _valid: + follow.calculate_steering(_accel) + agent._apply_steering(_accel, delta) + + +func _on_Drawer_path_established(points: Array) -> void: + var positions := PoolVector3Array() + for p in points: + positions.append(Vector3(p.x, p.y, 0)) + path.create_path(positions) + _valid = true diff --git a/godot/Demos/GroupBehaviors/GroupBehaviorsDemo.gd b/godot/Demos/GroupBehaviors/GroupBehaviorsDemo.gd new file mode 100644 index 0000000..51ab7ea --- /dev/null +++ b/godot/Demos/GroupBehaviors/GroupBehaviorsDemo.gd @@ -0,0 +1,79 @@ +extends Node + +onready var spawner := $Spawner + +export (float, 0, 2000, 40.0) var linear_speed_max := 600.0 setget set_linear_speed_max +export (float, 0, 9000, 2.0) var linear_accel_max := 40.0 setget set_linear_accel_max +export (float, 0, 300, 2.0) var proximity_radius := 140.0 setget set_proximity_radius +export (float, 0, 200000, 250) var separation_decay_coefficient := 2000.0 setget set_separation_decay_coef +export (float, 0, 2, 0.1) var cohesion_strength := 0.1 setget set_cohesion_strength +export (float, 0, 10, 0.2) var separation_strength := 1.5 setget set_separation_strength +export var show_proximity_radius := true setget set_show_proximity_radius + + +func _ready() -> void: + spawner.setup( + linear_speed_max, + linear_accel_max, + proximity_radius, + separation_decay_coefficient, + cohesion_strength, + separation_strength, + show_proximity_radius + ) + + +func set_linear_speed_max(value: float) -> void: + linear_speed_max = value + if not is_inside_tree(): + return + + spawner.set_linear_speed_max(value) + + +func set_linear_accel_max(value: float) -> void: + linear_accel_max = value + if not is_inside_tree(): + return + + spawner.set_linear_accel_max(value) + + +func set_proximity_radius(value: float) -> void: + proximity_radius = value + if not is_inside_tree(): + return + + spawner.set_proximity_radius(value) + + +func set_show_proximity_radius(value: bool) -> void: + show_proximity_radius = value + if not is_inside_tree(): + return + + spawner.set_show_proximity_radius(value) + + +func set_separation_decay_coef(value: float) -> void: + separation_decay_coefficient = value + if not is_inside_tree(): + return + + spawner.set_separation_decay_coef(value) + + +func set_cohesion_strength(value: float) -> void: + cohesion_strength = value + if not is_inside_tree(): + return + + spawner.set_cohesion_strength(value) + + +func set_separation_strength(value: float) -> void: + separation_strength = value + if not is_inside_tree(): + return + + spawner.set_separation_strength(value) diff --git a/godot/Demos/GroupBehaviors/GroupBehaviorsDemo.tscn b/godot/Demos/GroupBehaviors/GroupBehaviorsDemo.tscn new file mode 100644 index 0000000..2f27d9a --- /dev/null +++ b/godot/Demos/GroupBehaviors/GroupBehaviorsDemo.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://Demos/GroupBehaviors/Member.tscn" type="PackedScene" id=1] +[ext_resource path="res://Demos/GroupBehaviors/Spawner.gd" type="Script" id=2] +[ext_resource path="res://Demos/GroupBehaviors/GroupBehaviorsDemo.gd" type="Script" id=3] +[ext_resource path="res://Demos/Utils/DemoInterface.tscn" type="PackedScene" id=4] +[ext_resource path="res://Demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5] + +[node name="GroupBehaviorsDemo" type="Node"] +script = ExtResource( 3 ) +linear_accel_max = 4234.0 +proximity_radius = 158.0 +separation_decay_coefficient = 121500.0 +cohesion_strength = 0.2 +separation_strength = 8.8 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )] + +[node name="Spawner" type="Node2D" parent="."] +position = Vector2( 512, 300 ) +script = ExtResource( 2 ) +member = ExtResource( 1 ) + +[node name="DemoInterface" parent="." instance=ExtResource( 4 )] +text_bbcode = "Group Behavior Demo +Each of the \"Agents\" are both attempting to stay separated from each other but within reach of their nearest group's center of mass." diff --git a/godot/Demos/GroupBehaviors/GroupBehaviorsDemo.tscn.bak b/godot/Demos/GroupBehaviors/GroupBehaviorsDemo.tscn.bak new file mode 100644 index 0000000..b288389 --- /dev/null +++ b/godot/Demos/GroupBehaviors/GroupBehaviorsDemo.tscn.bak @@ -0,0 +1,26 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://demos/GroupBehaviors/Member.tscn" type="PackedScene" id=1] +[ext_resource path="res://demos/GroupBehaviors/Spawner.gd" type="Script" id=2] +[ext_resource path="res://demos/GroupBehaviors/GroupBehaviorsDemo.gd" type="Script" id=3] +[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=4] +[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5] + +[node name="GroupBehaviorsDemo" type="Node"] +script = ExtResource( 3 ) +linear_accel_max = 4234.0 +proximity_radius = 158.0 +separation_decay_coefficient = 121500.0 +cohesion_strength = 0.2 +separation_strength = 8.8 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )] + +[node name="Spawner" type="Node2D" parent="."] +position = Vector2( 512, 300 ) +script = ExtResource( 2 ) +member = ExtResource( 1 ) + +[node name="DemoInterface" parent="." instance=ExtResource( 4 )] +text_bbcode = "Group Behavior Demo +Each of the \"Agents\" are both attempting to stay separated from each other but within reach of their nearest group's center of mass." diff --git a/godot/Demos/GroupBehaviors/Member.gd b/godot/Demos/GroupBehaviors/Member.gd new file mode 100644 index 0000000..e068884 --- /dev/null +++ b/godot/Demos/GroupBehaviors/Member.gd @@ -0,0 +1,52 @@ +extends KinematicBody2D + +var separation: GSAISeparation +var cohesion: GSAICohesion +var proximity: GSAIRadiusProximity +var agent := GSAIKinematicBody2DAgent.new(self) +var blend := GSAIBlend.new(agent) +var acceleration := GSAITargetAcceleration.new() +var draw_proximity := false + +var _color := Color.red +var _velocity := Vector2() + +onready var collision_shape := $CollisionShape2D + + +func setup( + linear_speed_max: float, + linear_accel_max: float, + proximity_radius: float, + separation_decay_coefficient: float, + cohesion_strength: float, + separation_strength: float +) -> void: + _color = Color(rand_range(0.5, 1), rand_range(0.25, 1), rand_range(0, 1)) + collision_shape.inner_color = _color + + agent.linear_acceleration_max = linear_accel_max + agent.linear_speed_max = linear_speed_max + agent.linear_drag_percentage = 0.1 + + proximity = GSAIRadiusProximity.new(agent, [], proximity_radius) + separation = GSAISeparation.new(agent, proximity) + separation.decay_coefficient = separation_decay_coefficient + cohesion = GSAICohesion.new(agent, proximity) + blend.add(separation, separation_strength) + blend.add(cohesion, cohesion_strength) + + +func _draw() -> void: + if draw_proximity: + draw_circle(Vector2.ZERO, proximity.radius, Color(0.4, 1.0, 0.89, 0.3)) + + +func _physics_process(delta: float) -> void: + if blend: + blend.calculate_steering(acceleration) + agent._apply_steering(acceleration, delta) + + +func set_neighbors(neighbor: Array) -> void: + proximity.agents = neighbor diff --git a/godot/Demos/GroupBehaviors/Member.tscn b/godot/Demos/GroupBehaviors/Member.tscn new file mode 100644 index 0000000..63207e1 --- /dev/null +++ b/godot/Demos/GroupBehaviors/Member.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://Demos/GroupBehaviors/Member.gd" type="Script" id=1] +[ext_resource path="res://Demos/Utils/CircleDraw.gd" type="Script" id=3] + +[sub_resource type="CircleShape2D" id=1] +radius = 16.0 + +[node name="Member" type="KinematicBody2D"] +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) +script = ExtResource( 3 ) +outer_color = Color( 0.301961, 0.65098, 1, 1 ) +stroke = 4.0 diff --git a/godot/Demos/GroupBehaviors/Member.tscn.bak b/godot/Demos/GroupBehaviors/Member.tscn.bak new file mode 100644 index 0000000..0baef77 --- /dev/null +++ b/godot/Demos/GroupBehaviors/Member.tscn.bak @@ -0,0 +1,16 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://demos/GroupBehaviors/Member.gd" type="Script" id=1] +[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=3] + +[sub_resource type="CircleShape2D" id=1] +radius = 16.0 + +[node name="Member" type="KinematicBody2D"] +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) +script = ExtResource( 3 ) +outer_color = Color( 0.301961, 0.65098, 1, 1 ) +stroke = 4.0 diff --git a/godot/Demos/GroupBehaviors/Spawner.gd b/godot/Demos/GroupBehaviors/Spawner.gd new file mode 100644 index 0000000..d4b7193 --- /dev/null +++ b/godot/Demos/GroupBehaviors/Spawner.gd @@ -0,0 +1,73 @@ +extends Node2D + +export var member: PackedScene + + +func setup( + linear_speed_max: float, + linear_accel_max: float, + proximity_radius: float, + separation_decay_coefficient: float, + cohesion_strength: float, + separation_strength: float, + show_proximity_radius: bool +) -> void: + var followers := [] + for i in range(19): + var follower := member.instance() + add_child(follower) + follower.position += Vector2(rand_range(-60, 60), rand_range(-60, 60)) + followers.append(follower) + follower.setup( + linear_speed_max, + linear_accel_max, + proximity_radius, + separation_decay_coefficient, + cohesion_strength, + separation_strength + ) + if i == 0 and show_proximity_radius: + follower.draw_proximity = true + follower.update() + var agents := [] + for i in followers: + agents.append(i.agent) + for i in followers: + i.proximity.agents = agents + + +func set_linear_speed_max(value: float) -> void: + for child in get_children(): + child.agent.linear_speed_max = value + + +func set_linear_accel_max(value: float) -> void: + for child in get_children(): + child.agent.linear_acceleration_max = value + + +func set_proximity_radius(value: float) -> void: + for child in get_children(): + child.proximity.radius = value + if child == get_child(0): + child.update() + + +func set_show_proximity_radius(value: bool) -> void: + get_child(0).draw_proximity = value + get_child(0).update() + + +func set_separation_decay_coef(value: float) -> void: + for child in get_children(): + child.separation.decay_coefficient = value + + +func set_cohesion_strength(value: float) -> void: + for child in get_children(): + child.blend.get_behavior_at(1).weight = value + + +func set_separation_strength(value: float) -> void: + for child in get_children(): + child.blend.get_behavior_at(0).weight = value diff --git a/godot/Demos/PopulateItemList.gd b/godot/Demos/PopulateItemList.gd new file mode 100644 index 0000000..cd1bf6e --- /dev/null +++ b/godot/Demos/PopulateItemList.gd @@ -0,0 +1,68 @@ +extends ItemList + +signal demo_selected(scene_path) + +var file_paths := PoolStringArray() + + +func _ready() -> void: + # warning-ignore:return_value_discarded + self.connect("item_selected", self, "_on_item_selected") + + var this_directory: String = get_tree().current_scene.filename.rsplit("/", false, 1)[0] + file_paths = _find_files(this_directory, ["*Demo.tscn"], true) + populate(file_paths) + select(0) + + +func populate(demos: PoolStringArray) -> void: + for path in demos: + var demo_name: String = path.rsplit("/", true, 1)[-1] + demo_name = demo_name.rsplit("Demo", true, 1)[0] + demo_name = sentencify(demo_name) + add_item(demo_name) + + +func sentencify(line: String) -> String: + var regex := RegEx.new() + # warning-ignore:return_value_discarded + regex.compile("[A-Z]") + + line = line.split(".", true, 1)[0] + line = regex.sub(line, " $0", true) + return line + + +func _find_files( + dirpath := "", patterns := PoolStringArray(), is_recursive := false, do_skip_hidden := true +) -> PoolStringArray: + var paths := PoolStringArray() + var directory := Directory.new() + + if not directory.dir_exists(dirpath): + printerr("The directory does not exist: %s" % dirpath) + return paths + if not directory.open(dirpath) == OK: + printerr("Could not open the following dirpath: %s" % dirpath) + return paths + + # warning-ignore:return_value_discarded + directory.list_dir_begin(true, do_skip_hidden) + var file_name := directory.get_next() + while file_name != "": + if directory.current_is_dir() and is_recursive: + var subdirectory := dirpath.plus_file(file_name) + paths.append_array(_find_files(subdirectory, patterns, is_recursive)) + else: + for pattern in patterns: + if file_name.match(pattern): + paths.append(dirpath.plus_file(file_name)) + file_name = directory.get_next() + + directory.list_dir_end() + return paths + + +func _on_item_selected(index: int) -> void: + var demo_path := file_paths[index] + emit_signal("demo_selected", demo_path) diff --git a/godot/Demos/PursueSeek/BoundaryManager.gd b/godot/Demos/PursueSeek/BoundaryManager.gd new file mode 100644 index 0000000..a5062cb --- /dev/null +++ b/godot/Demos/PursueSeek/BoundaryManager.gd @@ -0,0 +1,15 @@ +extends Node2D +# Wraps the ships' positions around the world border. + +var _world_bounds: Vector2 + + +func _ready() -> void: + _world_bounds = Vector2( + ProjectSettings["display/window/size/width"], ProjectSettings["display/window/size/height"] + ) + + +func _physics_process(_delta: float) -> void: + for ship in get_children(): + ship.position = ship.position.posmodv(_world_bounds) diff --git a/godot/Demos/PursueSeek/Player.gd b/godot/Demos/PursueSeek/Player.gd new file mode 100644 index 0000000..8bc3588 --- /dev/null +++ b/godot/Demos/PursueSeek/Player.gd @@ -0,0 +1,96 @@ +extends KinematicBody2D +# Controls the player ship's movements based on player input. + +export var thruster_strength := 175.0 +export var side_thruster_strength := 10.0 +export var velocity_max := 300.0 +export var angular_velocity_max := 2.0 +export var angular_drag := 0.025 +export var linear_drag := 0.025 + +var _linear_velocity := Vector2() +var _angular_velocity := 0.0 + +onready var agent := GSAISteeringAgent.new() + + +func _physics_process(delta: float) -> void: + var movement := _get_movement() + _angular_velocity = _calculate_angular_velocity( + movement.x, + _angular_velocity, + side_thruster_strength, + angular_velocity_max, + angular_drag, + delta + ) + rotation += _angular_velocity * delta + + _linear_velocity = _calculate_linear_velocity( + movement.y, + _linear_velocity, + Vector2.UP.rotated(rotation), + linear_drag, + thruster_strength, + velocity_max, + delta + ) + + _linear_velocity = move_and_slide(_linear_velocity) + _update_agent() + + +func _calculate_angular_velocity( + horizontal_movement: float, + current_velocity: float, + _thruster_strength: float, + _velocity_max: float, + ship_drag: float, + delta: float +) -> float: + var velocity := clamp( + current_velocity + _thruster_strength * horizontal_movement * delta, + -_velocity_max, + _velocity_max + ) + + velocity = lerp(velocity, 0, ship_drag) + + return velocity + + +func _calculate_linear_velocity( + vertical_movement: float, + current_velocity: Vector2, + facing_direction: Vector2, + ship_drag_coefficient: float, + strength: float, + speed_max: float, + delta: float +) -> Vector2: + var actual_strength := 0.0 + if vertical_movement > 0: + actual_strength = strength + elif vertical_movement < 0: + actual_strength = -strength / 1.5 + + var velocity := current_velocity + facing_direction * actual_strength * delta + velocity = velocity.linear_interpolate(Vector2.ZERO, ship_drag_coefficient) + + return velocity.clamped(speed_max) + + +func _get_movement() -> Vector2: + return Vector2( + Input.get_action_strength("sf_right") - Input.get_action_strength("sf_left"), + Input.get_action_strength("sf_up") - Input.get_action_strength("sf_down") + ) + + +func _update_agent() -> void: + agent.position.x = global_position.x + agent.position.y = global_position.y + agent.linear_velocity.x = _linear_velocity.x + agent.linear_velocity.y = _linear_velocity.y + agent.angular_velocity = _angular_velocity + agent.orientation = rotation diff --git a/godot/Demos/PursueSeek/PursueAndSeekDemo.gd b/godot/Demos/PursueSeek/PursueAndSeekDemo.gd new file mode 100644 index 0000000..e888235 --- /dev/null +++ b/godot/Demos/PursueSeek/PursueAndSeekDemo.gd @@ -0,0 +1,39 @@ +extends Node + +export (float, 0, 2000, 40) var linear_speed_max := 120.0 setget set_linear_speed_max +export (float, 0, 2000, 20) var linear_accel_max := 10.0 setget set_linear_accel_max +export (float, 0, 5, 0.1) var predict_time := 1.0 setget set_predict_time + +onready var pursuer := $BoundaryManager/Pursuer +onready var seeker := $BoundaryManager/Seeker + + +func _ready() -> void: + pursuer.setup(predict_time, linear_speed_max, linear_accel_max) + seeker.setup(predict_time, linear_speed_max, linear_accel_max) + + +func set_linear_speed_max(value: float) -> void: + linear_speed_max = value + if not is_inside_tree(): + return + + pursuer.agent.linear_speed_max = value + seeker.agent.linear_speed_max = value + + +func set_linear_accel_max(value: float) -> void: + linear_accel_max = value + if not is_inside_tree(): + return + + pursuer.agent.linear_acceleration_max = value + seeker.agent.linear_acceleration_max = value + + +func set_predict_time(value: float) -> void: + predict_time = value + if not is_inside_tree(): + return + + pursuer._behavior.predict_time_max = value diff --git a/godot/Demos/PursueSeek/PursueAndSeekDemo.tscn b/godot/Demos/PursueSeek/PursueAndSeekDemo.tscn new file mode 100644 index 0000000..2196f05 --- /dev/null +++ b/godot/Demos/PursueSeek/PursueAndSeekDemo.tscn @@ -0,0 +1,92 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://Demos/PursueSeek/Pursuer.gd" type="Script" id=1] +[ext_resource path="res://Demos/PursueSeek/Player.gd" type="Script" id=2] +[ext_resource path="res://Demos/PursueSeek/BoundaryManager.gd" type="Script" id=3] +[ext_resource path="res://Demos/PursueSeek/PursueAndSeekDemo.gd" type="Script" id=4] +[ext_resource path="res://Demos/Utils/DemoInterface.tscn" type="PackedScene" id=5] +[ext_resource path="res://Demos/Utils/Line2DDraw.gd" type="Script" id=6] +[ext_resource path="res://Demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=7] + +[node name="PursueVSSeekDemo" type="Node"] +script = ExtResource( 4 ) +linear_speed_max = 1280.0 +linear_accel_max = 1040.0 +predict_time = 1.1 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 7 )] + +[node name="BoundaryManager" type="Node2D" parent="."] +script = ExtResource( 3 ) + +[node name="Player" type="KinematicBody2D" parent="BoundaryManager"] +position = Vector2( 307.552, 555.999 ) +rotation = 1.5708 +collision_mask = 2 +script = ExtResource( 2 ) +__meta__ = { +"_edit_group_": true +} +thruster_strength = 1000.0 +side_thruster_strength = 40.0 +velocity_max = 450.0 +angular_velocity_max = 3.0 + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="BoundaryManager/Player"] +polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 ) + +[node name="Line2D" type="Line2D" parent="BoundaryManager/Player"] +points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 ) +width = 8.0 +default_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +joint_mode = 2 +antialiased = true +script = ExtResource( 6 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) + +[node name="Pursuer" type="KinematicBody2D" parent="BoundaryManager"] +position = Vector2( 1240.22, 866.784 ) +collision_layer = 2 +script = ExtResource( 1 ) +__meta__ = { +"_edit_group_": true +} + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="BoundaryManager/Pursuer"] +polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 ) + +[node name="Line2D" type="Line2D" parent="BoundaryManager/Pursuer"] +points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 ) +width = 8.0 +default_color = Color( 1, 0.709804, 0.439216, 1 ) +joint_mode = 2 +antialiased = true +script = ExtResource( 6 ) +inner_color = Color( 0.890196, 0.411765, 0.337255, 1 ) + +[node name="Seeker" type="KinematicBody2D" parent="BoundaryManager"] +position = Vector2( 1240.22, 280.108 ) +rotation = 3.14159 +collision_layer = 2 +script = ExtResource( 1 ) +__meta__ = { +"_edit_group_": true +} +use_seek = true + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="BoundaryManager/Seeker"] +polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 ) + +[node name="Line2D" type="Line2D" parent="BoundaryManager/Seeker"] +points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 ) +width = 8.0 +default_color = Color( 0.301961, 0.65098, 1, 1 ) +joint_mode = 2 +antialiased = true +script = ExtResource( 6 ) +inner_color = Color( 0.294118, 0.356863, 0.670588, 1 ) + +[node name="DemoInterface" parent="." instance=ExtResource( 5 )] +text_bbcode = "Pursue vs. Seek Demo +Move the player around with WASD and notice the [color=#ffb570]orange Pursuer[/color] and the [color=aqua]blue Seeker[/color] follow +the [color=lime]green \"Ship\"[/color] around" diff --git a/godot/Demos/PursueSeek/PursueAndSeekDemo.tscn.bak b/godot/Demos/PursueSeek/PursueAndSeekDemo.tscn.bak new file mode 100644 index 0000000..f7417cc --- /dev/null +++ b/godot/Demos/PursueSeek/PursueAndSeekDemo.tscn.bak @@ -0,0 +1,92 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://demos/PursueSeek/Pursuer.gd" type="Script" id=1] +[ext_resource path="res://demos/PursueSeek/Player.gd" type="Script" id=2] +[ext_resource path="res://demos/PursueSeek/BoundaryManager.gd" type="Script" id=3] +[ext_resource path="res://demos/PursueSeek/PursueAndSeekDemo.gd" type="Script" id=4] +[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=5] +[ext_resource path="res://demos/Utils/Line2DDraw.gd" type="Script" id=6] +[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=7] + +[node name="PursueVSSeekDemo" type="Node"] +script = ExtResource( 4 ) +linear_speed_max = 1280.0 +linear_accel_max = 1040.0 +predict_time = 1.1 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 7 )] + +[node name="BoundaryManager" type="Node2D" parent="."] +script = ExtResource( 3 ) + +[node name="Player" type="KinematicBody2D" parent="BoundaryManager"] +position = Vector2( 307.552, 555.999 ) +rotation = 1.5708 +collision_mask = 2 +script = ExtResource( 2 ) +__meta__ = { +"_edit_group_": true +} +thruster_strength = 1000.0 +side_thruster_strength = 40.0 +velocity_max = 450.0 +angular_velocity_max = 3.0 + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="BoundaryManager/Player"] +polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 ) + +[node name="Line2D" type="Line2D" parent="BoundaryManager/Player"] +points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 ) +width = 8.0 +default_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +joint_mode = 2 +antialiased = true +script = ExtResource( 6 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) + +[node name="Pursuer" type="KinematicBody2D" parent="BoundaryManager"] +position = Vector2( 1240.22, 866.784 ) +collision_layer = 2 +script = ExtResource( 1 ) +__meta__ = { +"_edit_group_": true +} + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="BoundaryManager/Pursuer"] +polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 ) + +[node name="Line2D" type="Line2D" parent="BoundaryManager/Pursuer"] +points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 ) +width = 8.0 +default_color = Color( 1, 0.709804, 0.439216, 1 ) +joint_mode = 2 +antialiased = true +script = ExtResource( 6 ) +inner_color = Color( 0.890196, 0.411765, 0.337255, 1 ) + +[node name="Seeker" type="KinematicBody2D" parent="BoundaryManager"] +position = Vector2( 1240.22, 280.108 ) +rotation = 3.14159 +collision_layer = 2 +script = ExtResource( 1 ) +__meta__ = { +"_edit_group_": true +} +use_seek = true + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="BoundaryManager/Seeker"] +polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 ) + +[node name="Line2D" type="Line2D" parent="BoundaryManager/Seeker"] +points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 ) +width = 8.0 +default_color = Color( 0.301961, 0.65098, 1, 1 ) +joint_mode = 2 +antialiased = true +script = ExtResource( 6 ) +inner_color = Color( 0.294118, 0.356863, 0.670588, 1 ) + +[node name="DemoInterface" parent="." instance=ExtResource( 5 )] +text_bbcode = "Pursue vs. Seek Demo +Move the player around with WASD and notice the [color=#ffb570]orange Pursuer[/color] and the [color=aqua]blue Seeker[/color] follow +the [color=lime]green \"Ship\"[/color] around" diff --git a/godot/Demos/PursueSeek/Pursuer.gd b/godot/Demos/PursueSeek/Pursuer.gd new file mode 100644 index 0000000..04ebdf6 --- /dev/null +++ b/godot/Demos/PursueSeek/Pursuer.gd @@ -0,0 +1,65 @@ +extends KinematicBody2D +# Represents a ship that chases after the player. + +export var use_seek: bool = false + +var _blend: GSAIBlend + +var _linear_drag_coefficient := 0.025 +var _angular_drag := 0.1 +var _direction_face := GSAIAgentLocation.new() + +onready var agent := GSAIKinematicBody2DAgent.new(self) +onready var accel := GSAITargetAcceleration.new() +onready var player_agent: GSAISteeringAgent = owner.find_node("Player", true, false).agent + + +func _ready() -> void: + agent.calculate_velocities = false + set_physics_process(false) + + +func _physics_process(delta: float) -> void: + _direction_face.position = agent.position + accel.linear.normalized() + + _blend.calculate_steering(accel) + + agent.angular_velocity = clamp( + agent.angular_velocity + accel.angular * delta, -agent.angular_speed_max, agent.angular_speed_max + ) + agent.angular_velocity = lerp(agent.angular_velocity, 0, _angular_drag) + + rotation += agent.angular_velocity * delta + + var linear_velocity := ( + GSAIUtils.to_vector2(agent.linear_velocity) + + (GSAIUtils.angle_to_vector2(rotation) * -agent.linear_acceleration_max * delta) + ) + linear_velocity = linear_velocity.clamped(agent.linear_speed_max) + linear_velocity = linear_velocity.linear_interpolate(Vector2.ZERO, _linear_drag_coefficient) + + linear_velocity = move_and_slide(linear_velocity) + agent.linear_velocity = GSAIUtils.to_vector3(linear_velocity) + + +func setup(predict_time: float, linear_speed_max: float, linear_accel_max: float) -> void: + var behavior: GSAISteeringBehavior + if use_seek: + behavior = GSAISeek.new(agent, player_agent) + else: + behavior = GSAIPursue.new(agent, player_agent, predict_time) + + var orient_behavior := GSAIFace.new(agent, _direction_face) + orient_behavior.alignment_tolerance = deg2rad(5) + orient_behavior.deceleration_radius = deg2rad(30) + + _blend = GSAIBlend.new(agent) + _blend.add(behavior, 1) + _blend.add(orient_behavior, 1) + + agent.angular_acceleration_max = deg2rad(1080) + agent.angular_speed_max = deg2rad(360) + agent.linear_acceleration_max = linear_accel_max + agent.linear_speed_max = linear_speed_max + + set_physics_process(true) diff --git a/godot/Demos/Quickstart/Agent.gd b/godot/Demos/Quickstart/Agent.gd new file mode 100644 index 0000000..5c90316 --- /dev/null +++ b/godot/Demos/Quickstart/Agent.gd @@ -0,0 +1,167 @@ +extends KinematicBody2D + +# Maximum possible linear velocity +export var speed_max := 450.0 +# Maximum change in linear velocity +export var acceleration_max := 50.0 +# Maximum rotation velocity represented in degrees +export var angular_speed_max := 240 +# Maximum change in rotation velocity represented in degrees +export var angular_acceleration_max := 40 + +export var health_max := 100 +export var flee_health_threshold := 20 + +var velocity := Vector2.ZERO +var angular_velocity := 0.0 +var linear_drag := 0.1 +var angular_drag := 0.1 + +# Holds the linear and angular components calculated by our steering behaviors. +var acceleration := GSAITargetAcceleration.new() + +onready var current_health := health_max + +# GSAISteeringAgent holds our agent's position, orientation, maximum speed and acceleration. +onready var agent := GSAISteeringAgent.new() + +onready var player: Node = get_tree().get_nodes_in_group("Player")[0] +# This assumes that our player class will keep its own agent updated. +onready var player_agent: GSAISteeringAgent = player.agent + +# Proximities represent an area with which an agent can identify where neighbors in its relevant +# group are. In our case, the group will feature the player, which will be used to avoid a +# collision with them. We use a radius proximity so the player is only relevant inside 100 pixels. +onready var proximity := GSAIRadiusProximity.new(agent, [player_agent], 100) + +# GSAIBlend combines behaviors together, calculating all of their acceleration together and adding +# them together, multiplied by a strength. We will have one for fleeing, and one for pursuing, +# toggling them depending on the agent's health. Since we want the agent to rotate AND move, then +# we aim to blend them together. +onready var flee_blend := GSAIBlend.new(agent) +onready var pursue_blend := GSAIBlend.new(agent) + +# GSAIPriority will be the main steering behavior we use. It holds sub-behaviors and will pick the +# first one that returns non-zero acceleration, ignoring any afterwards. +onready var priority := GSAIPriority.new(agent) + + +func _ready() -> void: + # ---------- Configuration for our agent ---------- + agent.linear_speed_max = speed_max + agent.linear_acceleration_max = acceleration_max + agent.angular_speed_max = deg2rad(angular_speed_max) + agent.angular_acceleration_max = deg2rad(angular_acceleration_max) + agent.bounding_radius = calculate_radius($CollisionPolygon2D.polygon) + update_agent() + + # ---------- Configuration for our behaviors ---------- + # Pursue will happen while the agent is in good health. It produces acceleration that takes + # the agent on an intercept course with the target, predicting its position in the future. + var pursue := GSAIPursue.new(agent, player_agent) + pursue.predict_time_max = 1.5 + + # Flee will happen while the agent is in bad health, so will start disabled. It produces + # acceleration that takes the agent directly away from the target with no prediction. + var flee := GSAIFlee.new(agent, player_agent) + + # AvoidCollision tries to keep the agent from running into any of the neighbors found in its + # proximity group. In our case, this will be the player, if they are close enough. + var avoid := GSAIAvoidCollisions.new(agent, proximity) + + # Face turns the agent to keep looking towards its target. It will be enabled while the agent + # is not fleeing due to low health. It tries to arrive 'on alignment' with 0 remaining velocity. + var face := GSAIFace.new(agent, player_agent) + + # We use deg2rad because the math in the toolkit assumes radians. + # How close for the agent to be 'aligned', if not exact. + face.alignment_tolerance = deg2rad(5) + # When to start slowing down + face.deceleration_radius = deg2rad(60) + + # LookWhereYouGo turns the agent to keep looking towards its direction of travel. It will only + # be enabled while the agent is at low health. + var look := GSAILookWhereYouGo.new(agent) + # How close for the agent to be 'aligned', if not exact + look.alignment_tolerance = deg2rad(5) + # When to start slowing down. + look.deceleration_radius = deg2rad(60) + + # Behaviors that are not enabled produce 0 acceleration. + # Adding our fleeing behaviors to a blend. The order does not matter. + flee_blend.is_enabled = false + flee_blend.add(look, 1) + flee_blend.add(flee, 1) + + # Adding our pursuit behaviors to a blend. The order does not matter. + pursue_blend.add(face, 1) + pursue_blend.add(pursue, 1) + + # Adding our final behaviors to the main priority behavior. The order does matter here. + # We want to avoid collision with the player first, flee from the player second when enabled, + # and pursue the player last when enabled. + priority.add(avoid) + priority.add(flee_blend) + priority.add(pursue_blend) + + +func _physics_process(delta: float) -> void: + # Make sure any change in position and speed has been recorded. + update_agent() + + if current_health <= flee_health_threshold: + pursue_blend.is_enabled = false + flee_blend.is_enabled = true + + # Calculate the desired acceleration. + priority.calculate_steering(acceleration) + + # We add the discovered acceleration to our linear velocity. The toolkit does not limit + # velocity, just acceleration, so we clamp the result ourselves here. + velocity = (velocity + Vector2(acceleration.linear.x, acceleration.linear.y) * delta).clamped( + agent.linear_speed_max + ) + + # This applies drag on the agent's motion, helping it to slow down naturally. + velocity = velocity.linear_interpolate(Vector2.ZERO, linear_drag) + + # And since we're using a KinematicBody2D, we use Godot's excellent move_and_slide to actually + # apply the final movement, and record any change in velocity the physics engine discovered. + velocity = move_and_slide(velocity) + + # We then do something similar to apply our agent's rotational speed. + angular_velocity = clamp( + angular_velocity + acceleration.angular * delta, -agent.angular_speed_max, agent.angular_speed_max + ) + # This applies drag on the agent's rotation, helping it slow down naturally. + angular_velocity = lerp(angular_velocity, 0, angular_drag) + rotation += angular_velocity * delta + + +# In order to support both 2D and 3D, the toolkit uses Vector3, so the conversion is required +# when using 2D nodes. The Z component can be left to 0 safely. +func update_agent() -> void: + agent.position.x = global_position.x + agent.position.y = global_position.y + agent.orientation = rotation + agent.linear_velocity.x = velocity.x + agent.linear_velocity.y = velocity.y + agent.angular_velocity = angular_velocity + + +# We calculate the radius from the collision shape - this will approximate the agent's size in the +# game world, to avoid collisions with the player. +func calculate_radius(polygon: PoolVector2Array) -> float: + var furthest_point := Vector2(-INF, -INF) + for p in polygon: + if abs(p.x) > furthest_point.x: + furthest_point.x = p.x + if abs(p.y) > furthest_point.y: + furthest_point.y = p.y + return furthest_point.length() + + +func damage(amount: int) -> void: + current_health -= amount + if current_health <= 0: + queue_free() diff --git a/godot/Demos/Quickstart/Bullet.gd b/godot/Demos/Quickstart/Bullet.gd new file mode 100644 index 0000000..a33fc8f --- /dev/null +++ b/godot/Demos/Quickstart/Bullet.gd @@ -0,0 +1,33 @@ +extends KinematicBody2D + +export var speed := 1500.0 + +var velocity := Vector2.ZERO +var player: Node + +onready var timer := $Lifetime + + +func _ready() -> void: + timer.connect("timeout", self, "_on_Lifetime_timeout") + timer.start() + + +func _physics_process(delta: float) -> void: + var collision := move_and_collide(velocity * delta) + if collision: + timer.stop() + clear() + collision.collider.damage(10) + + +func start(direction: Vector2) -> void: + velocity = direction * speed + + +func clear() -> void: + queue_free() + + +func _on_Lifetime_timeout() -> void: + clear() diff --git a/godot/Demos/Quickstart/Bullet.tscn b/godot/Demos/Quickstart/Bullet.tscn new file mode 100644 index 0000000..60ceb8d --- /dev/null +++ b/godot/Demos/Quickstart/Bullet.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://Demos/Utils/CircleDraw.gd" type="Script" id=1] +[ext_resource path="res://Demos/Quickstart/Bullet.gd" type="Script" id=2] + +[sub_resource type="CircleShape2D" id=1] +radius = 4.0 + +[node name="Bullet" type="KinematicBody2D"] +collision_layer = 4 +collision_mask = 2 +script = ExtResource( 2 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) +script = ExtResource( 1 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +stroke = 2.0 + +[node name="Lifetime" type="Timer" parent="."] +process_mode = 0 +wait_time = 3.0 diff --git a/godot/Demos/Quickstart/Bullet.tscn.bak b/godot/Demos/Quickstart/Bullet.tscn.bak new file mode 100644 index 0000000..7f6d9b4 --- /dev/null +++ b/godot/Demos/Quickstart/Bullet.tscn.bak @@ -0,0 +1,23 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=1] +[ext_resource path="res://demos/Quickstart/Bullet.gd" type="Script" id=2] + +[sub_resource type="CircleShape2D" id=1] +radius = 4.0 + +[node name="Bullet" type="KinematicBody2D"] +collision_layer = 4 +collision_mask = 2 +script = ExtResource( 2 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) +script = ExtResource( 1 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +stroke = 2.0 + +[node name="Lifetime" type="Timer" parent="."] +process_mode = 0 +wait_time = 3.0 diff --git a/godot/Demos/Quickstart/Player.gd b/godot/Demos/Quickstart/Player.gd new file mode 100644 index 0000000..40bcc4c --- /dev/null +++ b/godot/Demos/Quickstart/Player.gd @@ -0,0 +1,92 @@ +extends KinematicBody2D + +export var speed_max := 650.0 +export var acceleration_max := 70.0 +export var rotation_speed_max := 240 +export var rotation_accel_max := 40 +export var bullet: PackedScene + +var velocity := Vector2.ZERO +var angular_velocity := 0.0 +var direction := Vector2.RIGHT + +onready var agent := GSAISteeringAgent.new() +onready var proxy_target := GSAIAgentLocation.new() +onready var face := GSAIFace.new(agent, proxy_target) +onready var accel := GSAITargetAcceleration.new() +onready var bullets := owner.get_node("Bullets") + + +func _ready() -> void: + agent.linear_speed_max = speed_max + agent.linear_acceleration_max = acceleration_max + agent.angular_speed_max = deg2rad(rotation_speed_max) + agent.angular_acceleration_max = deg2rad(rotation_accel_max) + agent.bounding_radius = calculate_radius($CollisionPolygon2D.polygon) + update_agent() + + var mouse_pos := get_global_mouse_position() + proxy_target.position.x = mouse_pos.x + proxy_target.position.y = mouse_pos.y + + face.alignment_tolerance = deg2rad(5) + face.deceleration_radius = deg2rad(45) + + +func _physics_process(delta: float) -> void: + update_agent() + + var movement := get_movement() + + direction = GSAIUtils.angle_to_vector2(rotation) + + velocity += direction * acceleration_max * movement * delta + velocity = velocity.clamped(speed_max) + velocity = velocity.linear_interpolate(Vector2.ZERO, 0.1) + velocity = move_and_slide(velocity) + + face.calculate_steering(accel) + angular_velocity += accel.angular * delta + angular_velocity = clamp(angular_velocity, -agent.angular_speed_max, agent.angular_speed_max) + angular_velocity = lerp(angular_velocity, 0, 0.1) + rotation += angular_velocity * delta + + +func _unhandled_input(event: InputEvent) -> void: + if event is InputEventMouseMotion: + var mouse_pos: Vector2 = event.position + proxy_target.position.x = mouse_pos.x + proxy_target.position.y = mouse_pos.y + elif event is InputEventMouseButton: + if event.button_index == BUTTON_LEFT and event.pressed: + var next_bullet := bullet.instance() + next_bullet.global_position = ( + global_position + - direction * (agent.bounding_radius - 5) + ) + next_bullet.player = self + next_bullet.start(-direction) + bullets.add_child(next_bullet) + + +func get_movement() -> float: + return Input.get_action_strength("sf_down") - Input.get_action_strength("sf_up") + + +func update_agent() -> void: + agent.position.x = global_position.x + agent.position.y = global_position.y + agent.orientation = rotation + agent.linear_velocity.x = velocity.x + agent.linear_velocity.y = velocity.y + agent.angular_velocity = angular_velocity + + +func calculate_radius(polygon: PoolVector2Array) -> float: + var furthest_point := Vector2(-INF, -INF) + for p in polygon: + if abs(p.x) > furthest_point.x: + furthest_point.x = p.x + if abs(p.y) > furthest_point.y: + furthest_point.y = p.y + return furthest_point.length() diff --git a/godot/Demos/Quickstart/QuickStartDemo.tscn b/godot/Demos/Quickstart/QuickStartDemo.tscn new file mode 100644 index 0000000..19e2854 --- /dev/null +++ b/godot/Demos/Quickstart/QuickStartDemo.tscn @@ -0,0 +1,61 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://Demos/Utils/Line2DDraw.gd" type="Script" id=1] +[ext_resource path="res://Demos/Quickstart/Agent.gd" type="Script" id=2] +[ext_resource path="res://Demos/Quickstart/Player.gd" type="Script" id=3] +[ext_resource path="res://Demos/Quickstart/Bullet.tscn" type="PackedScene" id=4] +[ext_resource path="res://Demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5] + +[node name="QuickStartDemo" type="Node"] + +[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )] + +[node name="Player" type="KinematicBody2D" parent="." groups=[ +"Player", +]] +position = Vector2( 402.346, 573.791 ) +rotation = 1.5708 +collision_mask = 2 +script = ExtResource( 3 ) +speed_max = 900.0 +acceleration_max = 4200.0 +rotation_speed_max = 360 +rotation_accel_max = 1280 +bullet = ExtResource( 4 ) + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Player"] +polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 ) + +[node name="Line2D" type="Line2D" parent="Player"] +points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 ) +width = 8.0 +default_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +joint_mode = 2 +antialiased = true +script = ExtResource( 1 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) + +[node name="Agent" type="KinematicBody2D" parent="."] +position = Vector2( 974.675, 266.224 ) +rotation = 1.5708 +collision_layer = 2 +collision_mask = 5 +script = ExtResource( 2 ) +speed_max = 600.0 +acceleration_max = 2800.0 +angular_speed_max = 360 +angular_acceleration_max = 1280 + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Agent"] +polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 ) + +[node name="Line2D" type="Line2D" parent="Agent"] +points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 ) +width = 8.0 +default_color = Color( 1, 0.709804, 0.439216, 1 ) +joint_mode = 2 +antialiased = true +script = ExtResource( 1 ) +inner_color = Color( 0.890196, 0.411765, 0.337255, 1 ) + +[node name="Bullets" type="Node2D" parent="."] diff --git a/godot/Demos/Quickstart/QuickStartDemo.tscn.bak b/godot/Demos/Quickstart/QuickStartDemo.tscn.bak new file mode 100644 index 0000000..bbbca17 --- /dev/null +++ b/godot/Demos/Quickstart/QuickStartDemo.tscn.bak @@ -0,0 +1,61 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://demos/Utils/Line2DDraw.gd" type="Script" id=1] +[ext_resource path="res://demos/Quickstart/Agent.gd" type="Script" id=2] +[ext_resource path="res://demos/Quickstart/Player.gd" type="Script" id=3] +[ext_resource path="res://demos/Quickstart/Bullet.tscn" type="PackedScene" id=4] +[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5] + +[node name="QuickStartDemo" type="Node"] + +[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )] + +[node name="Player" type="KinematicBody2D" parent="." groups=[ +"Player", +]] +position = Vector2( 402.346, 573.791 ) +rotation = 1.5708 +collision_mask = 2 +script = ExtResource( 3 ) +speed_max = 900.0 +acceleration_max = 4200.0 +rotation_speed_max = 360 +rotation_accel_max = 1280 +bullet = ExtResource( 4 ) + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Player"] +polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 ) + +[node name="Line2D" type="Line2D" parent="Player"] +points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 ) +width = 8.0 +default_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +joint_mode = 2 +antialiased = true +script = ExtResource( 1 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) + +[node name="Agent" type="KinematicBody2D" parent="."] +position = Vector2( 974.675, 266.224 ) +rotation = 1.5708 +collision_layer = 2 +collision_mask = 5 +script = ExtResource( 2 ) +speed_max = 600.0 +acceleration_max = 2800.0 +angular_speed_max = 360 +angular_acceleration_max = 1280 + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Agent"] +polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 ) + +[node name="Line2D" type="Line2D" parent="Agent"] +points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 ) +width = 8.0 +default_color = Color( 1, 0.709804, 0.439216, 1 ) +joint_mode = 2 +antialiased = true +script = ExtResource( 1 ) +inner_color = Color( 0.890196, 0.411765, 0.337255, 1 ) + +[node name="Bullets" type="Node2D" parent="."] diff --git a/godot/Demos/SeekFlee/Boundaries.gd b/godot/Demos/SeekFlee/Boundaries.gd new file mode 100644 index 0000000..f54e6cf --- /dev/null +++ b/godot/Demos/SeekFlee/Boundaries.gd @@ -0,0 +1,32 @@ +extends Node2D + +const COLOR := Color("8fde5d") + + +func _ready() -> void: + get_tree().root.connect("size_changed", self, "_on_SceneTree_size_changed") + _on_SceneTree_size_changed() + + +func _draw() -> void: + for b in get_children(): + var extents: Vector2 = b.get_node("CollisionShape2D").shape.extents + draw_rect(Rect2(b.global_position - extents, extents * 2), COLOR) + + +func _on_SceneTree_size_changed() -> void: + var size := Vector2( + ProjectSettings["display/window/size/width"], ProjectSettings["display/window/size/height"] + ) + for b in get_children(): + var boundary: String = b.name.rsplit("Boundary")[0] + match boundary: + "Left": + b.global_position = Vector2(0, size.y / 2) + "Right": + b.global_position = Vector2(size.x, size.y / 2) + "Top": + b.global_position = Vector2(size.x / 2, 0) + "Bottom": + b.global_position = Vector2(size.x / 2, size.y) + update() diff --git a/godot/Demos/SeekFlee/Player.gd b/godot/Demos/SeekFlee/Player.gd new file mode 100644 index 0000000..7008704 --- /dev/null +++ b/godot/Demos/SeekFlee/Player.gd @@ -0,0 +1,26 @@ +extends KinematicBody2D +# Class to control the player in basic left/right up/down movement. + +var speed: float +onready var agent := GSAIAgentLocation.new() + + +func _ready() -> void: + agent.position = GSAIUtils.to_vector3(global_position) + + +func _physics_process(_delta: float) -> void: + var movement := _get_movement() + if movement.length_squared() < 0.01: + return + + # warning-ignore:return_value_discarded + move_and_slide(movement * speed) + agent.position = GSAIUtils.to_vector3(global_position) + + +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") + ) diff --git a/godot/Demos/SeekFlee/SeekFleeDemo.gd b/godot/Demos/SeekFlee/SeekFleeDemo.gd new file mode 100644 index 0000000..027693c --- /dev/null +++ b/godot/Demos/SeekFlee/SeekFleeDemo.gd @@ -0,0 +1,82 @@ +extends Node +# Access helper class for children to access window boundaries. + +enum Mode { FLEE, SEEK } + +export (Mode) var behavior_mode := Mode.SEEK setget set_behavior_mode +export (float, 0, 1000, 30) var linear_speed_max := 200.0 setget set_linear_speed_max +export (float, 0, 2000, 40) var linear_accel_max := 10.0 setget set_linear_accel_max +export (float) var player_speed := 600.0 setget set_player_speed + +var camera_boundaries: Rect2 + +onready var player: KinematicBody2D = $Player +onready var spawner: Node2D = $Spawner + + +func _ready() -> void: + camera_boundaries = Rect2( + Vector2.ZERO, + Vector2( + ProjectSettings["display/window/size/width"], + ProjectSettings["display/window/size/height"] + ) + ) + + var rng := RandomNumberGenerator.new() + rng.randomize() + + player.speed = player_speed + + for i in range(spawner.entity_count): + var new_pos := Vector2( + rng.randf_range(0, camera_boundaries.size.x), + rng.randf_range(0, camera_boundaries.size.y) + ) + var entity: KinematicBody2D = spawner.Entity.instance() + entity.global_position = new_pos + entity.player_agent = player.agent + entity.start_speed = linear_speed_max + entity.start_accel = linear_accel_max + entity.use_seek = behavior_mode == Mode.SEEK + spawner.add_child(entity) + + +func set_behavior_mode(mode: int) -> void: + behavior_mode = mode + if not is_inside_tree(): + return + + match mode: + Mode.SEEK: + for child in spawner.get_children(): + child.use_seek = true + Mode.FLEE: + for child in spawner.get_children(): + child.use_seek = false + + +func set_linear_speed_max(value: float) -> void: + linear_speed_max = value + if not is_inside_tree(): + return + + for child in spawner.get_children(): + child.agent.linear_speed_max = value + + +func set_linear_accel_max(value: float) -> void: + linear_accel_max = value + if not is_inside_tree(): + return + + for child in spawner.get_children(): + child.agent.linear_acceleration_max = value + + +func set_player_speed(value: float) -> void: + player_speed = value + if not is_inside_tree(): + return + + player.speed = player_speed diff --git a/godot/Demos/SeekFlee/SeekFleeDemo.tscn b/godot/Demos/SeekFlee/SeekFleeDemo.tscn new file mode 100644 index 0000000..2b75042 --- /dev/null +++ b/godot/Demos/SeekFlee/SeekFleeDemo.tscn @@ -0,0 +1,81 @@ +[gd_scene load_steps=12 format=2] + +[ext_resource path="res://Demos/SeekFlee/Player.gd" type="Script" id=2] +[ext_resource path="res://Demos/SeekFlee/SeekFleeDemo.gd" type="Script" id=3] +[ext_resource path="res://Demos/SeekFlee/Spawner.gd" type="Script" id=4] +[ext_resource path="res://Demos/Utils/DemoInterface.tscn" type="PackedScene" id=5] +[ext_resource path="res://Demos/SeekFlee/Seeker.tscn" type="PackedScene" id=6] +[ext_resource path="res://Demos/Utils/CircleDraw.gd" type="Script" id=7] +[ext_resource path="res://Demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=8] +[ext_resource path="res://Demos/SeekFlee/Boundaries.gd" type="Script" id=9] + +[sub_resource type="CircleShape2D" id=1] +radius = 32.0 + +[sub_resource type="RectangleShape2D" id=2] +extents = Vector2( 10, 542 ) + +[sub_resource type="RectangleShape2D" id=3] +extents = Vector2( 965.654, 10 ) + +[node name="SeekFleeDemo" type="Node"] +script = ExtResource( 3 ) +linear_speed_max = 570.0 +linear_accel_max = 1160.0 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 8 )] + +[node name="Player" type="KinematicBody2D" parent="."] +position = Vector2( 960, 540 ) +collision_mask = 2 +script = ExtResource( 2 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Player"] +shape = SubResource( 1 ) +script = ExtResource( 7 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +stroke = 4.0 + +[node name="Boundaries" type="Node2D" parent="."] +script = ExtResource( 9 ) + +[node name="LeftBoundary" type="StaticBody2D" parent="Boundaries"] +position = Vector2( 0, 540 ) +collision_layer = 2 +collision_mask = 5 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Boundaries/LeftBoundary"] +shape = SubResource( 2 ) + +[node name="RightBoundary" type="StaticBody2D" parent="Boundaries"] +position = Vector2( 1920, 540 ) +collision_layer = 2 +collision_mask = 5 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Boundaries/RightBoundary"] +shape = SubResource( 2 ) + +[node name="TopBoundary" type="StaticBody2D" parent="Boundaries"] +position = Vector2( 960, 0 ) +collision_layer = 2 +collision_mask = 5 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Boundaries/TopBoundary"] +shape = SubResource( 3 ) + +[node name="BottomBoundary" type="StaticBody2D" parent="Boundaries"] +position = Vector2( 960, 1080 ) +collision_layer = 2 +collision_mask = 5 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Boundaries/BottomBoundary"] +shape = SubResource( 3 ) + +[node name="Spawner" type="Node2D" parent="."] +script = ExtResource( 4 ) +Entity = ExtResource( 6 ) + +[node name="DemoInterface" parent="." instance=ExtResource( 5 )] +text_bbcode = "Seek & Flee Demo +Move the [color=lime]green \"Player\"[/color] around with WASD and notice the [color=#ffb570]orange \"Enemies\"[/color] try to seek to or flee from the player." diff --git a/godot/Demos/SeekFlee/SeekFleeDemo.tscn.bak b/godot/Demos/SeekFlee/SeekFleeDemo.tscn.bak new file mode 100644 index 0000000..974d3ed --- /dev/null +++ b/godot/Demos/SeekFlee/SeekFleeDemo.tscn.bak @@ -0,0 +1,81 @@ +[gd_scene load_steps=12 format=2] + +[ext_resource path="res://demos/SeekFlee/Player.gd" type="Script" id=2] +[ext_resource path="res://demos/SeekFlee/SeekFleeDemo.gd" type="Script" id=3] +[ext_resource path="res://demos/SeekFlee/Spawner.gd" type="Script" id=4] +[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=5] +[ext_resource path="res://demos/SeekFlee/Seeker.tscn" type="PackedScene" id=6] +[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=7] +[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=8] +[ext_resource path="res://demos/SeekFlee/Boundaries.gd" type="Script" id=9] + +[sub_resource type="CircleShape2D" id=1] +radius = 32.0 + +[sub_resource type="RectangleShape2D" id=2] +extents = Vector2( 10, 542 ) + +[sub_resource type="RectangleShape2D" id=3] +extents = Vector2( 965.654, 10 ) + +[node name="SeekFleeDemo" type="Node"] +script = ExtResource( 3 ) +linear_speed_max = 570.0 +linear_accel_max = 1160.0 + +[node name="BackgroudLayer" parent="." instance=ExtResource( 8 )] + +[node name="Player" type="KinematicBody2D" parent="."] +position = Vector2( 960, 540 ) +collision_mask = 2 +script = ExtResource( 2 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Player"] +shape = SubResource( 1 ) +script = ExtResource( 7 ) +inner_color = Color( 0.235294, 0.639216, 0.439216, 1 ) +outer_color = Color( 0.560784, 0.870588, 0.364706, 1 ) +stroke = 4.0 + +[node name="Boundaries" type="Node2D" parent="."] +script = ExtResource( 9 ) + +[node name="LeftBoundary" type="StaticBody2D" parent="Boundaries"] +position = Vector2( 0, 540 ) +collision_layer = 2 +collision_mask = 5 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Boundaries/LeftBoundary"] +shape = SubResource( 2 ) + +[node name="RightBoundary" type="StaticBody2D" parent="Boundaries"] +position = Vector2( 1920, 540 ) +collision_layer = 2 +collision_mask = 5 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Boundaries/RightBoundary"] +shape = SubResource( 2 ) + +[node name="TopBoundary" type="StaticBody2D" parent="Boundaries"] +position = Vector2( 960, 0 ) +collision_layer = 2 +collision_mask = 5 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Boundaries/TopBoundary"] +shape = SubResource( 3 ) + +[node name="BottomBoundary" type="StaticBody2D" parent="Boundaries"] +position = Vector2( 960, 1080 ) +collision_layer = 2 +collision_mask = 5 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Boundaries/BottomBoundary"] +shape = SubResource( 3 ) + +[node name="Spawner" type="Node2D" parent="."] +script = ExtResource( 4 ) +Entity = ExtResource( 6 ) + +[node name="DemoInterface" parent="." instance=ExtResource( 5 )] +text_bbcode = "Seek & Flee Demo +Move the [color=lime]green \"Player\"[/color] around with WASD and notice the [color=#ffb570]orange \"Enemies\"[/color] try to seek to or flee from the player." diff --git a/godot/Demos/SeekFlee/Seeker.gd b/godot/Demos/SeekFlee/Seeker.gd new file mode 100644 index 0000000..e2252f3 --- /dev/null +++ b/godot/Demos/SeekFlee/Seeker.gd @@ -0,0 +1,29 @@ +extends KinematicBody2D + +var player_agent: GSAIAgentLocation +var velocity := Vector2.ZERO +var start_speed: float +var start_accel: float +var use_seek := true + +onready var agent := GSAIKinematicBody2DAgent.new(self) +onready var accel := GSAITargetAcceleration.new() +onready var seek := GSAISeek.new(agent, player_agent) +onready var flee := GSAIFlee.new(agent, player_agent) + + +func _ready() -> void: + agent.linear_acceleration_max = start_accel + agent.linear_speed_max = start_speed + + +func _physics_process(delta: float) -> void: + if not player_agent: + return + + if use_seek: + seek.calculate_steering(accel) + else: + flee.calculate_steering(accel) + + agent._apply_steering(accel, delta) diff --git a/godot/Demos/SeekFlee/Seeker.tscn b/godot/Demos/SeekFlee/Seeker.tscn new file mode 100644 index 0000000..e65c072 --- /dev/null +++ b/godot/Demos/SeekFlee/Seeker.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://Demos/SeekFlee/Seeker.gd" type="Script" id=1] +[ext_resource path="res://Demos/Utils/CircleDraw.gd" type="Script" id=2] + +[sub_resource type="CircleShape2D" id=1] +radius = 16.0 + +[node name="Seeker" type="KinematicBody2D"] +collision_layer = 4 +collision_mask = 2 +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) +script = ExtResource( 2 ) +inner_color = Color( 0.890196, 0.411765, 0.337255, 1 ) +outer_color = Color( 1, 0.709804, 0.439216, 1 ) +stroke = 4.0 diff --git a/godot/Demos/SeekFlee/Seeker.tscn.bak b/godot/Demos/SeekFlee/Seeker.tscn.bak new file mode 100644 index 0000000..9452469 --- /dev/null +++ b/godot/Demos/SeekFlee/Seeker.tscn.bak @@ -0,0 +1,19 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://demos/SeekFlee/Seeker.gd" type="Script" id=1] +[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=2] + +[sub_resource type="CircleShape2D" id=1] +radius = 16.0 + +[node name="Seeker" type="KinematicBody2D"] +collision_layer = 4 +collision_mask = 2 +script = ExtResource( 1 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 1 ) +script = ExtResource( 2 ) +inner_color = Color( 0.890196, 0.411765, 0.337255, 1 ) +outer_color = Color( 1, 0.709804, 0.439216, 1 ) +stroke = 4.0 diff --git a/godot/Demos/SeekFlee/Spawner.gd b/godot/Demos/SeekFlee/Spawner.gd new file mode 100644 index 0000000..abd3929 --- /dev/null +++ b/godot/Demos/SeekFlee/Spawner.gd @@ -0,0 +1,6 @@ +extends Node2D +# Holds data to instantiate and configure a number of agent entities. + +export (PackedScene) var Entity: PackedScene +export var entity_count := 10 +export var entity_color := Color.blue diff --git a/godot/Demos/Utils/BackgroudLayer.tscn b/godot/Demos/Utils/BackgroudLayer.tscn new file mode 100644 index 0000000..9b6a8f1 --- /dev/null +++ b/godot/Demos/Utils/BackgroudLayer.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://assets/sprites/background.png" type="Texture" id=1] + +[node name="BackgroudLayer" type="CanvasLayer"] +layer = -1 + +[node name="Background" type="TextureRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 +texture = ExtResource( 1 ) +expand = true +stretch_mode = 7 +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/godot/Demos/Utils/CircleDraw.gd b/godot/Demos/Utils/CircleDraw.gd new file mode 100644 index 0000000..1c51f05 --- /dev/null +++ b/godot/Demos/Utils/CircleDraw.gd @@ -0,0 +1,26 @@ +tool +extends CollisionShape2D + +export (Color) var inner_color := Color() setget set_inner_color +export (Color) var outer_color := Color() setget set_outer_color +export (float) var stroke := 0.0 setget set_stroke + + +func _draw() -> void: + draw_circle(Vector2.ZERO, shape.radius + stroke, outer_color) + draw_circle(Vector2.ZERO, shape.radius, inner_color) + + +func set_inner_color(val: Color) -> void: + inner_color = val + update() + + +func set_outer_color(val: Color) -> void: + outer_color = val + update() + + +func set_stroke(val: float) -> void: + stroke = val + update() diff --git a/godot/Demos/Utils/DemoInterface.gd b/godot/Demos/Utils/DemoInterface.gd new file mode 100644 index 0000000..93b7082 --- /dev/null +++ b/godot/Demos/Utils/DemoInterface.gd @@ -0,0 +1,13 @@ +tool +extends PanelContainer + +export (String, MULTILINE) var text_bbcode := "" setget set_text_bbcode + +onready var rich_text_label: RichTextLabel = $MarginContainer/RichTextLabel + + +func set_text_bbcode(value: String) -> void: + text_bbcode = value + if not rich_text_label: + yield(self, "ready") + rich_text_label.bbcode_text = text_bbcode diff --git a/godot/Demos/Utils/DemoInterface.tscn b/godot/Demos/Utils/DemoInterface.tscn new file mode 100644 index 0000000..7855926 --- /dev/null +++ b/godot/Demos/Utils/DemoInterface.tscn @@ -0,0 +1,37 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://assets/theme/gdquest.theme" type="Theme" id=1] +[ext_resource path="res://Demos/Utils/DemoInterface.gd" type="Script" id=2] + +[sub_resource type="GDScript" id=1] +script/source = "tool +extends RichTextLabel + +" + +[node name="DemoInterface" type="PanelContainer"] +anchor_right = 1.0 +margin_bottom = 140.0 +rect_min_size = Vector2( 1024, 0 ) +theme = ExtResource( 1 ) +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} +text_bbcode = "Replace this text for the demo." + +[node name="MarginContainer" type="MarginContainer" parent="."] +margin_right = 1920.0 +margin_bottom = 140.0 + +[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer"] +margin_left = 16.0 +margin_top = 16.0 +margin_right = 1904.0 +margin_bottom = 124.0 +rect_min_size = Vector2( 0, 55 ) +bbcode_enabled = true +bbcode_text = "Replace this text for the demo." +text = "Replace this text for the demo." +scroll_active = false +script = SubResource( 1 ) diff --git a/godot/Demos/Utils/DemoInterface.tscn.bak b/godot/Demos/Utils/DemoInterface.tscn.bak new file mode 100644 index 0000000..6c100ee --- /dev/null +++ b/godot/Demos/Utils/DemoInterface.tscn.bak @@ -0,0 +1,37 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://assets/theme/gdquest.theme" type="Theme" id=1] +[ext_resource path="res://demos/Utils/DemoInterface.gd" type="Script" id=2] + +[sub_resource type="GDScript" id=1] +script/source = "tool +extends RichTextLabel + +" + +[node name="DemoInterface" type="PanelContainer"] +anchor_right = 1.0 +margin_bottom = 140.0 +rect_min_size = Vector2( 1024, 0 ) +theme = ExtResource( 1 ) +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} +text_bbcode = "Replace this text for the demo." + +[node name="MarginContainer" type="MarginContainer" parent="."] +margin_right = 1920.0 +margin_bottom = 140.0 + +[node name="RichTextLabel" type="RichTextLabel" parent="MarginContainer"] +margin_left = 16.0 +margin_top = 16.0 +margin_right = 1904.0 +margin_bottom = 124.0 +rect_min_size = Vector2( 0, 55 ) +bbcode_enabled = true +bbcode_text = "Replace this text for the demo." +text = "Replace this text for the demo." +scroll_active = false +script = SubResource( 1 ) diff --git a/godot/Demos/Utils/Line2DDraw.gd b/godot/Demos/Utils/Line2DDraw.gd new file mode 100644 index 0000000..d1a7b5e --- /dev/null +++ b/godot/Demos/Utils/Line2DDraw.gd @@ -0,0 +1,13 @@ +tool +extends Line2D + +export (Color) var inner_color := Color() setget set_inner_color + + +func _draw() -> void: + draw_colored_polygon(points, inner_color) + + +func set_inner_color(val: Color) -> void: + inner_color = val + update() diff --git a/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIKinematicBody2DAgent.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIKinematicBody2DAgent.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIKinematicBody2DAgent.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIKinematicBody2DAgent.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIKinematicBody3DAgent.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIKinematicBody3DAgent.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIKinematicBody3DAgent.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIKinematicBody3DAgent.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIRigidBody2DAgent.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIRigidBody2DAgent.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIRigidBody2DAgent.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIRigidBody2DAgent.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIRigidBody3DAgent.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIRigidBody3DAgent.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIRigidBody3DAgent.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIRigidBody3DAgent.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAISpecializedAgent.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAISpecializedAgent.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Agents/GSAISpecializedAgent.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Agents/GSAISpecializedAgent.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIArrive.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIArrive.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIArrive.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIArrive.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIAvoidCollisions.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIAvoidCollisions.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIAvoidCollisions.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIAvoidCollisions.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIBlend.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIBlend.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIBlend.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIBlend.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAICohesion.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAICohesion.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAICohesion.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAICohesion.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIEvade.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIEvade.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIEvade.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIEvade.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFace.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFace.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFace.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFace.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFlee.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFlee.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFlee.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFlee.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFollowPath.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFollowPath.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFollowPath.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFollowPath.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAILookWhereYouGo.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAILookWhereYouGo.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAILookWhereYouGo.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAILookWhereYouGo.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIMatchOrientation.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIMatchOrientation.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIMatchOrientation.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIMatchOrientation.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIPriority.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIPriority.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIPriority.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIPriority.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIPursue.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIPursue.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIPursue.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIPursue.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAISeek.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAISeek.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAISeek.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAISeek.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAISeparation.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAISeparation.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAISeparation.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAISeparation.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/GSAIAgentLocation.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/GSAIAgentLocation.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/GSAIAgentLocation.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/GSAIAgentLocation.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/GSAIGroupBehavior.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/GSAIGroupBehavior.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/GSAIGroupBehavior.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/GSAIGroupBehavior.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/GSAIPath.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/GSAIPath.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/GSAIPath.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/GSAIPath.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/GSAISteeringAgent.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/GSAISteeringAgent.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/GSAISteeringAgent.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/GSAISteeringAgent.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/GSAISteeringBehavior.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/GSAISteeringBehavior.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/GSAISteeringBehavior.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/GSAISteeringBehavior.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/GSAITargetAcceleration.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/GSAITargetAcceleration.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/GSAITargetAcceleration.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/GSAITargetAcceleration.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/GSAIUtils.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/GSAIUtils.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/GSAIUtils.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/GSAIUtils.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIInfiniteProximity.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIInfiniteProximity.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIInfiniteProximity.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIInfiniteProximity.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIProximity.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIProximity.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIProximity.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIProximity.gd diff --git a/addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIRadiusProximity.gd b/godot/addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIRadiusProximity.gd similarity index 100% rename from addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIRadiusProximity.gd rename to godot/addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIRadiusProximity.gd diff --git a/godot/assets/icon.png b/godot/assets/icon.png new file mode 100644 index 0000000..ed8f05d Binary files /dev/null and b/godot/assets/icon.png differ diff --git a/godot/assets/icon.png.import b/godot/assets/icon.png.import new file mode 100644 index 0000000..4e9f7bb --- /dev/null +++ b/godot/assets/icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icon.png" +dest_files=[ "res://.import/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/godot/assets/icon.svg b/godot/assets/icon.svg new file mode 100644 index 0000000..b690016 --- /dev/null +++ b/godot/assets/icon.svg @@ -0,0 +1,151 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/godot/assets/icon.svg.import b/godot/assets/icon.svg.import new file mode 100644 index 0000000..d499e66 --- /dev/null +++ b/godot/assets/icon.svg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.svg-56083ea2a1f1a4f1e49773bdc6d7826c.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/icon.svg" +dest_files=[ "res://.import/icon.svg-56083ea2a1f1a4f1e49773bdc6d7826c.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/godot/assets/sprites/background.png b/godot/assets/sprites/background.png new file mode 100644 index 0000000..ad7e8ba Binary files /dev/null and b/godot/assets/sprites/background.png differ diff --git a/godot/assets/sprites/background.png.import b/godot/assets/sprites/background.png.import new file mode 100644 index 0000000..8d1c5f6 --- /dev/null +++ b/godot/assets/sprites/background.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/background.png-dde469fb1f19281f3784b52d4bea96cd.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sprites/background.png" +dest_files=[ "res://.import/background.png-dde469fb1f19281f3784b52d4bea96cd.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/godot/assets/theme/button/disabled.stylebox b/godot/assets/theme/button/disabled.stylebox new file mode 100644 index 0000000..252f924 Binary files /dev/null and b/godot/assets/theme/button/disabled.stylebox differ diff --git a/godot/assets/theme/button/focused.stylebox b/godot/assets/theme/button/focused.stylebox new file mode 100644 index 0000000..04863c6 Binary files /dev/null and b/godot/assets/theme/button/focused.stylebox differ diff --git a/godot/assets/theme/button/hover.stylebox b/godot/assets/theme/button/hover.stylebox new file mode 100644 index 0000000..08fb085 Binary files /dev/null and b/godot/assets/theme/button/hover.stylebox differ diff --git a/godot/assets/theme/button/normal.stylebox b/godot/assets/theme/button/normal.stylebox new file mode 100644 index 0000000..999edcf Binary files /dev/null and b/godot/assets/theme/button/normal.stylebox differ diff --git a/godot/assets/theme/button/pressed.stylebox b/godot/assets/theme/button/pressed.stylebox new file mode 100644 index 0000000..7cb801b Binary files /dev/null and b/godot/assets/theme/button/pressed.stylebox differ diff --git a/godot/assets/theme/empty.stylebox b/godot/assets/theme/empty.stylebox new file mode 100644 index 0000000..4467232 Binary files /dev/null and b/godot/assets/theme/empty.stylebox differ diff --git a/godot/assets/theme/fonts/default_font.tres b/godot/assets/theme/fonts/default_font.tres new file mode 100644 index 0000000..7ca6e3a --- /dev/null +++ b/godot/assets/theme/fonts/default_font.tres @@ -0,0 +1,8 @@ +[gd_resource type="DynamicFont" load_steps=2 format=2] + +[ext_resource path="res://assets/theme/fonts/montserrat/Montserrat-Medium.ttf" type="DynamicFontData" id=1] + +[resource] +size = 26 +use_filter = true +font_data = ExtResource( 1 ) diff --git a/godot/assets/theme/fonts/default_font_bold.tres b/godot/assets/theme/fonts/default_font_bold.tres new file mode 100644 index 0000000..92dcae0 --- /dev/null +++ b/godot/assets/theme/fonts/default_font_bold.tres @@ -0,0 +1,8 @@ +[gd_resource type="DynamicFont" load_steps=2 format=2] + +[ext_resource path="res://assets/theme/fonts/montserrat/Montserrat-Bold.ttf" type="DynamicFontData" id=1] + +[resource] +size = 26 +use_filter = true +font_data = ExtResource( 1 ) diff --git a/godot/assets/theme/fonts/default_font_code.tres b/godot/assets/theme/fonts/default_font_code.tres new file mode 100644 index 0000000..0138558 --- /dev/null +++ b/godot/assets/theme/fonts/default_font_code.tres @@ -0,0 +1,8 @@ +[gd_resource type="DynamicFont" load_steps=2 format=2] + +[ext_resource path="res://assets/theme/fonts/source_code_pro/SourceCodePro-Medium.otf" type="DynamicFontData" id=1] + +[resource] +size = 26 +use_filter = true +font_data = ExtResource( 1 ) diff --git a/godot/assets/theme/fonts/font_title.tres b/godot/assets/theme/fonts/font_title.tres new file mode 100644 index 0000000..a1788d3 --- /dev/null +++ b/godot/assets/theme/fonts/font_title.tres @@ -0,0 +1,8 @@ +[gd_resource type="DynamicFont" load_steps=2 format=2] + +[ext_resource path="res://assets/theme/fonts/montserrat/Montserrat-Black.ttf" type="DynamicFontData" id=1] + +[resource] +size = 34 +use_filter = true +font_data = ExtResource( 1 ) diff --git a/godot/assets/theme/fonts/montserrat/Montserrat-Black.ttf b/godot/assets/theme/fonts/montserrat/Montserrat-Black.ttf new file mode 100644 index 0000000..f0d24ad Binary files /dev/null and b/godot/assets/theme/fonts/montserrat/Montserrat-Black.ttf differ diff --git a/godot/assets/theme/fonts/montserrat/Montserrat-Bold.ttf b/godot/assets/theme/fonts/montserrat/Montserrat-Bold.ttf new file mode 100644 index 0000000..9a425b9 Binary files /dev/null and b/godot/assets/theme/fonts/montserrat/Montserrat-Bold.ttf differ diff --git a/godot/assets/theme/fonts/montserrat/Montserrat-Medium.ttf b/godot/assets/theme/fonts/montserrat/Montserrat-Medium.ttf new file mode 100644 index 0000000..db5b1af Binary files /dev/null and b/godot/assets/theme/fonts/montserrat/Montserrat-Medium.ttf differ diff --git a/godot/assets/theme/fonts/source_code_pro/SourceCodePro-Medium.otf b/godot/assets/theme/fonts/source_code_pro/SourceCodePro-Medium.otf new file mode 100644 index 0000000..1b42738 Binary files /dev/null and b/godot/assets/theme/fonts/source_code_pro/SourceCodePro-Medium.otf differ diff --git a/godot/assets/theme/gdquest.theme b/godot/assets/theme/gdquest.theme new file mode 100644 index 0000000..61b83dd Binary files /dev/null and b/godot/assets/theme/gdquest.theme differ diff --git a/godot/assets/theme/icons/chevron-right.svg b/godot/assets/theme/icons/chevron-right.svg new file mode 100644 index 0000000..258de41 --- /dev/null +++ b/godot/assets/theme/icons/chevron-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/godot/assets/theme/icons/chevron-right.svg.import b/godot/assets/theme/icons/chevron-right.svg.import new file mode 100644 index 0000000..000f669 --- /dev/null +++ b/godot/assets/theme/icons/chevron-right.svg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/chevron-right.svg-f77dee7a088177a2ac1d467f4c7cd3e1.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/theme/icons/chevron-right.svg" +dest_files=[ "res://.import/chevron-right.svg-f77dee7a088177a2ac1d467f4c7cd3e1.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/godot/assets/theme/icons/chevron-up.svg b/godot/assets/theme/icons/chevron-up.svg new file mode 100644 index 0000000..4eb5ecc --- /dev/null +++ b/godot/assets/theme/icons/chevron-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/godot/assets/theme/icons/chevron-up.svg.import b/godot/assets/theme/icons/chevron-up.svg.import new file mode 100644 index 0000000..14e96f7 --- /dev/null +++ b/godot/assets/theme/icons/chevron-up.svg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/chevron-up.svg-48b5b69265734774d0a7516dcc6f0863.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/theme/icons/chevron-up.svg" +dest_files=[ "res://.import/chevron-up.svg-48b5b69265734774d0a7516dcc6f0863.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/godot/assets/theme/panel/panel.stylebox b/godot/assets/theme/panel/panel.stylebox new file mode 100644 index 0000000..0c557d0 Binary files /dev/null and b/godot/assets/theme/panel/panel.stylebox differ diff --git a/godot/assets/theme/separator/line.tres b/godot/assets/theme/separator/line.tres new file mode 100644 index 0000000..49130dc --- /dev/null +++ b/godot/assets/theme/separator/line.tres @@ -0,0 +1,5 @@ +[gd_resource type="StyleBoxLine" format=2] + +[resource] +color = Color( 1, 1, 1, 0.196078 ) +thickness = 2 diff --git a/godot/assets/theme/slider/grabber_area.stylebox b/godot/assets/theme/slider/grabber_area.stylebox new file mode 100644 index 0000000..5fd31a9 Binary files /dev/null and b/godot/assets/theme/slider/grabber_area.stylebox differ diff --git a/godot/assets/theme/slider/slider.stylebox b/godot/assets/theme/slider/slider.stylebox new file mode 100644 index 0000000..f89f29b Binary files /dev/null and b/godot/assets/theme/slider/slider.stylebox differ diff --git a/godot/default_env.tres b/godot/default_env.tres new file mode 100644 index 0000000..20207a4 --- /dev/null +++ b/godot/default_env.tres @@ -0,0 +1,7 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/godot/project.godot b/godot/project.godot new file mode 100644 index 0000000..2de5182 --- /dev/null +++ b/godot/project.godot @@ -0,0 +1,245 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +_global_script_classes=[ { +"base": "Reference", +"class": "DemoPickerUI", +"language": "GDScript", +"path": "res://Demos/DemoPickerUI.gd" +}, { +"base": "Reference", +"class": "GSAIAgentLocation", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/GSAIAgentLocation.gd" +}, { +"base": "GSAISteeringBehavior", +"class": "GSAIArrive", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIArrive.gd" +}, { +"base": "GSAIGroupBehavior", +"class": "GSAIAvoidCollisions", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIAvoidCollisions.gd" +}, { +"base": "GSAISteeringBehavior", +"class": "GSAIBlend", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIBlend.gd" +}, { +"base": "GSAIGroupBehavior", +"class": "GSAICohesion", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAICohesion.gd" +}, { +"base": "GSAIPursue", +"class": "GSAIEvade", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIEvade.gd" +}, { +"base": "GSAIMatchOrientation", +"class": "GSAIFace", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFace.gd" +}, { +"base": "GSAISeek", +"class": "GSAIFlee", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFlee.gd" +}, { +"base": "GSAIArrive", +"class": "GSAIFollowPath", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIFollowPath.gd" +}, { +"base": "GSAISteeringBehavior", +"class": "GSAIGroupBehavior", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/GSAIGroupBehavior.gd" +}, { +"base": "GSAIProximity", +"class": "GSAIInfiniteProximity", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIInfiniteProximity.gd" +}, { +"base": "GSAISpecializedAgent", +"class": "GSAIKinematicBody2DAgent", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIKinematicBody2DAgent.gd" +}, { +"base": "GSAISpecializedAgent", +"class": "GSAIKinematicBody3DAgent", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIKinematicBody3DAgent.gd" +}, { +"base": "GSAIMatchOrientation", +"class": "GSAILookWhereYouGo", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAILookWhereYouGo.gd" +}, { +"base": "GSAISteeringBehavior", +"class": "GSAIMatchOrientation", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIMatchOrientation.gd" +}, { +"base": "Reference", +"class": "GSAIPath", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/GSAIPath.gd" +}, { +"base": "GSAISteeringBehavior", +"class": "GSAIPriority", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIPriority.gd" +}, { +"base": "Reference", +"class": "GSAIProximity", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIProximity.gd" +}, { +"base": "GSAISteeringBehavior", +"class": "GSAIPursue", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAIPursue.gd" +}, { +"base": "GSAIProximity", +"class": "GSAIRadiusProximity", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Proximities/GSAIRadiusProximity.gd" +}, { +"base": "GSAISpecializedAgent", +"class": "GSAIRigidBody2DAgent", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIRigidBody2DAgent.gd" +}, { +"base": "GSAISpecializedAgent", +"class": "GSAIRigidBody3DAgent", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Agents/GSAIRigidBody3DAgent.gd" +}, { +"base": "GSAISteeringBehavior", +"class": "GSAISeek", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAISeek.gd" +}, { +"base": "GSAIGroupBehavior", +"class": "GSAISeparation", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Behaviors/GSAISeparation.gd" +}, { +"base": "GSAISteeringAgent", +"class": "GSAISpecializedAgent", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/Agents/GSAISpecializedAgent.gd" +}, { +"base": "GSAIAgentLocation", +"class": "GSAISteeringAgent", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/GSAISteeringAgent.gd" +}, { +"base": "Reference", +"class": "GSAISteeringBehavior", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/GSAISteeringBehavior.gd" +}, { +"base": "Reference", +"class": "GSAITargetAcceleration", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/GSAITargetAcceleration.gd" +}, { +"base": "Reference", +"class": "GSAIUtils", +"language": "GDScript", +"path": "res://addons/com.gdquest.godot-steering-ai-framework/GSAIUtils.gd" +} ] +_global_script_class_icons={ +"DemoPickerUI": "", +"GSAIAgentLocation": "", +"GSAIArrive": "", +"GSAIAvoidCollisions": "", +"GSAIBlend": "", +"GSAICohesion": "", +"GSAIEvade": "", +"GSAIFace": "", +"GSAIFlee": "", +"GSAIFollowPath": "", +"GSAIGroupBehavior": "", +"GSAIInfiniteProximity": "", +"GSAIKinematicBody2DAgent": "", +"GSAIKinematicBody3DAgent": "", +"GSAILookWhereYouGo": "", +"GSAIMatchOrientation": "", +"GSAIPath": "", +"GSAIPriority": "", +"GSAIProximity": "", +"GSAIPursue": "", +"GSAIRadiusProximity": "", +"GSAIRigidBody2DAgent": "", +"GSAIRigidBody3DAgent": "", +"GSAISeek": "", +"GSAISeparation": "", +"GSAISpecializedAgent": "", +"GSAISteeringAgent": "", +"GSAISteeringBehavior": "", +"GSAITargetAcceleration": "", +"GSAIUtils": "" +} + +[application] + +config/name="Godot Steering AI Framework Demos" +run/main_scene="res://Demos/DemoSelector.tscn" +config/icon="res://assets/icon.png" + +[display] + +window/size/width=1920 +window/size/height=1080 +window/size/always_on_top=true +window/size/test_width=1280 +window/size/test_height=720 +window/stretch/mode="2d" +window/stretch/aspect="expand" + +[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) + ] +} +toggle_fullscreen={ +"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":16777254,"unicode":0,"echo":false,"script":null) + ] +} + +[rendering] + +environment/default_environment="res://default_env.tres"