Skip to main content
gamedev.net
🔒 Locked

Derived classes (inheritance)

Started by evolutional Jul 19, 2003 at 4:45 PM 8 replies 2.1k views
Original Post
evolutional
evolutional
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?
nullstate
nullstate
hey downgraded,

If I understand your question correctly, you would probably have some luck with a dynamic cast. Just be careful of upcasting.


Good luck,
nullstate



[edited by - nullstate on July 19, 2003 7:35:32 PM]
JohnBolton
JohnBolton
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
}
}
}
}
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
JohnBolton
JohnBolton
nullstate, casting should always be the last suggestion, never the first.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
nullstate
nullstate
Gotcha JohnBolton...learn something new everyday. Oh and next time, I''ll try to post about dynamic casting AFTER "double dispatch".(JK)

By the way, does RTTI affect preformance and speed that much?


Thanks,
nullstate
pi_equals_3
pi_equals_3
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.
evolutional
evolutional
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
JohnBolton
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.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
evolutional
evolutional
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.
evolutional
evolutional
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

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.