The Collectible class

The collectibles for this game will be represented by the Collectible class that inherits from GameObject and will be used to represent all three types of collectibles: the simple collectible, the rocket, and the balloon. It will possess a score value and a flag that marks whether it has been collected. It will possess functions to manage life events that we will discuss in this section, starting with the SetBody function:

void Collectible::SetBody(b2Body* body)
{
  b2PolygonShape collectible_shape;

  // create different box shapes for different collectibles
  switch(type_)
  {
  case E_GAME_OBJECT_COLLECTIBLE:
    collectible_shape.SetAsBox(SCREEN_TO_WORLD(
      m_obContentSize.width/2), SCREEN_TO_WORLD(
      m_obContentSize.height/2));
    break;
  case E_GAME_OBJECT_ROCKET:
  case E_GAME_OBJECT_BALLOON:
    collectible_shape.SetAsBox(SCREEN_TO_WORLD(
      m_obContentSize.width/2), SCREEN_TO_WORLD(
      m_obContentSize.height/4), b2Vec2(0, SCREEN_TO_WORLD(
      m_obContentSize.height/4)), 0);
    break;
  }

  // mark the fixture as a sensor
  b2FixtureDef collectible_fixture_def;
  collectible_fixture_def.shape = &collectible_shape;
  collectible_fixture_def.isSensor = true;
  body->CreateFixture(&collectible_fixture_def);

  // call parent class' function
  GameObject::SetBody(body);
}

All three collectibles will have a box shape fed into their fixtures but will look different based the value of type_ variable. One important thing to notice is that this time we set a new property of the b2FixtureDef class—the isSensor property. A sensor in Box2D, to quote the manual, is a fixture that detects a collision but does not produce a response.

This is exactly what we want in our game since it would look pretty awkward if the clown kept bouncing off every bowling pin, bottle rocket, and balloon. We wind up the function by creating the fixture and passing the body to the SetBody function of the parent class.

Now, let's define the Init and Reset functions, which will enable us to reuse this object throughout our game:

void Collectible::Init(b2Vec2 position)
{
  // initialise position and scale
  body_->SetTransform(position, 0);
  setScale(1.0f);
}

void Collectible::Reset()
{
  // reset position outside boundary of game
  body_->SetTransform(b2Vec2(SCREEN_TO_WORLD(-1 * WALL_WIDTH), 
    SCREEN_TO_WORLD(-1 * WALL_WIDTH)), 0);
  removeFromParentAndCleanup(true);
  is_collected_ = false;
}

The Init function sets the position of the body to the input provided and also resets the scale factor. This function will be called when the collectible has been added on to the game world. The Reset function—on the other hand—places the body right out of the screen while also removing itself from its parent and setting the is_collected_ flag to false. This function will be called when the collectible has been removed from the game world. That is all we need to do to make this collectible reusable. We will now define the behavior of the collectibles when they collide with the clown:

void Collectible::OnCollision()
{
  // can be collected only once
  if(is_collected_)
    return;

  is_collected_ = true;
  // add respective score
  game_world_->AddScore(score_);
  // scale down and exit
  runAction(CCSequence::createWithTwoActions(
  CCSequence::createWithTwoActions(CCScaleTo::create(0.01f, 1.2f), 
  CCScaleTo::create(0.1f, 0.0f)), CCCallFunc::create(this, 
  callfunc_selector(Collectible::AfterCollision))));

  // inform player of respective state change
  if(type_ == E_GAME_OBJECT_ROCKET)
  {
    game_world_->GetClown()->SetState(E_CLOWN_NONE);
    game_world_->GetClown()->SetState(E_CLOWN_ROCKET);
  }
  else if(type_ == E_GAME_OBJECT_BALLOON)
  {
    game_world_->GetClown()->SetState(E_CLOWN_NONE);
    game_world_->GetClown()->SetState(E_CLOWN_BALLOON);
  }

  ShowParticle();

  SOUND_ENGINE->playEffect("collectible.wav");
}

This function is called from the BeginContact function we saw in the previous section. A collectible can only be collected once and hence the return statement at the start of the function. Then we inform GameWorld to add the score for this collectible and also play a simple animation. Based on which type of collectible this is, we need to inform the clown that a change of state has occurred. While doing this, we first set the clown's state to none and then to either the rocket or balloon state. This is done to handle cases like when the clown is already in the rocket state and collides with another rocket. Since our clown's SetState function only responds to a state change, the preceding scenario won't show any effect. The last thing we do is show a small burst of some particles.

The AfterCollision function simply informs GameWorld that this collectible should now be removed. With these functions, we have more or less completed defining the behavior of the collectibles. However, we will need to write the code to implement the reusing and caching of these collectibles.

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

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