CollisionHandlerFloor Q?

Here’s a code snippet, I create a CollisionHandlerFloor to let the car move on uneven terrain without any force. But the result is odd. Although the intersection point is detected, the car is not been set to that point. I print out the ‘Z’ of the car when I move it by arrow keys. The car’s ‘z’ is always 0, but I can see its change in Z axis during running the code.

    # Space to hold the car.
    self.box = loader.loadModel("Models/Box")
    self.box.reparentTo(render)
    # The wall
    self.walls = self.box.find("**/wall_Coll")
    self.walls.node().setIntoCollideMask(BitMask32(0x3))
    # The ground
    self.boxGround = self.box.find("**/ground_Coll")
    self.boxGround.node().setIntoCollideMask(BitMask32(0x1))

    # Load the car and create a collision sphere and a collision ray for it.
    self.car = loader.loadModel("Models/Car")
    self.car.reparentTo(render)
    bounds = self.car.getChild(0).getBounds()
    center = bounds.getCenter()
    radius = bounds.getRadius()
    cSphere = CollisionSphere(center,radius)
    cNode = CollisionNode("Car")
    cNode.addSolid(cSphere)
    cNode.setFromCollideMask(BitMask32(0x3))
    cNode.setIntoCollideMask(BitMask32(0x1))
    self.carCollNodePath = self.car.attachNewNode(cNode)
    # Collision ray for the car.
    cRay = CollisionRay(0, 0, 0, 0, 0, -1)
    cNode = CollisionNode("Car_Ray_Down")
    cNode.addSolid(cRay)
    cNode.setFromCollideMask(BitMask32(0x1))
    self.carCollRayNodePath = self.car.attachNewNode(cNode)
    
    self.cTrav = CollisionTraverser()    
    self.pusher_car = PhysicsCollisionHandler()
    self.lifter= CollisionHandlerFloor() 
    self.lifter.addCollider(self.carCollRayNodePath, self.car) 
    self.cTrav.addCollider(self.carCollRayNodePath, self.lifter)

I’ve been careful about the Collision Handler and bitmask. Anybody can point out what’s wrong here? Thanks

There’s link to my code:
http://www.lilinhan.com/others/CD_1.rar

You may understand better if you run this!

I found some wrong parts there :

1. You still let collision of anything into ray to happen, which is not needed, right ?

    cNode = CollisionNode("Car_Ray_Down")
    cNode.addSolid(cRay)
    cNode.setFromCollideMask(BitMask32(0x1))

Add this :

    cNode.setIntoCollideMask(BitMask32.allOff())

2. What do you need the into-mask of the sphere for ?

    cNode = CollisionNode("Car")
    cNode.addSolid(cSphere)
    cNode.setFromCollideMask(BitMask32(0x3))
    cNode.setIntoCollideMask(BitMask32(0x1))

You set sphere’s into-mask to 0x1, while the ray also has the same from-mask.
That’s the source of your problem. CollisionHandlerFloor adjust your car’s Z based on collision of the ray into it’s own sphere. That’s why it’s Z never changed.
You’d better shut it down, unless you need it for something else (you should use other bit for that).

    cNode.setIntoCollideMask(BitMask32.allOff())
  1. You print your car’s Z, but the node actually moves around is not self.car. It stays on Z=0 all the time. The node which moves around is the physical node, self.carANP.

  2. angle = self.car.getH()*math.pi/180.0
    You convert degrees to radians by yourself. Python’s math module has radians method as well as degrees.

I’m not sure what causes the crazy jitter.

Stones falling down can collide into the car.

I made some changes to the bitmask. It works well now. But the ‘crazy jitter’, how it comes? Lemme check my code again!
Thanks ynjh_jo! :bulb:

Hi ynjh_jo, I know how the crazy jitter come.
The Collision Sphere around the car collides with the ground, also does the Collision ray of the car. Every time CollisionHandlerFloor try to move the car’s center to the intersection point, however, the Collision Sphere prevents the car move under the ground. So it jitters that way!
I add this

self.lifter= CollisionHandlerFloor() 
    self.lifter.setOffset(1.5)

It looks much better now!

Now, there’s a new problem.
It seems that two different CollisionHandlers cannot be associated with the same object. I use PhsicsCollisionHandler to prevent the stones falling through the ground. The result is good. However, when I add a CollisionHandlerEvent to the stone, the PhsicsCollisionHandler does not work. Surprise, the CollisionHandlerEvent works.

( I need to detect when the falling stones collide into the car. So I use CollisionHandlerEvent to send a message when the collision is detected. )

Sinppet:

    # The wall
    self.walls = self.box.find("**/wall_Coll")
    self.walls.node().setIntoCollideMask(BitMask32(0x1))
    self.walls.show()
    # The ground
    self.boxGround = self.box.find("**/ground_Coll")
    self.boxGround.node().setIntoCollideMask(BitMask32(0x9))
    self.boxGround.show()
    
    # Load the car and its collision sphere 
    self.car = loader.loadModel("Models/Car")
    self.car.reparentTo(render)
    self.car.setScale(0.8)
    self.car.setPos(0, 0, 0)
    self.car.setHpr(90, 0, 0)
    # add a sphere around the car to be collide with the walls
    # get the bounding sphere of the car
    bounds = self.car.getChild(0).getBounds()
    center = bounds.getCenter()
    radius = bounds.getRadius()
    cSphere = CollisionSphere(center,radius)
    cNode = CollisionNode("Car")
    cNode.addSolid(cSphere)
    cNode.setFromCollideMask(BitMask32(0x11))
    cNode.setIntoCollideMask(BitMask32(0x8))
    self.carCollNodePath = self.car.attachNewNode(cNode)
    # Collision ray for the car.
    cRay = CollisionRay(0, 0, 0, 0, 0, -1)
    cNode = CollisionNode("Car_Ray_Down")
    cNode.addSolid(cRay)
    cNode.setFromCollideMask(BitMask32(0x1))
    cNode.setIntoCollideMask(BitMask32.allOff())
    self.carCollRayNodePath = self.car.attachNewNode(cNode)
    
    # Load stones and their collision solids and rays.
    self.stones = []
    for i in range(5):
        stone = loader.loadModelCopy("Models/stone")
        stone.reparentTo(render)
        stone.setScale(0.7)
        stone.setPos( Vec3( random.uniform(-5, 5), random.uniform(-5, 5), random.uniform(5, 15) ) )
        self.stones.append(stone)
    
    self.cTrav = CollisionTraverser()
    self.pusher_stone = PhysicsCollisionHandler()  
    self.stoneAN = []     
    # Use a Collision Handler Event to deal with the explosion when
    # stone collides into the car.
    self.cHandler = CollisionHandlerEvent()
    self.cHandler.addInPattern("%fn-crash-%in")
    # self.cTrav.addCollider(self.carCollNodePath, self.cHandler)
    self.accept("Stone-crash-Car", self.accident)
     
    for stone in self.stones:
        # Create a sphere solid around each stone
        cSphere = CollisionSphere(stone.getChild(0).getBounds().getCenter(), stone.getChild(0).getBounds().getRadius())
        cNode = CollisionNode("Stone")
        cNode.addSolid(cSphere)
        cNode.setFromCollideMask(BitMask32(0x9))
        cNode.setIntoCollideMask(BitMask32(0x8))
        stoneCollNP = stone.attachNewNode(cNode)
        stoneCollNP.show()  
        i = self.stones.index(stone)
        stoneAN = ActorNode("stone-physics"+str(i))
        self.stoneAN.append(stoneAN)
        stoneANP = render.attachNewNode(stoneAN)
        base.physicsMgr.attachPhysicalNode(stoneAN)
        stone.reparentTo(stoneANP)
        self.pusher_stone.addCollider(stoneCollNP, stoneANP)
        self.cTrav.addCollider(stoneCollNP, self.pusher_stone) 
        # Comment the next, the world looks fine except cannot detect "Stone-crash-Car"
        self.cTrav.addCollider(stoneCollNP, self.cHandler)

I’ve also updated the link to my code.

Can I get CollisionEntry for CollisionHandlerPusher? Or how can I do somthing else except the default push back defined by the CollisionHandlerPusher?

Thanks a lot!

Unfortunately, you can’t.
You will have to write your own ‘pusher’ using the CollisionHandlerQueue, which returns an array of CollisionEntries.

Read –[THIS]–