Creating a Stable Foundation - 5 Years In The Making!
In late 2014, I made the bold decision to focus less with Source Engine mods and pick up an actual engine I could use without legal conflicts or worrying about knowing the right people. At the time, it was like all other options were telling me to forget everything I've picked up through the years of making popular maps and mods and learn something that's completely unique to their software. CSG tools were declared too uncool, and any engine that was nice enough to support it enforced that any and all CSG objects should be removed.
And there I found Leadwerks. The editor looked and acted like Valve's Hammer Editor and I could code my game in C++. While the Source Engine didn't really use modern C++ (It was more C with classes and a bunch of macros if anything anything) I felt more open to learn this than anything else at the time. Also, my internet wasn't great at the time so the small install size was a plus.
Only thing that threw me off from the start was that a lot wasn't done for you. With Leadwerks, YOU are in charge of window creation and YOU are in charge of how maps are loaded and cleared. Any engine I've tried, this is done for you and they give you documentation on how their system works for you to read which I'm not a big fan of.
After I shipped the Vectronic Demo in 2015, I wanted to have a nice C++ foundation framework to work on. Back then, there wasn't an Actor class to attach C++ functionality to entitles, the animation functionality was in a Lua script, and back then there was no editor materials so you had to make trigger boxes invisible. I wanted something that didn't need Lua to function and make life easier to make maps. I also wanted code for window and world handling to be automatic- to "just work", This started as the LEX template.
Looking back, the LEX template is a huge mess of code that did all of that. A demo game was made for a game tournament in 2015 or 2016 (I forgot tbh) called Crawler's Den. The entire game was written in C++. During the development time, my animation code I translated from the Lua variant got adapted into the base engine which made life much easier. This also made animations faster and easier for everybody. I also took time to look into cubemap reflections which I think really pushed for the probes in 4.1. In the end, the template was unstable and hard to work with. I was often afraid to clear and load a new map due to raw pointer issues.
I instead dropped the idea in favor of a similar system using Lua. Luawerks was everything I wanted LEX to be but much safer. It was more adoptable as most people only have the Standard Edition of Leadwerks. I finished the code and pushed it to the market place.
However, I really wanted to make a game with C++ and at this point VR was coming online which C++ is better suited for.
For the past 3 or so years, I was writing testing, scrapping and recycling code figuring out the "best" way of a system. I tried to do a translation of Luawerks to C++ but decided against it early on. I figured out why my code was crashing before, what objects I can Release when the entity deletes and overall became better at programming. However, a new engine was on the way and I didn't want to write code if I just had to redo it again.
I threw the 5 bucks a month for the early subscription at the time for access of the SDK of the new engine. Back then, I thought the new engine was just going to be "Leadwerks but faster" but that wasn't the case. I made a few macro's and #ifdef's to accommodate for this. Over time however, function names were changed, renamed, or removed completely. and the new engine slowly began to do things differently than Leadwerks.
It came to a point in which how my systems would work needed to be completely different for both engines. In late 2019, I decided to cut the code in half making one folder called "Core" for core app functionality. That part of the code would be translated for the new engine and tested occasionally. This is also the time when I decided to really look into input functions. The "Game" code was code I would just create as normal and worry about it converting it later a file at a time. You can play the results here.
In early 2020, I started a game project using this base but shelved the project due to the fact I was not happy with getting 150fps on a simple scene. This was also pushed when I threw in a fast VR implantation and thought it was really cool (But really slow!). I also was getting random crashes with an actor over something so something was still up with my design. The new engine was coming a long so I re-structured my base yet again.
As of today, after many years of work and research I now have a very clean framework that works on both Leadwerks AND the new engine. I see this as more important than ever now as I expect a lot of people are gonna come in for the new engine and be in the same position I was in 2014.
At minimum, this is how your main function should look like and will compile with both engines!
#include "pch.h" #include "gamewindow.h" #include "stage.h" int main(int argc, const char* argv[]) { // Create Window App auto window = CreateGameWindow("FPSGame"); // Create a stage. auto stage = CreateStage(window); stage->LoadSceneFile("Maps/start.map"); // App Loop. while (window->Closed() == false) { stage->Update(); } }
This code will create a window, load a map/scene file and update accordingly. Not only for my games, but this also works really well with my current "non-game" project!
I wish to go into how into this deeper at a later date, but I thought I should bring context to the last 5 years. Although I didn't get to build a game within that time, I had a blast figuring all this out.
I'll leave off with screen shots. Remember. it's same code base doing the same thing for each engine!
Leadwerks 4:
New Engine:
- 2
2 Comments
Recommended Comments