Lara´s Engine
A small, selfwritten C++ game engine based on the Qt framework designed for 2D Games

About
The Idea
This project is my attempt to create a simple 2D game engine from scratch.
Why go through all this trouble to build a wonky engine all by myself, when there are a bunch of very powerful engines already out there, ready for me to use?
Well, the answer is that since I was a child, I was always driven by the burning question “how?”. How does the world around us function? How does a computer function? How does a video game function? I mean yes, dreaming about new cool game ideas is super fun, especially with friends or colleagues, but at the end of the day, I always wanted to know how these magical pieces of art work!
So, I decided to challenge myself, to make use of my 10 years of coding experience and to figure out the “how”!
Features
3 step GameObject implementation
At the heart of every game are the countless unique elements you use to bring your vision to life, so it was one of my goals to make the process of adding a new game object as quick and easy as possible, while keeping it as flexible as possible.
-
Step one: Define a unique TypId for your new class
-
Step two: Subclass GameObject and call its constructor with your newly defined TypId
-
Step Three: Create a new entry in Textures.json, with your TypId as key and the path to your desired texture as value.
Enjoy!! It's not doing much yet, but you can add an object of your new class to the engine's object list and admire it on screen!
Your new game object should move or react to the player's input? Override the Update() function!
Your game object should be able to collide with other objects and react to a collision? Set the collisionOn value to true and override the HandleCrash() function! You can also activate the collision detection by adding an entry named "collisionOn" to your game objects JSON file and set it's value to true.
You can learn more about JSON files in the following section!
JSON Support
The engine uses a variety of JSON files to avoid the need for hardcoded values as much as possible. All JSON files are to be located in a subfolder called JSON.
Texture.json: Here you can define every texture your game will need. Simply add a new entry to the "textures" array. The first value of an entry is the unique TextureId, this can be anything you like. The second value is the path to your texture file. If the TextureId is identical with an GameObject's TypdD, the texture will be automaticly assigned to your GameObject.
Sounds.json: Similar to the Texture.json, you can use this file to define any sounds your game will need. Simply add a new entry to the "sounds" array. The first value of an entry is the unique SoundId, this can be anything you like. The second value is the path to your sound file. The SoundId is used to acces, play and stop the sound at any point.
GameObject.json: In addition to the two JSON files mentioned above, you can place a JSON file named like the TypId of one of your GameObject subclasses, in the JSON subfolder. In doing so, the JSON file will automaticly get loaded when you create an object of this subclass and you can override the function ReadJSON() to use its content as you wish.
There are a few predefined values, that will automaticly get used, once you added them to your game object's JSON file:
-
"collisionOn": boolean, enables the automated collision detetction.
-
"hitPoints": integer, the amount of health point your object should start with.
-
"collisionDmg": integer, the damage another object suffers when colliding with this object.
-
"velocity": [double x, double y], the default velocity that will get applied to the obejct overy frame. For a more complex movement, override the game objects Update() function!
FPS independent game loop
Every frame, the engine calculates the discrepancy between your target FPS and the actual FPS your game is running with as a factor. You can set and change the target FPS at any point, as well as the FPS limit. Is the actual FPS matching your target FPS, the factor is 1. You can then use the factor at the Update() function of your GameObject's subclasses, to calculate any kind of stuff, like movement, independent of the actual frame rate.
Events
You can quickly implement trigger based events by subclassing the Event class!
Every frame, the engine will check all active events by calling the CheckCondition() function. If it's returning true the events Run() function will be called.
You dont need your event anymore? Simply set the active value to false and the event will automaticly get removed.
Level
Now we have our nice game objects and all sorts of events, but how do we organize them?
We wrap them into a level!
Create a subclass of Level and define a unquie LevelId. The id will later be used to set / change the active level.
Start(): This function will be called once, after your level got active. Use this function to initialize / reset every necessary value. Add the needed game objects and events, play some sweet background music, you name it!
ProcessInput(): This function will get called every frame, before updating any game object's. Here you can react to the players input, independent of a game object. This can be useful for example if you want to pause the game, or return to the menue screen once a specific key is pressed.
The Game Object Handler
This is a singleton class, accessible at any point of the game and the backbone of my engine!
Not only does it manage the list of every available level, game object, event, texture and sound effect, you can quickly acces them by using their id and you can change every setting like the active level, the target FPS, the FPS limit and the game status, with the help of this very object.