Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Collision detection and multiple inheritence

This thread is locked; no one can reply to it. rss feed Print
Collision detection and multiple inheritence
23yrold3yrold
Member #1,134
March 2001
avatar

Okay.

Here's the deal; some objects in my game have different manners for detecting collision than others. Right now everything's a bounding box, but for the next iteration of this game engine I need 3D. I might throw in bounding spheres later too, but anyway. Now, here's an idea of my current class hierarchy:

   BaseClass
   |----------------------------->GameEntity
   |                              |-->Player
   |--->GamePlatform              |-->Enemy
   |    |-->SpritePlatform            |-->EnemyType1
   |    |-->3DVectorBasedPlatform     |-->EnemyType2
   |    |-->Tilemap                   |-->etc.
   |
   |-->ParticleSystem
   |-->etc.

Now some of these objects (like SpritePlatforms, some enemies and particles, and maybe the player) can and are represented by sprites using my 2D animation class, which carries the bounding box data with it. This 2D animation storage is currently built into the base class. Some of the objects I would like to represent using 3D polygons and rotatable bounding polys, which I can't do right now.

Here's a system I thought of: remove the animation system from BaseClass. In fact, remove all the graphics and collision handling code from all those objects! Mua ha ha ha ha ha! In its place, I would create (in this case) two classes for handling this stuff; one would be a C2DObject with the current sprites and boxes, and the other would be a C3DObject with 3D model and animation data, and whatever I decide is a good method for checking collision detection. Obviously, 2D objects can collide with 3D ones (this being a 2D game engine, that's easy :)).

So now here's the wild idea; I would declare some of those classes above in this manner now:

   class SpritePlatform: public Platform, public C2DObject
   class VectorBasedPlatform: public Platform, public C3DObject
   class EnemyType1: public GameEntity, public C2DObject
   class EnemyType2: public GameEntity, public C3DObject

And now, when two objects get in each other's personal elbow space, the game can check the object type and call the correct collision detection code. In fact, I may have to check this since I've never done it, but I could probably just make some overloaded collision functions that take pointers to C2DObject's and C3DObject's, and then just call those functions with wild abandon since the right function would get called by the object's type! I'm giddy just thinking of it!

Any thoughts? Just brainstorming here, but it sounds pretty solid to me ...

EDIT: C'mon, relevant posts >_< I'm trying to keep this forum alive, dammit ... we can go OT around post 50, I promise ...

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Thomas Fjellstrom
Member #476
June 2000
avatar

I thought basing you layout on one main "base" class was a no-no... Well, what do I know.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

damage
Member #3,438
April 2003

Nice ascii graphics there. Leaves Visio for dead ;)

I actually developed a sector-map template which uses nifty template stuff to make collision detection generic . It's probably not the best choice for a platformer, but I'm hoping to use it in a 2D strategy game one day.

but I could probably just make some overloaded collision functions that take pointers to C2DObject's and C3DObject's, and then just call those functions with wild abandon since the right function would get called by the object's type!

Unfortunately, overloaded functions don't work that way. Overloaded functions are resolved at compile-time, so they don't perform run-time type checking. There's no elegant (read: symmetric) way to do collision detection really.

But a new idea in C++ (but an old idea in other languages) is "multimethods" which are like virtual functions but they are related to two or more classes instead of just one. Collision detection is a perfect application for them, realy.

____
Don't have anything private. Don't do anything silly like having a hidden name and address field with get_name and set_address and get_name and set_name functions. - Bjarne Stroustrop, creator of C++

X-G
Member #856
December 2000
avatar

I'm thinking more along the lines of aggregating bounding box types ...

You could implement something like a bounding box handler with a base class and two children; one for 2D collision and one for 3D collision. Make it like a functor if you want. Then keep a pointer in a base class like CCollidable and some handy functions for setting the collision type. Would allow for fast and easy switching between collision types without cluttering it up with extra classes you can't multiple-inherit from ... plus you could easily have box detection for some enemies, and then quickly change to pixel-based without having to mess with all the classes - just change the collision type to C2DPixel (or whatever you call it).

Just an idea ...

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

23yrold3yrold
Member #1,134
March 2001
avatar

The idea behind the multiple inheritence is that some enemies need this 2D functionality, and some need the 3D functionality. I can add both to the base class so all cases are covered (yuck) or I can add them to the later base classes (still not so great) or I can just make classes out of them and have whatever inherit their properties (yay!) I think it's the better idea, and it lets me call collision detection functions by type to boot.

damage: I'll look into that "multimethods" thing; someone is encouraged to post a good link if they know one ...

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

X-G
Member #856
December 2000
avatar

What about my aggregation suggestion? A pointer to a CBaseCollisionHandler in the base class doesn't do much harm ...

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

23yrold3yrold
Member #1,134
March 2001
avatar

Well if two objects have a pointer to a function for handling collision detection, which one gets called? Maybe be more specific, not sure I get you ...

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

X-G
Member #856
December 2000
avatar

Not to a function - to an object. And it shouldn't matter which one gets called - if object A and B collide, both A.collidesWith(B) and B.collidesWith(A) should be true.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

23yrold3yrold
Member #1,134
March 2001
avatar

Right now I only use one collision check. If the player punches an enemy, the enemy is informed that it has been hit and the player is informed that it has hit something. So it's not just general collision; I have Hit_By and Has_Hit functions.

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

X-G
Member #856
December 2000
avatar

But it's not really just collision detection, is it? How do you know if the enemy rushed into your fist or you actually punched it?

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

23yrold3yrold
Member #1,134
March 2001
avatar

The active "fist" bounding box is only present during the punch animation ;)

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

X-G
Member #856
December 2000
avatar

There you go - if the monster collides with something that classifies itself as such a bounding box, let it do nothing, and let that entity call GetsHit and HasHit as appropriate.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Korval
Member #1,538
September 2001
avatar

Really, C++ inhieritance is a bad idea for a generic collision system. The fundamental problem is that the collision function needs access to the private members of both objects, as well as some understanding of how to collide the two objects together.

Rather than take a C++ approach, you should take a C approach. Construct a table. For each type of collision primitive, there is both a row and a column. Each collidable object type (box, sphere, etc) is derived from the same base class; that class only implements a GetType function. Then, someone registers a collision function between two of these primitives (say, sphere and box).

When given collidable objects, all you need to do to collide them is get the types, look them up in the table, and call that function.

23yrold3yrold
Member #1,134
March 2001
avatar

The table idea already occured to me; I just didn't feel like doing that for only four possible collision scenarios :) But I can work that in; those functions can be friends. I'm going to write a little demo to see if I can get that working; thanks.

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Go to: