The DeltaEngineCpp repo is not simply a .NET C++/CLI version of the DeltaEngine, but instead a complete port to native C++11 code. It contains the code that is required to make the DeltaEngine work on platforms that do not support .NET code directly. Unlike the .NET public repository the native source code is only partially available (as header files, all test projects with full source code plus compiled libraries). This is mainly because we do generate compiled code directly while keeping the header files for each platform in sync. Currently do not plan to support native code back into the .NET public repository where we all work in. If you have a full company Delta Engine Services license and a signed NDA, please contact us so we can provide you with as much information, debugging files and full library source code we can provide. You are free to change any open part of the source code or extend it, which is easy to do. Changing low level components is dangeous and can cause code to become platform dependent quickly, but changing anything at a higher layer (above low level graphics, platform, multimedia, etc. modules) is highly encouraged.
We think DeltaEngineCpp is mostly useful for C++ programmers, for people that do not want to learn C# or for anyone still believing it makes a difference to write in native code only (we don't think it matters nowadays, profiling and optimizing whatever is slow is a much more useful approach than getting into language wars). There is obviously a lot of advantages with C++ like more control over the source code, memory management and tons of libraries. We do support C++ as a first class citizen of the Delta Engine, but we are not C++ gurus and we much rather program in C# and let C++ code be generated from it. Feel free to modify and if you have tips or want to join the team, let us know :)
Please note that we also plan to support more programming languages in the future (like Java, Lua, Python, maybe HTML5/Javascript?). We don't know yet, but if you have ideas or feedback or even want to help out, use the Forum. Thank you.
All the tools used for programming in C#, with the following additions:
All of these dependencies are included in DeltaEngine (Hypodermic, boost), but you can also install and use other versions (just copy into the appropriate directories). See Getting Started with Cpp for more information. For easier testing and debugging the engine is developed mostly in debug mode. Released libraries are in Release mode for better performance!
Following environment paths are recommended, but not required (you can still use the default paths and everything works, or fix up the paths yourself in your project):Before any code can be added to a new project, the following steps must be made:
1 2 | #include "Graphics/OpenGL/OpenGLImage.h"#include "Graphics/OpenGL/OpenGLDevice.h" |
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <ImportGroup Label="PropertySheets" /> <PropertyGroup Label="UserMacros" /> <PropertyGroup /> <ItemDefinitionGroup> <Link> <AdditionalDependencies>DeltaEngine.Graphics.OpenGL.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup /></Project> |


Tests are written using Visual Studio Native Unit Test Support because it is the easiest way to test native code in VS. Hence, new test projects must be created using the Native Test Project template. Afterwards, the default solution folders and precompiled headers should be removed.
Note: When using Run All or the automatic test runner after each build of the Test Explorer window in Visual Studio, it is highly recommended to limit the tests with a filter to -Trait:"Slow" to exclude all slow and integration tests. Remove the filter to run integration tests from time to time.

There should not be any header file except for helper classes (e.g. Mocks). There must be only one .cppfile per class to test, which should have the following format:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <CppUnitTest.h>#include "MyProject/MyClass.h"using namespace Microsoft::VisualStudio::CppUnitTestFramework;namespace DeltaEngine { namespace MyNamespace { namespace Tests{ TEST_CLASS(MyClassTests) { public: TEST_METHOD(MyClass_TestMethodName) { // Some test here. Assert::AreEqual(expectedValue, actualValue); } TEST_METHOD(MyClass_OtherTest) { // Other test here. Assert::IsTrue(trueValue); } // ... };}}} |
Writing mocks is not as easy or automated like in .NET, but still possible via Google Mock. Usually (like in many cases with simple C# mocks) it is more than enough to quickly create your own derived class without any mocking framework in the test project where the mock is needed.
Simple example, for a more complex one check out the MockWindow in DeltaEngine.Platforms.Tests:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class MockWindow : public Window, public IDisposable{public: MockWindow(List<string>* output) { this->output = output; } void Run() { output->Add("Window.Run"); } void Dispose() {} private: List<string>* output;}; |
You should test as much as possible with automated unit tests and run all tests after each build. However tests that take longer than 10ms should be integration tests and tests that need user input should be visual tests. An example is closing a window after confirming visually it has been created and looks correct. While compiling and starting automatic unit tests takes much longer in C++ than in C#, the actual execution speed of unit tests is much faster as there is no additional startup overhead, assembly loading costs or reflection. This means many tests that would be too slow in C# might fit into an automatic unit test in C++, but you should still make sure tests are as fast as possible and no actual windows, devices, etc. are created in automatic unit tests, which would annoy or confuse the programmer.
When derving from TestStarter class you can easily define integration and visual tests and when testing, they actually runs the same test method multiple times for each registered resolver. This is very useful for namespaces like graphics, multimedia, input, etc. tests, which need to be run with each framework separately.
For example take a look at WindowTests of DeltaEngine.Platforms.Tests, which runs either Integration tests or a Visual test:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | TEST_CLASS(WindowTests), TestStarter{public: VISUAL_TEST(Window_CreateWindow, std::shared_ptr<HypodermicResolver> resolver) { Start<Window>(resolver, [](std::shared_ptr<Window> window) { Assert::IsTrue(window->GetIsVisible()); }); } INTEGRATION_TEST(Window_ChangeTotalSize, std::shared_ptr<HypodermicResolver> resolver) { Start<Window>(resolver, [](std::shared_ptr<Window> window) { window->SetTotalPixelSize(Size(200.0f, 200.0f)); Assert::AreEqual(Size(200.0f, 200.0f), window->GetTotalPixelSize()); }); }}; |
The following structure is used in all files:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #pragma once#include "ElapsedTime.h"#include "Hypodermic/AutowiredConstructor.h"#include <memory> namespace DeltaEngine { namespace Core{ // Provides the current app run time and delta time for the frame. All times are in seconds. class Time { public: typedef Hypodermic::AutowiredConstructor<Time(ElapsedTime*)> AutowiredSignature; Time(std::shared_ptr<ElapsedTime> elapsed); int GetFps(); float GetCurrentDelta(); long long GetMilliseconds(); void Run(); bool CheckEvery(float timeStepInSeconds); // Returns an accurate seconds float value for today, would get inaccurate with more days. float GetSecondsSinceStartToday(); private: void SetFpsTo60InitiallyAndSetUsefulInitialValues(); void UpdateFpsEverySecond(); #pragma warning(disable: 4251) const std::shared_ptr<ElapsedTime> elapsed; int fps; int framesCounter; long long thisFrameTicks; long long lastFrameTicks; float currentDelta; };}} |
Each non-test namespace should have a header file and props file, located in the solution directory. These file are designed to help users including a whole namespace and all needed libraries easily, but it does not have to be used. In fact in the engine these files are never used and it is a better practice to only include headers and libraries you really need. However it is much simpler to just include a header and props file to get started with your project.
1 2 3 4 | #include "SomeRequiredLibraryHeader.h"#include "MyNamespace\HatFactory.h"#include "MyNamespace\BigHat.h"#include "MyNamespace\SmallHat.h" |
Every source file should start with an include statement for the corresponding namespace's header file. The namespace should also be used.
The implementation of class members should follow all the same rules as for C# files, except that static proprieties assignments must appear last.
1 2 3 4 5 6 7 | #include "DeltaEngine.MyNamespace.h"using namespace DeltaEngine::MyNamespace; void HatFactory::MakeCap(){ // ...} |
Except for these summaries, no comments are usually not allowed in the code. Like in C# code TODO, HACK, commented out code and other author comments are forbidden, only when something really needs explanation (which is not that rare in C++) a comment should be used to help explain the issue to the reader.
Consts should only be used whenever some code requires const parameters (e.g. Assert::AreEqual for unit testing), usually this means operators are const. When the C++ code is generated const will be inserted if the generator knows that the body won't modify the parameters or fields. However sometimes const will be obmitted when not necessary for performance reasons (non-const code can sometimes be optimized better in C++11).
Const parameters and methods can be called with or without const parameters, but not the other way around. Most code affected by const is low level code for datatypes and basic classes. Also const is designed to be used as a protection for a programmer not to modify stuff at the wrong places, so you will also find it in high layers or in user written code when the programmer wants to avoid mistakes. For the mostly generated engine code it does not matter, but it might still be helpful to know if a method does not modify pointers passed into it (usually only happens when we would use ref or out in C#, which is very rare).
In tests, your own projects, game code, etc. you should of course use const where possible.
1 2 3 4 | class Window : public virtual Core::Object, public virtualCore::IDisposable{ //...} |
To enable build times go to Visual Studio -> Options -> Projects and Solutions -> VC++ Project Settings and enable Build Timing:

Use smart pointers if possible and especially at high level. Pointers should only be used when strictly necessary (when C++ does not provide any other reasonable solution). For small classes using them as value types usually makes more sense and is faster (datatypes, simple and short classes, etc.). In the case of doubt on whether or not to use pointers (or if std::shared_ptr might slow down some performance critical code), simply make a speed test for both solutions (in unit tests and integration tests) and optimize then.
1 2 3 4 | Detected memory leaks! Dumping objects ->{2123} normal block at 0x036073A8, 32 bytes long. Data: 69 6D 61 67 69 6E 61 74 69 6F 6E 20 74 65 63 68{355} normal block at 0x008CB2B8, 140 bytes long. Data: < a > 94 0B 61 01 00 00 00 00 CD CD CD CD 00 00 00 00... |
C++ compilers commonly generate several warnings, even for perfectly working code. Yet, warnings should be treated as errors, and solved before being pushed to the repository. Hence, the \wxcompiler flag should be enabled. The same goes for linker warnings (use the same /wx linker flag). Only as a last resort linker warnings should be disabled (e.g. when you understand the warning and just disagree with the linker).
When warnings are not solvable, or simply do not make sense, they should be ignored using the "disable" prepocessor directive.