Skip to content

Commit

Permalink
#19 : add an example how to share a blackboard in multiple trees
Browse files Browse the repository at this point in the history
  • Loading branch information
Earewien committed Jan 29, 2023
1 parent 88285d7 commit f0c0a74
Show file tree
Hide file tree
Showing 5 changed files with 264 additions and 0 deletions.
12 changes: 12 additions & 0 deletions examples/blackboard_sharing/README.MD
Original file line number Diff line number Diff line change
@@ -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.
42 changes: 42 additions & 0 deletions examples/blackboard_sharing/main.gd
Original file line number Diff line number Diff line change
@@ -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
#------------------------------------------

23 changes: 23 additions & 0 deletions examples/blackboard_sharing/main.tscn
Original file line number Diff line number Diff line change
@@ -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"
63 changes: 63 additions & 0 deletions examples/blackboard_sharing/player.gd
Original file line number Diff line number Diff line change
@@ -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
124 changes: 124 additions & 0 deletions examples/blackboard_sharing/player.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
[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 = ["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 = ["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"
method_arguments = []

[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 = ["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 = ["blackboard.get_data(\"next_talking\")"]

0 comments on commit f0c0a74

Please sign in to comment.