Collide function for many nodes

I am attepting to create a collision function that I can use on a parent node, or single node, which will make that node and all of its childs collide with the floor and ajust the Z height when the move. Useing the code from the ralph sample.

This is what I have at the moment, it takes a node as an argument. When it runs it does lower there Z so that they are the same leevl as the floor model, but they all have the same Z height, instead of individual Z heights.

class collisionClass():   
    def __init__(self, classNode):
        self.node = classNode
        for child in self.node.getChildren():
            localid = self.node.getTag("id") + "_ray"
            self.cTrav = CollisionTraverser()

            self.miyuGroundRay = CollisionRay()
            self.miyuGroundRay.setOrigin(0,0,1000)
            self.miyuGroundRay.setDirection(0,0,-1)
            self.miyuGroundCol = CollisionNode(localid)
            self.miyuGroundCol.addSolid(self.miyuGroundRay)
            self.miyuGroundCol.setFromCollideMask(BitMask32.bit(0))
            self.miyuGroundCol.setIntoCollideMask(BitMask32.allOff())
            self.miyuGroundColNp = self.node.attachNewNode(self.miyuGroundCol)
            self.miyuGroundHandler = CollisionHandlerQueue()
            self.cTrav.addCollider(self.miyuGroundColNp, self.miyuGroundHandler)
        taskMgr.add(self.collisions, "collisions")
        #print child.ls()
        
    def collisions(self, task):
        self.cTrav.traverse(render)
        childPos = self.node.getPos()
        # Now check for collisions.
        for child in self.node.getChildren():
            entries = []
            for i in range(self.miyuGroundHandler.getNumEntries()):
                entry = self.miyuGroundHandler.getEntry(i)
                entries.append(entry)
            entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                         x.getSurfacePoint(render).getZ()))
            if (len(entries)>0) and (entries[0].getIntoNode().getName() == "Floor"):
                child.setZ(entries[0].getSurfacePoint(render).getZ())
            else:
                child.setPos(childPos)
        return Task.cont

Any one got an Idea, heres the full code.

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject # Used for events I belive [CHECK]
from direct.task import Task # Uses for tasks
import sys # used for events and all them nekos ^-^
from pandac.PandaModules import *

# - Create a more effective way to load many NPCs
# - Apply Collisions to them individualy
        
class collisionClass():   
    def __init__(self, classNode):
        self.node = classNode
        for child in self.node.getChildren():
            localid = self.node.getTag("id") + "_ray"
            self.cTrav = CollisionTraverser()

            self.miyuGroundRay = CollisionRay()
            self.miyuGroundRay.setOrigin(0,0,1000)
            self.miyuGroundRay.setDirection(0,0,-1)
            self.miyuGroundCol = CollisionNode(localid)
            self.miyuGroundCol.addSolid(self.miyuGroundRay)
            self.miyuGroundCol.setFromCollideMask(BitMask32.bit(0))
            self.miyuGroundCol.setIntoCollideMask(BitMask32.allOff())
            self.miyuGroundColNp = self.node.attachNewNode(self.miyuGroundCol)
            self.miyuGroundHandler = CollisionHandlerQueue()
            self.cTrav.addCollider(self.miyuGroundColNp, self.miyuGroundHandler)
            #print child.ls()
        taskMgr.add(self.collisions, "collisions")
        
       
    def collisions(self, task):
        self.cTrav.traverse(render)
        childPos = self.node.getPos()
        # Now check for collisions.
        for child in self.node.getChildren():
            entries = []
            for i in range(self.miyuGroundHandler.getNumEntries()):
                entry = self.miyuGroundHandler.getEntry(i)
                entries.append(entry)
            entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                         x.getSurfacePoint(render).getZ()))
            if (len(entries)>0) and (entries[0].getIntoNode().getName() == "Floor"):
                child.setZ(entries[0].getSurfacePoint(render).getZ())
            else:
                child.setPos(childPos)
        return Task.cont         

class world(DirectObject):
    def __init__(self):
        self.accept("escape", sys.exit)
        # Create flat floor
        cm=CardMaker('')
        cm.setFrame(-2,2,-2,2)
        floor = render.attachNewNode(PandaNode("Floor"))
        for y in range(12):
          for x in range(12):
            nn = floor.attachNewNode(cm.generate())
            nn.setP(-90)
            nn.setPos((x-6)*4, (y-6)*4, 0)
        floor.flattenStrong()
        
        self.miyu = loader.loadModel("panda")
        self.miyu.reparentTo(render)
        self.miyu.setPos(0,10,20)        
        
        collisionClass(self.miyu)
        
world()
run()

Welllll… if you only have one collider, and you’re getting position data off of that one collider, you only have one point worth of position data, so there’s no way you’ll be able to precisely fine-tune multiple objects to collide differently. You have a good efficiency idea lumping multiple geoms into a single node hierarchy to do a single collision, but this will only help you if you can afford to have the objects collide as a group or not-collide as a group, otherwise you’ll need to give each object its own collision geometry and plug each into your collision handler individually.

hmm, Thank you. I think I undertand, but I have no idea how to get it to work. :slight_smile:

I shall have too have a look around. Is there an example with something like this?