Golden Lord: After the Jam, part 2
In my last blog post, I described the basics of working in html52d, how Golden Lord was implemented using the features that were available, and some of the corners I cut during the jam in order to get it done faster.
Since then, I've been refactoring the code and https://ldjam.com/events/ludum-dare/43/golden-lord. (Try it out it if you haven't yet!)
I realized fairly early into the refactoring process that I needed a better way to organize the code and the assets. Throwing everything into .js files and loading it all from the HTML file worked, sure, but it was sloppy and I had to be careful about dependencies and global variables. And I discovered the limitations of the prefab structure I had built, but I didn't want to take the time to overhaul that during the jam itself.
The prefab system was intended to support class inheritance from the beginning. The asset manager would let you put anything you wanted in a prefab, so you could return a descriptor object like I showed in the last blog post, or you could return a constructor function or a class. And using a class meant that the problems I described before with adding additional functions went away. But this yielded an API inconsistency: you had to know whether a prefab was a descriptor (new Sprite(assets.prefab.hero)) or a class (new assets.prefab.Hero()) when you wanted to use it.
This was straightforward to fix. When loading prefabs on startup, the asset manager now wraps descriptors in a class that inherits from Sprite. Everything can be constructed the same way now.
Once I had this worked out I was able to refactor my character prefabs. I moved the common utility functions into a CharacterCore class that extends Sprite and made the prefabs into classes that extend CharacterCore. The awkward checks to see what kind of character it is turned into clean object-oriented function overrides. I'm MUCH happier with it now.
However, this inheritance scheme means that the characters have a load-time dependency now. This meant more global variables and more manual configuration of the load process. Normally I would have just used ES6 modules for the task, but browser support for these isn't quite universal enough for me to be comfortable with it yet. If you want to use them in your own code, it's perfectly well supported by html52d itself, so feel free to do so. Instead, I built a require() mechanism sort of like CommonJS or AMD modules, except it's a little cleaner than either of those.
While I was working on import machinery I also added a way for prefabs to define asset dependencies instead of requiring the developer to specify all of the assets that will ever be used up front. This can include runtime script dependencies too, though you can't use this syntax to pull in a class that you inherit from since the Javascript language requires that the superclass already be defined.
In the end, I'm a lot happier with how things are structured now. I still have some work to do because I'm not completely satisfied with the way the modularization works because there's no good way to minify them. I don't want to require a build system for development but I also don't want to prevent using a build system for deployment, so I've got some thinking to do. In the end I might go ahead and switch over to ES6 modules after all and let the build process be responsible for supporting older browsers.
