ActorType

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

    • Located in the Actors.h file of the source code is this excerpt:

      //TODO Boy I hope we can get rid of ActorTypes!
      enum ActorType
      {
      AT_Unknown,
      AT_Sphere,
      AT_Teapot,
      AT_TestObject,
      AT_Grid,
      AT_GenericMeshObject
      };

      The comment states a future endeavor to get rid of actor types. My question is, how do you get rid of them?

      As an example, if you are doing collision detection on objects and a player actor can collide with numerous types of actors, such as zombies, ogres, aliens, walls, doors, etc., how do you avoid the dreaded switch statement that would test for each possible case to determine what type of actor was collided with? That switch statement would become unwieldy with hundreds of different types of actors.

      What is an efficient way to eliminate actor types?
    • First off, a good way to eliminate the ActorType is by using a hash string, we use this at work and it has a ton of additional benefits

      - They can be statically hashed to reap the benefits of integer comparison
      - They can have their human readable string retrieved for things like data file construction
      - They don't need a large enumeration just to define different types

      As for your other question, generally you handle different actor types and their dynamics in components, however the specific case you mentioned with collision would generally be handled in a collision callback. Most physics API's have a callback system that allows you to specify which 'types' are registered to the callback, for instance you could register 'Sphere to Teapot' collisions with a callback that specifically handles this collision.
      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
    • Thanks for your response. I like the idea of using a hash string to eliminate enumeration/actor types.

      The collision example I gave was actually an example of something specific to my current situation which I'm trying to solve for a game I'm working on. I did some research on collision callbacks and I couldn't find a solid example of how to implement it. Are you able to provide some further insight into it whether its some code or a resource that delves into it? I need a nudge in the right direction.
    • A good code base to take a look at is the 'Chipmunk' physics library, however I can give you a decent overview

      - Actors are 'tagged' in some way, whether this is a generic tag or something specific to your collision component. Lets say tag 'A' and tag 'B'
      - You register with the callback system based on the 2 actor tags, this should ideally handle the case where 'A' is colliding with 'B' or 'B' is colliding with 'A'.
      - You will do a search through your callback container, which could be a map with a tag pair as the key, and a callback list as the value
      - Handle multiple callbacks to the same tag pair, Chipmunk doesn't let you, and this bummed me out
      - When you find a matching pair, traverse the list, calling each callback, and passing the actors as parameters

      Source Code

      1. struct CollisionCallbackKey
      2. {
      3. //Assume some constructors are here
      4. CHashString m_tagA, m_tagB;
      5. //Evaluation operator allowing for either order of the tag pair
      6. bool operator == (const CollisionCallbackKey & rhs)
      7. {
      8. return (m_tagA == rhs.m_tagA && m_tagB == rhs.m_tagB) || (m_tagA == rhs.m_tagB && m_tagB == rhs.m_tagA);
      9. }
      10. //You'll likely need more operators maybe for the map (not looking at a reference at the moment so bear with me)
      11. };
      12. typedef bool(*CollisionCallback)(ActorPtr, ActorPtr);
      13. typedef std::pair<ActorPtr, ActorPtr> CollisionPair; //We'll use this later for colliding actor pairs
      14. std::map<CollisionCallbackKey, std::list<CollisionCallback> > m_Callbacks; // This will be in your collision system somewhere
      15. void RegisterCollisionCallback(const CHashString & tagA, const CHashString & tagB, CollisionCallback pCallback)
      16. {
      17. CollisionCallbackKey key(tagA, tagB);
      18. //P.S. Do some checking here, ensure that we're not adding the same callback twice, but for brevity let's use our imagination here
      19. m_Callbacks[key].push_back(pCallback);
      20. }
      21. //Not sure how you're handling collisions, lets assume you have some sort of broadphase -> narrow phase check that pushes collisions into a list or something
      22. void ProcessCollisions()
      23. {
      24. //The list which is processed
      25. std::list<CollisionPair> collisions;
      26. //*Here*, just use you're imagination
      27. //For every collision that was determined
      28. for(auto collisionPair : collisions)
      29. {
      30. //Find the callback set for the pair
      31. auto it = m_Callbacks.find(CollisionCallbackKey(collisionPair.first->GetTag(), collisionPair.second->GetTag()));
      32. //Make sure it's good
      33. if(it != m_Callbacks.end())
      34. {
      35. //For each callback in the set
      36. for(auto callback : it.second)
      37. {
      38. //Call the callback, and pass the actors as parameters
      39. callback(collisionPair.first, collisionPair.second);
      40. }
      41. }
      42. }
      43. }
      Display All


      This is really crude, and may have some typos/syntactical stuff that you'd need to sort out as I'm not in front of my compiler right now, but this may get you started. Take a look at Chipmunk though as well.
      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

      The post was edited 1 time, last by mholley519 ().

    • I'm right at the edge of grasping this. What you posted helped tremendously. There is one last area where I'm still in the dark on, the actual callback:

      callback(collisionPair.first, collisionPair.second);

      How is the actual logic of the interaction between the two objects handled? If you have the player colliding with a zombie and he should be knocked back and lose some health, where is that handled? Is that in the callback itself? I'm confused on what the actual CallBack method and CollisionCallback class does/looks like.
    • Source Code

      1. typedef bool(*CollisionCallback)(ActorPtr, ActorPtr);


      This is a typedef for a function pointer so if you did

      Source Code

      1. bool PlayerToZombieCollision(ActorPtr pPlayer, ActorPtr pZombie)
      2. {
      3. pPlayer->KnockBack();
      4. float nDamage = 10.0f; //Magic Number
      5. pPlayer->TakeDamage(nDamage );
      6. pZombie->EatFlesh(nDamage);
      7. }
      8. static CHashString s_playerHash = CHashString("Player");
      9. static CHashString s_zombieHash = CHashString("Zombie");
      10. RegisterCollisionCallback(s_playerHash, s_zombieHash, &PlayerToZombieCollision);
      Display All

      This would register the function 'PlayerToZombieCollision' using the pointer to the function.
      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

      The post was edited 1 time, last by mholley519 ().

    • No problem.
      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