ExaStar Development Journal #6 – The Rewriting (sorta)
14 Feb 2018
Wow, I’m not that late to posting this time!!
Ok, so this journal is going to be a bit long in comparison to the others despite the small amount of bulletpoints, but there have been some important changes to how the game works, and I felt as if that warranted a complete journal altogether.
Assets, Assets, Assets
So, throughout most of ExaStar’s second development phase (relevant to the current, 2016 version of the project file, as described in Journal 1), I started shifting asset management away from Stencyl and into the game’s “data” directory. This started with EZImgInstance, which made it so that I could easily create images using files from the aforementioned data directory, and manipulate them almost as if they were actors/objects. This was a huge breakthrough, since before I had implemented this system, I needed to create a new actor type for literally everything, which made asset management a bit of a pain and added some extra heft to the game’s project file (which meant longer save and load times in the Stencyl toolset). Some time after I had that system in place, I decided to also apply the same to all of the music in the game. This was pretty important, as music actually makes up for a huge amount of the game’s size. This time, the implementation was pretty simple – I had an extension installed that could get sound data from the data directory, so all I had to do was plug it into the already existing sound calls.
Why did I do this you may ask? Well, Stencyl by default loads everything into memory when the game first opens (unless you have asset atlases set up beforehand, which I really did not want to mess with as a lot of the game’s assets are shared across multiple scenes, making it not worth the hassle). This is actually not much of a problem for me, personally; in fact, many games that are small enough to fit entirely in memory will do this! However, the issue with Stencyl’s asset loading implementation is the fact that there is essentially no loading screen. Instead, you get a blank, white screen (this is on Windows; you’ll a transparent screen on KDE, a black screen if you are on GNOME, or just an ever-bouncing icon in the dock on macOS) while the OS reports that it’s in a “non-responsive” state. Obviously, keeping end-users with slower disks in mind, I felt as if some people would likely get confused by this odd loading behavior, potentially leading to false reports of the game “crashing” on startup – when in reality, it’s just loading!!
So, to help combat this unhelpful loading screen, I did as I mentioned before, and essentially moved a lot of the images and music over to a separate directory that is not automatically loaded on startup. This worked pretty well, cutting the average time to load to around 1 second (on my SSD). Pretty cool, wouldn’t you say?
But then I noticed that, despite moving everything over to the data directory, the game was still having issues – namely, when running the game off of a flash drive (or even an energy-efficient HDD), there would be large freezes when loading music. The most common and most jarring area that this “freezing” occurred on was the title screen, which has to load music as soon as the scene loads. However, because of the music, the scene transition at the very beginning would get interrupted, and, instead of fading out, it would sometimes just cut straight to the title screen. Another area that had issues was the File Select, which has to load 2 music files as soon as it is entered (a “base” song as well as the same song but with added drums). The freezing caused the two music files to play slightly at an offset from each other (when they were supposed to play symmetrically), which was especially noticeable on slower drives. This was all not immediately noticeable since I mainly develop the game on systems that utilize SSDs, only rarely running the game off of an external drive.
So, I had to go back to the drawing board. Obviously, all of this freezing was due mainly to the fact that everything was no longer stored in memory, and instead streamed off the disk. I then set out to make my own asset management system, mainly covering these requirements:
- There needed to be some sort of loading screen, most favorably with a progress indicator.
- I needed to easily reference assets from code in a format that was short and readable.
- Both images and sounds would need to work with this system: all images, music, and sfx, with the exclusion of actors, backgrounds, tilesets, and fonts (which are all mainly supposed to be managed in Stencyl itself).
I started working away at this system aimlessly for a day or so before I put it to the side for winter break. During break, however, I did manage to write a tool that would index all of the applicable assets from the data folder and put their locations all into separate manifests. After break, I set out to model the asset loading system off of these manifests.
After around 1 hour of work (when I was in class, taking notes at the same time), I had a complete working prototype of the asset system up and ready to go! Now it was time to actually get it integrated into the game, instead of it just existing as a object that’s never used. After going through all of the game’s source code, replacing old music and sfx calls with calls to the asset system instead, and rewriting a large chunk of EZImageInstance to also integrate with the asset system, I was finally able to run the game for the first time in around 2 days!
After a few crashes in the first few scenes (which were due to small errors that I never caught in the integration process), I was finally able to test everything out, but… something was wrong. Terribly, terribly wrong. The game was probably in the most unstable state I had ever seen it. Scratch that – this was the most instability I had ever seen in any one of my games PERIOD. The random crashes still occurred, however this time it was due to errors I could not even trace. Most of my precious, beautiful interfaces I had spent hours perfecting either suddenly looked completely garbled or would just crash the game on creation. The best part of all, though, was that the asset loader wasn’t even doing its job! Take a look:
I thought that everything was fine up until this point – where did all of the outlines go? Why is there only one?
Looking at the settings screen, almost all of the buttons went missing. What the…?
Things got even worse ingame, with things such as the HUD, itemboxes, saveboxes, and various other UIs failing to appear
I spent an hour trying to track down each of these bugs (whilst pulling out
some a lot of hair), and eventually got some of the random crashes to stop. However, no matter how much I tried, I could not fix nor figure out why certain images were never loaded. I eventually called it a day, and just went to bed completely frustrated and generally afraid that I would need to roll back all of that hard work.
The next day came, and while I was busy at a family gathering, I was able to quickly design a debug tool to view all of the assets that were in memory. To my surprise, all of the assets showed up properly. This just led to even more questions and frustration, so I decided to stop myself from trying to fix the game again until I got back home the next day.
When I did begin work the next night, I eventually came to the incomplete conclusion of “Haxe’s management of passing variables by value vs reference is the cause of all of this.” This was a pretty baseless conclusion to start off with, and the next hour of looking up Haxe documentation and forum posts wasn’t really helping that claim either. However, before I completely gave up hope, I decided to stick in a small “.clone()” to the return statement for images, despite thinking that passing the image by reference should have worked anyways.
Lo and behold, the game was immediately up in near-working order again. What started out as a large jump in concluding the reason for this bug actually ended up being completely correct. All that was left were a few modifications to EZImageInstance’s animation procedures and constructor, and I was good to go!
All that work paid off too; I finally had the ability to add a proper loading screen to the beginning of the game, got the ability to reference assets in a much simpler way, and was able to get both images and sounds working in the same exact system, too!
With the creation of the new asset system, as well as the updated (and much more versatile) EZImageInstance, I finally decided to mark a new milestone in ExaStar’s development, which I now call the “AssetLoader Phase”, or just Phase 3. The previous phases, in case you were wondering, were:
- Phase 1 being the initial, visually-scripted versions of the game that used a resolution of 640×480 and slightly larger sprites, and essentially accounted for all builds of the game from Sep. 2016 – March 2017, and
- Phase 2 being the versions that began to use actual code instead of Stencyl’s visual scripting system, with downscaled sprites and important features such as the updated Party, Enemy, Map, Quest, and Inventory systems, as well as the Mapper. This phase accounted for all builds of the game from March 2017-December 2017.
After finally getting through this nightmare, I was finally able to work on other things…
Fixed Party Data Saving!
One of the things that I had issues with while attempting to save party, inventory, and quest data was that I couldn’t just write the objects themselves to save files; instead, this would just cause the game to dump its memory to the chosen save file, which would not even work due to there seemingly being a hard limit of around 512Kb on save files. So, I just opted to move the object’s most important data into arrays and saving that, which worked out fine. But, in my usual laziness, I never actually got around to fixing the saving of party data, which ended up being a 15 minute fix. With that working, the save system is basically in fully working order again.
An even better Grapefruit
For those who don’t know, Grapefruit is the codename for the game’s battle system. I don’t know if I mentioned this in a previous journal or not, but I decided to redo Grapefruit completely from the ground up after the conversion to Haxe, but never got around to adding onto it until recently. Essentially, I recently created a new model for how Grapefruit works; instead of it being one large scene behavior, it is now modular; there is a base scene behavior that loads everything, and multiple “modules” which control separate areas of the battle system. They can all communicate with each other, however the new, modular nature of Grapefruit makes stuff a lot less complex to work with, as modules can store their own variables that are relevant only to that module, and not others.
Speaking of Grapefruit, I’ve been brainstorming multiple ideas for the game’s battles, as I wanted to replace the old rhythm-based attack system that I planned to add before. After deciding that this attack system would be too tedious and a bit limiting in terms of what could be added, I looked for other ways to “spice up” battles a bit; my first idea was having a sort of platformer game that you’d need to complete in order to execute attacks, but I decided that this was too gimmicky. Another idea that I had was a sort of “minigame” for each attack, however I felt as if this was a bit too similar to Undertale’s battle system, so I quickly scratched that idea out. The conclusion? Skip the gimmicks! Instead, I decided to add onto the more strategical aspect of JRPGs and introduce a sort of card-based system. Essentially, cards serve more or less the same purpose that the rhythm-based attacks did. However, instead of having attacks rely on an external “game”, instead the cards will just add a bonus of some sort to an attack – much like the bonuses that one could get for exceeding the beat limit on the rhythm attacks. There’s a ton of complexity as to what I can do with the card system – So much so that I’ve been coming up with ideas non-stop, as opposed to the limited ideas with the rhythm attacks. I may lay this card system out in the next journal, as I have yet to actually write all of these ideas down somewhere (oops).
That about wraps it up for this journal! Hope you enjoyed reading what was essentially a 2-hour long brain-dump =)