I believe I've found an official Answer to my Problem (Object Factories)

This is a discussion on I believe I've found an official Answer to my Problem (Object Factories) within the Game Programming forums, part of the General Programming Boards category; Ah, I see Bubba, thats how I thought you meant it (after rereading it a few times). Of course besides ...

  1. #46
    Dae
    Dae is offline
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Ah, I see Bubba, thats how I thought you meant it (after rereading it a few times). Of course besides the specific game programming lingo, that I haven't learned yet. Your system definetly seems efficient. I'd love to make a newb version of it, haha, too bad I won't be able to impliment anything of the sort until I learn more about the specific game programming part.

    Thanks for the help of course, anything I can get.

    I'll continue following your work, I think this is the forth topic you've shared insight on your engine.
    Last edited by Dae; 12-18-2005 at 05:59 AM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  2. #47
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,590
    Well my 'engine' so to speak is not anywhere close to this. This is my design philosophy. The engine died a horrible defrag death - so I'm recoding it. I did recover a lot of my lost files from my dev team but it will need some re-work.

    The engine for the Zelda remake we are doing is the same engine I used in XSpace. Starting over in XSpace allows me to implement this design from the word go. This will speed up development and plus the new blender version exports into X file format. Quite nice. Now to learn blender, which doesn't look fun. Perhaps some modellers are in order here.

    Also going to rewrite the DX sound engine to use DirectSound instead of DirectMusic. Did some more research and seems DSound has more to offer. It is possible to get DSound from DMusic so I will prob go that route. My music system unfortunately died in the defrag as did my animation system so I must start over. The music system is fairly simple and the animation is well a pain in the arse but I'll get it.

    I'm learning just as you guys are. It's threads like this that helped me.
    Very good thread.

  3. #48
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    Message-based systems are very interesting, but they can cause problems when you try to track what's going on in the game. And unless your message system is good, it can lead to very ugly and unmaintainable code. (I would, for example, consider Win32 messages quite ugly.) Nevertheless, the decoupling it offers is a great advantage.
    Messages also allow very interesting effects. For example, pressing the move forward key in some games might not directly make your character move, it might send the game server a request to move forward. This game server might be on a remote machine, or in-process - many games, like Quake 3 or Diablo 2, realize single-player games by launching a local multiplayer server. The game server then sends a move message back to the client, which makes your character move.
    One visible effect of this is phantom hits in Diablo 2. The server and client, although running in the same process, are effectively independent. Now, in multiplayer the server might be on a remote computer, and messages might be delayed. For this reason, Diablo calculates many things, in particular projectile hit testing, twice - once on the server for the game mechanics, and once on the client for graphics. Sometimes the two disagree. When that happens, you can see monsters die from your fireball, but the fireball itself flies on. This can even happen in single player, because server and client are still separate.
    Nevertheless, it's a nice example of message passing. The physics engine on the server makes the fireball move, and tests intersections with monsters. When they intersect, it does damage, potentially sending kill messages. These messages reach the client, and you see monsters die apparently without having been hit.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  4. #49
    Dae
    Dae is offline
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Hmm, Bubba,

    Theres just two things I don't understand:

    1) How do you have something tracking all the game objects when subclasses are different? If you were using a map you'd have to use Object*, which is the base class and you lose methods specific to the subclass. Are you keeping track of just Object* and then using a virtual method (thats doubtful) to send commands to which would reach the subclass, where a huge switch statement would be? I doubt that because you said Object->Fire();, which means you have access to specific subclass methods. So are you keeping track of every subclass in its own map or such? but wouldn't that be quite hard considering youd need to add a map for every new subclass, and find a way to organize their id's correctly to boot.

    2) How do you get a return value from a system message to that command scope from Object (that might be needed)? MessageSys->SendMessageToObject(MSG_FIRE,Object,TargetObjec t)

    I like the idea, definetly. I'm still unsure about how to go about it though so I'll stick with the basics for now, but as soon as I can I'll attempt a message system.
    Last edited by Dae; 12-18-2005 at 03:13 PM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  5. #50
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    ad 1) Plain Object*. (Although in his system, it's something similar but not identical.) His system is constructed in a way that he doesn't need to access the subclasses' methods. It's in the messages. And there's no need for a switch statement either - what would that do?

    ad 2) You don't. If there's a response, the target of the message will in turn send a message back.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  6. #51
    Dae
    Dae is offline
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by CornedBee
    ad 1) Plain Object*. (Although in his system, it's something similar but not identical.) His system is constructed in a way that he doesn't need to access the subclasses' methods. It's in the messages. And there's no need for a switch statement either - what would that do?

    ad 2) You don't. If there's a response, the target of the message will in turn send a message back.
    In his example he used the method Fire(), which would be a subclass method, eh? Also hes going to need to access subclasses eventually, and if everythings based on ID then I dont see any other choice than storing the entire subclass to be accessed (no upcasting to Object*).

    What if in if(Mouse.Pressed(Controls.dwFire)) theres a few messages to send. The first sends something, the second is based the result of the previous, and the third is based off the previous. You'd need that message to be immediate because the next message depends on the results, and to be sent to the middle of that if statement (aka. something returned).

    EDIT: I assumed MSG_FIRE is an ID to a command Object is to perform on TargetObject, and Object and TargetObject are IDs to their corresponding objects. You said it then processes what the command is... how do you do that other than a switch/if?

    Another thing I don't get is what if the messages are more complex than just 3 parameters.. overload a ton of message abilities?
    Last edited by Dae; 12-18-2005 at 05:27 PM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  7. #52
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,590
    Well at the base level it is a switch. This may seem odd but it will end up looking like a MsgProc in Win32 programming. But when you get it working you can implement other things like multi-player, GUI, etc, quite easily. Just add more messages.

    The message system needs to be robust. In fact you should create a RegisterClass function that actually registers the object with the system. The system then contains a pointer to the message function in the class. You must use a functor for this which is annoying, but you can get it to work. This way all Objects can receive messages and you know where they are going to receive it at. As well each Object will have a message queue so that messages can be pumped and/or retrieved/sent to other objects, etc, etc.

    You can use inheritance to derive from Object. Object would contain the default function for handling common messages. However there are other ways to do this. In my theory, the default handler is inside of CMessageSystem and each message is a class in itself. So you have this:

    CMessageSystem
    --CMessageRouter -> sends/receives CMessage(s)
    --CMessageHandler -> default handler class for default behavior on messages

    CMessage

    What needs to be sorted out is that if the class does not re-define a message handler for the message, I need to auto-call the default handler. I haven't quite figured out how to do this w/o having a lot of macro crap.
    Last edited by VirtualAce; 12-18-2005 at 05:49 PM.

  8. #53
    Dae
    Dae is offline
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Hmm, Object would contain the default function for handling common messages. Wouldn't that be the switch of some sort? or some type of lookup. Wouldn't there have to be some virtual function somewhere in order to access subclasses methods because you're storing Object*'s?

    Sounds like one hell of a tied up framework. Too bad I'm not even doing multiplayer so I can't take advantage of all its features.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  9. #54
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964
    Quote Originally Posted by Dae
    Hmm, Object would contain the default function for handling common messages.

    I'd say that would be more of an "Update" function, in my case Dae...
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  10. #55
    Dae
    Dae is offline
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Yes, well, that would be a virtual method. Theres 2 reasons why that doesn't make sense. 1) Bubba's against virtual methods and hasnt said it was virtual when I mentioned it. 2) If it is virtual then the handling would be done in the subclass too (because you'd have to have a method in the subclass (Update) to call those subclass methods based on the parameter), but Bubba said the handling was done in the base class.

    But without it being virtual, I don't see how you're using Object*'s and calling methods of the subclasses from the base class. Thats the most confusing part.

    EDIT: I have another question, if you're working off all ID's, then wouldn't retrieving the instances to use all the time from a map be O(log n) instead of O(1), and wouldnt that be a lot of calls? Or is that not an issue in a network game.
    Last edited by Dae; 12-18-2005 at 09:14 PM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  11. #56
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,590
    You only retrieve IDs when needed.

    Code:
    DWORD dwNeededID=ObjectContainer[x].dwID;
    DWORD dwCacheID=0;
    
    
    if (m_dwCurTexID!=dwNeededID)
    {
      bool InCache=TextureCache.IsInCache(dwNeededID,&dwCacheID);
      if (!InCache)
      {
        //Cache miss
        Device->SetTexture(0,TextureContainer[dwNeededID]);
        m_dwCurTexID=dwNeededID;
        TextureCache.PutInCache(dwNeededID);
      }
      else
      {
         //Cache hit
         Device->SetTexture(0,TextureContainer[dwCacheID]);
         RendererCache.Update();
         m_dwCurTexID=dwCacheID;
      }
    
    }
    I'm afraid I don't understand why you are not understanding how this works.
    Last edited by VirtualAce; 12-18-2005 at 11:21 PM.

  12. #57
    Dae
    Dae is offline
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    I understand how that works. You're passing around the ID. I see now how you're using it, that the search wouldn't be necessary.

    The only thing I'm still unclear on is your messaging system. You are sending the Object commands, which are handled in the base class Object. Now you said it would use something along the lines of a switch to resolve the command. Now if SHOOT_FIRE is the command, which is part of the subclass Sorcerer, how do you call that function when you're using a container of Objects? You'd have to make the handler in Object virtual, and overwrite that handler in the subclass Sorcerer to add more command handling specific to Sorcerer (probably calling Object's handler first to see if it can handle it). Is that wrong? does it have more to do with the functor thats giving you the ability to call subclass methods?

    Sorry for bothering you, but I just couldn't figure out how that part worked. I did try to make some pseudo code before I posted though.
    Last edited by Dae; 12-19-2005 at 12:54 AM. Reason: understanding more now..
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  13. #58
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,590
    To give you an idea of how this ID stuff works I'll show you my animation class system.

    Note this class is for Windows GDI. DirectX would look just a tad different.

    CAnimSystem.h
    Code:
    #ifndef CANIMSYSTEM
    #define CANIMSYSTEM
    
    
    #include "CTileSystem.h"
    
    
    class CAnimSequence;
    
    class CAnimFrame
    {
      friend class CAnimSequence;
      DWORD m_dwTileID;
      float m_fFrameDuration;
      CPoint m_XYOffsets;
    
    
      public:
        CAnimFrame(void):m_dwTileID(0),m_fFrameDuration(0.0f),
                         m_XYOffsets(0,0) {}
    
        void Create(DWORD dwID,float fFrameDuration,CPoint XYOffsets)
        {
          m_dwTileID=dwID;
          m_fFrameDuration=fFrameDuration;
          m_XYOffsets=XYOffsets;
        }
    
        
    
    };
    
    class CAnimSequence
    {
      std::vector<CAnimFrame *> AnimFrames;
    
      CPoint m_Position;
      DWORD m_dwCurFrame;
      float m_fAccumTime;
    
      CTileManager *m_pTileManager;
      bool m_bLooping;
      
      public:
        CAnimSequence(void):m_dwCurFrame(0),m_Position(0,0),m_bLooping(false),
                            m_fAccumTime(0.0f) {}
    
        virtual ~CAnimSequence(void)
        {
          AnimFrames.clear();
        }
    
        void Create(CPoint pos,CTileManager *ptrTileManager,bool bLooping=true)
        {
          m_Position.x=pos.x;
          m_Position.y=pos.y;
          m_dwCurFrame=0;
          m_pTileManager=ptrTileManager;
          m_bLooping=bLooping;
          m_fAccumTime=0.0f;
          
        }
    
        void AddFrame(DWORD dwID,float fFrameDuration,CPoint XYOffsets)
        {
          CAnimFrame *frame=new CAnimFrame();
          frame->Create(dwID,fFrameDuration,XYOffsets);
    
          AnimFrames.push_back(frame);
        }
    
        void SetFrameData(DWORD dwID,float fFrameDuration,CPoint XYOffsets)
        {
          if (dwID<AnimFrames.size())
          {
            AnimFrames[dwID]->m_fFrameDuration=fFrameDuration;
            AnimFrames[dwID]->m_XYOffsets=XYOffsets;
          }
        }
    
        void Reset(void) {m_dwCurFrame=0,m_fAccumTime=0.0f;}
        void Update(float fTimeDelta);
        void Draw(CDC *pDC,int iScrollX=0,int iScrollY=0);
    
    };
    
    
    class CAnimSequenceContainer
    {
      std::vector<CAnimSequence *> AnimSeqs;
    
    public:
      CAnimSequenceContainer(void) {}
      virtual ~CAnimSequenceContainer(void)
      {
        AnimSeqs.clear();
      }
    
      void AddSeq(CAnimSequence *ptrSeq)
      {
        AnimSeqs.push_back(ptrSeq);
    
      }
    
      void Update(float fTimeDelta)
      {
        for (DWORD i=0;i<AnimSeqs.size();i++)
        {
          AnimSeqs[i]->Update(fTimeDelta);
        }
      }
    
      void Draw(CDC *pDC,int iScrollX=0,int iScrollY=0)
      {
        for (DWORD i=0;i<AnimSeqs.size();i++)
        {
          AnimSeqs[i]->Draw(pDC,iScrollX,iScrollY);
        }
      }
    
    };
    
    
    #endif
    CAnimSystem.cpp
    Code:
    #include <stdafx.h>
    #include "CAnimSystem.h"
    #include "MainFrm.h"
    #include "ZeldaEditorView.h"
    
    
    
    void CAnimSequence::Update(float fTimeDelta)
    {
      m_fAccumTime+=fTimeDelta;
    
      if (m_fAccumTime>=AnimFrames[m_dwCurFrame]->m_fFrameDuration)
      {
        m_fAccumTime=0.0f;
        m_dwCurFrame++;
        if (m_dwCurFrame>AnimFrames.size())
        {
          m_dwCurFrame=0;
          m_fAccumTime=0.0f;
        }
      }
    }
    
    void CAnimSequence::Draw(CDC *pDC,int iScrollX,int iScrollY)
    {
      //Draw to pDC with TileDC
    
      if (AnimFrames.size()>0)
      {
        CRect rect;
        CMainFrame *ptrFrame=(CMainFrame *)AfxGetMainWnd();
        CZeldaEditorView *ptrView=(CZeldaEditorView *)ptrFrame->GetActiveView();
        ptrView->m_wndTileRenderer.GetClientRect(&rect);
    
        DWORD m_dwTileID=AnimFrames[m_dwCurFrame]->m_dwTileID;
        CDC *TileDC=m_pTileManager->GetDC(m_dwTileID);
    
        int ScreenX=m_Position.x+AnimFrames[m_dwCurFrame]->m_XYOffsets.x;
        int ScreenY=m_Position.y+AnimFrames[m_dwCurFrame]->m_XYOffsets.y;
    
        m_Position.x=ScreenX;
        m_Position.y=ScreenY;
    
        ScreenX+=iScrollX;
        ScreenY+=iScrollY;
    
        if (ScreenX>rect.left && ScreenX<rect.right && ScreenY>rect.top &&
          ScreenY<rect.bottom)
        {
          pDC->BitBlt(ScreenX,ScreenY,
                      ptrView->m_wndTileRenderer.m_RenderInfo.dwViewTileSize,
                      ptrView->m_wndTileRenderer.m_RenderInfo.dwViewTileSize,
                      TileDC,
                      0,0,
                      SRCCOPY);
        }
      }
    }

  14. #59
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,590
    And to answer the questions of monster problems.

    This would be much better:

    Code:
    enum Modes  
    {
      SET_X=0x01,
      SET_Y=0x02,
      SET_HEALTH=0x04;
      SET_STAMINA=0x08;
    };
    
    
    struct MonsterAttributes
    {
      int iPosx;
      int iPosy;
      int iHealth;
      int iStamina;
     
    };
    
    class Monster
    {
      DWORD m_dwID;
      MonsterAttributes MonsterInfo;
    
      Monster(void);
      Monster(const MonsterAttributes m);
      Monster(const Monster &m);
      virtual ~Monster(void);
      
      void SetInfo(int mode,int value)
      {
       if ((mode & Modes::SET_X)==Modes::SET_X)
       {
         MonsterInfo.iPosx=value;
       }
    
       ...
       ...
      }
     }
    };
    
    class MonsterContainer
    {
      std::vector<Monster *>  Monsters;
    
      //Cannot copy monster container
      MonsterContainer(const MonsterContainer &m) {}
      MonsterContainer &operator (const MonsterContainer &m) {}
    
      public:
        virtual ~MonsterContainer(void)
        {
           for (int i=0;i<Monsters.size();i++)
           {
              //MSVC 6 bug
              if (Monsters[i])
              {
                 delete Monsters[i];
              }
           }
    
        }
        DWORD Add(MonsterAttributes &attr)
        {
           Monster *m=new Monster(attr);
           Monsters.push_back(&m);
           return Monsters.size()-1;
        }
      
        bool Remove(DWORD dwID);
        void Update(void);
        ...
    
    };
    There really is no need to derive from Monster.
    Last edited by VirtualAce; 12-19-2005 at 06:10 AM.

  15. #60
    Dae
    Dae is offline
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Ohhh I see now. The containers do their own thing with the IDs, but the IDs match up to the ID returned from your monster container?

    What I thought was going on was you had an Object Container and were using that to get your object instances based on ID and then worked with those (originally I assumed a map). So what do you do if you want to add extra functionality to a Monster? For instance FireBall(), when not all Monsters should have that method? Just add every method to Monster? Or add some scripting/retrieve from file system that CornedBee was talking about and Diablo?

    That makes a lot more sense now at least. I was trying to get some psuedo c++ code (obviously bubbeudo), but I found if I was retrieving Object's from an ObjectSystem then there would be no use for a functor (because I could just call it from the object), therefor a map (in MessageSystem) either, so that didn't match up with what you were saying.

    Would inheriting from MessageSystem solve the problem to have them use the default handler unless defined? might be kind of illogical though.

    This is some of the bubbeudo I got from your posts, without all the bells and whistles, in order to try and grasp the message system (I think I failed):

    Code:
    #include <iostream>
    #include <vector>
    
    #include "windows.h"
    
    struct ObjectInfo;
    class Object;
    class ObjectContainer;
    class Message;
    class MessageSystem;
    
    class Message
    {
    public:
        std::vector<DWORD> ObjectIDs;
        std::vector<DWORD> CommandIDs;
    };
    
    struct ObjectInfo
    {
        DWORD dwStartIndex;
        DWORD dwEndIndex;
        DWORD dwID;
        DWORD *dwTextureIDs;
    };
    
    class Object
    {
    private:
        ObjectInfo ObjectData;
    
    public:
        //queue and such here
    
        void RecieveMessage(Message* p_Message)
        {
            HandleMessage(p_Message);
        }
    
        //enum commands { FIRE, ICE, LIGHTNING }
    
        void HandleMessage(Message* p_Message)
        {
            //handle all commands in the message
            for(int i = 0; i < p_Message->CommandIDs.size(); ++i) {
                switch(p_Message->CommandIDs[i]) {
                    case 1: Fire(p_Message->ObjectIDs[i]);
                    break;
                    case 2: Ice(p_Message->ObjectIDs[i]);
                    break;
                    case 3: Lightning(p_Message->ObjectIDs[i]);
                    break;
                }
            }
        }
    
        void Fire(DWORD dwID) { std::cout << "Fire! on " << dwID << std::endl; }
        void Ice(DWORD dwID) { std::cout << "Ice! on " << dwID << std::endl; }
        void Lightning(DWORD dwID) { std::cout << "Lightning! on " << dwID << std::endl; }
    
        DWORD GetID(void) { return ObjectData.dwID; }
        void SetID(DWORD dwID) { ObjectData.dwID = dwID; }
    };
    
    class ObjectContainer
    {
        std::vector<Object*> m_Objects;
    
        static ObjectContainer* m_Instance;
    
    public:
        Object* GetObject(DWORD dwID)
        {
            return m_Objects[dwID];
        }
    
        DWORD Add(void)
        {
            Object* Obj = new Object();
            Obj->SetID(m_Objects.size()-1);
            m_Objects.push_back(Obj);
    
            return m_Objects.size()-1;
        }
    
        bool Remove(DWORD dwID)
        {
            delete m_Objects[dwID];
        }
    
        static ObjectContainer* Instance(void)
        {
            if(!m_Instance) {
                m_Instance = new ObjectContainer;
            }
    
            return m_Instance;
        }
    };
    
    ObjectContainer* ObjectContainer::m_Instance = 0;
    
    class MessageSystem
    {
    private:
        //std::vector<DWORD> m_Registered;
        static MessageSystem* m_Instance;
    
    public:
        void RegisterObject(DWORD dwID)
        {
            //
        }
    
        void SendMessageToObject(Message* p_Message, DWORD dwID)
        {
            ObjectContainer::Instance()->GetObject(dwID)->RecieveMessage(p_Message);
        }
    
        //enum commands { DIE, STUFF }
    
        void HandleMessage(Message* p_Message)
        {
            for(int i = 0; i < p_Message->CommandIDs.size(); ++i) {
                switch(p_Message->CommandIDs[i]) {
                    case 1: //Defualt1();
                    break;
                    case 2: //Defualt2();
                    break;
                }
            }
        }
    
        static MessageSystem* Instance()
        {
            if(!m_Instance) {
                m_Instance = new MessageSystem;
            }
    
            return m_Instance;
        }
    };
    
    MessageSystem* MessageSystem::m_Instance = 0;
    
    int main()
    {
        ObjectContainer* ObjCon = ObjectContainer::Instance();
        MessageSystem* MsgSys = MessageSystem::Instance();
    
        DWORD Obj = ObjCon->Add();
    
        //MsdSys->RegisterObject(Obj);
    
        Message* Msg = new Message;
        Msg->CommandIDs.push_back(3); //Lightning Command 3
        Msg->ObjectIDs.push_back(2); //Use Command on Object 2
        Msg->CommandIDs.push_back(1); //Fire Command 1
        Msg->ObjectIDs.push_back(4); //Use Command on Object 4
    
        MsgSys->SendMessageToObject(Msg, Obj);
    
        std::cin.get();
    }
    As you can see, HandleMessage() has a switch, and thats the only way I could visualize it. Maybe its the handler that I'm ultimately unclear on. Like if you're recieving messages that use command IDs like FIRE_BALL, then wouldn't you HAVE to use a switch to resolve the function. And if you did derive from Object in my example, then you would have to make it virtual and overwrite it in the derived so it could call its new methods. See why I'm so confused? lol.

    Anyway, feel free to give up on me whenever - I won't mind. I'm having a hard time understanding because my experience with game programming is: few days; my experience in c++ is: 6 months (include vacation/school/learning flash/java).

    EDIT: Updated the bubbeudo a bit based on your last posts before I go out.

    EDIT: I'll reread all your posts and see if I can impliment some stuff and hopefully understand whats going on.
    Last edited by Dae; 12-19-2005 at 03:00 PM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

Page 4 of 5 FirstFirst 12345 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. using this as synchronization object
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 03-22-2008, 07:49 AM
  2. problem with answer going to default?
    By Patrick1234 in forum C++ Programming
    Replies: 4
    Last Post: 10-02-2002, 09:11 AM
  3. slight problem just can't see the answer
    By anthonye in forum C++ Programming
    Replies: 1
    Last Post: 07-05-2002, 08:45 AM
  4. I've ran into a problem
    By Mike Jones in forum C Programming
    Replies: 1
    Last Post: 03-27-2002, 03:08 PM
  5. code help :)
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 02-28-2002, 12:12 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21