Over the course of four months, I created the beginnings of a game engine in Visual Studio C++. It includes data structures like linked lists and hashmaps, event systems, parsing from JSON files, rendering, and a few other components necessary to create a game.

Structure
The game engine is based mostly on two classes: Scope and Datum. Datum is a runtime dynamic type data storage that can store ints, floats, string, vec4s, mat4s, Scopes, and classes extending the RTTI (Run Time Type Information) class. Scopes are wrappers for multiple Datum objects, sort of like a struct for dynamic data. They have parents and children, so they are often linked to other Scopes.
Attributed is a class that extends scope. Instead of just having list of Datum objects, it has many attributes, either added at compile time or runtime. Each attribute, which is a Datum, has a name, and no two attributes can be named the same. Attributed allows my JSON parser to read through a file and store the different data types as attributes on the class during runtime. This allows a game to be data driven and wildly cuts down on compile times.
Entities wrap Attributed, and they function very similarly to GameObjects from Unity, with a defined structure and a list of variables. Actions can also be appended to Entities, which execute code when a specific condition is met. Actions can be included in the JSON file to make entities.
The engine also has an event system, which is similar to how event systems work in many other engines. Certain events are enqueued to a list when their condition has been met, and they execute after a given time delay.