HaxeFlixel 5.4.0

We've finally released Haxeflixel 5.4.0, our largest release in quite some time, arguably larger than the 5.0.0 release! This release focuses heavily on assets and animations, like the new FlxAsepriteUtil and the new Multi-Atlas system.

What took so long?

We try to release new versions of HaxeFlixel around once a month, and have been, for the most part. This one took much longer, the previous version, 5.3.1, was released in early May, that's almost 5 months! The main reason is because we really wanted to get things right, The Aseprite utils, alone, add around 20+ new types and it's not good to release them prematurely, only to rename, reorganize or retool them in a later patch. This ended being a good call, since we did end up iterating on and organizing these utils, later.

Another reason the release was delayed was that George, our lead maintainer finally went on his honeymoon. He didn't feel like touching a computer while visiting his motherland for most of September, with views like this, I'm sure you wouldn't want to either!

Aseprite Utils

By far the biggest development of HaxeFlixel 5.4.0 is the various tools that utilize Aseprite's atlas exporting tools. For those unaware, Aseprite is a very popular animated sprite editor and pixel art tool, we can't recommend it enough for anyone using HaxeFlixel, especially for pixel-art games. The main goal of FlxAsepriteUtil is to allow devs to define animation data using Aseprite's tags rather than in code.

(Made using the Animated Pixel Adventurer set by rvros)

The resulting atlas can easily be applied to a sprite with the following code using the addAseAtlasTagsByPrefix or addAseAtlasTagsByIndex to create an animation for every tag in your .aseprite file.

hero = new FlxSprite(50, 50);
hero.loadAseAtlasAndTagsByPrefix("assets/images/adventurer.png", "assets/images/adventurer.json");
hero.animation.play("idle");
add(hero);
HAXE

You can expect more Aseprite focus tools to come now that we've created handy typedefs for Aseprite atlas metadata. One future plan is to use Aseprite's slicing feature to generate 9-slice data or per-frame hitboxes, but it's much easier for you to use this data to roll your own features, for example to see per-frame slice data on an atlas's labelled "attackRect":

var atlasData:AseAtlas = Assets.getText(myAtlasJsonPath);
for (slice in atlasData.meta.slices)
{
    if (slice.name == "attackRect")
    {
        for (key in slice.keys)
        {
            // store per-frame slice data
            trace('frame: ${key.frame} bounds: ${key.bounds}');
        }
    }
}
HAXE

We have immediate plans to utilize more Aseprite fields, such as the tags' "Repeat" and "Animation Direction" fields. You can expect those in the next release (Update (5.4.1): this change has been added!).

Combining Multiple Atlases

This feature was specifically made with our Funkin' devs and modders in mind. As the demand for HD atlases with large amounts of animations increase, their atlas image size grows well beyond the limit that flixel can currently handle. By combining multiple atlases at runtime devs can better compartmentalize their animations, ultimately allowing FlxSprites to have more animations without having to switch graphics every time you change a sprite's animation. Splitting up animations also allows you to load them separately, for instance, if you only need certain animations on certain levels.

This project's art pipeline could really benefit from multi-atlas since each character is made from about a dozen different aseprite files, each with potentially dozens of frames.

(Art by Adam V., you should [hire him](https://twitter.com/Koolboyman/status/1672366422767591424)!)

Here's an example of how to add atlases to another

// create an atlas for each file
var idleAtlas = FlxAtlasFrames.fromAseprite('assets/images/snowman-idle.png', 'assets/images/snowman-idle.json');
var jumpAtlas = FlxAtlasFrames.fromAseprite('assets/images/snowman-jump.png', 'assets/images/snowman-jump.json');
var walkAtlas = FlxAtlasFrames.fromAseprite('assets/images/snowman-walk.png', 'assets/images/snowman-walk.json');
var blockAtlas = FlxAtlasFrames.fromAseprite('assets/images/snowman-block.png', 'assets/images/snowman-block.json');

// combine all the atlases by adding to the idle atlas
idleAtlas.addAtlas(jumpAtlas);
idleAtlas.addAtlas(walkAtlas);
idleAtlas.addAtlas(blockAtlas);

// create the FlxSprite
var snowman = new FlxSprite();
snowman.frames = idleAtlas;

// add all the anims
snowman.animation.addByPrefix("idle", "snowman-idle_anim");
snowman.animation.addByPrefix("jump", "snowman-jump_anim");
snowman.animation.addByPrefix("walk", "snowman-walk_anim");
snowman.animation.addByPrefix("block", "snowman-block_anim");

// add it to the state
add(snowman);
HAXE

Animation Time Scaling

We've added a timeScale field to FlxAnimationController. This can be used to slow down or speed up animations. For instance, you can change a walk cycle's animation speed to match the sprite's changing movement speed, or you can easily implement a power up or skill that increases attack rate. Here's an example of 4 sprites using different timescale properties whenever the attack animation is played:

Update (5.4.1): We've also added the timeScale field to each individual animation, rather than just the animation controller.

A List of Every Asset

Lastly, we've added the allFiles field to classes generated via FlxAssets.buildFileReferences, AKA: AssetPaths. This is just an easy way to iterate or search a list of every asset included in this build. if you don't like the name allFiles you can specify a custom name in the listField arg of buildFileReferences.

What's Next?