Loading other states from an XML file

Our MainMenuState class now loads from an XML file. We need to make our other states do the same. We will only cover the code that has changed, so assume that everything else has remained the same when following through this section.

Loading the play state

We will start with PlayState.cpp and its onEnter function.

bool PlayState::onEnter()
{
  // parse the state
  StateParser stateParser;
  stateParser.parseState("test.xml", s_playID, &m_gameObjects, 
  &m_textureIDList);

  std::cout << "entering PlayState
";
  return true;
}

We must also add the new texture clearing code that we had in MainMenuState to the onExit function.

// clear the texture manager
for(int i = 0; i < m_textureIDList.size(); i++)
{
  TheTextureManager::Instance()->
  clearFromTextureMap(m_textureIDList[i]);
}

These are the only alterations that we will need to do here but we must also update our XML file to have something to load in PlayState.

<PLAY>
<TEXTURES>
  <texture filename="helicopter.png" ID="helicopter"/>
  <texture filename="helicopter2.png" ID="helicopter2"/>
</TEXTURES>

<OBJECTS>
  <object type="Player" x="500" y="100" width="128" height="55" 
  textureID="helicopter" numFrames="4"/>
  <object type="Enemy" x="100" y="100" width="128" height="55" 
  textureID="helicopter2" numFrames="4"/>
</OBJECTS>
</PLAY>

Our Enemy object will now need to set its initial velocity in its load function rather than the constructor, otherwise the load function would override it.

void Enemy::load(const LoaderParams *pParams)
{
  SDLGameObject::load(pParams);
  m_velocity.setY(2);
}

Finally we must register these objects with the factory. We can do this in the Game::init function just like the MenuButton object.

TheGameObjectFactory::Instance()->registerType("Player", new PlayerCreator());
TheGameObjectFactory::Instance()->registerType("Enemy", new EnemyCreator());

Loading the pause state

Our PauseState class must now inherit from MenuState as we want it to contain callbacks. We must update the PauseState.h file to first inherit from MenuState.

class PauseState : public MenuState

We must also declare the setCallbacks function.

virtual void setCallbacks(const std::vector<Callback>& callbacks);

Now we must update the PauseState.cpp file, starting with the onEnter function.

bool PauseState::onEnter()
{
  StateParser stateParser;
  stateParser.parseState("test.xml", s_pauseID, &m_gameObjects, 
  &m_textureIDList);

  m_callbacks.push_back(0);
  m_callbacks.push_back(s_pauseToMain);
  m_callbacks.push_back(s_resumePlay);

  setCallbacks(m_callbacks);

  std::cout << "entering PauseState
";
  return true;
}

The setCallbacks function is exactly like MainMenuState.

void PauseState::setCallbacks(const std::vector<Callback>& 
callbacks)
{
  // go through the game objects
  for(int i = 0; i < m_gameObjects.size(); i++)
  {
    // if they are of type MenuButton then assign a callback based 
    on the id passed in from the file
    if(dynamic_cast<MenuButton*>(m_gameObjects[i]))
    {
      MenuButton* pButton = 
      dynamic_cast<MenuButton*>(m_gameObjects[i]);
      pButton->setCallback(callbacks[pButton->getCallbackID()]);
    }
  }
}

Finally we must add the texture clearing code to onExit.

// clear the texture manager
for(int i = 0; i < m_textureIDList.size(); i++)
{
  TheTextureManager::Instance()->
  clearFromTextureMap(m_textureIDList[i]);
}

And then update our XML file to include this state.

<PAUSE>
<TEXTURES>
  <texture filename="resume.png" ID="resumebutton"/>
  <texture filename="main.png" ID="mainbutton"/>
</TEXTURES>

<OBJECTS>
  <object type="MenuButton" x="200" y="100" width="200" 
  height="80" textureID="mainbutton" numFrames="0" 
  callbackID="1"/>
  <object type="MenuButton" x="200" y="300" width="200" 
  height="80" textureID="resumebutton" numFrames="0" 
  callbackID="2"/>
</OBJECTS>
</PAUSE>

Loading the game over state

Our final state is GameOverState. Again this will be very similar to other states and we will only cover what has changed. Since we want GameOverState to handle callbacks it will now inherit from MenuState.

class GameOverState : public MenuState

We will then declare the setCallbacks function.

virtual void setCallbacks(const std::vector<Callback>& callbacks);

The onEnter function should be looking very familiar now.

bool GameOverState::onEnter()
{
  // parse the state
  StateParser stateParser;
  stateParser.parseState("test.xml", s_gameOverID, &m_gameObjects, 
  &m_textureIDList);
  m_callbacks.push_back(0);
  m_callbacks.push_back(s_gameOverToMain);
  m_callbacks.push_back(s_restartPlay);

  // set the callbacks for menu items
  setCallbacks(m_callbacks);

  std::cout << "entering PauseState
";
  return true;
}

The texture clearing method is the same as in the previous states, so we will leave you to implement that yourself. In fact onExit is looking so similar between states that it would be a good idea to make a generic implementation for it in GameState and just use that; again we will leave that to you.

You may have noticed the similarity between the onEnter functions. It would be great to have a default onEnter implementation but, unfortunately, due to the need to specify different callback functions, our callback implementation will not allow this and this is one of its main flaws.

Our AnimatedGraphic class will now need to grab the animSpeed value from LoaderParams in its load function.

void AnimatedGraphic::load(const LoaderParams *pParams)
{
  SDLGameObject::load(pParams);
  m_animSpeed = pParams->getAnimSpeed();
}

We will also have to register this type with GameObjectFactory.

TheGameObjectFactory::Instance()->registerType("AnimatedGraphic", new AnimatedGraphicCreator());

And finally we can update the XML file to include this state:

<GAMEOVER>
<TEXTURES>
  <texture filename="gameover.png" ID="gameovertext"/>
  <texture filename="main.png" ID="mainbutton"/>
  <texture filename="restart.png" ID="restartbutton"/>
</TEXTURES>

<OBJECTS>
  <object type="AnimatedGraphic" x="200" y="100" width="190" 
  height="30" textureID="gameovertext" numFrames="2" 
  animSpeed="2"/>
  <object type="MenuButton" x="200" y="200" width="200" 
  height="80" textureID="mainbutton" numFrames="0" 
  callbackID="1"/>
  <object type="MenuButton" x="200" y="300" width="200" 
  height="80" textureID="restartbutton" numFrames="0" 
  callbackID="2"/>
</OBJECTS>
</GAMEOVER>

We now have all of our states loading from the XML file and one of the biggest benefits of this is that you do not have to recompile the game when you change a value. Go ahead and change the XML file to move positions or even use different textures for objects; if the XML is saved then you can just run the game again and it will use the new values. This is a huge time saver for us and gives us complete control over a state without the need to recompile our game.

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

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