Creating and removing objects and components

In order to use the Component Object Model, first create a game object, then add some components, then finally add it to the M5ObjectManager which calls an update on the game object every frame. Let's look at some code for creating objects and components.

If we wanted to create a Player object to fly around on screen, but stay within the bounds of the screen, we could do this inside the Init method of a stage:

M5Object* pObj = new M5Object(AT_Player); 
GfxComponent* pGfxComp = new GfxComponent;
PlayerInputComponent* pInput = new PlayerInputComponent;
ClampComponent* pClamp = new ClampComponent;
pObj->AddComponent(pGfxComp);
pObj->AddComponent(pInput);
pObj->AddComponent(pClamp );
//Set position, rotation, scale here
//...
M5ObjectManager::AddObject(pObj);

This code works fine, but there are a few problems. First, we didn't specify what texture we want. However, we could easily add a textureID or filename as a parameter to the GfxComponent constructor. The larger problem is that this code was tedious to write and we don't want to write it again and again. If we are creating a Player in another stage, it will likely contain the exact same code. So a better approach is to factor this code into the M5ObjectManager:

M5Object* M5ObjectManager::CreateObject(M5ArcheTypes type) 
{
switch(type)
{
case AT_Player:
M5Object* pObj = new M5Object(AT_Player);
GfxComponent* pGfxComp = new GfxComponent;
PlayerInputComponent* pInput = new PlayerInputComponent;
ClampComponent* pClamp = new ClampComponent;
pObj->AddComponent(pGfxComp);
pObj->AddComponent(pInput);
pObj->AddComponent(pClamp );
AddObject(pObj);
//Set position, rotation, scale here
//...
return pObj;
break;
case AT_Bullet:
//...More Code here

Now in our stage Init function, we can simply write the following:

M5Object* pObj = M5ObjectManager::CreateObject(AT_Splash); 
//Set additional data here if needed

However, this is pretty hardcoded. This explicitly creates all of the components that a Player (and every type) needs, which means that our M5ObjectManager now contains game-specific code. The benefit of using the Component Object Model is that it is flexible, but we have lost some of that flexibility by having a hardcoded switch statement. We really want our designers, not programmers, to choose what goes into a Player, Raider, or SuperRaider. That means loading our object types from a file. In our case, we will use INI files because they are simple to use and simple to understand. They consist of global or labeled sections of key/value pairs. Here is an example Player archetype found in Player.ini:

posX  = 0 
posY = 0
velX = 0
velY = 0
scaleX = 10
scaleY = 10
rot = 0
rotVel = 0
components = GfxComponent PlayerInputComponent ClampComponent

[GfxComponent]
texture = playerShip.tga

[PlayerInputComponent]
forwardSpeed = 100
bulletSpeed = 7000
rotationSpeed = 10

Notice that the first (global) section of the INI file contains all data found in the M5object. Since we know that those variables always exist in the object, they are placed at the top. This includes a list of components that this archetype will use. Here we have GfxComponent, PlayerInputComponent, and ClampComponent. The next sections are data associated with each component, for example, with the GfxComponent we can specify our texture to load. The ClampComponent doesn't need any data loaded so we didn't need to add a section for it.

Comparing the Component Object Model with the monolithic object or the inheritance tree, we can see that the component-based approach is vastly more flexible and reusable. With this method, we can write as many different components as we want and let the designer choose what behaviors each object uses. The best part is that everything but the most game-specific components can be reused in another game.

That means that the PlayerInputComponent probably can't be reused in another game, but the ClampComponent and GfxComponent can be used whether we are making another Space Shooter, Platformer, or Racer.

One note about components used for graphics and physics, such as GfxComponent and CircleColliderComponent: these are special in the sense that they need to interact with core engines in a way that other components may not need to. For example, the Graphics engine might want to organize these components based on whether they are world space objects or screen space objects (referred to as HUD space, since these would be things such as buttons and health bars). The Physics engine might want to use a special partition data structure to minimize the number of collision tests that need to be performed. For this reason, these components are automatically registered to their respective core engines when created through the object Manager and they automatically unregister when they are deleted.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.190.175