Home - dprandle/nsengine GitHub Wiki
I will go through some basics here on what an engine is and what this engine is trying to accomplish. To see specifics you should navigate using the right panel to tutorials of interest.
A game engine is nothing more than a bunch of functions, classes, variables, etc that provide some basic functionality/backbone so that it much faster and easier to create a game. For example, to draw something to the screen a lot of setup stuff has to happen. Let’s assume we are going to use OpenGL.
First we need to setup a window in whatever operating system we are targeting. Each operating system will have a different set of header files we need to include and functions we need to call in order to do this. Let’s assume we have done everything necessary and now have a blank window.
Next, we would need to create an OpenGL context and call some more operating system dependent functions in order to set up the pixel drawing format and assign the above window to this context. With all this done, we should now have a black screen with nothing on it. With the OpenGL context created, we can use OpenGL functions to draw to the screen.
In this day and age, if we are rendering using either Direct3D or OpenGL then we need to be using shaders. In order to use a shader we have to call some functions to supply OpenGL with source code, then compile and link the shaders before they can be used. When all of this is done, another function is used to set the shader as current, and then more functions are called to supply the shader with vertices and other information so that it can render something. If you are interested in this process check out http://ogldev.atspace.co.uk/ for a more thorough guide.
Anyways, now that we have all that setup we need to figure out how to get vertex information loaded in to our game. To do this we gotta read in some .obj or .dae or .fbx files and parse through it to get vertex information and load it in to a std::vector or array or something.
This is just the beginning. Did you notice something in common with all of the above steps? They are required really no matter what game you are making. Wouldn’t it be nice if we wrote some code that would do all this stuff and then just used it in the other games we made?
This is exactly what an engine does. With an engine, for example, rather than write all of the above code, you might only have to write something like…
#include <nsengine.h>
#include <nsglfw.h>
int main()
{
glfw_setup(ivec2(400,400), false, "My Game");
uint32 i = nse.create_context();
nse.start();
while (glfw_window_open())
{
nse.update();
glfw_update();
}
nse.shutdown();
glfw_shutdown();
return 0;
}
This code uses GLFW library to create the window - which has glfw_* functions in the engine to wrap the GLFW functionality. The glfw_setup function sets up a screen that is 400 by 400 - false indicates that we don’t want fullscreen, and the last parameter is the window title. This is a lot less code to get started with making a game.
“nsengine” is an entity component system engine (ECS). Rather than using a deep inheritance hierarchy, it uses components to give game objects their behaviors. Components can be attached and removed from entities during execution. “Systems” are used to update components which are attached to entities, and/or perform logic based upon certain component’s data.
In general, attaching a component to an entity will result in the entity being updated by some system, and detaching the component will stop the updating. For example, if a render component (which contains data about how to draw the entity to the screen) is attached to an entity, the entity will be processed by the render system. If the entity is added to a scene, it will be rendered. If the render component is detached, the entity will no longer be rendered - but it would still be part of the scene.
Besides systems and components, the engine provides many other useful classes/functions for making games or editors. There is a selection system, for example, to handle mapping mouse movements to 3 dimensional movements. There is an input system which maps certain key presses to trigger events. There is an event system where events are routed to systems which have registered their interest in the event type. There are multiple “resource” classes along with a standardized saving and loading system.
All of these different aspects will be covered in this wiki in more detail. Also, a series of guides go through everything from the process of setting up basic GLFW based and Qt based projects, to adding your own components, systems, resources, and resource managers to the engine. I believe learning by example is the easiest way to understand something, and so I will try to discuss all engine features by attaching actual working code to the tutorial.
The engine was created as a means to an end. The project started in 2013 when Alex Bourne and I set off to create a basic platform which could house hex tile based games. The result is a bit more extensive than originally planned, yet there is still plenty of room for improvement and expansion.
I love understanding what’s under the hood. In a large way, this engine is a culmination of my learning and exploring through what is under the hood in a game engine. I used to hear the words “game engine” and would think of something mystical and magical: Something that I would never really understand.
Another reason why I set out to make a game engine is that I want to understand how everything works so that it is easy to customize functionality. I intend to make it as easy as possible for others who may use it to do the same.
Provide a re-usable set of modules that can be easily be extended or appended without having to change any existing code.
When writing code for the engine, the following guidelines should be followed:
- All systems and components should be addable and removable without crashing the engine
- Underscore case should be used for any public interface
- An event handler should not create events that it handles
- Code should work on Windows, Linux, and Mac (no OS specific function calls unless guarded with #ifdef WIN_32 or whatever OS)
- If source code is copied from somewhere else, make sure the author is okay with it and list the url in a comment next to the code
- Code must be developed under the influence of coffee
And some Git guidelines
- Any major changes should be implemented in a branch other than master, and only merged after successful testing
- Though it is fine if local commits don’t compile, never push a non-compiling commit to the repository
- Write simple messages with commits
- Do not add any of the auto-generated files from the build process
- If a 3rd party library is added follow the format in the “deps” folder
- Do not delete everything and then commit and push