Actors and Components

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Actors and Components

      Hi, I'm currently trying to build my own 3d game engine and have been using this book as a great resource. At Uni I took computer games programming and while walking away with a 2:2 in my degree, I feel like I don't know enough to have companies hire me. That's why I wanted to make a game engine and really set about learning as many different aspects as I can and then hopefully in future, make a game in the engine.

      Straight out of uni I spent time making an XNA game for XBLIG and while that did get on the marketplace it didn't make me any money.

      So enough back story, here is my problem:

      I'm looking at having an Actor that has multiple components rather than the inheriting system that I have used in my past games. For this I have been following the code that starts on page 161. Most of it seems straight forward except I am getting some errors with it in Visual Studio 2010.

      It's all to do with the StrongActorPtr and StrongActorComponentPtr. I have these declared in ActorFactory.h like this:

      typedef std::shared_ptr<Actor> StrongActorPtr;
      typedef std::shared_ptr<ActorComponent> StrongActorComponentPtr;

      I had to include the std to remove errors so I am not sure if I am on the right track with that.

      Visual studio is giving me the error of:
      Error 33 error C2065: 'Actor' : undeclared identifier ActorFactory.h 14

      In relation to:
      typedef std::shared_ptr<Actor> StrongActorPtr;

      My Actor.h file is included along with <memory>

      From this there are many other undiclared identifiers and I believe it is all stemming from these shared_ptr's.

      Another problem is the use of ComponentId in the code. I assumed that it was an unsigned long like ActorId?

      I'm hoping someone will be able to point me in the right direction with this.
    • It's hard to say with what you have provided, but I would try some different things

      - Is the 'Actor' class in a namespace? If so, you will need to use the namespace name or declare you will be using the namespace globally. ie. using namespace name;

      - Is the Actor header included before it is referenced?

      I don't think the issue is the shared pointer in this case
      as you would instead recieve the error in regards
      to shared_ptr being an undeclared identifier.

      The error could actually be multiple other things, even a misplaced '}' which is throwing off the declaration of the 'Actor' class.
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz
    • It's hard to debug this without seeing the code. Can you post the relevant sections as well as the full error list?

      -Rez
    • Thanks for the quick response.

      The first error in ActorFactory.h:
      syntax error : missing ';' before '*' ActorFactory.h
      in regards to:
      typedef ActorComponent *(*ActorComponentCreator)(void);
      It also has the error:
      missing type specifier - int assumed. Note: C++ does not support default-int ActorFactory.h

      The next line:
      typedef std::map<std::string, ActorComponentCreator> ActorComponentCreatorMap;
      has this error:
      'std::map' : 'ActorComponentCreator' is not a valid template type argument for parameter '_Ty' ActorFactory.h
      Along with:
      'ActorComponent' : redefinition; different basic types ActorComponent.h


      I don't want to just throw every single error out there but hopefully these are the start of the problem. I've also included my header files:


      ActorFactory.h:

      C Source Code

      1. #pragma once
      2. #include <memory>
      3. #include <map>
      4. #include "Actor.h"
      5. #include "ActorComponent.h"
      6. #include "tinyxml\tinyxml.h"
      7. typedef ActorComponent *(*ActorComponentCreator)(void);
      8. typedef std::map<std::string, ActorComponentCreator> ActorComponentCreatorMap;
      9. typedef unsigned long ActorId;
      10. typedef unsigned long ComponentId;
      11. typedef std::shared_ptr<Actor> StrongActorPtr;
      12. typedef std::shared_ptr<ActorComponent> StrongActorComponentPtr;
      13. class ActorFactory
      14. {
      15. ActorId m_lastActorId;
      16. protected:
      17. ActorComponentCreatorMap m_actorComponentCreators;
      18. public:
      19. ActorFactory(void);
      20. ~ActorFactory(void);
      21. StrongActorPtr CreateActor(const char* actorResource);
      22. protected:
      23. virtual StrongActorComponentPtr CreateComponent(TiXmlElement* pData);
      24. private:
      25. ActorId GetNextActorId(void) {++m_lastActorId; return m_lastActorId; }
      26. };
      Display All


      Actor.h:

      C Source Code

      1. #pragma once
      2. #include <map>
      3. #include <memory>
      4. #include "ActorFactory.h"
      5. #include "tinyxml\tinyxml.h"
      6. #include "tinyxml\tinystr.h"
      7. typedef unsigned long ActorId;
      8. typedef unsigned long ComponentId;
      9. class Actor
      10. {
      11. friend class ActorFactory;
      12. typedef std::map<ComponentId, StrongActorComponentPtr> ActorComponents;
      13. public:
      14. ActorId m_id;
      15. ActorComponents m_components;
      16. explicit Actor(ActorId id);
      17. ~Actor(void);
      18. bool Init(TiXmlElement* pData);
      19. void PostInit(void);
      20. void Destory(void);
      21. void Update();
      22. ActorId GetId(void) const { return m_id; }
      23. //Template function for retrieving components
      24. template<class ComponentType>
      25. std::weak_ptr<ComponentType> GetComponent(ComponentId id)
      26. {
      27. ActorComponents::iterator findIt = m_components.find(id);
      28. if (findIt != m_components.end())
      29. {
      30. StrongActorComponentPtr pBase(findIt->second);
      31. //cast to subclass version of the pointer
      32. std::shared_ptr<ComponentType> pSub(std::tr1::static_pointer_cast<ComponentType>(pBase));
      33. std::weak_ptr<ComponentType> pWeakSub(pSub); //Convert strong ptr to weak
      34. return pWeakSub; //Return weak ptr
      35. }
      36. else
      37. {
      38. return std::weak_ptr<ComponentType>();
      39. }
      40. }
      41. private:
      42. void AddComponent(StrongActorComponentPtr pComponent);
      43. };
      Display All


      ActorComponent.h:

      C Source Code

      1. #pragma once
      2. #include "ActorFactory.h"
      3. #include <map>
      4. #include <memory>
      5. class ActorComponent
      6. {
      7. friend class ActorFactory;
      8. protected:
      9. StrongActorPtr m_pOwner;
      10. public:
      11. virtual ~ActorComponent(void);
      12. virtual bool VInit(TiXmlElement* pData) = 0;
      13. virtual void VPostInit(void) {}
      14. virtual void VUpdate() {}
      15. virtual ComponentId VGetComponentId(void) const = 0;
      16. private:
      17. void SetOwner(StrongActorPtr pOwner) { m_pOwner = pOwner; }
      18. };
      Display All


      Thanks again.
    • I think you have a circular include issue going on here. You're including ActorComponent.h which tries to include ActorFactory.h, which tries to include ActorComponent.h, etc. You should try your best to never #include any file inside of headers. This isn't always possible, but you should get rid of as many as possible by forward-declaring stuff.

      For example, ActorComponent.h doesn't need to include ActorFactory.h at all.

      -Rez
    • Originally posted by rezination
      I think you have a circular include issue going on here. You're including ActorComponent.h which tries to include ActorFactory.h, which tries to include ActorComponent.h, etc. You should try your best to never #include any file inside of headers. This isn't always possible, but you should get rid of as many as possible by forward-declaring stuff.

      For example, ActorComponent.h doesn't need to include ActorFactory.h at all.

      -Rez


      Removing this from ActorComponent.h leaves me with errors like 'pOwner' undeclared identifier.

      Though ActorFactory seems to think that Actor is an undeclared identifier but the actor class is included before this. In relation to:
      typedef std::shared_ptr<Actor> StrongActorPtr;

      IntelliSense is saying that StrongActorPtr and ComponentId are undefined in ActorComponent.h.
    • You have to forward declare that stuff. So at the top somewhere you have:

      Source Code

      1. class Actor;


      -Rez
    • Originally posted by rezination
      You have to forward declare that stuff. So at the top somewhere you have:

      Source Code

      1. class Actor;


      -Rez


      Aha, thankyou. That set me on the right track.

      One thing I had to do though was typedef those Ptr's in each file, is there a cleaner way of doing that?

      At least now I have it compiling so I can get back to actually playing around with it.

      Thanks again!
    • You don't have to use a typedef, you can just type it all out every time you use it, but typedefs help. It keeps you from having to type out shared_ptr<ActorComponent> everywhere. It also allows you to easily change it without having to change every place that it's used. For example, I often use typedefs for IDs so that I can change the type very easily.

      -Rez