Collision Problems...

I can’t get my collisions to work. I followed the way that the ball-in-maze sample does it. I know that the collision geometry is being detected since it shows up when I render it.

As far as I can tell, it should work similar to the maze…

What am I doing wrong. Oh, and I am using the latest 1.5.1.

Here is my code:

import direct.directbase.DirectStart
from direct.task import Task 
from pandac.PandaModules import AmbientLight,DirectionalLight,LightAttrib
from pandac.PandaModules import Material,Vec4,BitMask32,Vec3
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import CollisionTraverser,CollisionNode
from pandac.PandaModules import CollisionHandlerQueue,CollisionRay

base.disableMouse()
camera.setPosHpr(0, 0, 250, 0, -90, 0)

#load the board for the ball to stay on.
playBoard = render.attachNewNode("playBoard")

play = loader.loadModel("models/trayWater")

play.reparentTo(playBoard)
play.setScale(5,5,2)

#load the ball
ballRoot = playBoard.attachNewNode("ballRoot")

ball = loader.loadModel("models/ball")

ball.reparentTo(ballRoot)
ball.setScale(5,5,5)
ball.setX(0)

#load the paddle for the ball to bounce off of
paddleP1 = playBoard.attachNewNode("paddleP1")

paddle = loader.loadModel("models/paddle")

paddle.reparentTo(paddleP1)
paddle.reparentTo(playBoard)
paddle.setScale(8,8,7)

#set up lighting
lAttrib = LightAttrib.makeAllOff()

directionalLight = DirectionalLight( "directionalLight" )

directionalLight.setDirection( Vec3( 0, 0, -1 ) )

directionalLight.setColor( Vec4( 0.375, 0.375, 0.375, 1 ) )

directionalLight.setSpecularColor(Vec4(1,1,1,1))

lAttrib = lAttrib.addLight( directionalLight )

ball.node().setAttrib( lAttrib )
play.node().setAttrib( lAttrib )

paddle.node().setAttrib( lAttrib )

#ballV = Vec3(0,0,0)

#create tasks for testing purposes
def moveY(task):
    # Put some code here
    ballPosY = ball.getY()
    ball.setY(ballPosY+.1)
    return Task.cont 
def moveX(task):
    # Put some code here
    ballPosX = ball.getX()
    ball.setX(ballPosX+.1)
    return Task.cont 


#taskMgr.add(moveX, "moveX")

#create events to test things with
def mouseClick():
  print "mouse clicked"
  taskMgr.remove("moveX")
  taskMgr.add(moveY, "moveY")
def mouse3Click():
  print "mouse3 clicked"
  taskMgr.remove("moveY")
  taskMgr.add(moveX, "moveX")
base.accept("mouse1", mouseClick)
base.accept("mouse3", mouse3Click)

#get the colision stuff from the board model
playCol = play.find("**/trayWater")
playCol.node().setIntoCollideMask(BitMask32.bit(0))
playCol.show()

#get the collision from the ball
ballCol = ball.find("**/ball")
ballCol.node().setFromCollideMask(BitMask32.bit(0))
#ballCol.node().setIntoCollideMask(BitMask32.allOff())
ballCol.show()

#tell the computer to deal with the collisions
#pretty much ripped off from ball-in-maze
cTrav = CollisionTraverser()
cHandler = CollisionHandlerQueue()
cTrav.addCollider(playCol, cHandler)
cTrav.addCollider(ballCol, cHandler)

cTrav.showCollisions(render)

#create a task to detect when a collision occurs and move th ball to the middle of the tray.
def collisonTask(task):
  #print cHandler.getNumEntries()
  for i in range(cHandler.getNumEntries()):
    print "there was a collision"
    ball.setPos(0,0,0)
    #entry = cHandler.getEntry(i)
    #name = entry.getIntoNode().getName()
    #if name == "ball":
    #   ball.setPos(0,0,0)
    #   print "trayWater collide"
  return Task.cont

taskMgr.add(collisonTask, "collisonTask")

run()

Are you saying you modified the maze demo and now it isn’t working? What result exactly did you expect to obtain?

Um, I guess I wasn’t very clear… I followed the steps described in the maze demo to set up my collisions.

Basically I have a tray that the ball is in. When the ball hits the side of the tray, then there should be a collision. As far as I can tell, there isn’t… Hence why I asked for help.

Your collision traverser doesn’t do the traversal at all.
You should tell it to do the traversal :

cTrav.traverse(render)

in collisonTask.

The maze code is different, since the traverser used is base.cTrav, which always do the traversal for you under the hood.
Have you read this part ?

    #For a traverser to actually do collisions, you need to call
    #traverser.traverse() on a part of the scene. Fortunatly, base has a
    #task that does this for the entire scene once a frame. This sets up our
    #traverser as the one to be called automatically
    base.cTrav = self.cTrav

Thanks! That fixed my lack of collisions. :smiley:

I guess I did miss that section. :blush:

Ok, so my collisions are being detected. But it isn’t changing the position of the ball like it is supposed to.

def wallCollide(self, colEntry):
    print "wallCollide"
    norm = colEntry.getSurfaceNormal(render) * -1.0
    curSpeed = self.ballV.length()
    inVec = self.ballV / curSpeed                 #The direction of travel
    velAngle = norm.dot(inVec)                    #Angle of incidance
    hitDir = colEntry.getSurfacePoint(render) - self.ballRoot.getPos()
    hitDir.normalize()                            
    hitAngle = norm.dot(hitDir)
    if velAngle > 0 and hitAngle > .995:
      print "inside if velAngle"
      #Standard reflection equation
      reflectVec = (norm * norm.dot(inVec * -1) * 2) + inVec
      
      #This makes the velocity half of what it was if the hit was dead-on
      #and nearly exactly what it was if this is a glancing blow
      self.ballV = reflectVec * (curSpeed * (((1-velAngle)*.5)+.5))
      #Since we have a collision, the ball is already a little bit buried in
      #the wall. This calculates a vector needed to move it so that it is
      #exactly touching the wall
      disp = (colEntry.getSurfacePoint(render) -
              colEntry.getInteriorPoint(render))
      newPos = self.ball.getPos() + disp
      self.ball.setPos(newPos)

Again, ripped off of the ball-in-maze tutorial… The function is getting executed since my print statements get run.

I think my problem has to do with this error I get when I run the file.

What does that mean?

Thanks!

You can only use a sphere, ray, or line as the active (“from”) collision solid.