The Simple Factory pattern

The Entity-Component pattern along with using composition in preference to inheritance sounds great at first glance but brings with it some problems of its own. Not least of which it exacerbates all the problems we discussed in Chapter 18, Introduction to Design Patterns and much more!. It would mean that our new GameObject class would need to know about all the different types of component and every single type of object in the game. How would it add all the correct components to itself?

It is true that if we are to have this universal GameObject class that can be anything we want it to be whether a Diver, Patroller, PlayerShip, PinkElephant or whatever then we are going to have to code some logic that "knows" about constructing these super-flexible GameObject instances and composes them with the correct components. But adding all this code into the class itself would make it exceptionally unwieldy and defeat the entire reason for using the Entity-Component pattern.

We would need a constructor that did something like this hypothetical GameObject code:

class GameObject{
   MovementComponent mMoveComp;
   GraphicsComponent mGraphComp;
   InputComponent mInpComp;
   Transform mTransform;
   // More members here
// The constructor
GameObject(String type){
      if(type == "diver"){
            mMoveComp = new DiverMovementComponent ();   
            mGraphComp = new StdGraphicsComponent();
      }
      else if(type =="chaser"){
              mMoveComp = new ChaserMovementComponent();
              mGraphComp = new StdGraphicsComponent();
      }
      // etc.
      …

}
}

And don't forget we will need to do the same for each type of alien, background, player for each and every component. The GameObject would need to know not just which components go with which GameObject but also which GameObjects didn't need certain components like input-related components for controlling the player GameObject.

For example, in Chapter 19, Listening with the Observer Pattern, Multitouch and Building a Particle System we coded a UIController class that registered with the GameEngine class as an observer. It was made aware of the HUD buttons by passing an ArrayList of Rect objects to its handleInput method each time GameEngine received touch data in the onTouchEvent method.

The GameObject class would need to understand all this logic. Any benefit or efficiency gained from using composition over inheritance with the Entity-Component pattern would be completely lost.

Furthermore, what if the game designer suddenly announced a new type of alien, perhaps a Cloaker alien which teleports near to the player takes a shot then teleports away again. It is fine to code a new GraphicsComponent, perhaps a CloakingGraphicsComponent that 'knows' when it is visible and invisible along with a new MovementComponent, perhaps a CloakerMovementComponent that teleports instead of moving in the conventional manner but are we really going to have to add a whole bunch of new if statements to the GameObject constructor? Yes, is the unfortunate answer in this situation.

In fact, the situation is even worse than this. What happens if the game designer proclaims one morning that Divers can now cloak! Divers now need not just a different type of GraphicsComponent. Back into the GameObject class we go to edit all those if statements. Then the game designer realises that although the cloaking-divers are cool, the original divers that were always visible were more menacing. We need divers and cloaking-divers. More changes required.

If you want a new GameObject that accepts input and then things get even worse because the class instantiating the GameObject must make sure to pass in a GameEngineBroadcaster reference and the GameObject must know what to do with it.

Also notice that every GameObject has an InputComponent but not every GameObject needs one. This is a waste of memory and will either mean initializing the InputComponent when it is not needed and wasting calls from the GameEngineBroadcaster or having a NULL InputComponent in almost every GameObject just waiting to crash the game at any moment.

The last thing to notice in the previous hypothetical code is the object of type Transform. All GameObject instances will be composed with a Transform object that holds details like size, position and more besides. More details on the Transform class as we proceed with the chapter.

At last some good news

In fact, there are even more scenarios that can be imagined and they all end up with a bigger and bigger GameObject class. The Factory pattern or more correctly in this project, the Simple Factory pattern is the solution to these GameObject woes and the perfect partner to the Entity-Component pattern

Note

The Simple Factory pattern is just an easier way to begin to learn the Factory pattern. Why not do a Web search for the Factory pattern once you have completed this project.

The game designer will provide a specification for each and every type of object in the game and the programmer will provide a factory class that builds GameObject instances from the game designer's specifications. When the game designer comes up with quirky ideas for entities then all we need to do is ask for a new specification. Sometimes that will involve adding a new production line to the factory that uses existing components and sometimes it will mean coding new components or perhaps updating existing components. The point is that it won't matter how inventive the game designer is the GameObject, GameEngine, Renderer and PhysicsEngine remain unchanged. Perhaps something like this:

GameObject currentObject = new GameObject;
switch (objectType) {case "diver":
         currentObject.setMovement (new DiverMovement());
         currentObject.setDrawing (new StdDrawing());
         break;
case "chaser":
      currentObject.setMovement (new ChaserMovement());
      currentObject.setDrawing (new StdDrawing());
      break;
}

In the code the current object type is checked and the appropriate components (classes) are added to it. Both the chaser and the diver have a StdDrawing component but both have different movement (update) components. The setMovement and setDrawing methods are part of GameObject and we will see their real-life equivalents later in the chapter. This code is not the same as we will be using but it is not too far from it.

It is true that the code strongly resembles the code which we have just discussed and revealed to be so totally inadequate. The huge distinction, however, is that this code can exist in just a single instance of a factory class and not in every single instance of GameObject. Also, this class does not even have to persist beyond the phase of our game when the GameObjects are set up ready for action.

We will also take things further by coding a Level class that will decide which types and quantities of these specifications to spawn. This further separates roles and responsibilities of game design, specific level design and game engine/factory coding.

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

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