I'm just playing around making a "dungeon crawl" from the article posted here: http://www.cplusplus.com/forum/articles/12974/. My only experience with C++ and OOP in general is with those exercises, plus codeAbbey, so not a whole lot.
The question: What is the best way to handle game states? Right now I have a "GameManager" class, which has a setGameState function. This function sets a private bool, which is what controls the "game loop" in GameManager.cpp. Here's the code:
void GameManager::play()
{
Level level;
Player player;
char playerMove;
level.load("level1.txt", player, enemies_);
// Game loop
while (!player.getStatus())
{
level.print(player);
if (isWon_)
{
std::cout << "You win!\n";
}
std::cout << "Enter a move: ";
// Pause the program and wait for player input
playerMove = _getch();
level.movePlayer(playerMove, player);
}
// Player has died
level.print(player);
std::cout << "You died! Game Over!\n";
}
void GameManager::setGameStatus()
{
isWon_ = true;
}
Here is where I get lost. In my main.cpp, I'm creating an instance of GameManager and calling play(). In my "level" class I need to be able to call the GameManager's setGameState function. As you can see though, my "level" instance is being created inside the GameManager itself. Since GameManager is being created in main.cpp, I can't pass it by reference to my level class, so I can utilize the member functions. I feel like I'm going about this the wrong way. Does anyone have anything I can research, or nudge me in the right direction? I understand "manager" classes are considered singleton(?) and perhaps should be avoided, so if anyone has another way to implement the functionality, I'd love to learn it. Currently I'm looking at static members, is that something I should be looking harder at? Thanks for any help.
Since GameManager is being created in main.cpp, I can't pass it by reference to my level class
Yes, you can.
IMO GameManager should not have a variable that its children set. The typically desired flow of information is: parent class requests a piece of information from a child (e.g. by calling a function), and the child gives back that information (e.g. by returning a value).
What I would suggest instead is to code the victory conditions as a function in GameManager that you call to see if they've been met. The victory conditions should be general, like "is the player standing on coordinates (x, y)?" The function should ask for the relevant pieces of information from the corresponding classes and figure out the state of the game.
This way the game rules are encoded in a single place, rather than being spread all over the codebase.
Awesome explanation, and was exactly what I was looking for. I moved the condition check to GameManager and had it checking a bool in my level. In other words, the child has no direct access to the parent class, but the parent class requests certain data from each class to determine game state. I was trying to have the child change the parent, which was odd. Thanks again!