The Engine
The engine's design focuses on flexibility, allowing for the simple
expansion of its functionality. It can be easily modified to
accommodate platforms that are constrained by certain factors,
such as memory.
The engine is broken up into two distinct pieces: the framework and
the managers. The framework contains the parts of the game that
are duplicated; that is, there will be multiple instances of them. It also
contains items that have to do with execution of the main game loop.
The managers are singletons that the game logic depends on.
Figure 3 illustrates the different sections that make up the engine.
Figure 3. The high-level architecture of the engine.
Notice that the game processing functionality, referred to as a
system, is treated as a separate entity from the engine. This
modularity makes the engine the "glue" for tying all the functionality
together. Modularity also allows the systems to be loaded or unloaded
as needed.
The interfaces are the means of communication between the engine
and the systems: The systems implement the interface so that the
engine can access a system's functionality, and the engine implements
the interface so that the systems can access the managers.
For more information about this concept, refer to Appendix A.
As described in the Parallel Execution State section, the systems are
inherently discrete-systems can run in parallel without interfering
with the execution of other systems. This does cause some problems
when systems need to communicate with each other, because
the data is not guaranteed to be in a stable state. Two reasons for
inter-system communication are:
The first communication problem is solved by implementing the state
manager mentioned in the previous section.
To solve the second problem, a mechanism is included through which
a system can provide a service that a different system can use.
Framework
The framework ties all the different pieces of the engine together.
Engine initialization occurs within the framework, with the exception
of the managers, which are globally instantiated. The information
about the scene is also stored in the framework. For flexibility,
the scene is implemented as what is called a universal scene, which
contains universal objects-containers for tying together the different
functional parts of a scene.
The game loop is also located within the framework. Figure 4
shows its flow.
Figure 4. The main game loop.
The first step in the game loop is to process all pending OS window
messages because the engine operates in a windowed environment.
The engine will be unresponsive to the OS if this is not done. The
scheduler next issues the systems' tasks with the task manager, and
then the changes that the state manager has been keeping track of
are distributed to all interested parties. Finally, the framework checks
the execution status to see if the engine should quit or perform
some other engine execution action, such as go to the next scene.
The engine execution status is located in the environment manager,
which is described later in this article.
Scheduler
The scheduler holds the master clock for execution, which is set at a
pre-determined frequency. The clock can also run at an unlimited rate,
for things like benchmarking mode, so that there is no waiting for the
clock time to expire before proceeding.
The scheduler submits systems for execution, via the task manager,
on a clock tick. For free step mode, the scheduler communicates with
the systems to determine how many clock ticks they will need to
complete their execution. Then it determines which systems are ready
for execution and which ones will be finished by a certain clock tick.
The scheduler can adjust this amount if it determines that a system needs more execution time. Lock step mode has all systems start and
end on the same clock, so the scheduler will wait for all systems to
complete execution.
Universal Scene and Objects
The universal scene and objects are containers for the functionality
that is implemented within the systems. By themselves, the universal
scene and objects have no functionality other than being able to
interact with the engine. They can, however, be extended to include
the functionality that is available in a system, which gives them the
ability to take on the properties of any available system without
having to be tied to a specific system. This is called loose coupling.
Loose coupling is important because it allows the systems to be
independent of each other and run in parallel.
Figure 5 illustrates the universal scene and object extension
of a system.
Figure 5. The universal scene and object extension.
Here's how extensions work: A universal scene is extended to have
graphics, physics, and other properties. The graphics scene extension
initializes the display and other things, and the physics scene extension
sets up the rigid body world, such as gravity. Scenes contain
objects, so a universal scene has several universal objects. Similarly,
the universal object, contained in the universal scene, is extended
to have graphics, physics, and other properties. The graphics object
extension draws the object on screen, and the physics object
extension is responsible for the rigid body interaction of the object
with other rigid bodies.
For a more detailed diagram showing the relationship between the
engine and the systems, refer to Appendix B.
The universal scene and universal objects are also responsible for
registering their extensions with the state manager, so that the
extensions are notified of changes made by other extensions
(that is, other systems). For example, the graphics extension would
be registered to receive notification of position and orientation
changes made by the physics extension.
|
Reminds me of Erlang.
Can you post some test results ?
Corei7 performance scaling will probably be decent (around 4x I bet) :p
But did you have the opportunity to tests on a xeon 7400 (6 cores) or on a dualxeon (12 cores) ?
Vincent