239 lines
9.7 KiB
GDScript
239 lines
9.7 KiB
GDScript
class_name StateAnimatedActor
|
|
extends State
|
|
## Animation and movement state class
|
|
##
|
|
## A state intended to control the movement and animation
|
|
## functions of a KinimaticBody2D node. Initialized with a
|
|
## player, movement node, and kinematicbody2d
|
|
## I think if we also had modifier states that transfered along with the enter and entrance of nodes, that would be helpful.
|
|
##
|
|
## @WIP
|
|
|
|
# export (NodePath) var jump_node
|
|
|
|
# onready var jump_state: State = get_node(jump_node)
|
|
|
|
## Deprecated
|
|
# export var animation_name: String
|
|
|
|
export var move_speed: float = 60
|
|
|
|
export(Array, String) var animation_sequence
|
|
|
|
signal frame_reached(state_name, animation_name, frame_number)
|
|
export(Dictionary) var emitter_frame_subscriptions
|
|
var frame_signal_emitted: bool = false
|
|
|
|
# this just wouldn't work well. Maybe I can try a resource
|
|
# export(Array, NodePath) var transition_state_nodes
|
|
|
|
#TODO: I think these two variables accidentally serve the same purpose
|
|
# I think one was intended to be a string of the current animation name.
|
|
var animation_index: int = 0
|
|
var current_animation_sequence: int = 0
|
|
var animation_suffix: String = '';
|
|
|
|
var mod_animation_sequence = [PoolStringArray()]
|
|
|
|
var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity")
|
|
|
|
var animations: AnimatedSprite
|
|
var move_component: MovementComponent
|
|
var parent: KinematicBody2D
|
|
|
|
#animation_name :String, frame_number : int, animation_sequence :Array
|
|
var previous_animation_name : String
|
|
var previous_state_frame_number : int
|
|
var previous_state_name: String
|
|
|
|
#var animation_sequence_timer: Timer
|
|
|
|
|
|
|
|
func _ready():
|
|
##TODO: this bit me in the butt. Should add a safety or something.
|
|
# Only add timout node if timer value was specified.
|
|
if(timeout_seconds > 0.0):
|
|
state_timeout = Timer.new()
|
|
state_timeout.wait_time = timeout_seconds
|
|
state_timeout.one_shot = true
|
|
state_timeout.autostart = false
|
|
add_child(state_timeout)
|
|
|
|
|
|
func enter() -> void:
|
|
# animations.connect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
|
|
mod_animation_sequence.clear()
|
|
#mod_animation_sequence = animation_sequence.duplicate(true)
|
|
mod_animation_sequence.append_array(animation_sequence)
|
|
# Reset animation suffix in case there isn't one
|
|
animation_suffix = ''
|
|
animation_index = 0
|
|
current_animation_sequence = 0
|
|
#var enter_animation = ''
|
|
var enter_frame = 0
|
|
|
|
if debug_state:
|
|
print(parent.name, " entering State: ", self.name)
|
|
move_component.current_movement_state = self.name
|
|
emit_signal("state_entered")
|
|
#modifier_stack_ref = state_modifiers
|
|
|
|
# A new attempt at animation modifiers
|
|
if modifier_stack_ref.empty() == false:
|
|
print("nope: ")
|
|
var i = modifier_stack_ref.size() - 1
|
|
##NOTE: i apparently reverse range itteration doesn't work
|
|
#for i in range(modifier_stack_ref.size(), 0): # work in reverse
|
|
while (i >= 0 and modifier_stack_ref[i].modifier_type != "None"):
|
|
print("Animation Modifier!: ",modifier_stack_ref[i].modifier_type)
|
|
match modifier_stack_ref[i].modifier_type:
|
|
"Exit Animation":
|
|
mod_animation_sequence.push_front(modifier_stack_ref[i].animation_name)
|
|
enter_frame = modifier_stack_ref[i].starting_frame
|
|
|
|
# Gonna ty and avoid this for now
|
|
#modifier_stack_ref.pop_at(i) # we're done with this modifier
|
|
|
|
"Animation Suffix":
|
|
if animations.frames.has_animation(mod_animation_sequence[animation_index] + modifier_stack_ref[i].animation_name):
|
|
animation_suffix = modifier_stack_ref[i].animation_name
|
|
else:
|
|
print("Warning!: Animation suffix that doesn't exist ",
|
|
mod_animation_sequence[animation_index] + modifier_stack_ref[i].animation_name)
|
|
"Replace Animation":
|
|
#animations.play(modifier_stack_ref[i].animation_name)
|
|
#animations.frame = modifier_stack_ref[i].starting_frame
|
|
mod_animation_sequence.clear()
|
|
mod_animation_sequence.push_back(modifier_stack_ref[i].animation_name)
|
|
enter_frame = modifier_stack_ref[i].starting_frame
|
|
i -= 1
|
|
|
|
|
|
# if modifier_stack_ref.empty() == false: # a modifier is applied
|
|
# if modifier_stack_ref[-1].animation_name != '': # the first one has an animation
|
|
# if modifier_stack_ref[-1].animation_suffix: # it's a suffix type
|
|
# if mod_animation_sequence.size() > 0: # the current animation is multipart (sequence > 0)
|
|
# animation_index = 0
|
|
# current_animation_sequence = 0
|
|
# # Guess I don't need this one anymore
|
|
# #if animations.frames.get_animation_names().has(animation_sequence[animation_index] + modifier_stack_ref[-1].animation_name):
|
|
# if animations.frames.has_animation(mod_animation_sequence[animation_index] + modifier_stack_ref[-1].animation_name):
|
|
# animation_suffix = modifier_stack_ref[-1].animation_name
|
|
# elif modifier_stack_ref[-1].pre_append_animation == true: # it's a pre-append type
|
|
# #animation_sequence.size()
|
|
# print ("DEBUG: A prepend animation")
|
|
# #mod_animation_sequence = animation_sequence
|
|
# mod_animation_sequence.push_front(modifier_stack_ref[-1].animation_name)
|
|
# else:
|
|
# animations.play(modifier_stack_ref[-1].animation_name)
|
|
# animations.frame = modifier_stack_ref[-1].starting_frame
|
|
# return
|
|
|
|
if mod_animation_sequence.size() > 0:
|
|
if debug_state:
|
|
print("Starting Animation: " , mod_animation_sequence[animation_index] + animation_suffix)
|
|
animations.play(mod_animation_sequence[animation_index] + animation_suffix)
|
|
#TODO: maybe check current animatio has this frame
|
|
animations.frame = enter_frame
|
|
else:
|
|
print("Error! Resolved to empty animation sequence!?")
|
|
return
|
|
|
|
func exit() -> void:
|
|
emit_signal("state_exited")
|
|
# animations.disconnect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
|
|
return
|
|
|
|
func process_input(_event: InputEvent) -> State:
|
|
return null
|
|
|
|
func process_frame(_delta: float) -> State:
|
|
#if animation_sequence.size() > 0 and current_animation_sequence != animation_index:
|
|
if mod_animation_sequence.size() > animation_index and current_animation_sequence != animation_index:
|
|
#TODO: why was I doing this
|
|
# if animation_index >= mod_animation_sequence.size():
|
|
# animation_index = 0
|
|
##TODO: Add a safety check here.
|
|
animations.play(mod_animation_sequence[animation_index] + animation_suffix)
|
|
if debug_state:
|
|
print("An animation sequence: ", mod_animation_sequence[animation_index - 1], " -> ",
|
|
animations.animation , " (", animation_index, ")")
|
|
current_animation_sequence = animation_index
|
|
# We have no more sequence animations and the current one doesn't loop
|
|
# we do this to prevent the default idle animation from playing.
|
|
if animation_index >= mod_animation_sequence.size() and animations.frames.get_animation_loop(
|
|
animations.animation) == false:
|
|
animations.stop()
|
|
|
|
# Singal based frame call.
|
|
if emitter_frame_subscriptions.has(animations.frame):
|
|
if emitter_frame_subscriptions[animations.frame] == animations.animation:
|
|
if frame_signal_emitted == false:
|
|
emit_signal("frame_reached", self.name, animations.animation, animations.frame)
|
|
# Try to only so this once.
|
|
frame_signal_emitted = true
|
|
else:
|
|
frame_signal_emitted = false
|
|
|
|
return null
|
|
|
|
func process_physics(_delta: float) -> State:
|
|
move_actor_as_desired(_delta)
|
|
return null
|
|
|
|
#func _on_AnimatedSprite_animation_finished():
|
|
# if animations.frames.get_animation_loop(animations.animation) == false:
|
|
# animation_index += 1
|
|
|
|
func move_actor_as_desired(delta: float):
|
|
move_component.velocity.y += gravity * delta
|
|
#parent.velocity = parent.move_and_slide(parent.velocity, Vector2(0, -1))
|
|
move_component.velocity.x = move_component.desired_movement_vector.x * move_speed
|
|
move_component.velocity = parent.move_and_slide(move_component.velocity, Vector2(0, -1))
|
|
|
|
func push_animation_state_modifier(modifier: StateModifier):
|
|
## This function attempt to optimally place multiple modifiers in an array
|
|
# in such a way where the first elements are modifiers without animation changes
|
|
# the last elements are animation changes or animation suffixes.
|
|
# there is some potential for performance issues at scale with this kinds of operations.
|
|
|
|
# This function will grow in complexity as needed but the idea is that here is
|
|
# where different modifier logic can be tested and developed.
|
|
|
|
# First assure this modifer isn't already there. If it is, maybe I should reset it?
|
|
if modifier_stack_ref.has(modifier) == false:
|
|
modifier.enter() # call enter function of the modifier
|
|
if modifier_stack_ref.size() > 0: # only bother with this if multiple modifers applied
|
|
# Get the last modifier in the stack
|
|
var last_modifer: StateModifier = modifier_stack_ref[-1]
|
|
# If the modifier at the back and the new one are the same type, we have a problem.
|
|
if last_modifer.modifier_type == modifier.modifier_type and last_modifer.modifier_type != 'None':
|
|
print("WARNING: Multiple same type modifiers applying.")
|
|
# Replace the modifier
|
|
modifier_stack_ref.pop_back()
|
|
modifier_stack_ref.push_back(modifier)
|
|
else:
|
|
match last_modifer.modifier_type:
|
|
"None":
|
|
# no special processing, push it to the front of a list
|
|
modifier_stack_ref.push_front(modifier)
|
|
"Exit Animation":
|
|
if modifier.modifier_type == "Animation Suffix":
|
|
# We place this at the back so we can still modify it maybe?
|
|
modifier_stack_ref.push_back(modifier)
|
|
"Animation Suffix":
|
|
if modifier.modifier_type == "Exit Animation":
|
|
# We have to place this one right before maybe?
|
|
# Whoops! Forgot to actually do this
|
|
#modifier_stack_ref.push_back(modifier)
|
|
modifier_stack_ref.insert(modifier_stack_ref.size() - 1, modifier)
|
|
# if last_modifer.animation_name != '': # and if an animation applies
|
|
# if last_modifer.pre_append_animation == modifier.pre_append_animation: # They're the same type
|
|
# if modifier.pre_append_animation == true and modifier_stack_ref[-1].animation_suffix == true:
|
|
# modifier.animation_suffix
|
|
# modifier_stack_ref.push_back(modifier)
|
|
else:
|
|
modifier_stack_ref.push_front(modifier)
|
|
|