Collision detection/handling for RPG style games

Hello,

I am playing around with RPG style games, and I have some problems finding the right approach to collision detections. What I want to have a a human character that can move on uneven ground, that can jump and that won’t walk through objects like walls or tables.

I best approach so far is to have one collision ray down from the center of the player for collision detection with ground (using CollisionHandlerGravity), and one collision sphere for collision with obstacles (using CollisionHandlerPusher):

        self.np = Actor.Actor( path, { } )

        # Ground collision ( ray )
        self.ray = CollisionRay( 0, 0, 1, 0, 0, -1 )
        self.rayNP = self.np.attachNewNode( CollisionNode( 'ray' ) )
        self.rayNP.node( ).addSolid(  self.ray )
        self.rayNP.node( ).setFromCollideMask( BitMask32.bit( 1 ) )
        self.rayNP.node( ).setIntoCollideMask( BitMask32.allOff( ) )

        self.handler1 = CollisionHandlerGravity( )
        self.handler1.setGravity( 9.8 )
        self.handler1.addCollider( self.rayNP, self.np )

        base.cTrav.addCollider( self.rayNP, self.handler1 )

        # Obstacle collision ( sphere )
        self.sphere = CollisionSphere( 0, 0, 1, 0.7 )
        self.sphereNP = self.np.attachNewNode( CollisionNode( 'sphere' ) )
        self.sphereNP.node( ).addSolid(  self.sphere )
        self.sphereNP.node( ).setFromCollideMask( BitMask32.bit( 2 ) )
        self.sphereNP.node( ).setIntoCollideMask( BitMask32.allOff( ) )

        self.handler2 = CollisionHandlerPusher( )
        self.handler2.addCollider( self.sphereNP, self.np )

        base.cTrav.addCollider( self.sphereNP, self.handler2 )

Walking over uneven ground and staying out of wall works fine so far, except for when I run into 90 degree edges of buildings.

(1) When running straight into a wall I get stopped (fine). Now I turn slightly to the left or right and I slip along the wall (still fine). But when I reach an edge I suddenly get kicked forwards, until I am past the edge (not fine).

(2) If I approach the edge diagonal, that is about 135 degrees from both walls, then I get trapped at the edge, and can’t move left or right but have to retreat. Perhaps a screenshot helps explaining this situation: http://www.dachau.net/users/pfrogner/problem.jpg

Since I am probably not the only one doing RPG style games I would like to ask for help with collision detection/handling:

  • What is the best approach for collision detection in RPG style games?
  • What handlers should I use, or should I try to implement an own handler?
  • Is this a problem that can be solved by modeling, perhaps avoiding sharp edges?
  • Is it advisable to switch to ODE?

So far I don’t have need for physics besides jumping/gravity. Any help or comments are highly appreciated.
enn0x

It’s a bit of a cop-out answer, I know, but it may be that the best thing is just to avoid sharp edges like this in your modeling. They do cause problems.

However, we have wrestled with variants on this problem from time to time. I had thought we had solved this particular problem fairly well, and I’m surprised you’re still experiencing it. Are you using the latest version of Panda?

David

I’ve experienced the same problem using v1.3.2.
From the source (collisionHandlerPusher.cxx):

It pulls the node back to where it shouldn’t be. Would it help if we use a little magnitude of that shove to slide the node along the polygon, instead of simply discard it ?
Uhm…, one more silly question : why don’t you include zero in these :

if (p1->dist_to_plane(p2->get_collision_origin()) < 0 &&
    p2->dist_to_plane(p1->get_collision_origin()) < 0)

I am using Panda3D 1.3.2 too, Windows binaries, not modified.

Thank you both for your answers. I think ynij_jo found exactly the right place in the source code, sinde I have these lines in my log files whenever I get near to such a sharp edge:

// Each polygon is behind the other one.  That
// means we have a convex corner, and therefore
// we should discard one of the shoves (or the
// user will get stuck coming at a convex
// corner).
if (collide_cat.is_debug()) {
  collide_cat.debug()
    << "Discarding shove from convex corner.\n";
}

// This time, unlike the case of two parallel
...

enn0x