Bee State Machine
This commit is contained in:
parent
20bcab01b1
commit
752131c955
16 changed files with 467 additions and 13 deletions
55
entities/scripts/bee.gd
Normal file
55
entities/scripts/bee.gd
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
extends Node2D
|
||||
class_name Bee
|
||||
|
||||
@onready var fsm = $StateMachine as FiniteStateMachine
|
||||
@onready var drone_manager = get_tree().get_first_node_in_group("dronemanager") as DroneManager
|
||||
|
||||
@export var nectar : int = 0
|
||||
@export var speed : int = 30
|
||||
|
||||
var latest_target_director : int = 0
|
||||
|
||||
# This is updated when the bee enters or exits a flower patch
|
||||
var in_range_of_flowers : bool = false
|
||||
|
||||
func _ready():
|
||||
Log.pr("I have never bee-n so ready!")
|
||||
|
||||
Log.pr(fsm.current_state.name)
|
||||
|
||||
## Get the next target to move to
|
||||
## If we have no nectar, we need to go up the director list
|
||||
## If we have nectar, we need to go down the director list
|
||||
## If we are at the lower director, we need to go the hive
|
||||
## If we are at the highest director, we need to go to a flower
|
||||
func get_next_target():
|
||||
if nectar == 0:
|
||||
Log.pr("I have no nectar")
|
||||
|
||||
## If there is a next directory drone, lets go to it
|
||||
var next_drone = drone_manager.get_next_director(latest_target_director)
|
||||
if next_drone:
|
||||
Log.pr("Next drone target", next_drone)
|
||||
latest_target_director = next_drone.visit_order
|
||||
return next_drone
|
||||
|
||||
## If there is no next drone, check for a collector drone
|
||||
var collector_drone = drone_manager.get_collector()
|
||||
if collector_drone:
|
||||
Log.pr("Collector drone target", collector_drone)
|
||||
return collector_drone
|
||||
else:
|
||||
Log.pr("I have nectar")
|
||||
|
||||
## Let's go home, we need the previous director drones location
|
||||
var previous_drone = drone_manager.get_previous_director(latest_target_director)
|
||||
if previous_drone:
|
||||
Log.pr("Previous drone target", previous_drone)
|
||||
latest_target_director = previous_drone.visit_order
|
||||
return previous_drone
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
19
entities/scripts/bee_hit_box.gd
Normal file
19
entities/scripts/bee_hit_box.gd
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
extends Area2D
|
||||
|
||||
@onready var bee = get_parent() as Bee
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
|
||||
|
||||
func _on_area_entered(area:Area2D):
|
||||
## Check if the area entered is a flower patch
|
||||
if area.is_in_group("flowers"):
|
||||
bee.in_range_of_flowers = true
|
||||
Log.pr("I found some flowers!")
|
||||
|
||||
func _on_area_exited(area:Area2D):
|
||||
## Check if the area exited is a flower patch
|
||||
if area.is_in_group("flowers"):
|
||||
bee.in_range_of_flowers = false
|
||||
Log.pr("I left the flowers!")
|
||||
|
|
@ -1,11 +1,17 @@
|
|||
class_name DirectorDrone extends Drone
|
||||
|
||||
@export var visit_order : int = 0 :
|
||||
get:
|
||||
return visit_order
|
||||
set(value):
|
||||
visit_order = value
|
||||
update_label_value()
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
pass
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(_delta):
|
||||
pass
|
||||
|
||||
func update_label_value():
|
||||
$Label.text = str(visit_order)
|
||||
69
entities/scripts/finite_state_machine.gd
Normal file
69
entities/scripts/finite_state_machine.gd
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
@icon("res://resources/icons/fsm.png")
|
||||
extends Node
|
||||
class_name FiniteStateMachine
|
||||
|
||||
var states : Dictionary = {}
|
||||
var current_state : State
|
||||
@export var initial_state : State
|
||||
|
||||
#NOTE This is a generic finite_state_machine, it handles all states, changes to this code will affect
|
||||
# everything that uses a state machine!
|
||||
|
||||
func _ready():
|
||||
Log.pr("FSM Ready")
|
||||
for child in get_children():
|
||||
if child is State:
|
||||
states[child.name.to_lower()] = child
|
||||
child.state_transition.connect(change_state)
|
||||
|
||||
Log.pr(states)
|
||||
|
||||
if initial_state:
|
||||
initial_state.enter()
|
||||
current_state = initial_state
|
||||
|
||||
# Call the current states update function
|
||||
func _process(delta):
|
||||
if current_state:
|
||||
current_state.update(delta)
|
||||
|
||||
# Use force_change_state cautiously, it immediately switches to a state regardless of any transitions.
|
||||
# This is used to force us into a 'death state' when killed
|
||||
func force_change_state(new_state : String):
|
||||
var newState = states.get(new_state.to_lower())
|
||||
|
||||
if !newState:
|
||||
print(new_state + " does not exist in the dictionary of states")
|
||||
return
|
||||
|
||||
if current_state == newState:
|
||||
print("State is same, aborting")
|
||||
return
|
||||
|
||||
# NOTE Calling exit like so: (current_state.Exit()) may cause warnings when flushing queries, like when the enemy is being removed after death.
|
||||
# call_deferred is safe and prevents this from occuring. We get the Exit function from the state as a callable and then call it in a thread-safe manner
|
||||
if current_state:
|
||||
var exit_callable = Callable(current_state, "exit")
|
||||
exit_callable.call_deferred()
|
||||
|
||||
newState.enter()
|
||||
|
||||
current_state = newState
|
||||
|
||||
func change_state(source_state : State, new_state_name : String):
|
||||
if source_state != current_state:
|
||||
#print("Invalid change_state trying from: " + source_state.name + " but currently in: " + current_state.name)
|
||||
#This typically only happens when trying to switch from death state following a force_change
|
||||
return
|
||||
|
||||
var new_state = states.get(new_state_name.to_lower())
|
||||
if !new_state:
|
||||
print("New state is empty")
|
||||
return
|
||||
|
||||
if current_state:
|
||||
current_state.exit()
|
||||
|
||||
new_state.enter()
|
||||
|
||||
current_state = new_state
|
||||
15
entities/scripts/state.gd
Normal file
15
entities/scripts/state.gd
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
@icon("res://resources/icons/fsm.png")
|
||||
extends Node
|
||||
class_name State
|
||||
|
||||
signal state_transition
|
||||
|
||||
func enter(_msg := {}):
|
||||
pass
|
||||
|
||||
func exit():
|
||||
pass
|
||||
|
||||
func update(_delta:float):
|
||||
pass
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue