Revisiting Wave Animation Logic

Hi all,

A question about wave animation in Aseprite came up on the PixelArt subreddit a while back. It shared a tutorial on animating fire with AfterEffects. The Reddit post prompted me to revisit an older thread on this forum.

https://twitter.com/artofsully/status/955853823347601408

In a response on Reddit, someone mentioned using SpookyGhost. I’ve not tried this software, but I watched a demo video on animating a tree. I re-checked GIMP’s wave Filters, too. Turns out, it has at least four: Distorts > Waves, Animated > Waves, Distorts > Ripples and Animated > Rippling. The animated filters stack each frame onto a new layer.

As for the logic behind waves (one type, anyway, that I’ll call radial): Suppose we’re in 3D. The 2D Euclidean distance of a point on an xy plane from an epicenter is converted to an angle, which is supplied to a wave function. The wave output displaces the point on the z axis (or changes a color, etc.). Here’s a visualization:

https://twitter.com/beesandbombs/status/940639806522085376

The main problem, imo, in 2D is the direction to displace a point without a z axis. In the older thread, displacing on the negative y axis seemed natural. This created the illusion of a two-thirds top-down view as in 16-bit era Legend of Zelda games.

waveWarpGif

For a long term script I’m working on, I displaced in the direction of the point relative to the epicenter. This created the illusion of a complete top-down perspective. Then, I added an angle in case a user wanted a twist. There could be a way to toggle between rotating the pixel’s direction vs. an absolute direction, so as to change between 2/3rds and top-down, but I don’t yet feel the need for it.

The long term script I’m working on is here. The user interface looks like this currently.

bilinearWaveGif

I tried a bilinear wave as well. A pixel’s x coordinate is converted to an argument to give to a wave function. For example, frequency * tau * x / width. The result of the wave function is then used to displace the coordinate on the y axis. And vice versa - input y is used to displace x. The result could tile if done carefully.

Looks like SpookyGhost also uses horizontal and vertical waves, with more robust options. Krita’s wave filter is bilinear (but no animation options that I found).

interlacedGif2

Because the older thread mentioned EarthBound, I also tested an option for horizontal and vertical interlacing… In retrospect, this could be a separate dialog that splits an image or flattened sprite into two separate interlaced layers. There’s a discussion of how to skip and pick rows/columns on Stack Overflow.

threeParamChanges

Just about any parameter controlling the animation can itself be animated. This is the biggest problem I’m encountering. While I still have some room left, overall there’s not enough screen real estate to include every dialog widget and to clarify which axes are spatial and which axis is time. (I prefer not to open dialogs from dialogs.)

https://www.desmos.com/calculator/6gokrpqhvh

For example, the displacement force of a wave can change over space. Imagine an earthquake. A wave will displace a pixel more nearer to the epicenter than the periphery. The overall displacement can change over time as well. For looping animations, the user ideally would have control over the displacement at the beginning, middle and end of the loop.

layeredWave3

The current step I’m on is the ability to apply a wave to animations instead of still images. Above, the original animation was just a rotating color wheel. A radial wave was layered over it, then an interleaved wave was created from the last still frame and appended. A detail here is to deal with irregular frame durations. It’s not enough to create an angle from a formula like tau * frameNumber / totalFrames. My approach is to find the total duration of the sprite. Then the elapsed time at the current frame is divided by the total.

Some wave effects that I looked at offered a choice between wave types (sinusoidal, triangle, saw, square). I feel that those options aren’t necessary, but maybe someone knows a case where the choice makes a difference.

Lastly, as much as I like proc-gen animation, I think there’s value in learning how to create wave effects manually. Here is a tutorial from Adam C. Younis on fire:

There’s another one where he animates a cape.

Given how many parameters are possible, it’s unlikely that any one user will get everything they want unless they go full diy. That’s why I walked through some of the logic and decisions. It’s also why imo any built-in wave animation in Aseprite would be a long time in the making if it happened at all.

Cheers,
Jeremy

5 Likes

i share the sentiment that hand-made animation still has value and when done well, specific charm.
also, if someone decides to use vfx software like after effects, then i’d say there’s no reason to hold oneself back with simple wave warp effect - just use particle simulation ;]

anyway, i really like those example results, especially displace xy one.
is it possible with the current script to have gradually changing both amplitude and period on one axis? that way user could create for example basic water ripples in fake perspective. i think it would make the flames look a bit more interesting too.

Given how many parameters are possible, it’s unlikely that any one user will get everything they want unless they go full diy. That’s why I walked through some of the logic and decisions. It’s also why imo any built-in wave animation in Aseprite would be a long time in the making if it happened at all.

:point_up:

Any update on this ? I’m very interested about what your work in progress is capable of. I could really use this on a project.

If you want to see what the script is capable of, the updated link is here, though there are so many dependencies, it’s easier to dl the whole repo. I’m not soliciting any further feature requests or considering suggestions.