Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

04.07.2012, 23:29

C++ - Compiler-Fehler - Spielzustand-Automaten

Guten Abend :),

leider ist es mir nicht möglich, den Beispiel-Code aus dem Wiki-Artikel zu den Spielzustand-Automaten, zu kompilieren. Ich erhalte folgende Ausgabe:

Quellcode

1
2
3
4
5
6
7
8
9
10
 error C2678: Binärer Operator '!=': Es konnte kein Operator gefunden werden, der einen linksseitigen Operanden vom Typ 'D1I::GameState' akzeptiert (oder keine geeignete Konvertierung möglich)
1>      kann 'eingebauter C++ Operator!=(D1I::GameState *, D1I::GameState *)' sein
1>      bei Anpassung der Argumentliste '(D1I::GameState, D1I::GameState *)'
1>...\statemanager.cpp(64) : error C2440: '=': 'std::pair<_Ty1,_Ty2>' kann nicht in 'D1I::GameState *' konvertiert werden
1>      with
1>      [
1>          _Ty1=const std::string,
1>          _Ty2=D1I::GameState *
1>      ]
1>      Kein benutzerdefinierter Konvertierungsoperator verfügbar, der diese Konvertierung durchführen kann, oder der Operator kann nicht aufgerufen werden


Der Code dazu ist:
StateManager.cpp - Funktion - SetState

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void StateManager::SetState(const std::string &id)
{
stateIterator nextStateIt = mStatesByID.find(id);

// Wenn der Zustand im Manager registriert ist
if (nextStateIt != mStatesByID.end())
{
// und nicht der aktuelle ist
FEHLER IST HIER ===> if(*nextStateIt != mCurrentState) <===
{
// OnLeave vom vorherigen State aufrufen, falls es einen gab
if (mCurrentState != NULL)
{
mCurrentState->OnLeave();
}

Nennenswert(?) wäre noch die Tatsache, dass sich sowohl der StateManager als auch die abstrakte Klasse GameState im selben namespace befinden. Ich habe leider keine Ahnung wo ich ansetzen muss, daher bitte ich um Hilfe.. :)

Grüße

rnlf

Frischling

Beiträge: 85

Beruf: Softwareingenieur Raumfahrt

  • Private Nachricht senden

2

05.07.2012, 09:39

Ich kenne den Beispiel-Code nicht, aber für mich sieht es so aus, als müsstest du in der fehlerhaften Zeile noch auf den Wert des Iterators verweisen. Weil mStatesByID eine map zu sein scheint, müsstest du statt

C-/C++-Quelltext

1
*nextStateIt

C-/C++-Quelltext

1
nextStateIt->second
benutzen.

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

3

05.07.2012, 10:32

So compiliert der Code bei mir (ohne Gewähr auf Korrektheit). Mir scheint allerdings der Code wurde von C# direkt übernommen (string.Format, ...), auf jeden Fall kann der Code nicht getestet worden sein.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//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->second;
  }
}

//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->second != _currentState)
    {
      //Rufe OnLeave() vom alten Zustand auf, falls es einen gab
      if (_currentState != NULL)
        _currentState->OnLeave();

      //setze den neuen aktuellen Zustand
      _currentState = nextStateIt->second;

      //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->OnUpdate(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->OnRender();
}
@D13_Dreinig

Werbeanzeige