2. Game Objects

Objects and classes are fundamental to Grit. They are a convenient way to structure your game. Objects can be anything from a chunk of terrain, to a building, to a soda can. If you want to make a large world they are the only way to access Grit's streaming subsystem to efficiently determine the set of nearby objects, and background load incoming disk resources.

Objects can either be activated or not. Activated objects are near the camera and consume more machine capabilities (RAM, CPU, etc). In a streaming game, the majority of objects are unactivated, allowing the world to extend well beyond the horizon. All objects have at least a spawn position in 3D space and a rendering distance. Grit will use this information to activate objects as the player moves within their individual ranges.

Activated objects typically have a graphical and/or physical representation, or some active behaviour. Unactivated objects typically lie dormant, holding a tiny amount of state. There are technical limitations on what kind of data can be stored in an object when it is unactivated, for example it is not allowed to have a physical / graphical representation. This is necessary to allow scaling to large worlds.

Objects are created by instantiating a class at a particular location. The class describes the general nature of its objects. It holds the code that defines the object's behaviour, and default values for its attributes. For example, the rendering distance is typically the same for all objects of a given class, so the object inherits that attribute from its class (although the object can override it if desired). The only attribute that must be given per object is the spawn position, which is used by the streaming subsystem. All other attributes can be left to class defaults or overridden as desired. The set of available attributes depends on the class being used.

For example, a sentry turret may, as it streams in, create a graphics body for its base and another graphics body for the barrel of its gun, allowing the barrel to rotate independently to the base. It may also create a physics representation for the base (so the player can't walk through it, and to allow it to receive bullet hits, etc.). It can also create an audio body for playing whirring noises as it moves. The code to create all of this state is put in a callback called activate. There is another callback, deactivate that is called as the object streams out, and typically destroys these bodies. Thus all of this extra state exists only while the turret is close enough to the player to be visible.

Turret
Turret with a rendering distance of 100m.

As a trivial example, a ball of energy that floats up and down could be implemented with an object. The game designer writes a class with an initialisation callback that creates a graphics body in the graphics world, and stores a pointer to it in a field of the new object. The class also has a destruction callback that can be used to clean up the graphics body when the object is removed from the scene. Finally, there is a per-step callback to move the ball around, presumably using a sin function or similar. If a light source is desired, then a light body would be created in the graphics world as well, and e.g. its intensity can be modified in the step callback. Similarly, other graphics bodies, particles, and physical behaviour can be added if desired. Audio bodies can be added in the audio world. All of these "bodies", which manifest in independent subsystems, are created and controlled by the object in question.