Spelmotor Engine


ProjectSpelmotor Engine (Avans minor ‘Systems Programming in C++’)
RoleEngine programmer – Stakeholder communication
Team size5
ToolsC++ – Custom engine – Cmake – Git – GitHub boards
Duration09/2025 – 01/2026

View the source code on GitHub: [https://github.com/Systems-Programming-in-C-Minor-Project/the-engine]

Project overview

During the “Systems Programming in C++” minor at Avans University of Applied Sciences, I collaborated with a team of 4 to design and implement a custom game engine from scratch in C++. We aimed for a network focused engine where creating games with multiplayer elements would be accesible and user friendly. The first 10 weeks were spend designing the architecture and implementation details of the engine, the following 7 weeks were spent developing The Engine and buildinga small demo game to showcase its capabilities.

Responsibilities

Within the team, besides being responsible for designing and developing parts of the engine, I took on the role of being the primary point of contact between our team and our stakeholders.

My main responsibilites included:

  • Designing parts of the architecture of the engine in collaborative setting
  • Creating UML diagrams and other forms of documentation to support the design
  • Keeping our stakeholders up to date in professional manner
  • Keeping the team up to date and informed about stakeholder requirements, deliverables and deadlines
  • Raising questions and claryfying uncertainties with stakeholders
  • Developing engine systems using Scrum methology conform sprint goals
  • Reviewing pull requests and contributing to code quality
  • Managing and tracking (my) tasks within the shared backlog
  • Adhering to code and commit conventions, including unit tests and documentation when opening a pull request
  • Communicate my progress with team members

Contributions

During the project, I contributed to the design and implementation of a few core systems:

  • GameObject and Components architecture
  • Game AI architecture
  • Networking components and architecture
  • Demo game

Game Object and Components architecture

Similar to Unity engine, The Engine uses a GameObject centric architecture where GameObjects can exist with one or more components. Some components may be behaviours, which a Scene object operates on. A SceneManager object manages all scenes and is responsible for updating and rendering the active scene, loading other scenes and moving objects between scenes.

The UML diagram shows the initial high-level design concept for the GameObject architecture. I focused mainly on the relationship and responsibilities of each class rather than concrete implementation details, which were probably going to change during development time.

Once development time started, I took it upon myself to implement this part of the engine directly because other systems were dependant on GameObject and Components to work as intended. After implementing the GameObject, Component and Behaviour classes. UnitTests were implemented to test for functionality and edge cases.
Although I did not develop the Scene related classes myself, I was responsible for correctly calling the lifetime methods of the Behaviour components within those classes, ensuring each behaviour was correctly initialised and updated throughout the program’s lifecycle. Additional unit tests were implemented to ensure this would always work as intended.

Game AI Architecture

I was in charge of designing and implementing the AI systems within our engine. I designed three versions of an Agent component with different complexity which were aimed to be friendly to use and work straight out of the box:

The first version implements an Agent component similar to a force driven entity, using a set of modules to compute it’s motion force. The engine would feature a few basic modules, where developers can create their own modules by implementing the abstract BaseAgentModule in their classes. Weights are used to control the influence of a given module, allowing developers to control the produced motion vector.

Version two extends on the first version and adds perception modules. A shared blackboard class is used to share and update data between modules and agents, allowing different modules to work with the same data without direct coupling.

The modules from the first version now fall under MotionModules, which are coördinated by an Agent’s MotionHandler.
The PerceptionHandler modules the sensing ability of an agent, and can make use of modules like vision cones, line of sight checks and hearing cues.

Additionally, developers can create their own motion and perception modules and plug them into their respective handlers to be integrated correctly and with ease.

The third version implements a lightweight navigation system along with relevant components. A NavigationAgent behaviour was added, which is able to navigate between a set of points in world space on a grid. The paths are provided by the NavigationSystem, which operates on a NavigationGrid, which divides the world space into walkable and non-walkable NavigationCells.

A IPathFinder class is used to find the path between two given points. Even though A* is almost always the preferred algorithm for games, this approach allows developers to use another algorithm with ease.

An obstacle in the world is defined by attaching an AgentObstacle to the GameObject. This component uses it’s Collider component (if attached to the same GameObject) or a manual given size to define the bounds of the obstacle. The NavigationSystem would use all AgentComponents in the active scene to bake the NavigationGrid, using the baked obstacles to carve their nodes from the grid to make them inaccessible. Because of time constraints, we as team decided it was okay for our implementation to do this only once instead of updating during runtime, which limits the use of this component for GameObjects that are changing positions during runtime.

Implementation

The final implementation combines the first and third version of the designs, aligning with stakeholder wishes. The agent motion modules architecture was implemented as designed in the first version, along with a few built in modules: seek, flee, wander and follow path.
Additionally, I aimed for an extensible, usable and modular navigation system, based on the design of the third version. The end result in the current version of the Spelmotor engine is an Agent component that uses AgentModules to determine it’s steering force and can make use of it’s own IPathFinder to find a path between itself and a given point using the Scene-accesible NavigationSystem.

The NavigationSystem computes paths between two points, using a given IPathFinder. To do so, it operates on an abstract INavigationSurface, which has built-in implementation for a NavigationGrid. This abstraction allows the system to be extended in future implementations, such as a mesh or 3D volume.

Additionally, the IPathFinders operate on a IPathfindingGraph instead of a INavigationSurface. This abstraction exposes only the neccessary information needed for pathfinding, without coupling pathfinding directly to a concrete surface.

In the current version of the Spelmotor engine, an Agent component can be put on a GameObject to simulate a moving agent in the game world. Using the built-in modules, the Agent can seek, flee and wander depending on the distance between him and a provided target. Additionally, the Agent can find paths to a given target and move along it using the same modules. A few examples of these Agents can be seen below.

The Agent (blue) follows a path towards the player (green), avoiding baked obstacles (red)

Networking architecture

Description of my role here (message handlers, NetworkBehaviours, usability, attributes C# desire.

Networking was the main focus for Spelmotor engine. In the designing phase, I contributed to the usability of networking components for our users. Inspired by Mirror Networing, we experimented with different approaches to integrate networking components in a friendly to use and accessible way.

The above diagram shows an initial version of the developer’s API when working with our engine networking components. This design featured a NetworkBehaviour and NetworkIdentity components that would be added to a GameObject. Inside the NetworkBehaviour, the user could add all their logic that should be going over the network, while the NetworkIdentity serves as the identifying label of an object with network capabilities. The NetworkManager in the active scene would be responsible for delivering the network messages to the required receivers (NetworkBehaviours), using an external INetworkTransport interface.

For the NetworkBehaviours, we really wanted to use a similar approach to Mirror Networking that uses custom C# attributes to tag functions that are network related. In the end, we decided to let go of the idea because the primary solution was a custom reflection system, which was too time consuming for our project.

Other contributions to our networking architecture was designing the flow to route incoming messages to the end points. I implemented the base classes for message handlers so future concrete messages would be handled accordingly.

In the final product, most of my design and implementations had been changed one way or another. Despite this, I did gain valuable insights into network architecture for games and how to design the overall flow of the needed components.

Demo Game

To test the capabilities of our engine, we created a demo game. I was in charge for designing the demo and features, and worked solo to set up the project and create the foundational features. The features I implemented in roughly 1-2 weeks were:

  • Health system, usable for players, enemies and items
  • Player movement logic
  • Weapon and ammunition system
  • Interactables such as ammo and item pick ups
  • Object and scene factory

In the end, we managed to create a small demo where multiple players could play together to defeat a few enemies, all synchornized over the network.

Description of my contributions to the design document and setting up the game repo and flow

Implementation details of classes and architecture and bug reporting/fixing during

Main menu of the demo game
In-game footage of the demo

Reflection

Designing and implementing a custom game engine in C++ came with a variety of challenges, both technical and process-oriented.

One of the main challenges on the technical side, was designing and implementing a scalable architecture adhering to SOLID principles for a game engine. With all team members being new to C++ during the design phase, this lead to a lot of uncertainties and open questions related to the architecture and implementation details.

Another key challenge was designing reusable and extensible systems rather than specific solutions. As game developer, I often have a single problem in front of me that I can work on. As engine developer however, I need a different mindset to design the systems in a way that they can be used in a number of ways. On the other side of the coin, this presented additional challenges to not over-engineer certain systems and balancing the complexity with usability and simplicity. For instance, abstracting the specific path finding algorithm sounded like a good approach, but will any other algorithm besides A* really ever be preferred?

Another challenge, mostly related to the design phase of the project, was using my game developer experience for the right things. Primarily experienced with Unity-engine, I caught myself on a few occasions wanting to implement things in a way similar to Unity, without having clear reasoning behind it. This was problematic; only using a specific engine or framework as source or inspiration clouds the judgement and could prevent me from finding the solution that fits best within the context of our engine. I first caught myself doing this while designing the networking API, which steered me into looking at Unreal engine and their solutions for networking.

Process wise, working in a team of students from different IT fields proved to be challenging. Our group consisted of software engineering, game development and technical informatics students, each from a different university. This mix of experience and expertise took some time to get used to, as well as deciding the tools and methods to work on the project. This, in combination of all of us being new to C++, lead to more challenges related to working together as a cohesive team instead of individuals. Intuitively, splitting responsibilities and topics to research was the correct approach, but this proved to hinder us when presenting our findings to our stakeholders and being able to answer their questions and feedback.

Validating each other’s designs and implementations was also challenging because of the inexperience with C++. I often found myself not being able to give detailed feedback on someone else’s implementation, due to them understanding their system better than I did. Although this was primarily a concern in the early phase of the project, giving and receiving valuable feedback without critizing was something we had to work on to find the right balance, even in the later stages.

A final but core challenge related to the process was balancing the quality of code and architecture with the available time. Because we had only 7 weeks to implement the complete engine and demo game; code reviews, quality assurance and testing were not always up to the standard we wanted to follow. Following our own guidelines, code conventions and practices, unit test requirements and comment formatting were the primary victims of the lack of balance, which primarily affected the polish of the end product.

Retrospective

Working on this project improved my understanding of game engine architecture and SOLID principles. Although familiar with the principles beforehand, this project really taught me how to apply it and especially why. Additionally, I’ve gained a lot more experience with applying programming design patterns, something I had been using for quite a while already but often just because they are viewed as good practices.

Working in an environment outside larger game engines and other frameworks really made me understand the use cases of all these important concepts and practices. Overall, this project improved my decision making when it comes to designing and implementing an architecture within a given context, whereas I feel a lot more confident in being able to tackle larger problems in a systematic way. Besides directly programming, I’ve gained a lot more experience with formulating my architecture design and iterating on them through the use of UML’s, something I will definitely bring to future projects.

At the same time, this project has highlighted a few areas for further improvement. Although I have found ways to first work on the architecture in UML’s, then work on code, I found that I can make things more complex and engineered then they need to be. While maintaining a clean and SOLID architecture is generally good, I still have a lot to learn when it comes to balancing complexity with simplicity, especially in time constrained situtations. In future projects I will take my time to analyse the problems at hand and design the correct approach for it, as well as being critical when it comes to my designed implementation and if it really solves the specific problem in a way that should be done.

Working collaboratively on a larger project like this with different developers was very meaningfull for me. As the game developer within our group, I’ve experienced somewhat of a tutoring role in certain situations, which made me more comfortable of voicing my opinions and thoughts on technical topics. Additionally, as primary contact with stakeholders, I’ve gained more confidence in taking a leading position within group settings, where I feel more comfortable speaking up and taking initiative for important deliverables, as well as checking up on others. Although I can sometimes struggle with feeling comfortable in a leading role, these positive experiences sparked my interest and confidence for related roles, something I hope to be able to explore in future projects.

Finally, working on Spelmotor engine sparked a new interest in engine development and creating reusable tools, as well as the C++ programming language. I’m excited to apply all my new experience and insights into further projects, and will take my time to delve deeper into designing flexible tools that other game developers can use in their projects. Additionally, I aim to improve my C++ knowledge so I can confidently work with it in game-related environments to further increase my skillset.
Working on Spelmotor marked an important step in my game developer journey, where I’ve increased my interests in building complex systems and tool with the C++ programming language.