Spielzustand-Automaten
Aus Spieleprogrammierer-Wiki
(Unterschied zwischen Versionen)
[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.