Using builders with objects

Our game objects are mostly just collections of components. Each object type will have different components and component data based on the decisions of the designer. As the development progresses, those collections are likely to change. Remember, even though each individual component has a builder in the factory, the object will need to somehow instantiate the separate components. Let's look at shortened examples of using builders for the Player and Raider objects:

//PlayerBuilder.h-------------------- 
#include "M5ObjectBuilder.h"

class PlayerBuilder: public M5ObjectBuilder
{
public:
virtual M5Object* Build(void);
};

//PlayerBuilder.cpp--------------------
#include "PlayerBuilder.h"
#include "M5Object.h"
#include "M5ObjectManager.h"

M5Object* PlayerBuilder::Build(void)
{
M5Object* pObj = new M5Object;
//Build and set Gfx component for player
GfxComponent* pGfx =
M5ObjectManager::CreateComponent(CT_GfxComponent);
pGfx->SetTexture("playerShip.tga");
pGfx->SetDrawSpace(DS_WORLD);

//Build and set input component for player
PlayerInputComponent* pPI =
M5ObjectManager::CreateComponent(CT_PlayerInputComponent);
pPI->SetSpeed(100);
pPI->SetRotationSpeed(10);

pObj->AddComponent(pGfx);
pObj->AddComponent(pPI);

//...add more components here

return pObj;
}

//RaiderBuilder.h--------------------
#include "M5ObjectBuilder.h"

class RaiderBuilder: public M5ObjectBuilder
{
public:
virtual M5Object* Build(void);
};

// RaiderBuilder.cpp--------------------
#include "RaiderBuilder.h"
#include "M5Object.h"
#include "M5ObjectManager.h"

M5Object* RaiderBuilder::Build(void)
{
M5Object* pObj = new M5Object;
//Build and set Gfx component for Raider
GfxComponent* pGfx =
M5ObjectManager::CreateComponent(CT_GfxComponent);
pGfx->SetTexture("enemyBlack3.tga");
pGfx->SetDrawSpace(DS_WORLD);

//Build and set behavior for Raider
ChasePlayerComponent* pCP =
M5ObjectManager::CreateComponent(CT_ChasePlayerComponent);
pPI->SetSpeed(40);

pObj->AddComponent(pGfx);
pObj->AddComponent(pCP);

return pObj;
}

In these two simple examples, we can see why each object builder needs to be different. Each specific object type will have a unique set of components. These examples only use two components each, but we haven't considered our physics colliders, any weapon components, or additional behaviors. Even in these short examples, both object types use a GfxComponent but the differences in data, such as texture, mean that we need different code. Since there is only one object class, as opposed to a hierarchy of derived classes, there is no way to let the object manage the creation of the necessary components.

To deal with this, we will either need a builder class for each object type or one object builder with a switch statement and a case for each object type. The problem with both solutions is that the list of components and the data for each component is likely to change often. Now, instead of being worried about high-level modules and dependencies, we have two new problems to be worried about.

The first problem is constant, and possibly long, compile times. We already know that as development continues, the game design will change. This could mean not only changing components, but also changing values inside those components. At some point, especially toward the end of development, the game may be complete, but not quite balanced. During this phase, game objects and the code responsible for them will be constantly tweaked. Changes in health, damage, speed, and other attributes could be changed frequently causing the code to be recompiled.

There are a lot of factors that can affect how long it takes to compile a project. In the best-case scenario, we would only change one file, and recompiling could be very fast. However, even a short build time such as 10 seconds can get annoying if the only thing that changed is a speed value from 10 to 11. Something as simple as balancing a single unit can take all day, and then still need additional tweaks as other units get balanced. Our goal here is to make modifying the object and seeing the results of the modification as fast as possible.

The second problem that comes up is related to who is responsible for making these balance changes. One scenario is that the programmer is responsible because all balance changes are code changes. This is a bad situation because, as we already mentioned, balancing can take a long time, and now both the designer and the programmer are involved. The designer may not be able to properly explain the desired result to the programmer, so they must sit together tweaking and compiling, repeatedly. It would be better if the designer was free to balance, and the programmer was free to fix bugs or optimize code where needed.

The other scenario is that the designer is responsible for making these balance changes to the code. The problem here is that the designer may not be as familiar with the engine, or with the programming language. It is very possible that the designer doesn't have programming experience at all, so they would not be familiar with IDEs or version control systems. The chance of introducing bugs or breaking the project could be very high.

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

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