Game Engine, C 1, P 1, Project Structure



Introduction

Why create a new game engine? The answer is simple: there are many game engines on the market, but most of them are lacking important features. Others on the other hand are big and powerful, but have other disadvantages.

Having said all of that, the main purpose of this series is to learn how to write your own modern game engine together. This series does not go deep into provided topics, nor does it explain surface aspects in detail. In case of misunderstandings, I may answer some comment explaining a difficult section of a post, or try to edit it with further explanations.

This Series Structure

It is difficult to tell out-of-the-box, what we will do in this or that post. What I hope to do is to dedicate each post to a different topic. After that, I will move to the second chapter: expanding everything. If at some point I get satisfied with what I have and call it a day, I might start the third chapter: revision and improvements.

Source Code

At the time of you reading this, there probably will be a separate page listing all of the series and additional info. You should find the source code there. Further thoughts on the project structure will be listed below in this post.

Other Game Engines

Now let us focus on other game engines and list their drawbacks (in my opinion). Keep in mind, that I am in no way a professional programmer with years of experience (at the time of writing), so I will probably get a lot of stuff wrong. Everything listed here may be not accurate after some time passes.
  • Unity - very powerful with the Job System and High Definition Render Pipeline, but some powerful C# features that it uses can make it a disadvantage.
  • Unreal Engine - very powerful, even Open Source, but doesn't run well on my PC.
  • Godot - good community and Open Source, but lacks documentation, examples, etc.
  • Lumberyard -lacks support for older systems, cumbersome UI.

Conclusions

Based on this data and my assumptions, we can set us some goals for the first few parts of this series.
  • Make a Job System, make it actually useful and not just "being there".
  • Make a rendering pipeline, make it scriptable (even if at compile time). 
  • Make a level / asset streaming factory for seamless gameplay.
  • Make an editor to edit maps.
  • Make a sound api wrapper, try to sound as realistic (with aid of effects) as possible.
  • Make material support.
  • Make a scripting language wrapper.
  • Make a physics api wrapper.
  • Make a UI library for use in games (I want to make it as close to xml-based ones as possible with support for more optimized versions like in WinApi).
This list does not represent further parts of the series (and won't be updated), but should give you a basic overview of what we will be doing.

Project Structure

Now it is time to discuss our project structure. I plan to have documentation for the engine, dedicating a whole short post to it, so I need a folder to put it into. I plan to separate tests, engine and example apps, so I'll need folders for them too. I decided to call my engine VividEngine, so there will be a lot of references to this name throughout the posts.

In the end, I settled on this project folder structure inside the root project folder:
  • Build
  • Vivid-Docs
  • Vivid-Project
    • Libs (for external libraries)
    • VividCore (for the engine itself)
      • inc (for public includes)
        • vivid_core
      • inc_private (for private includes)
        • vivid_core
      • src (for source files)
        • vivid_core
    • VividTests  (for unit testing)
    • VividGame (a game using VividEngine)
Although it is far from perfect, it works well for a small projects. Everything here is pretty self-explanatory, except for the Libs folder, to which we will return in later posts.

Program suite

The last thing I want to talk about in this post is the list of programs and libraries we will use. Let us start with the libraries.

Rendering

To be honest, at the time of writing this post I am quite unfamiliar with DirectX, especially its newer versions. However, I want to use it at some point (probably through a separate rendering pipeline as discussed above), so stay tuned for that.

Considering the above paragraph, I will settle for now on OpenGL (3.x for now, later 4.x and Vulkan) with some context controllers on top. Context controllers are used to create and initialize windows, capture events (such as user input) and much more. Possible choices are:
  • FreeGLUT - old and clumsy.
  • GLFW - only window and input handling.
  • SDL2 - features of GLFW plus a 2d rendering API.
  • SFML - graphics, input, audio, networking.
With all that in mind, my choice for now is GLFW and here is why.

I am not trying to target mobile devices for now, so portability isn't really taken into consideration. My goal is to abstract the context controller library away from the game engine, so I can swap them when needed without major rewrites. Most of my code using these libraries will discard everything other than window and input handling, using other libraries for that.

SFML is out, because it is too overkill, providing many features I don't need and (based on reviews) obscuring features that are actually valuable. FreeGLUT and the likes are out, because they are just too old for modern standards. The code is very old-fashioned and difficult to grasp. SDL2 is a nice alternative, supporting multiple renderers, but it obscures some OpenGL / DirectX features to achieve multi-renderer support,which I am not fond of. Also, it does not use batching.

Now that we are done with our context controller, it is time to think about OpenGL extension loaders. They are used to provide declaration of OpenGL functions, enums, types and so on. Also, they can be used to load OpenGL extensions (functions, etc.), available through drivers but not yet in the OpenGL standard. A lot of performance can be gained on systems with graphics cards that support these extensions. Possible choices are:
  • GLEW - pretty old but still widely used.
  • GL3W - core profile of OpenGL 3 and 4, no extensions.
  • glLoadGen - similar to GL3W but with extensions and any OpenGL version.
  • GLAD - a modern extension loading library, has an online generator and provides hooks for debugging of OpenGL calls.
Again, best of these to me is GLAD. I have used all of the mentioned libraries before and I can safely say that I was very glad to use GLAD (sorry).

As you can see, choosing GLFW + GLAD was difficult in itself, so I am going to stop for now and come back to the topic of libraries in later posts.

Programs of choice

Now that we know, what we are working with, we need to select some useful applications. We will use them for everything from texture painting to account management.

First of all, we have to select an IDE. There are a lot of C / C++ IDEs on the market, every one of them has pros and cons. I will try to speak from my knowledge of them (even if it is close to none) and explain my choice. As usual, here is the list:
  • Visual Studio - I disliked it because of the MS C++ Compiler and constant hustle with libraries, but with added support for CMake it is very good. Still, it is large (filled with unused features) and sluggish.
  • Visual Studio Code - not an IDE (but a text editor) but still popular for small toy projects, has some useful features but most things are done by hand through the terminal.
  • QT Creator - a good choice, especially for people already using QT. Has poor refactoring and lacks proper IntelliSense for modern c++ features.
  • CLion - crashes when caching huge projects, tricky build tools integration.
  • CodeLite - code completion, IntelliSense and other features tend not to work properly. Very small development community.
  • NetBeans - slow, bad IntelliSense.
  • Code::Blocks - buggy, very bad IntelliSense.
Out of all these I am most familiar with VS and Code::Blocks. I use the former for Uni tasks and small tests. I use the latter for toy projects that I want to make as cross-platform as possible. My Code::Blocks is configured to use MinGW-W64 with its make, g++, etc. After taking VS CMake support, I decided to stick to it.

Now let's move to CMake. Why use it at all? Well, consider this: some reader on linux decides to run my code, but finds out I am using MS C++ Compiler. What now? The only option is to manually recreate the project on linux and recompile it. Sounds tedious and it is. With CMake a single code base can be redistributed to different compilers and systems. It also allows for custom building pipelines, which we will use later in these posts.

When we write some code, a good practice is to back it up and restore it in case of errors or emergencies. Backing up stuff can be tedious and difficult to maintain, so a version control utility is used instead. My utility of choice is Git.

A good addition to a workspace is a versatile text editor. There are many of them: VIM, Emacs, Atom, etc. I personally am used to Notepad++. It has support for temporary files, caching them on exit, so you don't lose them if you forget to press "Save".

As a matter of fact, we also need to think about documentation beforehand. I've found quite many documentation generators, some scripted on Ruby, some more renowned like Doxygen. My plan is to use Doxygen to generate a nice website with all the info I provide as comments, but Doxygen alone won't be enough to have a complete set of docs.

A kanban board can be used to track features, bugs, release cycles etc. Since this is a homebrew project, there is no need to seperate everything into sprints or other detailed steps, but having at least some grasp on project progress is useful. My choice here is Trello. It is not completely free, but it has everything I need.

A good practice for big projects is to develop UML Diagrams beforehand and during development. Since our project will be changed a lot, there is no need to store multiple versions of diagrams, but having them at all can be beneficial during meetups or even during development. My choice here is Draw.io. It has a cross-platform standalone application, has many different diagrams and lots of shapes to create custom ones.

I found it useful to also use an Office Suite during project development too. Aside from writing Game Design Documents and the likes, it can be helpful to write notes and explanations in a rich text file, format them with headers and so on, then generate a Table of Contents for fast navigation. Another cool usage I found is to use a Spreadsheet editor for ideas, features and bugs. While they can be used in their entirety inside the kanban board, it gives me satisfaction to have a huge table with many finished tasks and upcoming cool ideas. Also, since they are structured (at least they should be), we can work on them calculating success rates, etc. My Office Suite of choice is Open Office, but Libre Office is an excellent option too.

For texture editing I will use Gimp. My go-to solution before was to use Adobe Photoshop, but since I am trying to make this "walkthrough" as friendly as possible to users of all systems, it had to be ruled out. Recently, I discovered many artist youtubers who used Gimp for texture painting, which reignited my hope in free open source photo editors.

For modelling I will use Blender. It is very simple to use, free and extendable. With recent addition of Eevee in Blender 2.8 it became an even stronger competitor on the market. Other options include Autodesk 3ds Max or Maya and Cinema 4d, but they all are very expensive.

For sound editing I'll use Audacity. Whenever I have to crop or edit a sound file, I lean to it. Fast launch time, simple interface and good results - this is what I need. And Audacity delivers on that.

For video editing I'll use VirtualDub. It is a very simple editor, supporting only cropping, stitching and adding audio, but it is more than enough for us for now.

Conclusions

Now that we got ourselves a selection of different programs and libraries to use, let's list them together.
  • IDE: Visual Studio
    • Libraries: GLFW, GLAD
    • Toolchain: CMake
  • Helpers:
    • Version Control: Git
    • Docs: Doxygen
    • Kanban: Trello
    • UML: Draw.io
  • Editors:
    • Text: Notepad++
    • Office: OpenOffice
    • Image: Gimp
    • Model: Blender
    • Audio: Audacity
    • Video: VirtualDub
With such a list of tools, we should be able to create everything we need. The only thing left is to actually do it. You don't have to install everything listed here if you have alternatives or not enough free space. I am just saying that is is good to have these while working on a game engine.

Next post will focus on the setup of the project (Git, CMake, etc.). Go there?

Comments