Collision Problem

Ok, I’m slowly but surely beginning to grasp the concepts of Panda and python. I’m really struggling with the concepts of collisions. I put together the following code using the smiley face example shown in the manual. Now what I think should happen is ralph and his sphere should slide down the outside of the large collision sphere. What does happen is he goes though the sphere and then moves sideways as he approaches the bottom. Here is the code I am using. I don’t know if my code is wrong or what I think is suppose to happen is wrong.

import direct.directbase.DirectStart 
from pandac.PandaModules import * 
from direct.interval.IntervalGlobal import * 

#initialize traverser 
base.cTrav = CollisionTraverser() 

#initialize pusher 
pusher = CollisionHandlerPusher() 
        
#Load up Our Character and Position him slightly off the ground
smiley = loader.loadModel('ralph') 
smiley.reparentTo(render) 
smiley.setPos(0,15,2) 
smiley.setScale(.2)



#create a collision solid for this model 
cNode = CollisionNode('smiley') 
cNode.addSolid(CollisionSphere(0,0,3,2.8)) 
smileyC = smiley.attachNewNode(cNode) 
smileyC.show() 


        
#Load a second guy for col detection
frowney = loader.loadModel('ralph') 
frowney.reparentTo(render) 
frowney.setPos(0,15,-2) 
frowney.setScale(.2)

        
#create a collision solid for this model to react with
cNode = CollisionNode('frowney') 
cNode.addSolid(CollisionSphere(0,0,3.0,2.8)) 
frowneyC = frowney.attachNewNode(cNode) 
frowneyC.show() 
   

base.cTrav.addCollider(frowneyC,pusher) 
pusher.addCollider(frowneyC,frowney, base.drive.node()) 


frowney.posInterval(5,Point3(0,15,10),startPos=Point3(0,15,-2),fluid=1).loop()
        
run() 
 

I changed the code and made it even simpler, but it still won’t do what the smiley face example in the manual does. The first Ralph just passes right though the second one. Any help would be greatly appreciated. This is driving me NUTS!! This code seems to work perfectly I don’t see a difference though.

import direct.directbase.DirectStart 
from pandac.PandaModules import * 
from direct.interval.IntervalGlobal import * 

#initialize traverser 
base.cTrav = CollisionTraverser() 

#initialize pusher 
pusher = CollisionHandlerPusher() 

######### 

#load a model. reparent it to the camera so we can move it. 
smiley = loader.loadModel('ralph') 
smiley.reparentTo(render) 
smiley.setPos(0, 25.2,0) 
smiley.setScale(.2)

#create a collision solid for this model 
cNode = CollisionNode('smiley') 
cNode.addSolid(CollisionSphere(0,0,3,2.8)) 
smileyC = smiley.attachNewNode(cNode) 
smileyC.show() 

######### 

#load a model 
frowney = loader.loadModel('ralph') 
frowney.reparentTo(render) 
frowney.setPos(5, 26,0) 
frowney.setScale(.2)


#create a collsion solid for this model 
cNode = CollisionNode('frowney') 
cNode.addSolid(CollisionSphere(0,0,3,2.8)) 
frowneyC = frowney.attachNewNode(cNode) 
frowneyC.show() 

######### 
#add collision node to the traverser and the pusher 

base.cTrav.addCollider(frowneyC,pusher) 
pusher.addCollider(frowneyC,frowney, base.drive.node()) 

######### 

#have the one ball moving to help show what is happening 
frowney.posInterval(5,Point3(5,25,0),startPos=Point3(-5,25,0),fluid=1).loop() 

#run the world. move around with the mouse to see how the moving ball changes 
#course to avoid the one attached to the camera. 

run() 

Your code works great for me, i only changed the them to teapots (for they don’t need to be in the same directory to run the demo) and i made them slide down the y=0 axis so that i could rotate via mouse to look at it from the top and any side. See if this works for you as it does for me.


import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *

#initialize traverser
base.cTrav = CollisionTraverser()

#initialize pusher
pusher = CollisionHandlerPusher()

#########

#load a model. reparent it to the camera so we can move it.
smiley = loader.loadModel('teapot')
smiley.reparentTo(render)
smiley.setPos(0, 25.2-26,0)
smiley.setScale(.2)

#create a collision solid for this model
cNode = CollisionNode('smiley')
cNode.addSolid(CollisionSphere(0,0,3,2.8))
smileyC = smiley.attachNewNode(cNode)
smileyC.show()

#########

#load a model
frowney = loader.loadModel('teapot')
frowney.reparentTo(render)
frowney.setPos(5, 26-26,0)
frowney.setScale(.2)


#create a collsion solid for this model
cNode = CollisionNode('frowney')
cNode.addSolid(CollisionSphere(0,0,3,2.8))
frowneyC = frowney.attachNewNode(cNode)
frowneyC.show()

#########
#add collision node to the traverser and the pusher

base.cTrav.addCollider(frowneyC,pusher)
pusher.addCollider(frowneyC,frowney, base.drive.node())

#########

#have the one ball moving to help show what is happening
frowney.posInterval(5,Point3(5,25-26,0),startPos=Point3(-5,25-26,0),fluid=1).loop()

#run the world. move around with the mouse to see how the moving ball changes
#course to avoid the one attached to the camera.

run() 

the only thing that struck me as odd is the robber ban effect the Interval has on the teapot. I would expect Interval to act like that but maybe you would not. So here is the code with out the interval … maybe that is what you are looking for?


import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.task.Task import Task

#initialize traverser
base.cTrav = CollisionTraverser()

#initialize pusher
pusher = CollisionHandlerPusher()

#########

#load a model. reparent it to the camera so we can move it.
smiley = loader.loadModel('teapot')
smiley.reparentTo(render)
smiley.setPos(0, 25.2-26,0)
smiley.setScale(.2)

#create a collision solid for this model
cNode = CollisionNode('smiley')
cNode.addSolid(CollisionSphere(0,0,3,2.8))
smileyC = smiley.attachNewNode(cNode)
smileyC.show()

#########

#load a model
frowney = loader.loadModel('teapot')
frowney.reparentTo(render)
frowney.setPos(5, 26-26,0)
frowney.setScale(.2)


#create a collsion solid for this model
cNode = CollisionNode('frowney')
cNode.addSolid(CollisionSphere(0,0,3,2.8))
frowneyC = frowney.attachNewNode(cNode)
frowneyC.show()

#########
#add collision node to the traverser and the pusher

base.cTrav.addCollider(frowneyC,pusher)
pusher.addCollider(frowneyC,frowney, base.drive.node())

#########

#have the one ball moving to help show what is happening
#frowney.posInterval(5,Point3(5,25-26,0),startPos=Point3(-5,25-26,0),fluid=1).loop()

def move(task):
    frowney.setPos( frowney.getPos() + Vec3(.01,0,0))
    if frowney.getX() > 5:
        frowney.setX(-5)
        frowney.setY(0)
    return task.cont
taskMgr.add(move, 'move')



#run the world. move around with the mouse to see how the moving ball changes
#course to avoid the one attached to the camera.

run() 

Your code works fine for me. When I try to make them collide from right to left like in the second code I posted it works like I would expect. The code in my first post when I try to move them up and down. They just pass though each other. It seems that changing there position to vertical and the movement to vertical causes the collision not to be detected.

the point is that Interval has rubber bending effect which will mess up with collisions. Don’t use Interval and collisions together.

Thanks now I understand. You saved me from insanity

more code just what i had to test all possible collision ways.

import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.task.Task import Task
from random import *
#initialize traverser
base.cTrav = CollisionTraverser()

#initialize pusher
pusher = CollisionHandlerPusher()

#########

#load a model. reparent it to the camera so we can move it.
smiley = loader.loadModel('teapot')
smiley.reparentTo(render)
smiley.setPos(0,0,0)
smiley.setScale(.2)

#create a collision solid for this model
cNode = CollisionNode('smiley')
cNode.addSolid(CollisionSphere(0,0,0,5))
smileyC = smiley.attachNewNode(cNode)
smileyC.show()

#########

#load a model
frowney = loader.loadModel('teapot')
frowney.reparentTo(render)
frowney.setPos(0,0,0)
frowney.setScale(.2)


#create a collsion solid for this model
cNode = CollisionNode('frowney')
cNode.addSolid(CollisionSphere(0,0,0,3))
frowneyC = frowney.attachNewNode(cNode)
frowneyC.show()

#########
#add collision node to the traverser and the pusher

base.cTrav.addCollider(frowneyC,pusher)
pusher.addCollider(frowneyC,frowney, base.drive.node())

#########

#have the one ball moving to help show what is happening
#frowney.posInterval(5,Point3(5,25-26,0),startPos=Point3(-5,25-26,0),fluid=1).loop()

def move(task):
    frowney.setPos( frowney.getPos() + Vec3(.01,0,0))
    if frowney.getX() > 5:
        frowney.setX(-5)
        frowney.setY(uniform(-1,1))
        frowney.setZ(uniform(-1,1))
    return task.cont
taskMgr.add(move, 'move')



#run the world. move around with the mouse to see how the moving ball changes
#course to avoid the one attached to the camera.

run() 

Sorry, I’m being a pain and not getting this, but I have another problem. I’m moving Ralph around a level I created. If he hits a hill or a wall at an angle he slides along just like i would expect. But once he hits the flat ground or a wall straight on he goes right though. In any example I create if two objects hit straight on the collision isn’t detected. I’m using a simple movement code:

if (self.keyMap["forward"] != 0):
            self.ralph.setPos(self.ralph.getX(),self.ralph.getY()-.4,self.ralph.getZ())
        if (self.keyMap["back"] != 0):
            self.ralph.setPos(self.ralph.getX(),self.ralph.getY()+.4,self.ralph.getZ())
        if (self.keyMap["up"] != 0):
            self.ralph.setPos(self.ralph.getX(),self.ralph.getY(),self.ralph.getZ()+.4)
        if (self.keyMap["down"] != 0):
            self.ralph.setPos(self.ralph.getX(),self.ralph.getY(),self.ralph.getZ()-.4)
        if (self.keyMap["right"] != 0):
            self.ralph.setPos(self.ralph.getX()+.4,self.ralph.getY(),self.ralph.getZ())
        if (self.keyMap["left"] != 0):
            self.ralph.setPos(self.ralph.getX()-.4,self.ralph.getY(),self.ralph.getZ())

when he hits head on the repellent force cant push it as far so your set its positions. Try setFluidPos position first then look closely how tutorial does it. ( I think there he just gets stuck on collisions which does not help you much)

Also look at the collisions we did in iron angels discourse.panda3d.org/viewtopic.php?t=3568
we did not use CollisionHandlerPusher and don’t realy know how well it works. “A specialized kind of CollisionHandler that simply pushes back on things that attempt to move into solid walls. This is the simplest kind of “real-world” collisions you can have.” Probably was not written to exactly handle you teleporting him around .4 units (which is alot in collision scales) .4 units per frame would make you fly outside the game range quickly. Using some thing more gentile like .01 per frame would probably work as i have it in my demo.

code showing this:

import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.task.Task import Task
from random import *
#initialize traverser
base.cTrav = CollisionTraverser()

#initialize pusher
pusher = CollisionHandlerPusher()

#########

#load a model. reparent it to the camera so we can move it.
smiley = loader.loadModel('teapot')
smiley.reparentTo(render)
smiley.setPos(0,0,0)
smiley.setScale(.2)

#create a collision solid for this model
cNode = CollisionNode('smiley')
cNode.addSolid(CollisionSphere(0,0,0,5))
smileyC = smiley.attachNewNode(cNode)
smileyC.show()

#########

#load a model
frowney = loader.loadModel('teapot')
frowney.reparentTo(render)
frowney.setPos(0,0,0)
frowney.setScale(.2)


#create a collsion solid for this model
cNode = CollisionNode('frowney')
cNode.addSolid(CollisionSphere(0,0,0,3))
frowneyC = frowney.attachNewNode(cNode)
frowneyC.show()

#########
#add collision node to the traverser and the pusher

base.cTrav.addCollider(frowneyC,pusher)
pusher.addCollider(frowneyC,frowney, base.drive.node())

#########

#have the one ball moving to help show what is happening
#frowney.posInterval(5,Point3(5,25-26,0),startPos=Point3(-5,25-26,0),fluid=1).loop()

def move(task):
    frowney.setPos( frowney.getPos() + Vec3(.01,0,0))
    if frowney.getX() > 5:
        frowney.setX(-5)
        frowney.setY(0)
        frowney.setZ(0)
    return task.cont
taskMgr.add(move, 'move')



#run the world. move around with the mouse to see how the moving ball changes
#course to avoid the one attached to the camera.

run()