🔒 Locked
Derived classes (inheritance)
Advertisement
Original Post
I think this is the right place for this post... Here goes:
I''m working on the collision detection for my game, now each objects within the game is derived from the class ke_GameObject (which stores position, AABB info, scene model info, etc, etc). The game I''m making is a simple shooter, spaceship shoots spaceship, kinda thing. The main types of Objects in the game would be weaponfire and ships (and walls, obstacles, etc). When a new derived object is created, it pushes and instance of the gameobject base to a std::list which is used by the collision detection, movement update, etc routines. When I come to actually do my collision detection I can get the gameobject pointer of the two colliding objects, but is there any way to find out the actual object (ship/weaponfire) that the gameobject is the basis for?
or would I have to store lists of each of these types of objects and check them in the game code itself (eg: ship vs ship // ship vs weapon, etc)
How do full game engines do this?
Look up "double dispatch". It basically works like this:
typedef std::list< X * > ObjList;
ObjList Objects;
struct X
{
virtual void Collided( X * px ) = 0;
virtual void Collided( A * pa ) = 0;
virtual void Collided( B * pb ) = 0;
};
struct A : public X
{
virtual void Collided( X * px ) { px->Collided( this ); }
virtual void Collided( A * pa ) { CollidedAA( this, pa ); }
virtual void Collided( B * pb ) { CollidedAB( this, pb ); }
};
struct B : public X
{
virtual void Collided( X * px ) { px->Collided( this ); }
virtual void Collided( A * pa ) { CollidedAB( pa, this ); }
virtual void Collided( B * pb ) { CollidedBB( this, pb ); }
};
void CollidedAA( A * pa1, A * pa2 ) { ... }
void CollidedAB( A * pa, B * pb ) { ... }
void CollidedBB( B * pb1, B * pb2 ) { ... }
void CheckCollisions()
{
for ( ObjList::iterator ppObj1 = Objects.begin(); ppObj1 != Objects.end(); ++ppObj1 )
{
ObjList::iterator ppObj2 = ppObj1;
while ( ++ppObj2 != Objects.end() )
{
if ( (*ppObj1)->Collided( *ppObj2 ) )
{
// do collision stuff
}
}
}
}
nullstate, casting should always be the last suggestion, never the first.
What I''ve done in the past is include a file with an enum of the game''s various object types. Then each object has a member variable to represent its type. Each derived class''s constructor sets the type variable to the approproate type. The base object class just needs a function to access the type variable. This may not be a proper way to do it but it works for me.
nullstate: Yeah, I looked into casting, but I realised it could be dangerous
JohnBolton: Thanks, I''ll have a look into the double dispatch (google here I come!) I think I understand what your code is telling me, I''ll give it a shot.
pi_equals_3: Yes, this was my other thought and indeed it would work for this project - but in the future i''m attempting to build an engine that will handle all types of collisions, independant on the ''client'' game. I don''t think this would work for that, hence my post here.
I''ve already learnt so much in developing this game engine, I was hoping to use it as a base for future games too, but I figure I''m going to have to rewrite it to accomplish this! Now I guess I understand the genius of the Carmack iD crew!
JohnBolton: Thanks, I''ll have a look into the double dispatch (google here I come!) I think I understand what your code is telling me, I''ll give it a shot.
pi_equals_3: Yes, this was my other thought and indeed it would work for this project - but in the future i''m attempting to build an engine that will handle all types of collisions, independant on the ''client'' game. I don''t think this would work for that, hence my post here.
I''ve already learnt so much in developing this game engine, I was hoping to use it as a base for future games too, but I figure I''m going to have to rewrite it to accomplish this! Now I guess I understand the genius of the Carmack iD crew!
I believe that the method above is the fastest method, but there is a big drawback:
Everytime you add a new collidable class, you must add additional collision functions to all collidable classes. That is serious a problem in an engine where the user can create his own collidable objects.
A dynamic alternative is to build a map of collision functors indexed by a pair of objects types. Then for each collision check, look up the functor corresponding to the two object types and call it.
The drawback to using switch statements is this: it is hard-coded like the double dispatch and slower. If you have a large number of collidable types, then the switch statement method is also slower than the map method.
Everytime you add a new collidable class, you must add additional collision functions to all collidable classes. That is serious a problem in an engine where the user can create his own collidable objects.
A dynamic alternative is to build a map of collision functors indexed by a pair of objects types. Then for each collision check, look up the functor corresponding to the two object types and call it.
The drawback to using switch statements is this: it is hard-coded like the double dispatch and slower. If you have a large number of collidable types, then the switch statement method is also slower than the map method.
quote:
Original post by JohnBolton
A dynamic alternative is to build a map of collision functors indexed by a pair of objects types. Then for each collision check, look up the functor corresponding to the two object types and call it.
Yes, and I''m examining the concept of functors now. As I say, I could quite easily code these sort of functions for this particular game using the switch mehods, but it''d not be as good as other methods available.
I''ll examine the map of functors idea. I *think* I understand the basics of this, but I''ll have to read stuff to be sure.
Attempted various solutions of this and I must admit, I''m completely stuck.
I think what I''ll do (for now) is work within the context of this game and use John''s original ideas as a basis. Maybe when I get more confident and learn more, I''d be able to create all that functor nonsense, heh. Unless someone has a cast-iron example, I''ll carry on with this.
Thanks
I think what I''ll do (for now) is work within the context of this game and use John''s original ideas as a basis. Maybe when I get more confident and learn more, I''d be able to create all that functor nonsense, heh. Unless someone has a cast-iron example, I''ll carry on with this.
Thanks
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement