• 13
• 14
• 27
• 9
• 9

# Issue with program (class) design. Engine design question.

This topic is 2216 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

(C++)
I have a question about the class design in my game engine, but first, a little backstory. Any feedback, especially negative, is more than welcome!

States manage the flow of the game code.
Usualy, one state when finished starts another, and shuts itself down.

For example, the following states are run in order.

This state displays the main menu and runs the apporopreate state depending on what the user selects.
If the user selects 'New Game' the state 'ServerStatePlay' and 'ClientStateConnect' are run.

ClientStateConnect:
This state connects to a server, verifies some things like entity lists, and then runs 'ClientStatePlay'.

ClientStatePlay:
This is the state that handles the main gameplay.
It has many responsibilities.

The code to run a state looks like this:
 EngineAPI()->RunState( "ClientStateConnect" ); 
Versus
 EngienAPI()->RunState( new ClientStateConnect ); 

This start state-by-name system prevents cross-includes.

An example potential cross-include:
'ClientStateMainMenu' runs 'ClientStateConnect' and if the connection fails, 'ClientStateConnect' needs to run 'ClientStateMainMenu' again.

=Primary Issue=
I have no way cleanly send data to a state I am starting. For example, sending the servers ip address to 'ClientStateConnect' when I start it from 'clientStateMainMenu'.

The way this is currently handled is through console variables (an idea shamelessly stolen from the Source engine, my favorite). However, not all inter-state data makes sense as a console variable.

An example of that is, if a connection fails, 'ClientStateMainMenu' is run again from 'ClientStateConnect'. However, 'ClientStateMainMenu' needs to display a message telling the user that the connection has failed. How can I tell it that it should do that?

One (horrible) idea I had was to have a generic system whereby I could send data casted as a void* into the state.
 EngineAPI()->RunState( "ClientStateMainMenu", (void*)someData ); 
Which has obvious issues.

How could I best do somthing like this? I'm not even married to the whole state idea honestly.

##### Share on other sites
Sry but i don't see the problem of Cross-Includes.

You may pass any data you want to

 class Engine; class ClientStateMainMenu { public: ClientStateMainMenu(Engine* e); protected: Engine* engine; }; 

 #include "ClientStateMainMenu.h" #include "ClientStateConnect.h" #include "Engine.h" ClientStateMainMenu::ClientStateMainMenu(Engine* e) : engine(e) { Engine->RunState(new ClientStateConnect()); } 

ClientStateConnect.h
 class Engine; class ClientStateConnect { public: ClientStateConnect(Engine* e); protected: Engine* engine; }; 

ClientStateConnect.cpp
 #include "ClientStateConnect.h" #include "ClientStateMainMenu.h" #include "Engine.h" ClientStateConnect::ClientStateConnect(Engine* e) : engine(e) { if (!connect()) Engine->RunState(new ClientStateMainMenu()); } 

##### Share on other sites
Whoa you can do that?!
Black magics.

Is that considered bad form or anything?

##### Share on other sites
I have always only included one header in .cpps (the matching header file).

So including other headers in the .cpp would sure help allot.

##### Share on other sites
Include all the headers in the cpp that you need. Use forward declarations in headers. This is not bad form.

##### Share on other sites

Whoa you can do that?!
Black magics.

Is that considered bad form or anything?

No its not BlackMagic...
In Header files you should only include what is really needed and if possible forward declarations.
What i showed is actually good practice and how it should be done.

##### Share on other sites
Thanks, dunno why I was ever doing it the other way!