GodotWIP/src/state_machine_animated_actor.gd

143 lines
6.2 KiB
GDScript

class_name StateMachineAnimatedActor extends StateMachine
func change_state(new_state: State) -> void:
if current_state:
current_state.exit()
# Set parameters for information
if new_state is StateAnimatedActor and current_state is StateAnimatedActor:
set_previous_animation( current_state, new_state)
current_state = new_state
current_state.enter()
if(state_modifiers.size() > 0 and debug_state_machine):
print("Active Modifiers:")
for mods in state_modifiers:
print(mods.name)
func set_previous_animation( old_state: StateAnimatedActor, new_state: StateAnimatedActor ) -> void:
new_state.previous_animation_name = old_state.mod_animation_sequence[old_state.current_animation_sequence]
new_state.previous_state_frame_number = old_state.animations.frame
new_state.previous_state_name = old_state.name
#animation_name :String, frame_number : int, animation_sequence :Array
return
# Initialize the state machine by giving each child state a reference to the
# parent object it belongs to and enter the default starting_state.
func init_animated_actor(parent: KinematicBody2D, animations: AnimatedSprite, move_component: MovementComponent) -> void:
animations.connect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
for child in get_children():
if child is StateAnimatedActor:
if debug_state_machine:
print("Initializing State Node for ", parent.name, ": ", child.name)
child.parent = parent
child.animations = animations
child.move_component = move_component
child.modifier_stack_ref = state_modifiers
if debug_state_machine:
child.debug_state = true
# Initialize to the default state
change_state(get_node(starting_state))
func process_frame(delta: float) -> void:
# Check the state modifiers for timeouts, and maybe more conditions later
# If the modifier is no longer valid, pop it from the stack.
# We could iterate through a whole list of states but I'm not sure i want
# states to be that complex.
var current_anim_state :StateAnimatedActor = current_state
if state_modifiers.empty() == false:
for i in range(state_modifiers.size()):
# if this modifer is a timer based one
if state_modifiers[i].state_timeout.time_left == 0 and state_modifiers[i].timeout_seconds !=0:
# Need to do extra stuff if it's an animation based one
if state_modifiers[i].modifier_type == "Animation Suffix":
if debug_state_machine:
print("State Modifier Timeout: ", state_modifiers[i].name, " -> ", state_modifiers[i].animation_name)
# Reset animation suffix
current_anim_state.animation_suffix = ''
# Get the current frame of animation
var current_frame = current_anim_state.animations.frame
# Set the animation index to the current one
current_anim_state.animation_index = current_anim_state.current_animation_sequence
#current_anim_state.current_animation_sequence
#current_anim_state.animations.play()
current_anim_state.animations.play(
current_anim_state.mod_animation_sequence[current_anim_state.animation_index])
# Try to set the current frame to the same as before.
current_anim_state.animations.frames.frames.size() >= current_frame
current_anim_state.animations.frame = current_frame
##TODO:
# no longer needed this way maybe. way to overengineer man.
# if current_anim_state.animation_sequence.size() >= current_anim_state.mod_animation_sequence.size():
# print("Change sequence!: ", current_anim_state.mod_animation_sequence)
# print("Origin sequence!: ", current_state.mod_animation_sequence)
# current_anim_state.animations.play(
# current_anim_state.mod_animation_sequence[current_anim_state.animation_index])
# # Try to set the current frame to the same as before.
# current_anim_state.animations.frames.frames.size() >= current_frame
# current_anim_state.animations.frame = current_frame
# else:
# current_anim_state.animations.play(
# current_anim_state.animation_sequence[0])
if debug_state_machine:
print("Pop State Modifier: ", state_modifiers[i].name)
state_modifiers.pop_at(i)
# if state_modifiers[-1].state_timeout.time_left == 0 and state_modifiers[-1].pre_append_animation == false:
# if debug_state_machine:
# print("Pop State Modifier: ", state_modifiers[-1].name)
# state_modifiers.pop_back()
# # Reset animation suffix
# current_state.animation_suffix = ''
# var current_frame = current_state.animations.frame
# #current_state.animations.play(current_state.animation_sequence[current_state.animation_index])
# #TODO: Bodge to fix crash
# current_state.animation_index = 0
# current_state.current_animation_sequence = 0
# current_state.animations.play(current_state.animation_sequence[0])
# current_state.animations.frame = current_frame;
var new_state = current_state.process_frame(delta)
if new_state:
change_state(new_state)
func _on_AnimatedSprite_animation_finished():
##TODO:
# It's hard to pop an exit animation off when it's stacked with another kind of animation.
for i in state_modifiers.size():
if state_modifiers[i].modifier_type == "Exit Animation":
#print("Time to pop state modifer: ", state_modifiers[i].animation_name, current_state.animation_suffix, " <-> ", current_state.animations.animation + current_state.animation_suffix)
if (state_modifiers[i].animation_name + current_state.animation_suffix) == current_state.animations.animation:
print("Time to pop state modifer: ", state_modifiers[i].animation_name, current_state.animation_suffix, " <-> ", current_state.animations.animation )
print(current_state.mod_animation_sequence)
state_modifiers.pop_at(i)
current_state.animation_index += 1
break
# if state_modifiers.empty() == false:
# if state_modifiers[-1].pre_append_animation == true:
# if debug_state_machine:
# print("Pop State Modifier: ", state_modifiers[-1].name)
# state_modifiers.pop_back()
##TODO:
# consider just stopping the animation and index increment here.
if current_state.animations.frames.get_animation_loop(
current_state.animations.animation) == false:
if current_state.animation_sequence.size() > 0:
print("<-- next anim.")
current_state.animation_index += 1