2017-05-24 4 views
0

Meine Frage ist: Ich versuche, grundlegende Zustandsverwaltung in meinem Projekt zu implementieren, und ich steckte bei sich ändernden Zuständen. Ich habe alle meine Staaten in std::stack<State*> Container, und push/pop sie direkt von Application-Klasse oder von State-Klasse. Problem ist, wenn ich den aktuellen Zustand von State-Klasse ändern, kann es vor dem Aufruf der Render-Methode zerstört werden, was zu einer Ausnahme führt. Wie vermeide ich das? PS sorry für mein Englisch und mir bitte sagen, wenn etwas in meinem Problem/code klarC++ Implementieren von Zuständen

Anwendungsklasse isn:

void Application::pushState(State* state) 
{ 
    this->m_states.push(state); 
    this->m_states.top()->open();//enter state 
} 

void Application::popState() 
{ 
    if (!this->m_states.empty()) 
    { 
     this->m_states.top()->close();//leave state 
     delete this->m_states.top(); 
    } 

    if (!this->m_states.empty()) 
    this->m_states.pop(); 
} 

void Application::changeState(State* state) 
{ 
    if (!this->m_states.empty()) 
     popState(); 
    pushState(state); 
} 

State* Application::peekState() 
{ 
    if (this->m_states.empty()) return nullptr; 
    return this->m_states.top(); 
} 

void Application::mainLoop() 
{ 
    sf::Clock clock; 

    while (this->m_window.isOpen()) 
    { 
     sf::Time elapsed = clock.restart(); 
     float delta = elapsed.asSeconds(); 

     if (this->peekState() == nullptr) 
      this->m_window.close(); 
     this->peekState()->update(delta)//if i change state in State.update(), it may be that code below will now point to not existing state 

     if (this->peekState() == nullptr) 
      this->m_window.close(); 
     this->peekState()->render(delta); 
    } 
} 

State-Klasse:

void EditorState::update(const float delta) 
{ 
    sf::Event event; 
    while (this->m_application->m_window.pollEvent(event)) 
    { 
     if (event.type == sf::Event::Closed) 
     { 
      this->m_application->popState(); 
      return; 
     } 
    } 
} 

Okay das vielleicht nicht wirklich ein Problem, aber so etwas wie "wie" zu hinterfragen. Wie Sie in meinem Code sehen können, aktualisiere und rende ich Zustände in der mainLoop() Methode. Was herauszufinden ist, wie man diese Updates verwaltet, kann davon ausgehen, dass der Status vom Status selbst geändert werden kann, nicht nur von stateManager (in meinem Fall Application-Klasse)

+0

Willkommen bei Stack Overflow. Bitte nehmen Sie sich die Zeit, [The Tour] (http://stackoverflow.com/tour) zu lesen und beziehen Sie sich auf das Material aus der [Hilfe] (http://stackoverflow.com/help/asking), was und wie Sie können fragen Sie hier. –

+2

Sind Sie sicher, dass ein Stack die richtige Datenstruktur zum Speichern von Zuständen ist? Vielleicht interessiert dich [dies] (http://makulik.github.io/sttcl/). –

+0

Nicht sicher, vielleicht kann ich es in Vektor ändern, aber insgesamt ist das nicht, was mein Problem ist, denke ich – joe503

Antwort

1

Ok, also ich vermute, das ist für ein Spiel (aber es muss nicht sein). Anstatt zu tun, was du tust, um zwischen Zuständen zu wechseln, verwende ich eine Aufzählung.

enum class GameState { 
    MENU, PLAY, PAUSE 
} 

Dann in Ihrem Haupt-Header

GameState m_gameState = GameState::MENU; 

In Ihrem Haupt-Schleife können Sie überprüfen, was der aktuelle Stand, indem Sie einfach ist

if (m_gameState == GameState::MENU) 
{ 
    ... 
} 

tun, oder Sie können eine switch-Anweisung verwenden

switch (m_gameState) 
{ 
case GameState::MENU: 
    ... 
    break; 
case GameState::PLAY: 
    ... 
    break; 
case GameState::PAUSE: 
    ... 
    break; 
} 

Und, wenn Sie jemals den Zustand wechseln möchten, können Sie einfach tun

m_gameState = GameState::PAUSE; 

Hoffnung Ihre Frage damit beantwortet: D

Wenn nicht, muss ich falsch verstanden (sorry).

+0

Dies ist eine in Ordnung Lösung, aber dies könnte die Hauptschleife leicht mit einem Verhalten überschwemmen, das nicht in seiner Verantwortung liegt. Mit dem Ansatz von @powerglove kann er das in eine andere Klasse aufteilen. – Chringo

+0

Sie können dies in eine andere Klasse trennen, wenn Sie möchten, es ist nicht nur auf die eine Klasse beschränkt. (Auch @powerglove, wenn dies als Antwort funktioniert, achten Sie darauf, es zu markieren, danke) – Nybbit

Verwandte Themen