Sign in to follow this  

2D collision and component pattern, advice needed.

This topic is 816 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys, I am currently working on a simple dummy engine to improve my programming skill and learn more about game development.

I am  implementing simple 2D collision based on bounding boxes aligned with world X and Y. 

I am building my overall structure  on components, so my game entity class has a pointer to a "move" and "render" component. Now I introduced  a bounding box structure and a 2D bounding box collision components.

I implemented it and looks working fine but I have a couple of questions about it.

First of all my components only knows about 2D bbox because that is the  one should solve, what happens if I have other shapes for collision? Like convex shapes, spheres and capsules etc. I would guess is fairly normal in a game to have to deal with different kind of collision shapes right?

 

If it so does it mean my components will also need to be able to solve different combinations and means knowing about all the kind of collisions shapes? ex : 2dbbox with circle, 2dbbox with convex polygon etc.

 

My second question is about how to organize the data  for handling the different kind of bounding boxes etc, but one step at the time, I would like to address the first question first.

 

Thanks guys!

 

PS: here what I currently have, I know looks simple but there is already a basic engine pipeline running.

 

Share this post


Link to post
Share on other sites
Yeah, this is one of the many areas that blind application of the aspect-like variant of ECS falls down. Real engines use a third-party physics library that doesn't know squat about the engine's component model and has its own copy of the object transform, velocity, etc. The components just glue the physics buddies to the object model.

If you're writing your own, I _highly_ recommend doing the same structure. Your physics code should have it's own object for bodies and shapes independent of your ECS code. You very possibly _can't_ even share things like your transform/position directly between graphics, gameplay, and physics, as physics interpolation may be in play or you might want to try multithreading.

So far as structure, don't overthink it. The simplified ECS model fad is mostly garbage peddled by clueless Reddit hobbyists anyhow. It's entirely reasonable to have a big physics_body class that has position, velocity, mass, a shape descriptor, and general data elements or a union for aabb/sphere/etc.

If your game is slow, I promise you that blindly applying data-oriented design principles isn't going to fix anything, and that your problem will be something much higher level.

Share this post


Link to post
Share on other sites

Hi thank you, for now I don't plan any kind of dynamics just simple collision for crating a platform style game.

 

Your answer is most interesting, I hope to not say a pile of crap, if I do please let me know. I am reasoning about what you said, if I have two separated structures at one point I will need to sync right? that s how I see my  update_game() loop.

 

1) update_position()

2) resolve_collision() (which will move the char back if collision happens to avoid interpenetration)

3) render()

 

so between step 1 and 2 I might need some kind of sync if they don't work on the same data?

Anyway I would also like to know if usually it s common to have objects that have different volume representation to collide with each other. If so my component will need to become more bulky and to now a lot more on volume representation , aka spheres, capsules etc.

Edited by giordi

Share this post


Link to post
Share on other sites

It's worth mentioning that in most 2D games, esspecially older ones, the only forms of collision geometry are points and axis-aligned boxes, with more complicated shapes simulated by special-case boxes (the usual solution for sloped terrain) or collections of several bounding boxes.

Share this post


Link to post
Share on other sites

It's worth mentioning that in most 2D games, esspecially older ones, the only forms of collision geometry are points and axis-aligned boxes, with more complicated shapes simulated by special-case boxes (the usual solution for sloped terrain) or collections of several bounding boxes.

Thank you, the thing is that I am not making a 2D engine, I am trying to be general so I can add 3D element "easily" later on, like replace a sprite with a 3D char which still moves in 2D fashion etc, might be a bad idea overall but for now is the kind of approach I am taking. Which forces me to try to support different collision shapes or at least have the facility to extend to that fairly easily.

Which this lead me to the second question, I am trying design a way in which I can support different shapes without recurring in RTTI and mem cast in order to access the specific resources defining the bounding box.

What I was thinking for now was to have a series of vectors that would allow me to register bounding box pointers in it etc, which are still strongly typed. then in a smaller structure I will save an ID an a type, (so I can register this structure in a grid or similar for limiting amount of collision tests etc). This is all good an dandy but I will have to have a switch case inside my component filtering for the type but then I can call an overloaded function for the typed kind of collision, this ensure type safety and not RTTI.
A bit of pseudo code to make my explanation clearer:
 

BBox_storage
{
      vector<BBox2D> boxes;
      vector<sphereC> spheres;
      capsules<Capsule> capsules;
    ...
}

CmpBBox2D
{
     resolve_collision(obj )
    {
         vector<CollsionStruct> coll_struct;
         get_collision_from_grid(obj, coll_struct)
         for (auto coll: coll_struct)
         {
              switch (coll.type)
              {
                    case BBox::BBox2D:
                           collsion_BBox2D_BBox2D(obj, box_storage.boxes[coll]);
                           break;
                   case BBox::Sphere:
                           collsion_BBox2D_Sphere(obj,box_storage.sphere[coll]);
                   ....

             }
         }
    }

Something on those line, how bad would it be?

If I wanted to be super uber generic but with an higher level of indirection probably I could have  a map of function pointers resolving specific collision types and then compose the key of the map by merging the two types (which would be probably strings) and then access the function pointer in the map and call it. Not sure how that would be better, might have to think about it and evaluate the cost of such indirection which require string concatenation etc

Edited by giordi

Share this post


Link to post
Share on other sites

This topic is 816 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this