RPGH_Engine/system/ingame/humanoid/animation_handler.gd
2021-08-05 12:34:08 +02:00

126 lines
3.0 KiB
GDScript

extends Node
enum ViewDirection {
UP = 0,
UP_RIGHT = 1,
RIGHT = 2,
DOWN_RIGHT = 3,
DOWN = 4,
DOWN_LEFT = 5,
LEFT = 6,
UP_LEFT = 7
}
signal texture_position_updated(new_position)
signal tile_reached()
signal frame_pushed(frame_coord)
const SPEED = 100.0
const STEP = 8.0
const FRAMES_PER_SECOND = 8.0
var view_direction = ViewDirection.DOWN
var body_direction = Vector2.DOWN
var speed_multiplier = 1.0
# For movement.
var _previous_position
var _target_position
var _in_walk_animation = false
var _walk_interpolation_ratio = 0.0
# For sheet animation.
var _in_idle_frame = true
var _frame_timer = 0.0
var _previous_frame_timer = 0.0
var _next_initial_frame_timer = 0.0
var _frame_coords
var _previous_frame_coords
func _process(delta):
_handle_walk_animation(delta)
_handle_sprite_sheet_animation(delta)
func start_walk_animation(destination: Vector2):
_previous_position = _target_position
_target_position = destination
_in_walk_animation = true
_in_idle_frame = false
func stop_walk_animation():
_walk_interpolation_ratio = 0.0
_in_walk_animation = false
emit_signal("texture_position_updated", _target_position)
func set_position(new_position):
_previous_position = new_position
_target_position = new_position
emit_signal("texture_position_updated", _target_position)
func is_in_walk_animation():
return _in_walk_animation
func _handle_walk_animation(delta):
if _in_walk_animation:
_walk_interpolation_ratio += SPEED * speed_multiplier / STEP * delta
if _walk_interpolation_ratio >= 1.0:
_walk_interpolation_ratio -= 1.0
emit_signal("tile_reached")
else:
var next_position = _previous_position.linear_interpolate(
_target_position, _walk_interpolation_ratio)
emit_signal("texture_position_updated", next_position)
func _handle_sprite_sheet_animation(delta):
_frame_coords = Vector2.ZERO
if _in_walk_animation:
if _in_idle_frame:
_in_idle_frame = false
_frame_timer = _next_initial_frame_timer
_frame_coords.x = floor(_get_wraped_frame_timer(delta) + 1.0)
else:
if _in_idle_frame:
_frame_coords.x = 0.0
else:
_handle_after_walk_animation(delta)
_frame_coords.y = view_direction
if _frame_coords != _previous_frame_coords:
emit_signal("frame_pushed", _frame_coords)
# The humanoid is supposed to finish its walking animation,
# even if it already reached a whole tile.
func _handle_after_walk_animation(delta):
var wraped_previous_frame_timer = wrapf(_previous_frame_timer, 0.0, 4.0)
var wraped_frame_timer = _get_wraped_frame_timer(delta)
_next_initial_frame_timer = floor(wraped_frame_timer * 0.5) * 2.0
var walk_animation_frame = floor(wraped_frame_timer) + 1.0
var wraped_2 = wrapf(wraped_frame_timer, 1.0, 3.0) - 1.0
var previous_wraped_2 = wrapf(wraped_previous_frame_timer, 1.0, 3.0) - 1.0
if previous_wraped_2 > wraped_2:
_in_idle_frame = true
_frame_coords.x = 0.0
else:
_frame_coords.x = walk_animation_frame
func _get_wraped_frame_timer(delta):
_previous_frame_timer = _frame_timer
_frame_timer += delta * FRAMES_PER_SECOND
return wrapf(_frame_timer, 0.0, 4.0)