Spielzustand-Automaten

Aus Spieleprogrammierer-Wiki
(Unterschied zwischen Versionen)
Wechseln zu: Navigation, Suche
[unmarkierte Version][unmarkierte Version]
(State)
(StateManager)
Zeile 96: Zeile 96:
 
<xh4>C++</xh4>
 
<xh4>C++</xh4>
 
|
 
|
<sourcecode lang=cpp tab=4>class StateManager
+
<sourcecode lang=cpp tab=4>/* h-Datei: StateManager.h*/
 +
class StateManager
 
{
 
{
 
private:
 
private:
Zeile 113: Zeile 114:
 
   void Render();
 
   void Render();
 
};
 
};
 +
 +
/* cpp-Datei: StateManager.cpp */
 +
 +
//erzeugt ein StateManager-Objekt
 +
StateManager::StateManager():
 +
  _currentState(NULL)
 +
{
 +
}
 +
 +
//Löscht das StateManager-objekt mit allen Zuständen.
 +
StateManager::~StateManager()
 +
{
 +
  for(std::map<std::string, State*>::iterator it = _statesById.Begin(); it != _statesById.end(); ++it)
 +
  {
 +
    delete (*it);
 +
  }
 +
}
 +
 +
//Registriert einen Zustand für den Manager an Hand der ID. Diese muss
 +
//eindeutig und nicht leer sein.
 +
void StateManager::AddState(const std::string &id, State *state)
 +
{
 +
  if (id.length() == 0)
 +
    throw std::exception("Id has to be a valid string");
 +
  if (state == NULL)
 +
    throw std::exception("State must not be null");
 +
 
 +
  std::map<std::string, State*>::iterator it = _statesById.find(id);
 +
  if (it != _statesById.end())
 +
  {
 +
    std::string error("State with ID ");
 +
    error.append(id);
 +
    error.append(" already exist.");
 +
    throw std::exception(error.c_str());
 +
  }
 +
   
 +
  _statesById[id] = state;
 +
}
 +
 
 +
//Setzt den aktuellen Zustand
 +
void StateManager::SetState(const std::string &id)
 +
{
 +
  std::map<std::string, State*>::iterator nextStateIt = _statesById.find(id);
 +
 
 +
  //Wenn der Zustand im Manager registriert ist
 +
  if (nextStateIt != _statesById.end())
 +
  {
 +
    //und nicht der aktuelle ist
 +
    if (*nextStateIt != _currentState)
 +
    {
 +
      //Rufe OnLeave() vom alten Zustand auf, falls es einen gab
 +
      if (_currentState != NULL)
 +
        _currentState->OnLeave();
 +
       
 +
      //setze den neuen aktuellen Zustand
 +
      _currentState = *nextStateIt;
 +
     
 +
      //Initialisiere, wenn noch nicht getan
 +
      if (!_currentState->IsInitialized())
 +
        _currentState->Initialize();
 +
       
 +
      //Da zu einem neuen Zustand gewechselt worden ist, rufe das Eingangsereignis auf
 +
      _currentState->OnEnter();
 +
    }
 +
  }
 +
  else
 +
      //ansonsten gibt es diesen Zustand nicht!
 +
      throw new InvalidOperationException(string.Format("State with Id {0} does not exist.", id));
 +
}
 +
 
 +
//Aktualisert den Spielzustand. der Rückgabewert gibt an, ob das Programm weiterläuft.
 +
//Es läuft nicht weiter, wenn der aktuelle Zustand verlassen und kein weiterer Zustand zugewiesen wird.
 +
bool StateManager::Update(float elapsedTime)
 +
{
 +
  //Es muss ein Zustand gesetzt sein!
 +
  if (_currentState == NULL)
 +
    throw std::exception("Current state not set.");
 +
   
 +
  //aktualisere den Zustand und schaue, ob der Zustand eventuell verlassen werden soll
 +
  bool running = _currentState->Update(elapsedTime);
 +
 
 +
  //wenn er verlassen werden soll und der Folgezustand gesetzt ist
 +
  if (!running && !_currentState->NextState().length() > 0)
 +
  {
 +
    //Wechsle den Zustand
 +
    SetState(_currentState->NextState());
 +
   
 +
    //Programm läuft weiter
 +
    return true;
 +
  }
 +
 
 +
  //
 +
  return running;
 +
}
 +
 
 +
//Zeichnet den aktuellen Zustand.
 +
void StateManager::Render()
 +
{
 +
  //Es muss ein Zustand gesetzt sein!
 +
  if (_currentState == NULL)
 +
    throw std::exception("Current state not set.");
 +
   
 +
  //Zeichne den aktuellen Zustand
 +
  _currentState->Render();
 +
 +
}
 
</sourcecode>
 
</sourcecode>
 
}}
 
}}

Version vom 7. November 2011, 13:16 Uhr

Klicke hier, um diese Version anzusehen.

Meine Werkzeuge
Namensräume
Varianten
Aktionen
Navigation
Werkzeuge