[ANN] anitomata: Composable 2D sprite animations

I’m happy to announce the initial release of anitomata, a pure implementation of 2D sprite animation intended for use in gamedev.

An intro and additional resources are available here.

18 Likes

This looks sick! Congrats on the release. Can’t wait to use it in April for the next Ludum Dare :cowboy_hat_face:

2 Likes

Ludum Dare in Haskell? this is the future I’m here for ^^

2 Likes

I don’t agree with the library structure, consider a different approach:

A 2D animation is sequence of durations, each bound to some frame data. We can assume that animation starts at 0, the offset of each frame is unique and that all durations have a common divisor (e.g. 1/60 in a 60fps animation).

Frames can be referenced as a multiple of the divisor, therefore the entire library is reduceable to

data Animation =
       Animation
         { duration :: Time
         , divisor  :: Time
         , frames   :: IntMap Frame -- ^ indexed by divisor multiples
         }

build :: Config -> [RawFrame] -> Either Error Animation

-- | The time delta is enough knowledge to find the current divisor multiple,
--   then IntMap.lookupLE finds the frame.
frame
  :: Time      -- ^ animation started at
  -> Time      -- ^ current time
  -> Animation
  -> Frame

There are no moving parts in this approach and the functions can be customized however needed.


Admittedly this definition is small enough to not even require a library, anyone could just handroll this.

This misses — e.g. — looped animations.

Congrats on release jship!

2 Likes

A looped animation assumes that relevant current time is mod time_delta duration, whereas a non-looping one checks time_delta < duration and defaults to the last frame. Everything else is identical otherwise.

I think you’re missing the Semigroup instance for Animation, which is a big selling point of the library!

The future is now!

I’ve done LD in Haskell many times.

And others have too! For example: [1] [2]

1 Like

Please feel free to package up your own implementation - anitomata is not at all meant to be the only method for sprite animation in Haskell.

Its internal approach of building animations as lazy sequences of strict, reusable chunks is a point in the design space I find satisfying, and wrapping it up using a minimal Semigroup-based DSL has been pleasant in my gamedev experiments so far.

2 Likes

That looks great @jship , thanks for sharing! I’m presently using varying for animation, have you considered using it?

For example, how to change the anitomata duration dynamically to implement the system presented in this Giving Personality to Procedural Animations using Math video? For what it’s worth, here is my implementation with varying: AnimationFractal.secondOrder.

3 Likes

Thank you - I hadn’t explored varying. I think applying it to the animation duration is a very interesting idea. It looks like varying's Spline in particular could simplify adding more sophisticated duration overrides. The overrides in anitomata's initial release are very simple, but in the future I’d love to make things like cubic ease-in/ease-out available too.

2 Likes