GodotWIP/src/state_animated_actor.gd
2024-06-15 08:35:12 -07:00

141 lines
5.2 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 gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity")
var animations: AnimatedSprite
var move_component: MovementComponent
var parent: KinematicBody2D
#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")
# Reset animation suffix in case there isn't one
animation_suffix = ''
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
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 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(animation_sequence[animation_index] + modifier_stack_ref[-1].animation_name):
animation_suffix = 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 animation_sequence.size() > 0:
animation_index = 0
current_animation_sequence = 0
animations.play(animation_sequence[animation_index] + animation_suffix)
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 animation_sequence.size() > animation_index and current_animation_sequence != animation_index:
if animation_index >= animation_sequence.size():
animation_index = 0
##TODO: Add a safety check here.
animations.play(animation_sequence[animation_index] + animation_suffix)
if debug_state:
print("An animation sequence: ", 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 >= 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):
if modifier_stack_ref.has(modifier) == false:
modifier.enter()
modifier_stack_ref.push_front(modifier)