Jump to content

VeTaL

Members
  • Posts

    1,272
  • Joined

  • Last visited

Posts posted by VeTaL

  1. The problem with this statement is that when you want to do something in the remaining 1% your going to find yourself pushed for time. This is exactly where speed and efficiency comes in and what makes the difference in the end as to whether you can get the performance you want or not. The remaining 99% you can do little about as it's someone else's code

    bull's eye :rolleyes:

  2. Just wanted to drop 5 cents (share own experience)... Maybe obvious things, but just in case someone would find it usefull.

    As mentioned before, language is almost not playing a role in LE application: 99% of time is engine.dll

     

    I spend some hours, trying to resolve some CRT problems (i couldnt build release version), get a lot of additional experiense and... see no differ between debug and release builds in C++

     

    The scene is not too high loaded, but there are amount of code already in usage.

  3. //Maybe get the width of the AABB bounding box showing on-screen and adjust pixels appropriately?

     

    Looking like its too long.. Rick, maybe you sould just take the origin of model (if it is in center in 3d), move up (in 3d) and move (in 2d) panel half-of-its-width left?

  4. According to this thread and franck's request, i decided to upload my small working example of Cegui, which is done by this tutorial.

     

    First, you should download Binary version of cegui CEGUI-SDK-0.7.5-vc8.zip (you'll need SP1 for msvs 2008) or CEGUI-SDK-0.7.5-vc10.zip

     

    Consilder Cegui is installed in z:\CEGUI\cegui\include folder, and Leadwerks is in Z:\Leadwerks Engine SDK\CPP

    If not, open project's settings "Property -> C/C++ -> General -> Additional include directories" and change this string "Z:\Leadwerks Engine SDK\CPP;z:\CEGUI\cegui\include" so it will show pathes to your sources.

    Also change "Property -> Linker -> General-> Additional library directories" from "Z:\CEGUI\lib\" to your path to libs.

     

    Looking like thats all - it should works nice:

    post-648-0-42103000-1312192150_thumb.png

     

    Example (with sources, project for msvs 08, cegui datafiles and exe-file):

  5. Regarding previous state: you can for example enter the options screen from the main menu and from the pause. It is handy that the options menu knows what state to go back to.

    That has a sence.

     

    Regarding tweens: you should add states to your MenuStates. State_In, State_Idle, State_Out for example. This can be by design.

    This also has a sence, but States are already designed to do this job :)

    Just alternative way.

     

    Interface keyword in C++ is not interface in C# . You should just use class.

    Yes i can, but i like "interface" more :)

     

    I am talking about your abstract class methods like UpdateState, RenderState. In my opinion these can just be Update and Render. You know it's a state object.

    Also agree. But, as i said, i have RenderState and sometimes i need RenderEvent (which is inherited from another interface).

    But i'll remove them from this example to be more clear :)

  6. Big thanks to TheoLogic: i always knew that writing articles for others hepls myself a lot :)

     

    Your are leaking memory, you must use virtual destructors!!!

    Yep, fixed. States classes are created one time per launch, but anyway, mistake took a place.

     

    It is also very interesting to know the previous state on state activation. You may have a back button redirecting to a previous (not defined) state.

    Well, you can add one more state-rememberer to "_previousStateReturns = _stateReturns;"

    But generally, this is designed for

    MainMenu -> Options button -> OptionsMenu -> Save button -> MainMenu -> Start game button

     

    Deactivate a menu: I want a nice tween, like a fade or a slide. You have already activated the second one, which also wants a nice animation. You don't want buttons and so to be enabled during that animation. You may want to render another state during the animation (even at a different position), ...

    Generally, this system was designed exact for that. You just add new SplashState and FadeState.

    Or you can add private variable, which will be set to 0 while state Activation, and runs it from 0 to 100 in Update.

    And menu is unactive if this variable (consider fading) is less than 100.

     

    Maybe some remarks, I guess they are copy/paste errors:

    They are wellcomed :)

     

    - Interface in C++?

    Yep, why not?

     

    Extern enum? Enum is a custom type...

    It was designed to type "GameStatesEnum." and get the list of all states :)

     

    underscore prefix for function arguments?

    Typos: usually i use underscore prefix only for private fields.

     

    - You may want to loose that "State" in your methods. C++ is strongly typed, so you know you update a state, no need to say UpdateState and so on.

    Not sure i understand you right.

    In real project, i have functions

    *State - they are inherited from IGameStates

    *Event - they are inherited from IGameObject

     

    But that's another story :)

  7. As i collected some basic information and even tried to cathegorize it in one place (via LeaFAQ), i decided to contribute something from my own experience.

    This time it should be an article (i dont know now, how long this post will be) about menu state machine. Additionaly, there would be some information about interfases and inheritance.

    I didnt wrote atricles for a long time. Last time it was in about 2006, about 3DGameStudio, in Russian language (some states dated 2006-2007 are mine ...Nostalgy... :) ).

    Healthy critic is wellcome (even about grammar mistakes), as this is my first article in English.

     

     

    The main idea was taken from Irrlicht forum, when i made a game prototype for Gameloft content. So, lets rock!

     

    1. We have inerface - the abstract class, that can't be instanced. Our game states we will be inherited from this interface.

    // IGameStates.h
    
    interface IGameStates { 
    public: 
    	string name;
    
    	virtual void Activate()=0; 
    	virtual void Deactivate()=0; 
    	virtual int Update(float deltaTime)=0; 	
    	virtual void Render(float deltaTime)=0; 
    
    	virtual ~IGameStates() {};
    private:		
    }; 
    

    gameStateName; is optional, for debug reasons.

    Note that function is written like "Activate()=0", that means that functions must be defined in child class or you'll get an error.

     

    1.1 Also, we should have enumeration of all our game states. Commented code will show some possible usage of this system.

    // IGameStates.h
    
    extern enum GameStatesEnum
    {
    //LogoState = 0,
    //SplashState,
    //LoadingState,
    MenuState = 0,
    GameState,
    ChatState
    };
    

    [!!!]We will call states(integer) as MenuState, and states(classes) as StateMenu, so please, be carefull.

     

    2. Next, we will make new class, which will describe game state. First one will be main menu, here we should define those interface functions

    // StateMenu.h
    
    class StateMenu : public IGameStates
    {
    public:
    StateMenu(void);
    virtual ~StateMenu(void);
    
    // IGameStates
    virtual void Activate(); 
    virtual void Deactivate();
    virtual int Update(float deltaTime);
    virtual void Render(float deltaTime); 
    ***
    }
    

     

    2.1. Activate() describes activation of certain state (of cource, you can add Initialize() and call this only first time to load all resourses). In my case it will be

    // StateMenu.cpp
    
    void StateMenu::Activate()
    {
    _isLoginChatPressed = false;
    _isLoginGamePressed = false;
    _isQuitPressed = false;
    ****
    }
    

    DeactivateState(), obviously, describes deactivation of that state.

     

    Theese both functions will be called each time when game state would be changed to MenuState.

     

    2.2. UpdateState() is one of the most interesting parts. As you may notice, it returns int.

    [!!!] The main feature: in the main loop we will call this update function and we will check result. If state is the same (user didnt do anything), it should returns its own state. If not - it whould returns next state. I'll explain this little later, while describing main loop.

    // StateMenu.cpp
    
    int StateMenu::Update(float deltaTime)
    {
    SingletonOisManager.Update();
    
    if (_isLoginChatPressed)
    {
    	return ChatState;
    }
    if (_isLoginGamePressed)
    {
    	return GameState;
    }
    if (_isQuitPressed)
    {
    	SingletonGameManager.SetQuit(true);
    }
    
    return MenuState;
    }
    

    So, if player set one of this flags to "true", Update function will return ID of new state.

     

    RenderState() is just a simple render of menu of 3d world.

    //StateMenu.cpp
    
    void StateMenu::Render(float deltaTime)
    {
    SingletonGuiManager.Render(deltaTime); 
    Flip(1); // 1 = 60, 0 = unlimited
    }
    

     

    3. StateGame is the same, but it renders whole world, instead of Gui. StateChat is UI for testing network.

     

    4. In the header of our GameManager class (class, which contains main loop) we should make a container for all states.

    // GameManager.h
    
    IGameStates* _activeState;
    vector <IGameStates*> _listOfStates;
    int _stateReturns;
    int _previousStateReturns;
    

    Note, that vector holds IGameStates*, the parent of StateGame, StateChat, StateMenu and so on.

     

    5.1 In the body of our GameManager class, we should create and store all our states to vector

    // GameManager.cpp
    
    _listOfStates.push_back(new StateMenu());
    _listOfStates.push_back(new StateGame());
    _listOfStates.push_back(new StateChat());
    

    Now, we should select, which state will be the first.

    [!!!] Note, this is perfect for development: if you wish to work on your menu, you just set first state to load from. If you want to work on your game, you set game state. If you want to show it to your girlfriend (including splashscreen), you set splashscreen first, the next will be menu, and so on :).

    After that, we should activate selected state and run it for the first time.

    // GameManager.cpp
    
    	_activeState = _listOfStates.at(0); 
    	_activeState->Activate();
    	_stateReturns = _activeState->Update(0); // if you'll set here 0, you'll get StateMenu, if 1 - ypu'll get StateGame and so on
    	_previousStateReturns = _stateReturns;
    

     

    5.2 Main loop

    Its simple. Really :)

    // GameManager.cpp
    // Main loop
    
    		float CurrentTime = AppTime();
    		_deltaTime = (CurrentTime - _elapsedTime) * 0.001f; //1
    		_elapsedTime = CurrentTime;
    
    		_stateReturns = _activeState->Update(_deltaTime); //2
    
    		_activeState->Render(_deltaTime); //3
    
    		if (_stateReturns != _previousStateReturns) {  // 4
    			_previousStateReturns = _stateReturns;
    			_activeState->Deactivate();  // 5
    			_activeState = _listOfStates.at(_stateReturns); // 6
    			_activeState->Activate();  // 7
    		}		
    

     

    At first (1), we're counting deltatime.

    Next (2), we run UpdateState() and save results. Result can be the same state or new one.

    Then (3) we Render current state.

    Last step: we check (4) the result of UpdateState() with current state. If they are equal - its okay. If they are not equal, we should Deactivate current state(5), set new state (6) and activate it(7)!

    The loop is over, and it waits for new state changes.

     

     

     

     

     

    PS: if you'll ask me, how i set _isLoginChatPressed in StateMenu::UpdateState(), i'll answer that i'm also using event system, where each entity can be subscripted for a sertain event and be rised in time. This is large article, probably i'll make another one.

    Also, i'm using imgui, which is perfect for debugging, as its code-driven UI.

    void StateMenu::RenderGuiEvent( float gameLoopTime )
    {
    imguiBeginScrollArea("Main Menu",
    400, 250, 200, 200, &_debugScroll); 
    
    _isLoginChatPressed = imguiButton("Login to chat",true);
    _isLoginGamePressed = imguiButton("Login to play",true);
    _isQuitPressed = imguiButton("Quit",true);	
    
    imguiEndScrollArea();	
    }
    

     

    PPS: GameManager contains "Manager" on its end because its singleton.

     

    PPPS: "We will call states(integer) as MenuState, and states(classes) as StateMenu, so be carefull."

    This can disappoint for the first time, but believe me, its really simple.

×
×
  • Create New...