Sign in to follow this  
jamesleighe

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

Recommended Posts

jamesleighe    222
(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.

ClientStateMainMenu:
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:
[code]
EngineAPI()->RunState( "ClientStateConnect" );
[/code]
Versus
[code]
EngienAPI()->RunState( new ClientStateConnect );
[/code]

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.
[code]
EngineAPI()->RunState( "ClientStateMainMenu", (void*)someData );
[/code]
Which has obvious issues.

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

Share this post


Link to post
Share on other sites
Sudi    761
Sry but i don't see the problem of Cross-Includes.

You may pass any data you want to

ClientStateMainMenu.h
[CODE]
class Engine;
class ClientStateMainMenu
{
public:
ClientStateMainMenu(Engine* e);

protected:
Engine* engine;
};
[/CODE]

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

ClientStateConnect.h
[CODE]
class Engine;
class ClientStateConnect
{
public:
ClientStateConnect(Engine* e);

protected:
Engine* engine;
};
[/CODE]

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

Share this post


Link to post
Share on other sites
Sudi    761
[quote name='James Leighe' timestamp='1329670000' post='4914548']
Whoa you can do that?!
Black magics.

Is that considered bad form or anything?
[/quote]

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 this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this