I am a college student, working diligently on this project in his free time. If DustyEngine has helped you in any way, please donate just $1!
Dusty Engine is not a 3d engine. It is built upon Irrlicht, which is an extremely programmer-friendly and easy-to-learn 3d engine. Dusty Engine is also not a game object engine. Dusty Engine is an engine which allows the programmer to create classes of code which are executed in a time-based manner and when certain events occur, such as when the program wants to pause the game. By splitting the game into logical tasks which are collected together in branches of a large tree which are logically separated, the program can pause certain parts of a program but not others.
Pausing in the engine is time-independent. If a task or group of tasks are paused, 10 minutes pass, and then the tasks are unpaused, they will continue unaltered as though they had never been paused. This is one of the major benefits of the engine.
A second major benefit is that you can split certain functions of the game into logical groups, in which whole groups can be removed from the game or paused, while the rest of the game continues.
The task engine in Dusty Engine is implemented by a generic tree of independent "tasks" created by the programmer or built into the engine. These tasks have specific jobs which they do either every frame or after a certain, specific per-task amount of time has passed.
A "task" is a class which is composed of the follow functions: Reset(), OnCreation(), OnDestruction(), OnPause(), OnUnpause(), and OnUpdate(). Think of these functions as events that are called when certain actions occur that depend upon the task.
Reset() is a function that is called by a TaskManager in the engine which should reset any member variables in the task which need to be reset. Think of this function as resetting the task to the point it was when it was first instanciated. Implementing this function is optional, just as using a TaskManager is optional, though typically you need to create a Reset() function when the task is going to be managed by a TaskManager in order to avoid bugs.
OnCreation() is called when the task is added to the task tree (Note: This function is NOT called at the moment the task is instanciated, only when it is added to the task tree.)
OnDestruction() is called when the task is removed from the task tree (Note: This does not necessarily mean the task has been dropped from memory. It only means the task has been dropped from the task tree. If the task has not been grab()ed elsewhere in the program, it will be deleted when it is dropped from the tree.)
OnPause() is called when the task tree has paused this task.
OnUnpause() is called when this has been unpaused by the task tree.
OnUpdate() is typically the most important function in a task. It is the code which actually does the execution that accomplishes the task's purpose. It is called when the task tree when a specified amount of time has passed or it can be called every frame.

Here is an example of a task tree with 6 tasks on it. Tasks can be added under the root of the task tree, or added as children to another task. Any task can have any number of children. The root task does nothing.
Notice has task 3 is paused. Its children, task 5 and task 6 are also paused. If task 3 were to be unpaused, task 5 and task 6 would also be unpaused. Pausing or unpausing a task also pauses or unpauses its children tasks. This propogation also causes the OnPause() and OnUnpause() events to be called on children tasks as well as the parent task.
Each task has associated with it a priority. The priority is a time in milliseconds between executions of the task. If a task has a 1000 millisecond priority, then it will be executed once a second. A priority of 50 means the task will be executed every 50 milliseconds. Note that the millisecond counter is not precisely accurate, it is a few milliseconds off.
If a task has a priority of 0, it is to be executed each time the task tree is updated (which is typically every frame.)
The task tree will traverse its nodes using preorder traversal. Using the tree in the image above, the tasks will be queried in this order: 1, 4, 2, 3, 5, 6. This means that a parent task is executed first, and then all the children of that parent are executed in the order they were added to the parent.
Lets use the tree above as an example. Imagine each task was first executed at time 0. The current time (in milliseconds) is 30, and the tree is about to be updated. Below, the step is explained and the final execution of each step is in bold.
When the function DoUpdates() is called on the task tree, the tree will follow this logic:
1.) The priority of task 1 is 25, meaning it wants to executed every 25 milliseconds. 30 milliseconds have passed, so call OnUpdate() for task 1, and reset the time passed since task 1 was last executed to 0.
2.) Move on (using preorder traversal...) to the first child of task 1. That is task 4. Task 4 should be executed every 50 milliseconds. Only 30 milliseconds have passed since task 4 was last executed, so do not execute task 4.
3.) Move on to task 2. Task 2 should be executed every 30 milliseconds. 30 milliseconds have passed, so call OnUpdate() for task 2, and reset the time passed since task 2 was last executed to 0.
4.) Move on to task 3. Task 3 is paused, so do not execute it or any of its children.
5.) There are no more tasks to update, so the tree is finished updating, and the DoUpdates() function will return.
What follows is a simple example of the engine in action.
#include <dustyengine.h> #include <irrlicht.h> using namespace DustyEngine; using namespace irr; using namespace core; using namespace video; class ColorTask : public Task |
This extremely simple program when compiled and executed will create a window on the screen and then change the background color of that window twice a second. It uses a single task to accomplish this.
The program begins by defining a class ColorTask which inherits from DustyEngine::Task. The only purpose of this task is to create and store a random color when it's OnUpdate() function is called. It provides a method GetColor() to access that color.
Notice how only the OnUpdate() function has special code in it. Also notice GetColor() is not a function inherited from the Task class. GetColor() is a function that is specific only to the purpose of this task. You can add in functions such as this to task classes in order to make them more useful--in fact, in most cases it is necessary to do so. Tasks by themselves are a very generic construct, they must be extended in order to serve a purpose.
Notice that the OnPause(), OnUnpause(), OnCreation(), OnAddChild(), OnRemoveChild(), and OnDestruction() functions are implemented, but they don't do anything. This only means I didn't have any special need for something to happen when the task is created or destroyed, pause or unpaused. This does not mean that the task will not pause or unpause correctly.
Now, look at the main() function. The irrlichtdevice is created, and then immediately following a DustyDriver * object is created, using that irrlicht device. The DustyDriver is the central object to Dusty Engine. It allows access to all the functions and objects in the engine.
A ColorTask is created, and the video driver is gotten from irrlicht and the task tree is gotten from Dusty Engine.
What follows that is very important, "dustyTaskTree->AddTask(colorTask, NULL, 500);". This function call is
very important. This tells the task tree to add in the newly created
color task under the root node of the task tree (NULL means put it
under root) with a priority of 500 milliseconds. This tells the task
tree to execute the task every 500 milliseconds. There are many more
options in the AddTask() function which are not used here. Check it out
in the documentation.
The loop is what does the drawing. The program will loop until the window is closed. A scene is begun by the video driver, but what is sent to the video driver is what is important: The last parameter to beginScene() is the color that should be the background of the scene.
This color is retrieved from the colorTask! Meaning after the colorTask randomly generates a new color, the scene manager will then use that color.
The next important function call is "dustyTaskTree->DoUpdates();". This tells the task tree to execute all the tasks on the tree that should be executed. It follows the logic that was explained above.
I hope this has given you some insight into the inner workings of the engine, as well as its purpose and how it should be used. Check out the documentation, the forum, experiment, examine the built-in tasks and send me an email at dustyengine@daveandrews.org with any problems!