Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Managing Game States


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
17 replies to this topic

#1 destructivArts   Members   -  Reputation: 205

Like
0Likes
Like

Posted 20 March 2012 - 04:37 PM

Hello All!
I have recently completed Pong and Snake in Java from scratch. These were meant to be warm ups for bigger games.
They taught me how programming games works, and a lot about graphics.
One thing I did in both that I feel that there must be a better way of doing is keeping track of what part of the game the player is in.
For example, in both games, I simply created an integer variable called state.
0 = main menu
1 = in game
2 = game over
It's a pretty simple system. Both my run() and paintComponent() method checked it every frame and performed accordingly.

I was just wondering if there was a more effective way of doing this? I've been thinking for a while about it but I can't think of anything.
Any ideas?

Thanks,
Peter
-------------------------------------
"Other than that, I have no opinion."
My Blog - Check it Out

Sponsor:

#2 bollµ   Members   -  Reputation: 354

Like
1Likes
Like

Posted 20 March 2012 - 09:19 PM

yes, there is :] The state pattern - http://en.wikipedia.org/wiki/State_pattern. it's a pretty common one and it's used almost everywhere :) and I strongly suggest you check out enginuity - http://www.gamedev.net/page/resources/_/technical/game-programming/enginuity-part-i-r1947. They're a series of fantastic articles written by richard fine that covers everything you need to write a game engine :)

Have fun!
P.S - can we have the enginuity articles and a link to the state pattern stickied or something? a lot of people ask questions about this :)

a WIP 2d game engine: https://code.google.com/p/modulusengine/

English is not my first language, so do feel free to correct me :)


#3 L. Spiro   Crossbones+   -  Reputation: 14026

Like
0Likes
Like

Posted 21 March 2012 - 02:51 PM

You may find this useful: General Game/Engine Structure


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#4 marcjoel   Members   -  Reputation: 113

Like
-3Likes
Like

Posted 23 March 2012 - 08:32 AM

Make a base class of the States, let's say class BaseState. then inherit every state in it. for example: class MainMenuState : public BaseState. then make a class that handles the state, i.e. class StateManager. This class will just have a pointer to a BaseState. Register your real states to this manager then act accordingly. Heres a sample code.

class BaseState
{
public:
virtual void Update() = 0;
};

class MainMenuState : BaseState
{
public:
void Update();
};

class StateManager
{
private:
BaseState* current_state;
public:
void SetState(BaseState* state)
{
current_state = state;
}

void UpdateCurrentState()
{
current_state->Update();
}
};


Something like that Posted Image I hope it helped you Posted Image
Good day!

Edited by marcjoel, 02 August 2012 - 11:01 AM.


#5 L. Spiro   Crossbones+   -  Reputation: 14026

Like
0Likes
Like

Posted 23 March 2012 - 08:50 AM

Don't forget the reputation button. ;)
Good day!

It is considered poor etiquette to request reputation.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#6 Nanook   Members   -  Reputation: 505

Like
0Likes
Like

Posted 27 March 2012 - 05:33 PM

Great article YogurtEmperror..

I got something similar, but changing abit now with some new ideas from reading.. But where do you have your renderer? Do you store that in the base Game class so the Draw() can use it?

I think I might seperate it abit and have a Engine* where I store the engine resources and managers.. and a Game* for more game specific stuff.. that way I can use the Engine* in tools and have access to the resources without including game stuff..

#7 L. Spiro   Crossbones+   -  Reputation: 14026

Like
0Likes
Like

Posted 28 March 2012 - 05:58 AM

The best way to explain it is probably via a screenshot.
EngineOrg.png
This screenshot has not been “posed” in any way. I simply started up my project and took a screenshot as it last appeared.
The file names across the top each begin with a prefix. LSG, LSI, etc. LSG = L. Spiro Graphics. LSI = L. Spiro Image, etc. The non-intuitive one is LSD, which stands for L. Spiro Models, since LSM (L. Spiro Math) was already taken.

On the right you see every module (library) that is compiled in order to build the actual engine. There are 15.

The Image library (LSI) handles images in a generic way. It doesn’t know what DirectX is or what OpenGL is. But it knows how to read a lot of formats and convert between formats. And resample, resize, etc.

This is an important separation because it allows tools to not know or care about DirectX or OpenGL etc.

LSE stands for L. Spiro Engine, and LSG stands for L. Spiro Graphics.
These are separate entities, each knowing about their own field of study.
LSE uses LSG, as does anything that needs to render itself (terrain and models only, basically).


So no, I do not store the renderer in the game class.
And CGame (from my post) is held within the “lse” namespace. It is part of the engine. Part of what binds all of the other modules together.

This acts as a better way to allow tools access to only what they need instead of having them rely on the entire engine for only a small engine feature.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#8 Burnt_Fyr   Members   -  Reputation: 1245

Like
0Likes
Like

Posted 28 March 2012 - 08:17 AM

I think your on the right track Nanook, FWIW, my code is built much like L.Spiro's, and that kind of separation has taken me a while to really get to where i'm liking it(though still hating some parts). My games/demos themselves usually contain a main menu state, an options state, and a gamestate, everything else is either data or part of the engine itself.

#9 bollµ   Members   -  Reputation: 354

Like
0Likes
Like

Posted 28 March 2012 - 09:29 AM

WOW, heavily commented code yogurtEmperor :] Wish mine looked half as neat as that
Gotta start commenting... *opens Visual Studio 2010 and begins to type furiously*

a WIP 2d game engine: https://code.google.com/p/modulusengine/

English is not my first language, so do feel free to correct me :)


#10 Nanook   Members   -  Reputation: 505

Like
0Likes
Like

Posted 28 March 2012 - 11:58 AM

Ah yes I also have it seperated like that.. I dont have that many though.. I have a core library, graphics library, physics library and engine library.. but I also have it devided into sections by namespaces.. I used to have lots of libraries too but I found it got pretty hard to maintain them all.. I also have low level renderers (OpenGL, DirectX) and a high level one..

Still abit confused from your reply though.. I mean.. where do you set up the scene for each state? Atm. I'm doing that in the Init of my states(Or actualy in my editor, but I load it from file in the Init).. I pass a Engine* to all the functions of the state (Init, Draw, ...) .. then when I call Draw on the state I do engine->GetRenderer()->Draw(m_scene); ..

So I store an instance of my renderer in the Engine class..

#11 Nanook   Members   -  Reputation: 505

Like
0Likes
Like

Posted 28 March 2012 - 12:00 PM

Btw. do you have to open up your projects? Aren't they always open? :)

#12 L. Spiro   Crossbones+   -  Reputation: 14026

Like
0Likes
Like

Posted 29 March 2012 - 04:43 AM

I used to have one CSceneManager which was created by the CGame class, but then I had to make hacks to get multiple cameras working in the same scene when we wanted to draw one 3D scene and then another on top of it. Some objects were tagged to one camera and some to the other.
It didn’t make sense so in my new engine I let users create their own CSceneManager instances and as many of them as they please. This is a lot more elegant and efficient.

The scene is set up in the Init() class on CState.

As for how they are rendered, you have it backwards.
A rendered should never know what a scene is.
A scene knows what a scene is and it should render itself using the abstract and general-purpose functions provided to it by the renderer.

m_smScene.Draw().

The scene culls objects, selects the active camera, applies the projection matrices and other render states that need to be set, and eventually tells objects to draw themselves.
Objects set shaders for themselves, activate vertex and index buffers for themselves, and perform a render.


Btw. do you have to open up your projects? Aren't they always open? Posted Image

Not this week. I am watching Avatar: The Last Airbender by recommendation from a friend. But only 2 more left to watch.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#13 Nanook   Members   -  Reputation: 505

Like
0Likes
Like

Posted 29 March 2012 - 08:36 AM

Ah I see.. I only have the root node in my state and then pass that to the renderer.. so I guess my renderer is kind of acting as my scenemanager.. even though I'm still doing the traversal and culling in the scene nodes themself though.. sceneNode.GetRenderablesCulled().. I'll redesign it so I'll move stuff into a scenemanager..

Im not sure where I should put my templated resource managers.. the manager that make sure there is only one instance of each loaded resource at one time.. Right now I've put the resource managers related to the renderer in the renderer.. so the user would do:

void MyState::Init()
{
	 VertexBuffer vBuffer("vertexbuffer.file");
	 int handlevBuffer = m_renderer->Register(vBuffer);
	 IndexBuffer iBuffer("indexbuffer.file");
	 int handleiBuffer = m_renderer->Register(iBuffer);
	 // more setup
	 Renderable renderable(handlevBuffer, handleiBuffer, handleShader, ...);
	 m_scene->addNode(renderable);
}

So if I try to register a vertex buffer with a filename that is already registered it will return a handle to the one already registered instead of storing the new one.

Been thinking of having a ResourceManagerManager, but even the name of that sounds wrong Posted Image If I put it in the scenemanager I wont be able to use the same resource managers for the different scenes..

#14 L. Spiro   Crossbones+   -  Reputation: 14026

Like
0Likes
Like

Posted 30 March 2012 - 06:28 AM

You generally don’t load “vertex files” and “index files”.
You load models. Any sharing between vertex and index buffers can be predetermined offline, since it is unlikely any vertex buffers will ever be shared between models.
Trying to share all vertex buffers on a system-wide scale is over-engineering.

This is how mine looks:
LSVOID LSE_CALL CModelTest::Init( CGame * _pgGame, LSINT32 _ui32State, LSINT32 _ui32PrevState, LSUINTPTR _uptrUser ) {
    m_dmipInstance = m_sgpScene->CreateDrawableModelInstance( "KinoGirl.lsm" );
    m_sgpScene->CreateDrawableModelInstance( "Ground.lsm" )->SetCastsShadow( false );
}

You can probably agree that this would be more preferable for anyone using your engine, including yourself.

There is no need for a global general-purpose resource manager. Resources don’t have enough in common to warrant such a thing.
As far as anything managing resources goes, there are unique ones for the scene, models, etc.
And all of these are handled at a high level. For example you are proposing to share all vertex buffers period. What if I want to load the same one again so I can make changes to it?
A more common example of the same thing is textures. I very easily might want to apply some filter that is expensive if done in a shader, so I want to modify the original. But that would change all instances of it, so I need to be able to load multiple copies of it.

However I know that within my model library I am not modifying those textures. They are shared between each other and only each other. No other system is involved, so while it may be wasteful if a sprite were to later reload the same file, it is the lesser of evils and in practice never happens. And textures within the sprite system are shared amongst each other as well.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#15 Nanook   Members   -  Reputation: 505

Like
0Likes
Like

Posted 30 March 2012 - 07:42 AM

Yes the plan has been to load a renderable from file and the code loading the renderable will be loading vertex and index buffer like that.. so I would have

/renderables/Cube01/indexbuffer
/renderables/Cube01/vertexbuffer
/renderables/Cube01/shader
/renderables/Cube01/renderable
/textures/sometexture.png

The user would do something like loadRenderable('/meshes/Cube01/') and it would find the renderable file which have info on how stuff should be set up.. I got a dat archive file and a gui tool I've created and it exports any format with the assimp library and puts the files like that. hum.. maybe I should change it and put it all into my own model format.. Its easy to work with it when its like that though.. so I wasn't realy thinking of sharing the vertex buffers between different renderables as it is identified by the path in the dat file..

But you're saying that I should share renderables/textures, but still make it possible to load a seperate instance of it?

#16 achild   Crossbones+   -  Reputation: 1927

Like
0Likes
Like

Posted 30 March 2012 - 08:08 AM

...
What if I want to load the same one again so I can make changes to it?
...

Seems to me the best way to handle this would be to have a system which only loads resources once (from disk, DVD, internet, whatever) but employ copy-on-write semantics on your shared resources.

#17 L. Spiro   Crossbones+   -  Reputation: 14026

Like
0Likes
Like

Posted 30 March 2012 - 08:18 AM

But you're saying that I should share renderables/textures, but still make it possible to load a seperate instance of it?

Basically. The below reply provides a reason as to why.



...
What if I want to load the same one again so I can make changes to it?
...

Seems to me the best way to handle this would be to have a system which only loads resources once (from disk, DVD, internet, whatever) but employ copy-on-write semantics on your shared resources.

I saw a video about some game that allowed slicing enemies in half and I wanted to support such an ability in my own, and the best way I thought to do that was via copy-on-write.

But later I realized that the problem with copy-on-write is that it is hidden overhead. People might be doing it and incurring a significant amount of overhead without understanding why.
When it comes to game engines, this isn’t acceptable. Users should know what actions they are doing to cause performance issues and be pushed towards a more performant way of accomplishing the same thing.

But this is a perspective unique to myself—not everyone here is planning on making a business out of middleware.
My original mindset allowed copy-on-write because I wasn’t considering other people using my engine (even though that was my goal and I should have been). If you are just making your own personal engine, copy-on-write is a very elegant solution to this problem.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#18 Hiiri   Members   -  Reputation: 111

Like
0Likes
Like

Posted 04 April 2012 - 05:30 PM

Wouldn't some sort of stack of states work pretty well. You throw in the topmost of the stack the state you're showing currently, and once you're done with it, you pop it out. Then use some boolean value when creating state to determine, if the state manager goes further in the state stack. Like lets say you have following stack:

Options - state
Main game - state
The bottom - state

So looking this way, the control needs to go on the topmost object, but the logic update needs to go through whole stack. At least this would be the way how I would start implementing the controller, but probably other people have better ideas.

Maybe you could pass some values like, canDrawUnder and capturesController, or something like that to determine how far of the stack you must go.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS