Skip to content
sorressean edited this page Jul 25, 2018 · 2 revisions

Aspen's Component System

Overview

In this document I will discuss the workings of the component system, as well as provide a tutorial and code samples to help you create your own components. The tutorial is for the beginnings of a stat system, which you can feel free to use; it also highlights more advanced features, which should make it easier to understand the basics. (Tutorial is todo).

Background

Components provide a method to perform object composition on the fly and dynamically in the game, which can be extended to the script engine, or used in various other places to easily add and remove behavior from objects.

Components provide a has-a relationship for objects; you can start with a basic Entity object and add behavior.

think of components as containing specific types of behavior. You may decide to add a clothing, container and weapon component, but you wouldn't want every object to inherit all of these; instead, you can provide this functionality through individual components, and allow builders and scripters to add these to your object. This means that a weapon could be a container and a weapon, but doesn't have to be worn, or that a backpack could include clothing and container, for example.

The Component Meta

Components have two distinct pieces; the component object itself, and the component meta object. The Component Meta object exists as a placeholder for individual components. It contains information on what each component is, including, but not limited to the name and required dependencies for the component which it manages. While this provides an easy mechenism for grouping and managing types of components, it also serves to cut down on the memory footprint by alleviating the cost of storing a list of dependencies and name for each loaded component, along with any other information that will be shared across components of specific types in the future.

Component meta objects also have an interface, IComponentMeta which you can use to define your own versions of these objects. Unless you have a specific reason to do so, I recommend that you inherit the ComponentMeta class and instanciate the template to add extra features to individual ComponentMeta objects.

Component

The Component object is where all of the logic will be held for that specific component. You will likely want to inherit the Component object and extend this with your functionality. The Component object manages and maintains references to the object which it is attached to; you can think of the relationship as a many to one from the object to the components.

The only caveat to extending the Component object is that you need to make sure to call the constructor as with any other object, as there is work that takes place within the constructor itself.components also by default include a mechenism to register and call events as an EventManager as well as a storage system for properties which will be serialized with the component objects themselves.

Components Under The Hood

As previously mentioned, the Component object is used to hold information specific to individual components, while the Componentmeta object holds information specific to individual components under them. this means that clothing, armor, weapons would all have their own ComponentMeta from which components would be created.

the ComponentMeta object is a templated object, meaning that you'll need to instanciate it with individual components. If you are simply writing a component that other logic will attach, you can simply use the base ComponentMeta object. If you wish to add logic to the component itself (such as the component being added to a player or npc once it's created or logged in), you will need to create your own ComponentMeta, specialize it with the component you've defined and add that logic.

In the World object, there are two methods: RegisterComponent and CreateComponent which are simply wrappers to call the underlying ComponentFactory object. the component factory holds a mapping of <std::string, IComponentMeta*>. The key is the name of the component, and the value is a pointer to the ComponentMeta object currently stored. When CreateComponent is called, the Create methond on the ComponentMeta is called, which returns a new object of type T, which is the type passed into the ComponentMeta template. Each components has an Initialize method which is called prior to the component being attached to any object, so it should not be assumed that the component is attached to a specific object. Any logic that needs to take place after the component is attached to an object should subscribe to the events on the component itself.

Created components through World::CreateComponent will not be attached to an object; it is up to the user to call AddComponent on the object to which they want to add the component.

When the object's AddComponent is called, and assuming that the object already does not have a component by the same name, dependencies from the component meta are traversed and added. The Attach method on components is not virtual and should not be overridden; use events for this purpose.

Getting Started

Development

Tutorials and Documentation

Clone this wiki locally