module DragonSkeleton::Animations

Provides a simple functional style animation system.

In the simplest case, a frame is a hash of values to be set on the target and a duration:

animation = Animations.build(
  frames: [
    { tile_x: 0, tile_y: 0, duration: 5 },
    { tile_x: 32, tile_y: 0, duration: 5 }
  ]
)

It can then be started via ::start! on a target (e.g. a sprite):

sprite = { x: 100, y: 100, w: 32, h: 32, tile_w: 32, tile_h: 32, path: 'resources/character.png' }
animation_state = Animations.start! sprite, animation: animation

and every tick you need to call ::perform_tick to advance the animation:

Animations.perform_tick animation_state

By default the animation will stay on a frame until the duration is reached, then immediately move to the next frame but you can also specify an easing function to gradually interpolate between frames:

animation = Animations.build(
  frames: [
    { x: 0, y: 0, duration: 5, easing: :linear },
    { x: 100, tile_y: 100, duration: 5, easing: :linear }
  ]
)

Constants

EASING_FUNCTIONS

Easing functions for interpolating between frames.

Following easing functions are provided but you can also add your own to this hash:

:linear

Public Class Methods

build(frames:) click to toggle source

Builds an animation from a list of frames.

Each frame is a hash of values that will be set on the target when the frame becomes active except for the following reserved keys:

:duration

The number of ticks the frame will be active for.

This value is required except for the last frame of a non-repeating animation.

:metadata

A hash of metadata that is available via ::current_frame_metadata when the frame is active.

:easing

The easing function to use when interpolating between the current and next frame.

Check out the EASING_FUNCTIONS constant for a list of available easing functions.

# File lib/dragon_skeleton/animations.rb, line 73
def build(frames:)
  {
    frames: frames.map { |frame|
      {
        duration: frame[:duration],
        metadata: frame[:metadata],
        easing: frame[:easing] || :none,
        values: frame.except(:duration, :metadata, :easing)
      }
    }
  }
end
current_frame_metadata(animation_state) click to toggle source

Returns the metadata associated with the active frame of the animation.

# File lib/dragon_skeleton/animations.rb, line 111
def current_frame_metadata(animation_state)
  current_frame(animation_state)[:metadata]
end
finished?(animation_state) click to toggle source

Returns true if the animation has finished.

# File lib/dragon_skeleton/animations.rb, line 116
def finished?(animation_state)
  animation_state[:finished]
end
lerp(target, to:, duration:) click to toggle source

Creates and starts a one-time animation that will interpolate between the current values of the target and the values in the to hash.

Returns an animation state that can be passed to ::perform_tick.

# File lib/dragon_skeleton/animations.rb, line 39
def lerp(target, to:, duration:)
  first_frame_values = {}.tap { |frame|
    to.each_key do |key|
      frame[key] = target[key]
    end
  }
  animation = build(
    frames: [
      first_frame_values.merge!(duration: duration, easing: :linear),
      to.dup
    ]
  )
  start! target, animation: animation, repeat: false
end
perform_tick(animation_state) click to toggle source

Advances the animation by one tick.

# File lib/dragon_skeleton/animations.rb, line 105
def perform_tick(animation_state)
  next_tick animation_state
  update_target animation_state
end
start!(target, animation:, repeat: true) click to toggle source

Starts an animation on a target and returns an animation state which can be used to advance the animation via ::perform_tick.

By default the animation will repeat indefinitely but this can be disabled by setting repeat: false.

# File lib/dragon_skeleton/animations.rb, line 91
def start!(target, animation:, repeat: true)
  {
    animation: animation,
    target: target,
    frame_index: 0,
    ticks: 0,
    repeat: repeat,
    finished: false
  }.tap { |animation_state|
    update_target animation_state
  }
end