Weekly Wrap-up #19
Well, this was an interesting, although not overly productive week.
I decided I didn’t want to produce all our new characters/monsters into the game using sprite sheets since they are very limiting.
I found a library for Spriter that allowed us to produce the artwork directly onto the game screen just as you’d see it in Spriter itself (every frame is animated, not just keys like spritesheets).
At first it seemed to do really well, at least on the desktop. However, further testing on mobile devices sadly resulted in a less than desirable performance (the FPS was brought down to about 35-40)
After spending a large amount of time re-working the of the original Spriter API for performance I then realized it was using a much larger amount of memory that I felt it should be for what it was doing.
I found out after some testing it was because of the way it loaded the XML itself. It was using a self-made class that used massive amounts of string creations, then he copied all that data into more classes, then again into even more ! So many classes & objects, it was insane. And since they all shared the same string references, none of it could be collected by the garbage collector.
I did acknowledge that the problem of course is that there actually is a lot of information to load (think of all the keys of all the timelines of all the animations of all the entities). It adds up, so I was still expecting some memory usage, just not quite that much.
So, off I went into the world of XML parsing!
Version 1 !
I decided to look into various alternatives to loading the XML. I tried using XPath to make it so we’d only load the higher level information (up to animations), then only load those on “the fly” as needed. It was a good idea in theory, and didn’t work too bad overall, but actually ended up being even worse on memory (due to the DOM loading).
Version 2 !
Then I decided to try SAX version (where it only scans the file and you check on each node on the way through). I came up with a really neat way to work through the file and only load what I wanted with the XPath (only on certain nodes) allowing me to go through it without loading the XML into memory first. This worked great for memory, but ended up being horribly slow while in game itself (although the code I’m keeping for later in case I ever want to do “slower but on huge files” processing of XML). So, that one got scrapped.
Version 3 !
After those failures, then I decided to try out the JAXP built-in conversion of XML directly to java objects (similar to what I do now for JSON). Wish I had thought of that first and saved myself 4 days effort; I kicked myself because I used this all the time at work, just didn’t dawn on me I guess.
This worked perfectly, small on memory and quick also. One major problem came with it though after it was all nice and setup on the desktop….
Android doesn’t support Java JAXP !! Go figure 🙂
There are ways to work around it using full-packaged versions of Xerces, but I couldn’t really get any of the libraries to play nice with each other. I came close a few times, but then decided I’d look into other alternatives.
Version 4 !
So I did some additional looking around and found another library that did something very similar to JAXP but without requiring the libraries that Android doesn’t support. I spent some time doing some initial tests and they were looking good (not too bad on memory, but not great).
I was all set to go forward, then I ran one more test…
I tried to parse out a simple String array (String). I was shocked. Seemed that library had issues with knowing how to parse those and came up with some weird way of handling it that required you to have a “size” attached to each XML element. Odd…
So scraped that and decided to look into further alternatives.
Version 5 !
I then realized something…
I could just convert all their XML files into JSON, then use our existing JSON loading code to load it instead ! Brilliant; again, 5 days too late. At least I was learning some new stuff.
Using this saved having to manage and deal with more than one library. So I dug out the JAXP code from version 3 and setup all the objects to be read into the java beans, then told GSON to export them back out to JSON files in their “fully loaded state”.
So now when the game starts up, we have the data full prepared and ready to roll.
Adds about an additional 10Meg (other version were adding 50-100M each). Then it stables out and not much more increases past that. When the garbage collector come by, it quite often drops even lower and stays lower.
After spending the entire week rebuilding the API, it pretty much now presents something I should have just written myself; at least I got to borrow some of the “math” they used. I’ll probably clean it up a bit and create a Git fork of their original code to give back; but that’s a task for later.
The FPS is now pretty much 60 the whole time, it drops sometimes when the run across the screen, but otherwise it seems okay so far. I’ll keep checking on the performance, but I think it’s looking good now finally !
One thing I’ve noticed since putting them onto the smaller screen: Don’t make too subtle of animation movements, when they get resized, sometimes they end up just looking like weird “glitches” instead of actual movements. So I’ll likely have to keep an eye out for these and smooth things out over time.
Here’s a really short video showing off the new characters in game !