The Drag[en]gine is a fully customizable game engine and game development environment designed with modularity and extensibility in mind not requiring expensive licenses.
A longer answer to a question from the comment section about the engine API documentation as well as implementation specific informations.
Posted by Dragonlord on Nov 30th, 2010
To start first the question involved (by Bahl) and then the answer. Put it in an article so it does not collide with post length restriction and has comments separated from the rest (for better readability). The question revolves around the Drag[en]gine WIP Documentation.
Quote:Thanks for updating the doxygen :-). Let's see if I can summarize the API in a few handy words.
- under common the folders curve, math, shape for base geometry, color data classes and operations on them.
- the folder filesystem plus under common the folders string, xmlparser, file for base text persistence classes and operations on them.
- the folders logger, errortracing plus under common the folders exceptions for cross cutting error handling.
- the folder resources which seems to include mid and high level visual entities, artificial intelligence, physical and networking.
- the folder systems, containing the folder modules, containing interfaces for all modules, which then probably during runtime get their different implementations plugged at the will of the user.
All in all a neat setup :-). Maybe slightly unbalanced folder tree and a bit inconsistent sorting of the related structures, but oh well, systems grow and have a life ;-).
Now taking a look at the scripting:
- first impression is, it seems to be heavily relying on events and the implementation seems to be required to implement a lot of callbacks for AI, physics, rendering, network... . That sure covers the necessities for game logic, but seems quite cumbersome as a base layer.
- first idea is, I'd want to provide base game logic entities like avatar, tool, material, product, monster, machine, and some abstract game facilities to bind all the nuts and bolts together to something easily accessible. But maybe my short skim over the documentation made me overlook some gems that possibly already fulfill such desires?
I know it's a bit difficult to see the structure of the engine just from the DoxyGen without proper documentation in place yet. The basic view you obtained is not bad but there's actually sense behind the structure there. Let's see if I can state this quickly.
common: Contains classes which are used across various engine modules (hence do not belong to one module type). Scripting usually does not expose them directly with a few exceptions (curves, xml just for the case the scripting module has no XML itself). Hence for example to define the shape of a collider the scripts would use "collider.addSphere( center, radius )" instead of exposing a true sphere shape class (at the discretion of the scripting module). "string" is just a common place string/unicode implementation especially to simplify handling strings. "file" contains low-level stream handling access similar to iostreams. Hence it's not text-only and especially not require to be about files at all. "xmlparser" obviously provides xml read/write support using streams. "exception" provides a basic exception object for try/catch handling since C++ lacks this.
filesystem: Virtual File System. Independent of anything else. It just defines the structure of the VFS using containers and provides streams if asked for but by itself has nothing to do with "string", "xmlparser" or "file" (decPath is due to historical reasons in the wrong place, will be moved later on). So to handle a file you first get the stream from the VFS and then you can do whatever you want with it (like for example feeding it to an xml reader).
logger: Provides logging support for the engine, modules and launchers. Not made for error handling but debugging in the first place. Scripts usually never touch this. Supports multiple linked or independent logging chains.
errortracing: Provides error informations in the case of failure. Works like an exception trace. Used only by the engine, modules and launchers. Scripts usually never touch this.
resources: Building blocks of a game world and game behavior. Resources are low-level objects just containing definitions and states. Scripts manipulate the definition while modules provide the functionality and update states if required.
systems: This one is a bit special. A system is a class handling "single type modules". Something like this would be the "Graphics Module". Only one module of this type can be active at any time. It is also only resources affected by single type modules which have "peers". A peer is a per-resource, module-local storage space and one of the main reasons for why this engine rocks. Systems are required to handle creation and destruction of peers when single type modules are started/stopped. Hence peers live as long as their owner module is running while resources live longer (even through stopping/restarting the engine). The peers are found in "modules" as you noticed grouped by module type alongside the module interface. The scripts never touch peers at all as they are handled by the engine and modules.
Hopefully this improves a bit the understanding of the structure as the directory layout is like that for a reason. Concerning the events this is correct. You do not push states and data around between the engine, scripts and modules as this would create coupling and bad performance. For this purpose events are used which have been thoughtfully chosen so modules know what to do. The way the events are set up scripts scripts trigger events only if necessary. Furthermore event passing is fast as modules in general just acknowledge that something changed postponing the change to when it is actually needed. This is only possible since modules have full control over their peers. For modules this is indeed a bit more complex to deal with but this is not a problem since the idea is that modules are used across many games. The scripts themselves do not get in contact with events. You just alter objects the way you want. The scripting module and engine takes care of dispatching events where required.
Now concerning this system as the base of the game it is not. Sounds strange but unless you use a hardcore low level scripting module (which all three current modules are not) you never get to use this layer directory. Between your game and engine sits the scripting module which provides already a framework build on-top of this layer. In my game case there are even two layers. The DragonScript module provides a framework of classes (which you could not know off since there is no documentation of it available yet). This contains a bunch of classes handling game entities, game entity classes, preloading of resources, world management, player input handling and so forth. The game in turn is build on-top of this framework extending it with more classes related to game logic, player logic and game handling in general. Once the first release is close I'll move classes from the game into the script module so it is easier for people to begin.
So to sum it up the layering looks like that in the end (higher levels are based on the level right below skipping only further down if not otherwise possible):
1) Game Scripts (with game-mod framework, game implemented as a game-mod)
2) DragonScript Scripts
3) DragonScript Module (wrapping of engine classes as script classes)
Hence what you can see only already in form of documentation is level 4 and to some degree level 3 as it is mostly wrapping level 4 but also adding some convenience classes. What you actually work with though is level 2. This way you get already a script framework at hand. Furthermore since it is fully build on level 3 below you can exchange the framework with another one. This gives the potential to add later on for example frameworks suited for certain types of games. Nothing of that requires any changes to the game engine.