mirror of
https://github.com/Relintai/godot-steering-ai-framework.git
synced 2025-01-22 10:27:19 +01:00
parent
f73a972ad1
commit
16cc3efb43
@ -4,6 +4,9 @@ This document lists new features, improvements, changes, and bug fixes in every
|
|||||||
|
|
||||||
## Master
|
## 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
|
## Godot Steering AI Framework 3.0.0
|
||||||
|
|
||||||
### Changes
|
### 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.
|
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 -->
|
- [Godot Steering AI Framework](#godot-steering-ai-framework)
|
||||||
|
- [Getting the framework](#getting-the-framework)
|
||||||
**Table of Contents**
|
- [Introduction](#introduction)
|
||||||
|
- [The framework](#the-framework)
|
||||||
- [Introduction](#introduction)
|
- [How it works](#how-it-works)
|
||||||
- [The framework](#the-framework)
|
- [Documentation](#documentation)
|
||||||
- [Installation](#installation)
|
- [Contributing](#contributing)
|
||||||
- [Getting Started](#getting-started)
|
- [Support us](#support-us)
|
||||||
- [More information and resources](#more-information-and-resources)
|
- [Join the community](#join-the-community)
|
||||||
- [Example usage](#example-usage)
|
|
||||||
<!-- markdown-toc end -->
|
|
||||||
|
|
||||||
## Getting the framework
|
## 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
|
## 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