NOGDUS $1670.00 has been donated to NOGDUS!
May 28, 2017, 08:49:19 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1]   Go Down
  Print  
Author Topic: [Addon] ProcessManager/Process Class  (Read 2205 times)
0 Members and 1 Guest are viewing this topic.
Cycl0ne
Guest
« on: April 21, 2011, 05:15:23 AM »

Ok,

I need to work in my small game with alot of "processes". And after a look of the mains in pixie (all the examples). I noticed something like this in the mainloop:
Code:
// Main game loop
while (!gameStateManager.IsExitFlagSet())
{
// Get time elapsed since last update
float deltaTime=frameTime.Update();

// Update systems
inputManager.Update();
musicManager.Update(deltaTime);
audio.Update();
gameStateManager.Update(deltaTime);
spriteControllerManager.Update(deltaTime);
spriteSystem.Update(deltaTime);
spriteSystem.Render(screen.GetBackBuffer());

Ok, so if i would like to add some other Code, which is needed to be run in the mainloop, i have to grab the main.cpp and add another line like this:
newFunction(deltaTime); to the code -> Ugly  Roll Eyes Since i allways need to recompile the main.cpp on changes.

So i thought about a ProcessManager and a class you could inherit called Process, which handles your methods dynamically (ok i didnt really thought about it myself, ive seen it in an example Smiley But I thought instantly, this is cool, its sort a design paatern and would fit perfectly in design of my game and perhaps into pixie, doing everything a bit cooler:

Code:
class CProcessManager
{
public:
        void UpdateProcesses(float deltaMilliseconds);
        bool IsProcessActive( int nType );
        void Attach( CProcess pProcess );
        bool HasProcesses();

        ~CProcessManager();

protected:
        ProcessList     ProcessList_; 

private:
        void Detach(CProcess pProcess );
};

So ProcessManager will be in the Mainloop with the method:
cPM->UpdateProcesses(deltaTime);

Which handles now all processes i want to get achieved in the mainloop. Now to the root class Process which can be now inherited:

Code:
class CProcess
{
        friend class CProcessManager;

protected:
        int                             iType_;                // type of process running
        bool                            bKill_;                // tells manager to kill and remove
        bool                            bActive_;
        bool                            bPaused_;
        bool                            bInitialUpdate_;       // initial update?
        CProcess    pNext_;
       
private:
        unsigned int    uProcessFlags_;

public:
        CProcess(int ntype, unsigned int uOrder = 0);
        virtual ~CProcess();   

public:

        bool                    IsDead(void) const { return(m_bKill);};
        virtual void    VKill();
       
        int                     GetType(void) const { return(m_iType); };
        void                    SetType(const int t) { m_iType = t; };

        bool                    IsActive(void) const { return m_bActive; };
        void                    SetActive(const bool b) { m_bActive = b; };
        bool                    IsAttached()const;
        void                    SetAttached(const bool wantAttached);

        bool                    IsPaused(void) const { return m_bPaused; };
        virtual void    VTogglePause() {m_bPaused = !m_bPaused;}
       
        bool                    IsInitialized()const { return ! m_bInitialUpdate; };

        CProcess const GetNext(void) const { return(m_pNext);}
        void                    SetNext(CProcess nnext);
       
        virtual void            VOnUpdate(const float deltaMilliseconds);
        virtual void            VOnInitialize(){};
};

Now this is easy explained. I inherit CProcess in my class and then i do the following:
myNewProcessClass *newP = new myNewProcessClass([Initsomthing i could need]);

cPM->Attach(newP);

Now, to get thing really "Cool", lets create a Waiting Process, that waits for 3000ms and then kills itself activating another process (lets say a ticking time bomb):

Code:
class CWaitProcess : public CProcess
{
protected:
        float    uStart_;
        float    uStop_;

public:
        CWaitProcess(unsigned int iNumMill );
        virtual void VOnUpdate(const float deltaMilliseconds);
};

CWaitProcess::CWaitProcess(unsigned int iNumMill ) : CProcess( PROC_WAIT, 0 ), uStart_( 0 ), uStop_( iNumMill )
{
}

void CWaitProcess::VOnUpdate( const float deltaMilliseconds )
{
        CProcess::VOnUpdate( deltaMilliseconds );

        if ( bActive_ )
        {
                uStart_ += deltaMilliseconds;
               
                if (uStart_ >= uStop_ ) VKill();
        }
}

So you initialise your WaitProcess as Follows:
CWaitProcess *wait = new CWaitProcess(3.0f); //3000ms = 3seconds, since we are working here with floats.
MyOtherProcess *other = new MyOtherProcess;
wait->SetNext(other);
cPM->Attach(wait);

And voila youre gone and your Process is run 3000ms killing itself and then the new process is started, connected with yours.

Now one could go even further and encapsulate all pixie functions into the process "thing". Audio, Interface, SpriteMoving... So a new Main could look like this:

Code:
// Main game loop
while (!gameStateManager.IsExitFlagSet())
{
// Get time elapsed since last update
float deltaTime=frameTime.Update();

// Update systems
cPM->Update(deltaTime);
spriteSystem.Render(screen.GetBackBuffer());

What do you think? Looks nicer or?
Logged
Mattias Gustavsson
Moderator
Offline Offline

Respect: 58
« Reply #1 on: April 21, 2011, 03:01:56 PM »

Now, this is an interesting topic to discuss, from several aspects :-)

First of all, as a replacement for calling Update on all the systems in the main loop, I would *not* like it  Grin  In an early predecessor to Pixie, I used to have a system where Systems/Singletons could be specified in an XML file, so you could add, remove, rearrange and configure systems without even having to rebuild the executable. And it sounds nice in theory, but in practice I didn't like it at all - it just made it more difficult to follow the flow of the code, and so for Pixie I opted to have the main loop of the game *explicitly* create and call the singleton systems - which makes it very easy to read and modify, or step through in a debugger. It is worth noting, that these systems are generally major components, so initialisation order and update order can be of great importance, and there won't be all that many of them - I tend to put most game related system into a GameSession class, which you can probably see in some of my game examples (the GameSession class is meant to be created when the player enters the actual game (not just frontend screens), and then persist throughout the game, even as you move between gamestates).

For high-level flow through the game, I like the gamestate system, which I think allows for nice flow control without being too complicated.

But, I think that for general gameplay use, a system like your processes would be quite brilliant  Grin It would allow for very nice control of the gameplay aspects, almost like a scripting system of sorts, I think - especially how you present it with the Wait process and such. I could easily see how a system like this could be set up to run several tasks simultaneously as well, so that you could have a wait state running until it triggers, but at the same time have other states running to do other things. I mean, time-sliced, not multithreaded.

I think there's definitely merit in investigating a system like this further - it could be a GREAT help in managing the complexity of the game code, which is always nice. I'm a big fan of systems where you can set things up and let them run, and then pretty much forget about them, letting them run their course.

In fact, in the currently released version of Pixie, I have a SpriteAction system (as used sparingly in BabyViking and Lowriderz), which allows for setting up sprite movements and/or fades, and then they will run until they are done, and will be cleaned up and deleted automatically. It even have support for triggering one action after another one have finished. This is obviously on a much lower level than what you're suggesting, but it's a similar type of system.

I guess you would want to use a system of processes like you described for your game? I'd be really interested to hear how that works out for you, I think there can be a lot of value in such a system - if applied to the right areas Smiley
Logged
Cycl0ne
Guest
« Reply #2 on: April 21, 2011, 06:38:56 PM »

Hmm, no i dont want to throw out your singletons. i see the processmanager also as singleton to be accessable to all code.
What my purpose on this is, to schedule processes for the game:

example: you press a button and a door has to open. the opening of the door is an animation. so things could go like this:

button pressed -> create doorframe animation process -> send to process manager and forget about it.

then you have the animation of the door with all checks (monster blocking door?) and if the animation is finished. it gets deleted form the list.

another example could be:

you walk with you character in the dungeon and run in a trap:
trap code creates a Firball Shooter Process
-> Fireball Shooter shoots Fireballs (incl. Animation of them flying towards you (perhaps?)) (also a process being created) and if the fireballs are finished.. it revives the shooter.


3rd example:
Monster Generator. It creates every 5seconds monster if not enough monster are in the dungeon

4th example:
playing music, and if this process is finished, another title is played through another new process

5th example:
netcode is being executed as a process

6th example:
audio again: Ticking bomb. first process does this "tick tick tick" and after a given time it switches the new process which makes booom Smiley

7...8...9... :-)

all done through the process manager.

What i like on this system is, that everything is encapsulated like your cool gamestate mechanism. I dont have to put code in one big class, i can create small classes and put them together as i wish..

Ohh and another process could be the user input mechanism. Create a InputProcess and fetch the users input.

ps: of yourse this is not multithreaded. It is a cooperative taskscheduler ;-) Macos 8/9 and windows 3.11 had such a system, before everyone noticed a preempitive would be better ;-) (i coded a own Operating System 10 Years ago, where i used this kind of approach Smiley
Logged
Tags:
Pages: [1]   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines
.: Theme by Richard Marks :.
Valid XHTML 1.0! Valid CSS!