Du bist nicht angemeldet.

Werbeanzeige

1

28.12.2018, 11:35

FSM - Wie States verwalten?

Hallo Leute,

ich lerne gerade C++ und habe ein kleines Konsolen RPG angefangen (ohne Grafik/Sound).
Gesteuert wird alles über Texteingaben.

Das Spiel an sich ist als finite state machine aufgebaut. Im Anhang habe ich ein kleines Diagramm angehängt, welches die einzelnen States bzw. "Screens" im Zusammenspiel zeigen soll (Sprechblasen sind dabei die eigentlichen States, die Blöcke darunter die Menü-Elemente). Die einzelnen States erben von einem State-Interface welches 3 Methoden bereit stellt: OnEnter, OnExit, Update. Beim Initialisieren eines States muss ein Kontextobjekt übergeben werden.

Das Kontexobjekt hat dabei folgende Aufgaben: Referenz zum aktuellen State halten, eine Methode bereitstellen um den aktuellen State zu wechseln(dadurch kann ein State über die Referenz zum Kontextmenü selber entscheiden wann in einen anderen State gewechselt werden soll) sowie die Methoden des aktuellen States in der GameLoop aufrufen.

Nun habe ich folgendes Problem/Frage:

Wer sollte die eigentlichen Stateobjekte verwalten und wie sollte ich auf diese Zugreifen wenn ich den State wechseln möchte?

a) Macht es Sinn im Kontextobjekt einfach alle States einmalig zu initialisieren (dann könnte jeder State über das Kontextobjekt auf die anderen States zugreifen)
b) Sollte der jeweilige State seine möglichen Statenachbarn initialisieren und verwalten (z.B muss der BossScreen nur wissen wie er zum GameScreen State wechselt oder zum FightScreen State, nicht jedoch zum InventoryScreen State) ?.
c) Macht es Sinn eine dedizierte Datenstruktur anzulegen, welche den jeweiligen State mit seinen "TransistionNodes" speichert?
(CurrentState, [TransistionNode1, TransistionNode2])
Beispiel: (BossScreen*, [GameScreen*, FightScreen*])
d) Andere Ideen falls meine Frage verstanden wurde? XD

Vielen Dank für eure Zeit!
»Minerva/8« hat folgendes Bild angehängt:
  • Diagram.jpg

Nox

Supermoderator

Beiträge: 5 259

Beruf: Student

  • Private Nachricht senden

2

29.12.2018, 00:30

unter der Annahme, dass ich dein Fragen und Problemstellung korrekt verstanden habe:

zu a) kommt auf den Anwendungsfall bzw auch die "Mächtigkeit" der states an. Bei Spielen hält man typischerweise nur den Zustand im Speicher, der gerade aktiv ist. Je nach Platform und Anwendungsfall kann das aber stark variieren.

zu b) klingt so direkt nach kompliziert und gefährlich; z.B.potenziell könnte dadurch das "Hauptmenü" zweimal existieren, wenn es dumm läuft. Was aber durchaus existiert ist das Konzept, dass der Nachfolger beim "on exit" initialisiert und zurückgegeben wird. Birgt aber je nach Design die Gefahr, dass man eine riesige Schlange an Instanzen anhäuft, wenn man zyklische Verläufe hat, nur "vorwärts" aber nie "zurück" geht und nur beim "zurück" aufräumt.

zu c) klingt nach over engineering.

zu d) je nach persönlichen Präferenzen und Anwendungsfall darf man auch "einfache" Lösungen nutzen. Sprich: Lohnt es sich ein OO Zustandsystem zu implementieren oder äre es im konkreten Fall ggf robuster und einfacher auf simplere Konzepte zurückzugreifen(z.B. Zustandskodierung per Zahl und dann große switch Anweisung. Klassische FSM aus dem Microcontroller Bereich sehen z.b. so aus)?

generell: schon mal von der-Suchmaschine-deiner-Wahl zu "simple FSM c++" inspirieren lassen?
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

3

29.12.2018, 14:16

Erst mal vielen Dank für deine Antwort!

zu d) je nach persönlichen Präferenzen und Anwendungsfall darf man auch "einfache" Lösungen nutzen. Sprich: Lohnt es sich ein OO Zustandsystem zu implementieren oder äre es im konkreten Fall ggf robuster und einfacher auf simplere Konzepte zurückzugreifen(z.B. Zustandskodierung per Zahl und dann große switch Anweisung. Klassische FSM aus dem Microcontroller Bereich sehen z.b. so aus)?

generell: schon mal von der-Suchmaschine-deiner-Wahl zu "simple FSM c++" inspirieren lassen?


Klar, Google ist wohl immer die erste Anlaufstelle ^^. Jedoch finde ich überwiegend nur Artikel wie sowas implementiert wird und oft sind es dann auch nur "einfache" Beispiele in denen ich anhand meiner nicht vorhandenen C++ Kenntnisse nicht entscheiden kann ob das auch so Sinnvoll ist.
Ich habe aber jetzt im Buch "Game Programming Patterns" von Robert Nystrom geblättert und mir mal sein vorgehen angeschaut.

Im Endeffekt reicht es wohl in meinem Fall das ich die States einfach nach Bedarf initialisiere und beim wechseln der States den aktuellen lösche und durch den neuen austausche.

C-/C++-Quelltext

1
2
3
4
5
6
7
//This method must be used within the state object to change the state
void Game::SetState(State* state) {
    _currentState->OnExit();
    delete _currentState;
    _currentState = state;
    _currentState->OnEnter();
}

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void MainState::Update(int input) { 
    switch(input) {
        case 1: 
            _context->SetState(new GameState(_context));      
        break;
        
        case 2:
            exit(0);
        break;

        default:
            std::cout << "Invalid input!" << std::endl; 
        break;
    }
}

4

29.12.2018, 14:49

Guck dir mal std::unique_ptr an statt mit delete zu arbeiten. Und was ist input? Die Taste, die gedrückt wurde? Das kann man besser benennen, sonst weißt du irgendwann nicht mehr, was gemeint ist.

Werbeanzeige