This will be the last main update for the blog, I expect, for this year.
I’ve been quite busy in between work and Christmas, but I found a couple of hours today to get back to business. There are a few more days coming up over the holidays where I have all day to myself and I expect to make more progress, also.
The camera/joystick refactoring is essentially complete. The last two refactoring steps are to bundle the window/render classes, and to dismantle my material class.
The refactor of the window/render class will essentially hide the window class behind render. Future programmers using the classes will be able to interact directly with render, and render will make the appropriate changes to the window – programmers don’t need to know anything about window for it to work.
The material class refactor is a left-over from when I first started working on shaders, and was necessary as I did not understand fully how to send data to the gpu. My existing material class is undesirable because all of my vertexes currently store the material emissive/ambient/diffuse values, and they do not need the extra ‘colour’ value. When I wrote this prototype vertex class, I made the class tightly bound to the material class. This resulted in other classes, which required access to vertex, having to also acquire the material class. Separating (or removing!) material from vertex will reduce the complexity of the vertex class and subsequent classes that rely on it.
I’ve found it increasingly difficult to spend time programming at home while working full time. My desire is not reduced – I simply have less time available, yet still need to complete many tasks. I have not been able to go to Kendo since the start of November. That said, my job is excellent and I’m very happy there. Sadly, the contract expires soon, so unless it is extended, I may unwillingly find myself with a lot more programming time.
The next major steps are to implement some kind of AI and some simple 2D collisions. After the mind-numbing horror that was 3D collisions with object-oriented bounding boxes, 2D collision detection with axis-aligned bounding boxes ought to be a breeze.
Once again, this has mostly been ‘behind the scenes’ programming. Refactoring is simply pulling apart the system architecture and putting it back together in a more elegant fashion. I will have effectively pulled apart the entire engine by the end of this process, so that I am no longer modifying and extending a prototype – I will be extending and modifying a baseline version. This is quite exciting.
I am concerned that there has been no visual progress in the last few months, and that this will likely continue for the next update-or-two. Certainly, reading walls of text doesn’t make for a very interesting blog.
The MISRA rules specifically prohibit use of ‘new’ and ‘malloc’ and any manual allocation of memory. Declaring a variable that will be destroyed once it goes out of scope is fine.
I mentioned pointers, but we’re really interested in objects. You can create objects on the stack, or on the heap, in C++. If you create it on the heap, you need to allocate the memory using new; this is the ‘manual allocation’ that is prohibited.
If you allocate it on the stack, then the object will be destroyed once it goes out of scope. This is acceptable according to my understanding of the MISRA standard.
Creating objects on the stack is somewhat limited if I recall correctly. If your object has member variables that are themselves instances to other objects, then you need to provide a constructor initialisation list as well as predeclare the class, and probably other steps that I can’t remember right now.
Some examples and explanation of what I am talking about can be found at http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/
In practice, I’m not sure if this information was helpful to our engineers. I have noticed other such ‘loopholes’ that are being exploited, in particular regarding pointer arithmetic. However, the reasons the engineers have provided are sound, which causes me to question why MISRA does not discuss these ‘loopholes’ since they are the apparent solution to the constraints imposed.
Jan 2 update: I’ve finished refactoring ALL of the input classes. The major change is that there is now a single camera controller class; the mouse/joystick/keys all funnel through InputHandler, which calculates changes to the camera stack based on information from the user interface devices.
This allowed me to prune significant amounts of code from all of the user interface classes, including surprisingly the main game loop, since I was now only touching camera once, regardless of how I was accessing it. I’ve also been able to get rid of a whole bunch of “if(cameraMode == “mouse”)” type if statements.
I can now control which device is used by simply assigning it in init of the game, with “input->assignCameraRotator(“mouse”);” and changing ‘mouse’ to ‘joystick’ ‘gamepad’ ‘keys’ etc.
Once again, this is a quality of life, or behind-the-scenes, architecture improvement. It’s been hanging over my head for about two months now, and finally, it’s complete.
Now to look at the material class and see what the heck I was thinking when I wrote that thing nearly two years ago…
About 10 minutes later: OK that was more trivial than I recalled. Material is done. I have a nagging feeling there was something bigger in there that I wanted to look at, but I’ll move on for now.
So the last refactor now is to look at the drawing/rendering/camera classes and see if I can bundle this together more elegantly. I can’t complete this task at the moment as I wish to encapsulate my shaders/lighting classes, and these should be loaded from a file once I start building my environments using external files. This capability doesn’t exist yet, so instead I want to support this functionality to be added at a later date.
Upon review, my renderer class had precisely one function (render!) so I just rolled it right into the WindowHandler class and achieved the desired encapsulation.
So to wrap up the last few months; that’s the last ‘under the hood’ change I’ve been working on. There were two main steps completed – one, completely rework my scenes/actors so that they used composition and the decorator/flyweight design patterns. Now, scenes aren’t actually in existence anymore, and I only have actors, but those actors can be real 3D models or 2D textured quads (and anything else I throw in).
The second major change was a somewhat fundamental refactoring of the entire project, to divide related parts of code together, and only allowing a single bridge between those parts.
This has had the net result of improving the architecture so that is is flexible and able to incorporate changes easily.
This puts me essentially where I was at the end of October, when I wanted to work on the AI, but felt that there was too much rework required. I’ve now completed that rework, so it’s time to code up some AI for the enemy units.