Removed state machine for behavior trees

- Added Font Awesome Support
This commit is contained in:
Tony Bark 2023-03-14 06:30:58 -04:00
parent b133ee2680
commit c46d0e27e4
161 changed files with 7082 additions and 1083 deletions

View file

@ -0,0 +1,12 @@
# 🗣️ Sharing blackboard : the talking game !
This example demonstrates how to share a single blackboard in multiple behavior trees.
Sharing a blackboard can be necessary if you want to easily share data between trees, for example, to synchronize multiple NPCs.
The blackboard can be instantiate in a Scene Tree via the editor, or in a script (as in this example).
## Technical elements
- `main.tscn` : scene to run. The main scene instantiates a unique blackboard and give it to all player trees,
- `player.tscn` : a player in the talking game. They all share the same blackboard to known who is the next to talk.

View file

@ -0,0 +1,42 @@
extends Node2D
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
var _shared_blackboard:BTBlackboard
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _ready() -> void:
_shared_blackboard = BTBlackboard.new()
_shared_blackboard.set_data("next_talking", "Alice")
_shared_blackboard.set_data("players", [])
$"PlayerAlice/BTRoot/".blackboard = _shared_blackboard
$"PlayerBob/BTRoot/".blackboard = _shared_blackboard
$"PlayerCharles/BTRoot/".blackboard = _shared_blackboard
$"PlayerEmily/BTRoot/".blackboard = _shared_blackboard
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -0,0 +1,23 @@
[gd_scene load_steps=3 format=3 uid="uid://d1s5iyoblr4cm"]
[ext_resource type="Script" path="res://examples/blackboard_sharing/main.gd" id="1_g7q7h"]
[ext_resource type="PackedScene" uid="uid://7k8r0e84lcr3" path="res://examples/blackboard_sharing/player.tscn" id="2_y55mt"]
[node name="World" type="Node2D"]
script = ExtResource("1_g7q7h")
[node name="PlayerAlice" parent="." instance=ExtResource("2_y55mt")]
position = Vector2(509, 181)
player_name = "Alice"
[node name="PlayerBob" parent="." instance=ExtResource("2_y55mt")]
position = Vector2(515, 477)
player_name = "Bob"
[node name="PlayerCharles" parent="." instance=ExtResource("2_y55mt")]
position = Vector2(309, 324)
player_name = "Charles"
[node name="PlayerEmily" parent="." instance=ExtResource("2_y55mt")]
position = Vector2(733, 322)
player_name = "Emily"

View file

@ -0,0 +1,63 @@
extends Node2D
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export var player_name:String = "":
set(value):
player_name = value
if _name_label:
_name_label.text = player_name
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
@onready var _text_label:Label = $GUI/Text
@onready var _name_label:Label = $GUI/Name
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _ready() -> void:
_name_label.text = player_name
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func declare_presence(blackboard:BTBlackboard) -> int:
blackboard.get_data("players").append(player_name)
return BTTickResult.SUCCESS
func is_my_turn_to_talk(next_talking:String) -> bool:
return player_name == next_talking
func talk() -> int:
_text_label.visible = true
get_tree().create_timer(1).timeout.connect(func():_text_label.visible = false)
return BTTickResult.SUCCESS
func choose_next_player_talking(blackboard:BTBlackboard) -> int:
blackboard.set_data("next_talking", _pick_next_player(blackboard.get_data("players")))
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions privées
#------------------------------------------
func _pick_next_player(players:Array) -> String:
var result:String = players.pick_random()
while result == player_name:
result = players.pick_random()
return result

View file

@ -0,0 +1,123 @@
[gd_scene load_steps=11 format=3 uid="uid://7k8r0e84lcr3"]
[ext_resource type="Script" path="res://examples/blackboard_sharing/player.gd" id="1_1ti0g"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/BTRoot.gd" id="2_sdd0w"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Composite/BTSelector.gd" id="3_2v3m1"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Composite/BTSequence.gd" id="4_fjw5l"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Decorators/BTSuccess.gd" id="4_qnbqx"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTConditionCallable.gd" id="5_8tfvp"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Decorators/BTLimiter.gd" id="5_d3jao"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTActionCallable.gd" id="6_i6lan"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTActionWait.gd" id="10_1e6f0"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Decorators/BTInverter.gd" id="11_fvy66"]
[node name="Player" type="Node2D"]
script = ExtResource("1_1ti0g")
[node name="Shape" type="Node2D" parent="."]
[node name="Ahahahah" type="Polygon2D" parent="Shape"]
color = Color(0.188235, 0.490196, 0.505882, 1)
polygon = PackedVector2Array(-27, -55, 22, -55, 22, -25, 10, -18, 24, 17, -30, 17, -30, 17, -30, 17, -13, -18, -13, -18, -13, -18, -27, -26, -27, -26, -27, -26)
[node name="GUI" type="Control" parent="."]
layout_mode = 3
anchors_preset = 0
offset_left = -61.0
offset_top = -84.0
offset_right = 61.0
offset_bottom = -58.0
[node name="Text" type="Label" parent="GUI"]
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
text = "My turn !"
horizontal_alignment = 1
vertical_alignment = 1
[node name="Name" type="Label" parent="GUI"]
layout_mode = 0
offset_left = 24.0
offset_top = 104.0
offset_right = 98.0
offset_bottom = 127.0
horizontal_alignment = 1
vertical_alignment = 1
[node name="BTRoot" type="Node" parent="."]
script = ExtResource("2_sdd0w")
actor_path = NodePath("..")
[node name="Do" type="Node" parent="BTRoot"]
script = ExtResource("4_fjw5l")
[node name="Init" type="Node" parent="BTRoot/Do"]
script = ExtResource("4_fjw5l")
save_progression = true
[node name="Declare I am playing" type="Node" parent="BTRoot/Do/Init"]
script = ExtResource("4_qnbqx")
[node name="Do once" type="Node" parent="BTRoot/Do/Init/Declare I am playing"]
script = ExtResource("5_d3jao")
[node name="I\'m here !" type="Node" parent="BTRoot/Do/Init/Declare I am playing/Do once"]
script = ExtResource("6_i6lan")
method_owner_path = NodePath("../../../../../..")
method_name = "declare_presence"
method_arguments = Array[String](["blackboard"])
[node name="Invert" type="Node" parent="BTRoot/Do/Init"]
script = ExtResource("11_fvy66")
[node name="Do once" type="Node" parent="BTRoot/Do/Init/Invert"]
script = ExtResource("5_d3jao")
[node name="Wait 1s" type="Node" parent="BTRoot/Do/Init/Invert/Do once"]
script = ExtResource("10_1e6f0")
[node name="One Between" type="Node" parent="BTRoot/Do"]
script = ExtResource("3_2v3m1")
save_progression = true
[node name="I must talk" type="Node" parent="BTRoot/Do/One Between"]
script = ExtResource("4_fjw5l")
save_progression = true
[node name="Is my Turn ?" type="Node" parent="BTRoot/Do/One Between/I must talk"]
script = ExtResource("5_8tfvp")
method_owner_path = NodePath("../../../../..")
method_name = "is_my_turn_to_talk"
method_arguments = Array[String](["blackboard.get_data(\"next_talking\")"])
[node name="Talk" type="Node" parent="BTRoot/Do/One Between/I must talk"]
script = ExtResource("6_i6lan")
method_owner_path = NodePath("../../../../..")
method_name = "talk"
[node name="Wait a little bit" type="Node" parent="BTRoot/Do/One Between/I must talk"]
script = ExtResource("10_1e6f0")
random_deviation_ms = 300
[node name="Set Next Player To Talk" type="Node" parent="BTRoot/Do/One Between/I must talk"]
script = ExtResource("6_i6lan")
method_owner_path = NodePath("../../../../..")
method_name = "choose_next_player_talking"
method_arguments = Array[String](["blackboard"])
[node name="I must listen" type="Node" parent="BTRoot/Do/One Between"]
script = ExtResource("4_fjw5l")
[node name="Not my turn" type="Node" parent="BTRoot/Do/One Between/I must listen"]
script = ExtResource("11_fvy66")
[node name="Is my Turn ?" type="Node" parent="BTRoot/Do/One Between/I must listen/Not my turn"]
script = ExtResource("5_8tfvp")
method_owner_path = NodePath("../../../../../..")
method_name = "is_my_turn_to_talk"
method_arguments = Array[String](["blackboard.get_data(\"next_talking\")"])

View file

@ -0,0 +1,12 @@
# 🪵 Simple AI logic : the lumberjack !
This example is about a lumberjack that needs to cut logs. He can carry a certain quantity of logs before going back to the nearest warehouse to drop logs. When logs are dropped, he moves back to the tree he was cutting (or, the nearest tree if the tree is cut), and cut logs again.
The aim of this example is to show how to implement a simple AI logic, composed of differents phases, using a behavior tree. This is just a proposal, there are several ways to create our lumberjack !
In lumberjack behavior tree, you can notice there is no custom tree node (action or condition) : only based ones are used. To execute functional actions, like dropping logs, the `BTActionCallable` is used. It allows to call a method in a node. For simple behavior trees, it allows to contain all logic into the same script.
## Technical elements
- `main.tscn` : scene to run,
- `lumberjack.tscn` : the lumberjack. The behavior tree is in this scene.

49
examples/simple_ai_logic/env/tree.gd vendored Normal file
View file

@ -0,0 +1,49 @@
extends Node2D
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export var max_log_count:int = 3
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
@onready var remaining_logs:int = max_log_count
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _draw():
var poly = $ShapeFull/Leaves.polygon
for i in range(1 , poly.size()):
draw_line(poly[i-1] , poly[i], Color.BLACK , 1)
draw_line(poly[poly.size() - 1] , poly[0], Color.BLACK , 1)
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func has_logs() -> bool:
return remaining_logs > 0
func cut_log() -> void:
if remaining_logs > 0:
remaining_logs -= 1
if remaining_logs == 0:
queue_free()
#------------------------------------------
# Fonctions privées
#------------------------------------------

27
examples/simple_ai_logic/env/tree.tscn vendored Normal file
View file

@ -0,0 +1,27 @@
[gd_scene load_steps=5 format=3]
[ext_resource type="Script" path="res://examples/simple_ai_logic/env/tree.gd" id="1_r2ta2"]
[sub_resource type="Gradient" id="Gradient_aa3nm"]
colors = PackedColorArray(0.408848, 0.73338, 3.85046e-07, 1, 1, 1, 1, 1)
[sub_resource type="FastNoiseLite" id="FastNoiseLite_2o5uu"]
frequency = 0.025
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_0hflj"]
color_ramp = SubResource("Gradient_aa3nm")
noise = SubResource("FastNoiseLite_2o5uu")
[node name="Tree" type="Node2D" groups=["tree"]]
script = ExtResource("1_r2ta2")
[node name="ShapeFull" type="Node2D" parent="."]
[node name="Base" type="Polygon2D" parent="ShapeFull"]
color = Color(0.270588, 0.141176, 0, 1)
polygon = PackedVector2Array(-15, 7, -15, 7, 11, 7, 11, 7, 11, 7, 1, -6, 1, -6, 1, -6, 6, -38, -4, -38, -4, -38, -4, -38)
[node name="Leaves" type="Polygon2D" parent="ShapeFull"]
color = Color(0.121569, 0.301961, 0.0470588, 1)
texture = SubResource("NoiseTexture2D_0hflj")
polygon = PackedVector2Array(-3, -22, -3, -22, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -11, -26, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -18, -32, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -39, -23, -47, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -18, -60, -21, -76, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -22, -86, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, -7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 7, -95, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 19, -91, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 25, -84, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -69, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 29, -57, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 30, -49, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 33, -43, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 34, -36, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 31, -31, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 20, -25, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21, 7, -21)

View file

@ -0,0 +1,9 @@
[gd_scene format=3 uid="uid://i4372roabk7a"]
[node name="Warehouse" type="Node2D" groups=["warehouse"]]
[node name="Shape" type="Polygon2D" parent="."]
position = Vector2(0, 7)
scale = Vector2(0.28841, 0.28841)
color = Color(0.270588, 0.145098, 0.0117647, 1)
polygon = PackedVector2Array(-110.953, 0, 232.308, 0, 232.308, -225.374, 138.691, -298.187, -180.299, -218.439, -110.953, -218.439)

View file

@ -0,0 +1,102 @@
extends Node2D
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
@export_category("Logger")
@export var max_log_capacity:int = 2
#------------------------------------------
# Variables publiques
#------------------------------------------
var logs_count:int = 0
#------------------------------------------
# Variables privées
#------------------------------------------
@onready var _btroot:BTRoot = $AI
var _cutting_log:bool = false
var _cutting_tree:Node2D
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
#------------------------------------------
# Fonctions publiques
#------------------------------------------
func on_state_entered() :
_btroot.on_running.connect(func(s):print(s))
_btroot.on_idle.connect(func():print("idle..."))
_btroot.enabled = true
func can_carry_more_logs() -> bool:
return logs_count < max_log_capacity
func has_no_log() -> bool:
return logs_count == 0
func has_remaining_trees() -> bool:
return not get_tree().get_nodes_in_group("tree").is_empty()
func get_nearest_tree() -> Node2D:
var nearest_tree:Node2D
var nearest_distance_to_tree:float = 99999.0
for tree in get_tree().get_nodes_in_group("tree"):
var distance_to_tree:float = global_position.distance_to(tree.global_position)
if distance_to_tree < nearest_distance_to_tree:
nearest_distance_to_tree = distance_to_tree
nearest_tree = tree
return nearest_tree
func get_nearest_warehouse() -> Node2D:
var nearest_warehouse:Node2D
var nearest_distance_to_warehouse:float = 99999.0
for warehouse in get_tree().get_nodes_in_group("warehouse"):
var distance_to_warehouse:float = global_position.distance_to(warehouse.global_position)
if distance_to_warehouse < nearest_distance_to_warehouse:
nearest_distance_to_warehouse = distance_to_warehouse
nearest_warehouse = warehouse
return nearest_warehouse
func tree_is_valid(tree:Node2D) -> bool:
return is_instance_valid(tree) and tree.has_logs()
func cut_log(tree:Node2D) -> int:
if not _cutting_log:
_cutting_log = true
_cutting_tree = tree
get_tree().create_timer(1).timeout.connect(_on_log_cut, CONNECT_ONE_SHOT)
return BTTickResult.RUNNING if _cutting_log else BTTickResult.FAILURE
func drop_logs_to_warehouse() -> void:
logs_count = 0
func move_to(delta:float, node:Node2D) -> int:
if global_position.distance_to(node.global_position) > 10:
global_position = global_position.move_toward(node.global_position, delta * 300)
return BTTickResult.RUNNING
else:
return BTTickResult.SUCCESS
#------------------------------------------
# Fonctions privées
#------------------------------------------
func _on_log_cut() -> void:
if is_instance_valid(_cutting_tree):
_cutting_tree.cut_log()
_cutting_tree = null
logs_count += 1
_cutting_log = false

View file

@ -0,0 +1,167 @@
[gd_scene load_steps=11 format=3 uid="uid://bl8kvanpmae2g"]
[ext_resource type="Script" path="res://examples/simple_ai_logic/lumberjack.gd" id="1_4c8nf"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/BTRoot.gd" id="2_hoy6d"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Composite/BTSelector.gd" id="3_5vl0m"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Composite/BTSequence.gd" id="4_c83di"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Decorators/BTInverter.gd" id="5_iaq0m"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTConditionCallable.gd" id="6_wov0v"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTActionBlackboardSet.gd" id="7_f8o6y"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTActionCallable.gd" id="8_mjt8i"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Decorators/BTFailure.gd" id="9_ojjv5"]
[ext_resource type="Script" path="res://addons/yet_another_behavior_tree/src/Nodes/Leaves/BTActionBlackboardDelete.gd" id="10_7bq5a"]
[node name="LumberJack" type="Node2D"]
script = ExtResource("1_4c8nf")
[node name="Shape" type="Node2D" parent="."]
[node name="Polygon2D" type="Polygon2D" parent="Shape"]
color = Color(0.54902, 0.0862745, 0.117647, 1)
polygon = PackedVector2Array(-2, -5, -2, -2, -1, -2, -1, 0, -4, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, -5, 5, 4, 5, 1, 0, 1, -2, 2, -2, 2, -5)
[node name="AI" type="Node" parent="."]
script = ExtResource("2_hoy6d")
actor_path = NodePath("..")
[node name="One Between" type="Node" parent="AI"]
script = ExtResource("3_5vl0m")
[node name="Idle To Warehouse" type="Node" parent="AI/One Between"]
script = ExtResource("4_c83di")
[node name="No Remaining Tree" type="Node" parent="AI/One Between/Idle To Warehouse"]
script = ExtResource("5_iaq0m")
[node name="At Least One Tree" type="Node" parent="AI/One Between/Idle To Warehouse/No Remaining Tree"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../..")
method_name = "has_remaining_trees"
[node name="Has No Log" type="Node" parent="AI/One Between/Idle To Warehouse"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../..")
method_name = "has_no_log"
[node name="Move To Nearest Warehouse" type="Node" parent="AI/One Between/Idle To Warehouse"]
script = ExtResource("4_c83di")
[node name="Get Nearest Warehouse" type="Node" parent="AI/One Between/Idle To Warehouse/Move To Nearest Warehouse"]
script = ExtResource("7_f8o6y")
blackboard_key = "nearest_warehouse"
expression = "actor.get_nearest_warehouse()"
can_overwrite_value = true
[node name="Move To Warehouse" type="Node" parent="AI/One Between/Idle To Warehouse/Move To Nearest Warehouse"]
script = ExtResource("8_mjt8i")
method_owner_path = NodePath("../../../../..")
method_name = "move_to"
method_arguments = Array[String](["delta", "blackboard.get_data(\"nearest_warehouse\")"])
[node name="Put Logs To Warehouse" type="Node" parent="AI/One Between"]
script = ExtResource("4_c83di")
[node name="One Between" type="Node" parent="AI/One Between/Put Logs To Warehouse"]
script = ExtResource("3_5vl0m")
[node name="Can NOT Carry More Logs" type="Node" parent="AI/One Between/Put Logs To Warehouse/One Between"]
script = ExtResource("5_iaq0m")
[node name="Can Cary More Logs" type="Node" parent="AI/One Between/Put Logs To Warehouse/One Between/Can NOT Carry More Logs"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../../..")
method_name = "can_carry_more_logs"
[node name="No Remaining Tree" type="Node" parent="AI/One Between/Put Logs To Warehouse/One Between"]
script = ExtResource("5_iaq0m")
[node name="At Least One Tree" type="Node" parent="AI/One Between/Put Logs To Warehouse/One Between/No Remaining Tree"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../../..")
method_name = "has_remaining_trees"
[node name="Move To Nearest Warehouse" type="Node" parent="AI/One Between/Put Logs To Warehouse"]
script = ExtResource("4_c83di")
[node name="Get Nearest Warehouse" type="Node" parent="AI/One Between/Put Logs To Warehouse/Move To Nearest Warehouse"]
script = ExtResource("7_f8o6y")
blackboard_key = "nearest_warehouse"
expression = "actor.get_nearest_warehouse()"
can_overwrite_value = true
[node name="Move To Warehouse" type="Node" parent="AI/One Between/Put Logs To Warehouse/Move To Nearest Warehouse"]
script = ExtResource("8_mjt8i")
method_owner_path = NodePath("../../../../..")
method_name = "move_to"
method_arguments = Array[String](["delta", "blackboard.get_data(\"nearest_warehouse\")"])
[node name="Drop Logs" type="Node" parent="AI/One Between/Put Logs To Warehouse"]
script = ExtResource("8_mjt8i")
method_owner_path = NodePath("../../../..")
method_name = "drop_logs_to_warehouse"
[node name="Get Log" type="Node" parent="AI/One Between"]
script = ExtResource("4_c83di")
[node name="Can Carry More Logs" type="Node" parent="AI/One Between/Get Log"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../..")
method_name = "can_carry_more_logs"
[node name="Move To Nearest Tree" type="Node" parent="AI/One Between/Get Log"]
script = ExtResource("4_c83di")
[node name="Has Remaning Trees" type="Node" parent="AI/One Between/Get Log/Move To Nearest Tree"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../..")
method_name = "has_remaining_trees"
[node name="Get Nearest Tree" type="Node" parent="AI/One Between/Get Log/Move To Nearest Tree"]
script = ExtResource("7_f8o6y")
blackboard_key = "nearest_tree"
expression = "actor.get_nearest_tree()"
[node name="Stop If Nearest Tree If Invalid" type="Node" parent="AI/One Between/Get Log"]
script = ExtResource("4_c83di")
[node name="OR" type="Node" parent="AI/One Between/Get Log/Stop If Nearest Tree If Invalid"]
script = ExtResource("3_5vl0m")
[node name="Tree Is Valid" type="Node" parent="AI/One Between/Get Log/Stop If Nearest Tree If Invalid/OR"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../../..")
method_name = "tree_is_valid"
method_arguments = Array[String](["blackboard.get_data(\"nearest_tree\")"])
[node name="Stop Because Tree Invalid" type="Node" parent="AI/One Between/Get Log/Stop If Nearest Tree If Invalid/OR"]
script = ExtResource("9_ojjv5")
[node name="Delete Nearest Tree Ref" type="Node" parent="AI/One Between/Get Log/Stop If Nearest Tree If Invalid/OR/Stop Because Tree Invalid"]
script = ExtResource("10_7bq5a")
blackboard_key = "nearest_tree"
[node name="Move To Tree" type="Node" parent="AI/One Between/Get Log"]
script = ExtResource("8_mjt8i")
method_owner_path = NodePath("../../../..")
method_name = "move_to"
method_arguments = Array[String](["delta", "blackboard.get_data(\"nearest_tree\")"])
[node name="Cut Tree" type="Node" parent="AI/One Between/Get Log"]
script = ExtResource("4_c83di")
[node name="Nearest Tree Is Valid" type="Node" parent="AI/One Between/Get Log/Cut Tree"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../..")
method_name = "tree_is_valid"
method_arguments = Array[String](["blackboard.get_data(\"nearest_tree\")"])
[node name="Can Carry More Logs" type="Node" parent="AI/One Between/Get Log/Cut Tree"]
script = ExtResource("6_wov0v")
method_owner_path = NodePath("../../../../..")
method_name = "can_carry_more_logs"
[node name="Cut Log From Tree" type="Node" parent="AI/One Between/Get Log/Cut Tree"]
script = ExtResource("8_mjt8i")
method_owner_path = NodePath("../../../../..")
method_name = "cut_log"
method_arguments = Array[String](["blackboard.get_data(\"nearest_tree\")"])

View file

@ -0,0 +1,36 @@
extends Node2D
#------------------------------------------
# Signaux
#------------------------------------------
#------------------------------------------
# Exports
#------------------------------------------
#------------------------------------------
# Variables publiques
#------------------------------------------
#------------------------------------------
# Variables privées
#------------------------------------------
#------------------------------------------
# Fonctions Godot redéfinies
#------------------------------------------
func _process(_delta:float) -> void:
if Input.is_action_just_released("ui_accept"):
var new_tree:Node2D = preload("res://examples/simple_ai_logic/env/tree.tscn").instantiate()
new_tree.global_position = get_global_mouse_position()
$Trees.add_child(new_tree)
#------------------------------------------
# Fonctions publiques
#------------------------------------------
#------------------------------------------
# Fonctions privées
#------------------------------------------

View file

@ -0,0 +1,104 @@
[gd_scene load_steps=8 format=3 uid="uid://ccttcdvcigdoe"]
[ext_resource type="Script" path="res://examples/simple_ai_logic/main.gd" id="1_23dkn"]
[ext_resource type="PackedScene" uid="uid://i4372roabk7a" path="res://examples/simple_ai_logic/env/warehouse.tscn" id="2_hh1py"]
[ext_resource type="PackedScene" path="res://examples/simple_ai_logic/env/tree.tscn" id="3_qyub5"]
[ext_resource type="PackedScene" uid="uid://bl8kvanpmae2g" path="res://examples/simple_ai_logic/lumberjack.tscn" id="4_782kh"]
[sub_resource type="Gradient" id="Gradient_rssdc"]
colors = PackedColorArray(0.787759, 0.787759, 0.787759, 1, 1, 1, 1, 1)
[sub_resource type="FastNoiseLite" id="FastNoiseLite_ql20u"]
noise_type = 2
frequency = 0.005
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_181qe"]
width = 2050
height = 2050
color_ramp = SubResource("Gradient_rssdc")
noise = SubResource("FastNoiseLite_ql20u")
[node name="World" type="Node2D"]
script = ExtResource("1_23dkn")
[node name="Background" type="Polygon2D" parent="."]
color = Color(0.466667, 0.670588, 0, 1)
texture = SubResource("NoiseTexture2D_181qe")
polygon = PackedVector2Array(-7, -7, -7, -7, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, -7, 651, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1160, 655, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7, 1159, -7)
[node name="Warehouses" type="Node2D" parent="."]
[node name="Warehouse1" parent="Warehouses" instance=ExtResource("2_hh1py")]
position = Vector2(805, 229)
[node name="Warehouse2" parent="Warehouses" instance=ExtResource("2_hh1py")]
position = Vector2(268, 556)
[node name="Trees" type="Node2D" parent="."]
y_sort_enabled = true
[node name="Tree" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(132, 126)
[node name="Tree2" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(46, 69)
[node name="Tree3" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(186, 110)
[node name="Tree4" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(78, 126)
[node name="Tree5" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(140, 185)
[node name="Tree6" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(83, 215)
[node name="Tree7" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(581, 604)
[node name="Tree8" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(465, 473)
[node name="Tree9" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(503, 523)
[node name="Tree10" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(541, 495)
[node name="Tree11" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(1044, 124)
[node name="Tree12" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(1074, 235)
[node name="Tree13" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(976, 178)
[node name="Tree14" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(1035, 188)
[node name="Tree15" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(1091, 155)
[node name="Tree16" parent="Trees" instance=ExtResource("3_qyub5")]
position = Vector2(998, 101)
[node name="GUI" type="Control" parent="."]
layout_mode = 3
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="ControlDesc" type="Label" parent="GUI"]
layout_mode = 0
offset_left = 23.0
offset_top = 605.0
offset_right = 371.0
offset_bottom = 631.0
text = "SPACE : plant a tree at mouse location"
[node name="LumberJack" parent="." instance=ExtResource("4_782kh")]
position = Vector2(685, 300)
scale = Vector2(3.5, 3.5)