mirror of
https://github.com/Relintai/godot-steering-ai-framework.git
synced 2024-11-10 00:52:10 +01:00
parent
f73a972ad1
commit
16cc3efb43
@ -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
|
||||
|
24
README.md
24
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.
|
||||
|
||||
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
|
||||
|
||||
**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)
|
||||
<!-- markdown-toc end -->
|
||||
- [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
|
||||
|
||||
|
51
godot/Demos/Arrive/ArriveDemo.gd
Normal file
51
godot/Demos/Arrive/ArriveDemo.gd
Normal file
@ -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
|
39
godot/Demos/Arrive/ArriveDemo.tscn
Normal file
39
godot/Demos/Arrive/ArriveDemo.tscn
Normal file
@ -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]"
|
39
godot/Demos/Arrive/ArriveDemo.tscn.bak
Normal file
39
godot/Demos/Arrive/ArriveDemo.tscn.bak
Normal file
@ -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]"
|
28
godot/Demos/Arrive/Arriver.gd
Normal file
28
godot/Demos/Arrive/Arriver.gd
Normal file
@ -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
|
19
godot/Demos/Arrive/TargetDrawer.gd
Normal file
19
godot/Demos/Arrive/TargetDrawer.gd
Normal file
@ -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)
|
96
godot/Demos/Arrive3d/Arrive3dDemo.tscn
Normal file
96
godot/Demos/Arrive3d/Arrive3dDemo.tscn
Normal file
@ -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."
|
97
godot/Demos/Arrive3d/Arrive3dDemo.tscn.bak
Normal file
97
godot/Demos/Arrive3d/Arrive3dDemo.tscn.bak
Normal file
@ -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."
|
24
godot/Demos/Arrive3d/Camera.gd
Normal file
24
godot/Demos/Arrive3d/Camera.gd
Normal file
@ -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
|
92
godot/Demos/Arrive3d/Seek3dDemo.gd
Normal file
92
godot/Demos/Arrive3d/Seek3dDemo.gd
Normal file
@ -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
|
47
godot/Demos/Arrive3d/Seeker.gd
Normal file
47
godot/Demos/Arrive3d/Seeker.gd
Normal file
@ -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)
|
4
godot/Demos/Arrive3d/SeekerMat.tres
Normal file
4
godot/Demos/Arrive3d/SeekerMat.tres
Normal file
@ -0,0 +1,4 @@
|
||||
[gd_resource type="SpatialMaterial" format=2]
|
||||
|
||||
[resource]
|
||||
albedo_color = Color( 0.152941, 0.764706, 0.247059, 1 )
|
40
godot/Demos/AvoidCollisions/AvoidCollisionsDemo.gd
Normal file
40
godot/Demos/AvoidCollisions/AvoidCollisionsDemo.gd
Normal file
@ -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)
|
26
godot/Demos/AvoidCollisions/AvoidCollisionsDemo.tscn
Normal file
26
godot/Demos/AvoidCollisions/AvoidCollisionsDemo.tscn
Normal file
@ -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."
|
26
godot/Demos/AvoidCollisions/AvoidCollisionsDemo.tscn.bak
Normal file
26
godot/Demos/AvoidCollisions/AvoidCollisionsDemo.tscn.bak
Normal file
@ -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."
|
91
godot/Demos/AvoidCollisions/Avoider.gd
Normal file
91
godot/Demos/AvoidCollisions/Avoider.gd
Normal file
@ -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
|
17
godot/Demos/AvoidCollisions/Avoider.tscn
Normal file
17
godot/Demos/AvoidCollisions/Avoider.tscn
Normal file
@ -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
|
17
godot/Demos/AvoidCollisions/Avoider.tscn.bak
Normal file
17
godot/Demos/AvoidCollisions/Avoider.tscn.bak
Normal file
@ -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
|
66
godot/Demos/AvoidCollisions/Spawner.gd
Normal file
66
godot/Demos/AvoidCollisions/Spawner.gd
Normal file
@ -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()
|
28
godot/Demos/DemoPickerUI.gd
Normal file
28
godot/Demos/DemoPickerUI.gd
Normal file
@ -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")
|
16
godot/Demos/DemoPlayer.gd
Normal file
16
godot/Demos/DemoPlayer.gd
Normal file
@ -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()
|
84
godot/Demos/DemoSelector.tscn
Normal file
84
godot/Demos/DemoSelector.tscn
Normal file
@ -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
|
||||
}
|
30
godot/Demos/Demos.gd
Normal file
30
godot/Demos/Demos.gd
Normal file
@ -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()
|
61
godot/Demos/Face/FaceDemo.gd
Normal file
61
godot/Demos/Face/FaceDemo.gd
Normal file
@ -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
|
48
godot/Demos/Face/FaceDemo.tscn
Normal file
48
godot/Demos/Face/FaceDemo.tscn
Normal file
@ -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"
|
48
godot/Demos/Face/FaceDemo.tscn.bak
Normal file
48
godot/Demos/Face/FaceDemo.tscn.bak
Normal file
@ -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"
|
18
godot/Demos/Face/Player.gd
Normal file
18
godot/Demos/Face/Player.gd
Normal file
@ -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")
|
||||
)
|
43
godot/Demos/Face/Turret.gd
Normal file
43
godot/Demos/Face/Turret.gd
Normal file
@ -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
|
53
godot/Demos/FollowPath/Drawer.gd
Normal file
53
godot/Demos/FollowPath/Drawer.gd
Normal file
@ -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)
|
70
godot/Demos/FollowPath/FollowPathDemo.gd
Normal file
70
godot/Demos/FollowPath/FollowPathDemo.gd
Normal file
@ -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
|
37
godot/Demos/FollowPath/FollowPathDemo.tscn
Normal file
37
godot/Demos/FollowPath/FollowPathDemo.tscn
Normal file
@ -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."
|
37
godot/Demos/FollowPath/FollowPathDemo.tscn.bak
Normal file
37
godot/Demos/FollowPath/FollowPathDemo.tscn.bak
Normal file
@ -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."
|
49
godot/Demos/FollowPath/PathFollower.gd
Normal file
49
godot/Demos/FollowPath/PathFollower.gd
Normal file
@ -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
|
79
godot/Demos/GroupBehaviors/GroupBehaviorsDemo.gd
Normal file
79
godot/Demos/GroupBehaviors/GroupBehaviorsDemo.gd
Normal file
@ -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)
|
26
godot/Demos/GroupBehaviors/GroupBehaviorsDemo.tscn
Normal file
26
godot/Demos/GroupBehaviors/GroupBehaviorsDemo.tscn
Normal file
@ -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."
|
26
godot/Demos/GroupBehaviors/GroupBehaviorsDemo.tscn.bak
Normal file
26
godot/Demos/GroupBehaviors/GroupBehaviorsDemo.tscn.bak
Normal file
@ -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."
|
52
godot/Demos/GroupBehaviors/Member.gd
Normal file
52
godot/Demos/GroupBehaviors/Member.gd
Normal file
@ -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
|
16
godot/Demos/GroupBehaviors/Member.tscn
Normal file
16
godot/Demos/GroupBehaviors/Member.tscn
Normal file
@ -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
|
16
godot/Demos/GroupBehaviors/Member.tscn.bak
Normal file
16
godot/Demos/GroupBehaviors/Member.tscn.bak
Normal file
@ -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
|
73
godot/Demos/GroupBehaviors/Spawner.gd
Normal file
73
godot/Demos/GroupBehaviors/Spawner.gd
Normal file
@ -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
|
68
godot/Demos/PopulateItemList.gd
Normal file
68
godot/Demos/PopulateItemList.gd
Normal file
@ -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)
|
15
godot/Demos/PursueSeek/BoundaryManager.gd
Normal file
15
godot/Demos/PursueSeek/BoundaryManager.gd
Normal file
@ -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)
|
96
godot/Demos/PursueSeek/Player.gd
Normal file
96
godot/Demos/PursueSeek/Player.gd
Normal file
@ -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
|
39
godot/Demos/PursueSeek/PursueAndSeekDemo.gd
Normal file
39
godot/Demos/PursueSeek/PursueAndSeekDemo.gd
Normal file
@ -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
|
92
godot/Demos/PursueSeek/PursueAndSeekDemo.tscn
Normal file
92
godot/Demos/PursueSeek/PursueAndSeekDemo.tscn
Normal file
@ -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"
|
92
godot/Demos/PursueSeek/PursueAndSeekDemo.tscn.bak
Normal file
92
godot/Demos/PursueSeek/PursueAndSeekDemo.tscn.bak
Normal file
@ -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"
|
65
godot/Demos/PursueSeek/Pursuer.gd
Normal file
65
godot/Demos/PursueSeek/Pursuer.gd
Normal file
@ -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)
|
167
godot/Demos/Quickstart/Agent.gd
Normal file
167
godot/Demos/Quickstart/Agent.gd
Normal file
@ -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()
|
33
godot/Demos/Quickstart/Bullet.gd
Normal file
33
godot/Demos/Quickstart/Bullet.gd
Normal file
@ -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()
|
23
godot/Demos/Quickstart/Bullet.tscn
Normal file
23
godot/Demos/Quickstart/Bullet.tscn
Normal file
@ -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
|
23
godot/Demos/Quickstart/Bullet.tscn.bak
Normal file
23
godot/Demos/Quickstart/Bullet.tscn.bak
Normal file
@ -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
|
92
godot/Demos/Quickstart/Player.gd
Normal file
92
godot/Demos/Quickstart/Player.gd
Normal file
@ -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()
|
61
godot/Demos/Quickstart/QuickStartDemo.tscn
Normal file
61
godot/Demos/Quickstart/QuickStartDemo.tscn
Normal file
@ -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="."]
|
61
godot/Demos/Quickstart/QuickStartDemo.tscn.bak
Normal file
61
godot/Demos/Quickstart/QuickStartDemo.tscn.bak
Normal file
@ -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="."]
|
32
godot/Demos/SeekFlee/Boundaries.gd
Normal file
32
godot/Demos/SeekFlee/Boundaries.gd
Normal file
@ -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()
|
26
godot/Demos/SeekFlee/Player.gd
Normal file
26
godot/Demos/SeekFlee/Player.gd
Normal file
@ -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")
|
||||
)
|
82
godot/Demos/SeekFlee/SeekFleeDemo.gd
Normal file
82
godot/Demos/SeekFlee/SeekFleeDemo.gd
Normal file
@ -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
|
81
godot/Demos/SeekFlee/SeekFleeDemo.tscn
Normal file
81
godot/Demos/SeekFlee/SeekFleeDemo.tscn
Normal file
@ -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."
|
81
godot/Demos/SeekFlee/SeekFleeDemo.tscn.bak
Normal file
81
godot/Demos/SeekFlee/SeekFleeDemo.tscn.bak
Normal file
@ -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."
|
29
godot/Demos/SeekFlee/Seeker.gd
Normal file
29
godot/Demos/SeekFlee/Seeker.gd
Normal file
@ -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)
|
19
godot/Demos/SeekFlee/Seeker.tscn
Normal file
19
godot/Demos/SeekFlee/Seeker.tscn
Normal file
@ -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
|
19
godot/Demos/SeekFlee/Seeker.tscn.bak
Normal file
19
godot/Demos/SeekFlee/Seeker.tscn.bak
Normal file
@ -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
|
6
godot/Demos/SeekFlee/Spawner.gd
Normal file
6
godot/Demos/SeekFlee/Spawner.gd
Normal file
@ -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
|
17
godot/Demos/Utils/BackgroudLayer.tscn
Normal file
17
godot/Demos/Utils/BackgroudLayer.tscn
Normal file
@ -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
|
||||
}
|
26
godot/Demos/Utils/CircleDraw.gd
Normal file
26
godot/Demos/Utils/CircleDraw.gd
Normal file
@ -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()
|
13
godot/Demos/Utils/DemoInterface.gd
Normal file
13
godot/Demos/Utils/DemoInterface.gd
Normal file
@ -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
|
37
godot/Demos/Utils/DemoInterface.tscn
Normal file
37
godot/Demos/Utils/DemoInterface.tscn
Normal file
@ -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 )
|
37
godot/Demos/Utils/DemoInterface.tscn.bak
Normal file
37
godot/Demos/Utils/DemoInterface.tscn.bak
Normal file
@ -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 )
|
13
godot/Demos/Utils/Line2DDraw.gd
Normal file
13
godot/Demos/Utils/Line2DDraw.gd
Normal file
@ -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()
|
BIN
godot/assets/icon.png
Normal file
BIN
godot/assets/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user