A good way to explore Torque is to think of the engine as a series of integrated systems that work together to manage the mundane tasks of game development. As a game programmer, we want to avoid these low level details, but we need to understand how Torque deals with them, and learn how to correctly utlize the underlying systems, instead of fighting with them. Once you have a basic understanding of the primary systems and what they do, your development time with Torque will become much more effective and efficient.
Before we get into the key systems however, it's important to understand a fundamental aspect of Torque development: the platform layer.
Torque is designed from the ground up to allow developers to make their game abstracted completely away from the underlying hardware, so that once completed the project can be deployed to any platform that has an implementation for the hardware specific systems (see below). This is a huge benefit for game developers, allowing you to work on your project without focusing on (or even being aware of!) platform specific requirements or restrictions, other than how they would affect game play itself.
With careful understanding of how to work above the platform layer, projects developed with Torque can be easily ported to other operating systems and platforms.
Torque has dozens of systems and managers that you will eventually interact with, but for the most part you will be dealing with just a few extensively. Listed below are the systems you will be working with the most, including a brief description of their key tasks and responsibilities.
The Console is the lowest level system within the Torque Engine, and is responsible for:
While we work with the Console system every single day, most of what it does is automatic, and we do not do anything explicit to use the system. It is important however to understand what it does so that when you are implementing a new object in C++, you are aware of the requirements to work within the system.
The Simulation is where objects are maintained, and can be considered a big container where all of our objects live. It provides some powerful functionality, including:
The key benefits of the Simulation system are that we can search for, and reference objects by unique identifiers, which then allows us to call methods, modify data, and otherwise manipulate those objects. In addition, with proper use of smart referencing in C++ development, we can avoid most if not all situations where pointers can become corrupt and crash our executable.
The Network Connection system manages all of our client/server communications, and provides the ability for communications across the Internet and other networked environments. Torque utilizes UDP as the basis of the networking system, and implements a wide variety of capabilities on top of standard UDP:
The networking system within Torque is very complex, and will take time to learn to use effectively. Fortunately, for most uses the system automatically takes care of everything you need, so you don't have to!
New with Torque Game Engine Advanced, the GFX system is a fully hardware abstracted rendering system designed to completely isolate the developer from the underlying hardware requirements. GFX is specifically engineered to leverage the power of Graphics Processing Units on your video hardware, and utilizes many features to optimize rendering:
The GFX system is fully user expandable for a variety of hardware requirements (additional license may be required, see the EULA).
TGE-A 1.7 for the first time provides an abstraction layer for game sound, and mirrors the GFX system in utilization. Game Developers implement against the SFX abstraction layer, and SFX takes care of the hardware details by utilizing any available SFX Devices. TGE-A provides the following SFX devices out of the box:
Torque maintains reference count based information of all resources loaded into memory, and therefore minimized memory used by only keeping one copy of a resource available at any time. When your project requires access to the information contained within a resource, a reference to the already loaded information is returned instead. The Resource Manager allows developers to define any type of resource, and tracks many resources by default, including:
Game processing occurs at a fixed frequency of 32 milliseconds by stepping through the process list (a linked list of objects that derive from the GameBase class and have registered with the Simulation) one by one, and calling the method ::processTick() on each object.
Within this method, each object is responsible for updating itself in response to the passage of time, as well as reacting to any Move inputs that may have been delivered from the client for that object. Only one Move struct is delivered from the client, and only for one particular object, known as the control object.During the processTick() call, simply objects may do very little--possibly just rotating slowly in place such as how the Item class operates, while complex objects such as the Player may perform many tasks.
A complex game object however has quite a bit of responsibility, and may be responsible for:
In addition to ::processTick(), client side objects receive update calls as listed above for both interpolation requirements (::interpolateTick()), as well as animation and other variable rate time update needs (advanceTime()).
Client simulations are also responsible for staying synchronized with the data sent by the server, and in the case where the client simulation differs from the server's data, the client will correct any objects that are not synchronized back towards the state that the server dictates. Occasionally, if the client is very de-synchronized, they will "warp" objects back directly to the server's directed state, but only in situations where the de-synchronization is beyond acceptable limits.
Due to the nature of a networked environment, two simulations can never be exactly synchronized--since it takes time (known as latency) for data to travel from the server to the client, by definition the client is always "behind" the server. This sets up a situation where it makes sense for us to allow the client to manage it's own simulation, but correct towards the server's "true" state during it's Game Processing phase for each object.
For this to work well, the server is responsible for tracking data that has changed on every object in it's simulation, and when appropriate, deliver this data to each client so they can proceed with updating their simulation towards the authoritative server state.
The system that manages this complex interaction is known as the Ghosting System, and it is tightly coupled to both Game Processing and the Network Connection.
During a server's Game Processing loop, each object that has it's world properties (position, velocity, game state, or any user defined values that must be networked to the client) modified "marks" the data as being dirty by using a method provided by the NetObject class called setMaskBits().
In parallel with the Game Processing loop, there is a Net Update processing loop that tracks every object that each client knows about, and when any object within a client's list is marked as "dirty", it packs a network update to be delivered to the client for that object. Once it has iterated over all objects the client is aware of, it delivers this update to the client.
When the client receives a ghost update from the server for a particular object, it updates the information (knows as a delta), and then begins to correct back to the state the server has directed, giving us smooth corrections that are normally not noticeable by the player in any way.