What’s up yall. Since November, I’ve been making “Must Murder Mommy” with PhantomArcade. It’s the greatest game about killing your hot mom, which will be releasing for free on mobile and on the web (here on Newgrounds to be specific).
Phantom is a ballin’ animator, so the game is going to have a good amount of animation frames. However very few people actually discuss what goes into loading and handling all these animation frames. So I thought I’d share my experiences in trying to load a bunch of high quality animation to be used in the context of a video game.
(The current spritesheets/texture atlas for our main characters, an explanation on why I use spritesheets will be below)
Backstory
I think I’ll start with the “backstory” of the many different techniques and workflows to me trying to load a lot of frames into the game.
I’m using HaxeFlixel to make this game with my guy Phantom. It’s an open source cross-platform 2D game engine powered by Haxe and OpenFL. None of that nerd shit matters too much other than to give you the info that I ain’t using some hotshot mainstream game engine, such as Unity or Gamemaker. While HaxeFlixel is VERY robust and super great, it’s a bit harder to Google something and find some easy answer, or some plugin that’ll solve all my problems. A lot of the tech I have to figure out on my own, and that includes efficient animation loading and shit.
So onto the game stuff. In the very first week of development, the first issue for me was getting the animation to load in-game. Phantom uses Flash CS4 to animate, so initially I thought that I could use a SWF(what Flash exports files as) to load the animation (in high ass quality too, since it’d be vector!) However this didn’t work out as planned. While OpenFL does have some kind of support for loading SWF’s for animation: 1. I did not actually figure it out lol. and 2. I couldn’t get it interacting with the HaxeFlixel game engine shit. Meaning that the Flixel logic operates completely separate from what would be the animations that play. So I wouldn’t be able to set interactions between game objects, and the mom/kid without reworking A LOT of logic (or maybe I’m just a dumbass IDK lol).
So loading SWFs didn’t work. I then thought of using Adobe Animate’s built in spritesheet exporter. If I couldn’t get SWFs going, spritesheets are the next best thing. However things aren’t exactly all fine and dandy. The way that Animate exports spritesheets are less than ideal. I think when I tried, the spritesheets were off grid (which the way I was trying to load them at the time, I needed them to be on a grid basically). So that was out of the question too (for now….).
After pulling my hair out until about 3AM in the morning, I finally somewhat found a solution, albeit a bit garbage and shitty. What I went with back then, was to export the animations as PNG sequences, so a PNG for every frame of animation. And then I’d stitch them together into a sequence in Aseprite (pixel art tool lol) so I could then export them into a USABLE spritesheet. Why this was garbage and shitty was for a few reasons. First of all I had to basically sort through ALL of the PNGs and manually input them into Aseprite, which was very hard and time consuming because it was repetitive, Aseprite doesn’t handle big images too well, and my PC is shit too lol that prob didnt help Aseprite. It was also hard to manage the files and edit them for the future, thus slowed down seeing and prototyping new animations in-game.
The Github commits/updates (read bottom to top) of the game for that first night of trying to get animations loaded efficiently
The Aseprite/PNG sequence stuff was alright for a while. Mostly because I did it all in one session essentially so I didn’t deal with it too much. But when I did have to get new frames of animation in, I dreaded doing so. I knew I had to find another way. It was then when I remembered the tool Zoë, which is a tool to convert SWFs to spritesheets. This was SUPER helpful…. But only for so long.
Somewhat recent stuff I’ve tried
The Zoe website
The way that Zoe works, is that you input a SWF, and you get a spritesheet and/or PNG sequence of the animation. However there were a few catches. I had to export them all as one SWF, through movieclips. So in the .fla Flash file me or Phantom would have to organize all the animations into a single movie clip. Otherwise it would export them all as separate spritesheet files (which I’ll need only 1). But I went along and did that for a while anyways. Until I found out about Spritesheet packer.
Spritesheet packer is a ridiculously easy, lightweight, and free tool to convert a bunch of PNGs into a usable spritesheet. Actually I think the correct term is texture atlas? You may have noticed, but the images in the spritesheets at the top of this post aren’t aligned to some sort of grid, which I mentioned earlier that I needed them to be in. That’s because spritesheet packer also exports you a simple txt file, that would basically tell a parser where in the image file a certain frame is. So you don’t need the sprite sheet to be ordered chronologically, or in a grid, thus reducing the file size, and simplifying things in a few ways. And it turns out that good ol’ HaxeFlixel has a built in function for reading these Spritesheet packer txt files (called image maps btw). So my life got a lot easier from then on out. However I still had a few problems.
The imagemap file for the kid, the corresponding spritesheet is the one from the top of the post
I got animation loading almost all sorted out, and the workflow was pretty great too. I would export the frames from Adobe Animate into PNG sequences ( I ditched Zoe because it would require more file prepwork, like making sure it’s all top left aligned or something) and then I literally just drag and drop them into spritesheet packer then it spits out a nifty little texture atlas, and I could get it all loaded into the game. Should be fine right? Well that part was just about perfect (for now), however then there’s the way the coding handles and loads animations. For simple animations, HaxeFlixel had a nice and easy way to load animations which basically looked like this:
animation.add(”run”, [7, 8, 10, 11, 12], 12);
the first parameter (”run”) is the name of the animation that would be referenced in game. The second is an array of numbers (indicated by the square brackets) which is basically a list of where in the image map it will look for the frame of animation. The third parameter is simple the frames per second (12FPS because it’s essentially 24FPS on two’s, doesn’t work in all cases though). Now this works well in many many cases, but I think the single problem I had was that when I added new images to the spritesheet, it would offset the numbers in the imagemap, thus messing up which animations are which.
Current Workflow
This is where I use my final solution, which is referencing the imagemap files to get the correct frames, no matter what. So instead of referencing frames in a huge list that can change often:
animation.add(”run”, [7, 8, 10, 11, 12], 12);
animation.add(”poke”, [33, 35, 33, 34], 12);
Instead you break it down into smaller, sublists kinda:
animation.addByName(”run”, “kidRun_”, [0, 1, 2, 3, 4], “”, 12);
animation.addByName(”poke”, “kidPoke_”, [0, 2, 0, 1], “”, 12);
This function works very similar to the first one, except it has another parameter, which is the prefix (kidPoke_/kidRun_). So the game uses file names so that list position in the imagemap don’t affect the animations that are already implemented.
Things I may try in the future
This stuff is working all fine and dandy currently, but the workflow could be optimized. The dream would be to easily just work with SWF files, but like I mentioned earlier this would require a bit of heavy lifting on some of the backend tech. So the more realistic option is for me is to figure out how to parse Adobe Animate’s spritesheets and files properly. This would cut out the spritesheetpacker step, as well as cleanup the files more, since I would have no more use for PNG sequences. There’s probably gonna be some quirks and shit, but for now this seems like the next step if my current workflow is really bugging me.
So I think that’s it, hope all you goons may have learned something, and if you didn’t ah dangit OH WELL
(if there are things I could be more clear on please let me know and I’ll probably update this or something)
OatmealPecheneg
We are not just a goons, we are the horde.