-
Notifications
You must be signed in to change notification settings - Fork 0
Home
A new version is being worked on that is more modular, uses modern C++, cleaner more organized build files and more. You can see the progress here: https://github.com/2LoC
The 2LoC engine is a production ready engine with tight error checking and an emphasis on compile time checks (asserts) whenever possible. A major portion of the design time went into making the engine programmer friendly. Ambiguous/vague function parameters when creating or working with different objects by creating explicit types were avoided. This ensures that your types are compatible (at compile time). The coding practices encourage documentation via code and avoid (redundant) commenting wherever possible.
We tried to use best C++ practices (although looking back, the code can be improved a lot especially with C++11 and 14 features which the engine could not use at the time).
The 2LoC engine depends on tlocDep which must be compiled first. Optionally, you can also clone
tlocSamples.
Although the build process is quite flexible on where you put your files, for now we'll assume you have the following folder structure when you clone all 3 repositories:
.
..
tlocDep
tlocEngine
tlocSamples
The build process might seem complex at first. However, this configuration allows the greatest flexibility when working with different builds.
https://github.com/samaursa/tlocDep
https://github.com/samaursa/tlocEngine
https://github.com/samaursa/tlocSamples
Assuming you are in the root
of the repository:
mkdir build
cd build
cmake ../ -DDISTRIBUTION_BUILD=ON
cmake --build . --config "Debug"
This will create an INSTALL
folder in the root
of the repository which has a build
folder. If you had made a directory called build_2015
then you will find a build_2015
folder in there.
The reason to go this route is to allow different build configurations to work simultaneously. For example, we can have VS2012, VS2013
and VS2015
builds running simultaneously making it easier to test different builds before distributing the engine. Moreover, we can have Debug
and Release
builds for all the different configurations also running simultaneously.
The engine needs to know which tlocDep
distribution you are using and thus it needs its INSTALL
path.
mkdir build
cd build
cmake ../ -DDISTRIBUTION_BUILD=ON -DTLOC_DEP_INSTALL_PATH=../../tlocDep/INSTALL/build
cmake --build . --config "Debug"
NOTE: As pointed out before, the path ../../tlocDep/INSTALL/build
assumes the folder hierarchy shown above and that you named your build folder build
.
The samples need both the engine's and the dependency INSTALL
paths.
mkdir build
cd build
cmake ../ -DTLOC_DEP_INSTALL_PATH=../../tlocDep/INSTALL/build -DTLOC_ENGINE_INSTALL_PATH=../../tlocEngine/INSTALL/build
cmake --build . --config "Debug"
If you want to distribute your samples, then you should enable the option -DDISTRIBUTION_BUILD=ON
when generating the project. However, this project may have issues when debugging in Visual Studio.
Instead of overriding your current project's settings (under the build
folder), you can start a new CMake project under a different folder e.g. build_distr
. This setting must be used if using a continuous integration server such as Jenkins.
Most other engines are editor driven. That's their main goal, the engine is designed around the editor. 2LoC foregoes that approach and puts a heavier emphasis on making the engine friendlier for programmers.
The engine makes no attempt to compete with other engines. If you are a programmer and would like to program games so that you can learn more and keep your skills sharp, then this engine may be for you.
Our smart pointer implementations (and extensions) allow easier checking for memory leaks and segfaults. If you replace your raw pointers with VirtualPtr
you will be able to get all the benefits albeit with some cost in runtime speed (debug builds only). In release
builds, VirtualPtrs
are as fast as raw pointers and there is no performance penalty.
The engine uses CMake and is thus CI ready. The build machines went offline in late 2015 in favor of another, more modern, engine that is in the works (where once again, the editor will not be the main focus).
Each engine library is complemented with a test project. Although the coverage is not 100%, all the major components are tested regularly. Moreover, the tests can help identify issues on machines where any or all samples do not run properly.
Because the engine disallows the use of C++ exceptions (although they can be turned on for individual projects), error handling was given a lot of thought. The core_err::Error
class defines the basic functionality for the error handling system. In release
builds, the errors can optionally be compiled out to always assume SUCCESS
. This gives a measurable boost in runtime performance.
One of the core features of core_err::Error
is that, unlike return values, it cannot be ignored. The core_err:Error
records the file and line number of the error as well as the call site that caused the error. If there is an error which is not checked by the user (e.g. GLSL uniform
name mismatch) an assertion is fired.
The engine comes with its own logging system that is quite fast, although not as fast as spdlog or Pantheios. Unlike the other two libraries, it does not rely on the std library (which is a common theme in the engine), is quite lean and is easily extensible.
One of the biggest hurdles while working with large libraries with dependencies (such as the engine) is making sure that we're building against the correct version. The problem becomes tedious and error prone when a bug creeps in and the developer now has to determine which changeset the bug originated from.
We wanted to avoid something similar to git submodule
for any subproject with the engine as a dependency mainly to avoid waste of disk space. Thus, the internal versioning system was born where any project dependent on the engine requires a tlocVersionCheck.cpp
file which in turn checks the version set by the subproject against the current revision of the engine. If there is a mismatch, a compiler error is issued.
One of the biggest advantages over submodules
and similar is that the version numbers are searchable in the commit history. If subproject B
in on commit #40 and a bug was found to originate on commit #25, the developer can immediately know which version of the engine commit #25 compiled against.
The system can be bypassed very easily by commenting out an include
directive.
The engine was built when C++11 was not widely supported. Thus, all features in the engine before ver0.2 are implemented in C++03.
- Depends only on tlocDep
- No C++ Exceptions
- Mostly standard compliant STL implementation (without C++ exceptions) - with many added features and interfaces
- Containers
- String
- Iterators
- Algorithms
- Data structures
- High resolution timer
- Standard compliant smart pointers including some novel smart pointers
- All smart pointers and raw pointers convertible to
VirtualPtr
which helps debug pointers e.g. dangling references, destroyed SharedPtr and UniquePtr. InRelease
it is optimized to a raw pointer -
VirtualStackObject
which allows creation of objects on the stack with pointer semantics. This helps trace hard to find bugs when an object on the stack goes out of scope, is destroyed, but is referenced by aVirtualPtr
(remember, aVirtualPtr
is nothing more than a raw pointer inRelease
) - Data driven with a robust and easy to extend ECS implementation
- Built-in logger
- Custom window and input implementation (to avoid SFML, SDL dependency)
- Type-safe, RAII wrappers for OpenGL
- Compile time type checking for OpenGL
- e.g. uniforms and attribute types are checked at compile time to avoid sending the wrong data type - this removes a full class of OpenGL bugs when working with shaders
- Novel Shader Operator design allowing reuse of shader variables on different materials
- Many drop-in systems to make development easier:
- Camera system
- ArcBall camera control system
- Bounding box rendering system
- Extensible debug render system
- Static and dynamic text rendering system
- Material system
- Mesh render system
- Scene graph system
- Skybox rendering system
- Sprite animation system (called texture animator)
- Ray picking system (without external dependencies)
- Text rendering using Freetype
- PNG and JPEG loading using header only external libraries
- Built-in sprite support
- Rendering pipeline with command buffer
- Keyboard, mouse, joystick and touch support without external dependencies
- Fast vector, matrix, projection types
- Utility classes including pythagoras, angle, range and scale types
- Box2D driven physics engine with rigid body dynamics and events
Not to be confused with Unity prefabs. This is where the engine truly shines:
- Quickly and easily create components and systems using the prefab library
- Many built-in prefabs including
- Camera
- Mesh creation
- Scene graph related components
- Sprite
- Skybox
- Textures
- Text rendering
- Camera control
- Math
- Physics
- Animated rigs not supported
- Underlying data structures are not thread-safe
Here are some of the samples distributed with the engine:
Sprite switching on the same material. Animation state is controlled by the same entity.
Animation of multiple texture coordinates (saves space on sprite sheet)
Efficient storage of font sprites using the Guillotine Bin Packing algorithm.
Faster than dynamic text.
Note that the counter may seem like it is jittery - that's alignment at work (we didn't choose the best font to show off the alignment features)
Blitting to a texture.
Each texture uses a different storage format. The image types are set at compile time (using templates). The shader operator mechanism selects the correct internal format for OpenGL simply by passing the image type - again, at compile time.