Hey again, and happy Pi day! (3.14.2016 might’ve been over for most of you by the time I finish writing this)
It’s definitely been a long while since I last updated, but I DO have a reason. A pretty good one, in fact. The A-Engine project has been rebooted. That’s right, I’ve taken my time to build everything again from ground up. Now why did I go through all of this, you might ask. First, you should know that I’ve been working on this project for roughly 2 years now, and that the leap I’ve made during this period isn’t to be underestimated. I wasn’t really new to programming as much as I was new to C++, the language I picked for the job of writing the engine. So going through the old portions of the codebase was utterly painful to myself, and some of it felt like I was literally bodging my way through. That hinders more than one might think, and I believe that the effort of rebooting the whole project will pay off. Not to forget to mention the fact that the A-Engine is planned for an open source release, and was the source the one it used to be, I wouldn’t be surprised to find a couple of threatening messages in my inbox the next couple of weeks after it going online.. Knowing that some of you guys might have felt dispirited after hearing such news, I decided to wait before informing anyone until I’ve done a fair amount of work.
Now, of course, just prettifying the codebase wasn’t my only motive to go with such a plan. Upon integrating the new AScope and AExpression classes to the old thing, I realized I had greatly underestimated the task, and that there were lots of design flaws in the old code and the new pair of classes which would’ve made it very hard to fit. I focused too much on how flexible the classes are, but I didn’t think enough about the order things are created. Every object on the screen gets a scope of its own – a scope being an instance of the AScope class, I thought. Then the content of every tag in a .a file would be used to create an evaluat-able AExpression instances. An AExpression constructor requires an AScope instance argument for tokenizing arguments and for everything to compile. Now, the problem was that on-screen objects are usually created AFTER the .a files have been loaded (after the AExpressions for every tag has been compiled), but the AScope instances are created per on-screen object; AScope instances are created AFTER the AExpressions for tags have been compiled! That’s not possible because an AExpression instance requires and AScope instance to construct. You can see the circular dependency there as a sign of a serious design flaw. A solution was at sight: just start by creating a temporary AScope instance that is only used for creating AExpressions and then discard it. But that would’ve just been another bodge to add up to all of those in the source. The proper solution was to split the AScope class into two: AScopeNameSpaceData class that contains names of variables and such, and let the AScope class contain the contents of these variables and the functions available to that scope (pointer to values and functions, actually). Even after doing this, there would be a tad to do with the objects code to make things work correctly. There is no escaping it. Rewriting the Object class will have to happen.
From there, I had the new AScopeNamespaceData–AScope–AExpression class group to cover expression evaluation and the variable/function system. I had also rewritten the graphics related portion of the engine before as a new GraphicsManager by the end of 2015 and further updated recently to do some caching work and use a request system (in the loop where objects are updated, render requests are sent to the graphics manager. The graphics manager will then render all requests it received that frame in a giant loop which is to run in parallel with the physics calculation as a separate thread). Next on the list was writing a new .a file parser because the older one was terrible. That also means that I’ll have to modify all frame components’ and frames’ loading code to use the new parser. Then I knew I’d have to take some time to rewrite the Object class. At that point, I realized just rewriting the A-Engine isn’t very far from what I will be really doing, except if I go with rewriting, I won’t spend all the time trying to think of how to fix old code full of bodges but rather concentrate on coming up with better implementations overall.
This is my chance to restructure the source again, so my goal is to make the codebase as modular possible; I’ve got a hierarchy of different functionalities distributed to different top layer classes. First, there is the main AEngine class at the top, which branches up to instances of the GraphicsManager class (deals with graphics and rendering), the FileManager class (deals with loading .a files and caching them for use), the ScopeManager class (deals with managing scopes and namespaces), the ObjectManager class (deals with loading objects in game and instantiating on screen objects), the InputManager class (deals with taking input and mapping them to events the engine understands), the SoundManager class ( will deal with sounds and playing them), the PhysicsManager class (will deal with collisions and accurate responses) and the NetworkingManager (will deal with network play and stuff related to sending data across 2 networks). The latter 3, I haven’t started working on them yet, but they already have their place in the source and implementing them should be very straight forward with respect to the engine itself. The idea of going with such design will make it very easy to do any modifications, enhancements and even ports to other platforms later on or for those who wish to do it themselves.
I think I’ve written enough for this, even though I still wanted to write more about the changes and the great new features A-Engine has gotten as a result. I will try to write about this next week. If you have any comments, questions or inquiries, make sure you drop a comment! I will get back to your questions as soon as possible. Until then!