Panda3d Collisions made simple

today I added another missing snippet (beginner bunch) to talk about picking objects in 2D - roll up if interested

ok I got the collisions themselves working but im having issues with the whole handler see my code below

(the problem with the code is that the collision handler isnt passing info somehow the self.accept is doing nothing when it should run self.handleCollision im not sure why.) so i just gotta get this pass working and its all done! I will then convert into something that works better run outta panda with less extra stuff [PS: you should clean up these post’s soon (ask a mod)]

        base.cTrav=CollisionTraverser() #added for collisions
        self.collisionHandler = CollisionHandlerEvent() #added for collisions
        base.cTrav.showCollisions(base.render)
        
        """Collision masks
        terrain_and_models=BitMask32.bit(0)
        walls_nodes_buildings=BitMask32.bit(1)
        Collision masks end"""
        #Load the actor, with the loop animation currently turned off
        #actor's Z position is created relative to the ground terrain
        #Also this is now loaded from a CSV for GUI usage and it loads the entire set of actors for your use
        #The actors X and Y are stored in the csv as well for easy start placement
        self.InnerSphere = []
        self.InnerSpherePos = []

        CSVload = csv.reader(open('Models/Stage.csv', "rb"))
        for row in CSVload:
            Column1,Column2,Column3,Column4 = row
            if Column2 != "none": 
                #self.actor = Actor.Actor('smiley')
                self.actor = Actor.Actor("Models/InnerSphere/"+Column2) #my actual model load script
                self.InnerSphere.append(self.actor)
                self.InnerSpherePos.append(Vec3(float(Column3),float(Column4),0))

        for i in range(len(self.InnerSphere)):
            self.InnerSphere[i].reparentTo(render)
            self.InnerSphere[i].setPythonTag("InnerSphere",str(i))
            self.InnerSphere[i].setScale(1,1,1)
            self.InnerSphere[i].setPos(self.InnerSpherePos[i])
            self.InnerSphere[i].setCollideMask(BitMask32.bit(0))

            sphereNP=(base.render.attachNewNode(ActorNode('sphereNP')))
            sphereNP.reparentTo(self.InnerSphere[i])
            sphereNP.setPos(0,0,2.5)
            avatarSensor = sphereNP.attachNewNode(CollisionNode('smileysensor'))
            cs=CollisionSphere(0, 0, 0, 2.5)
            avatarSensor.node().addSolid(cs)
            avatarSensor.node().setFromCollideMask(BitMask32.allOff())
            avatarSensor.node().setIntoCollideMask(BitMask32.bit(1))
            # as said above, to act correctly we need to make clear to the system that this is just a sensor, with no solid parts
            #cs.setTangible(0)
            # you wanna see the sensor ball? just uncomment the following line then.
            avatarSensor.show()
            
            rayNP=base.render.attachNewNode(ActorNode('rayNP'))
            rayNP.reparentTo(self.InnerSphere[i])
            raygeometry = CollisionSegment(0, 0, 0, 0, -10, 0)
            avatarRay = rayNP.attachNewNode(CollisionNode('avatarRay'))
            avatarRay.node().addSolid(raygeometry)
            rayNP.setPos(0,-2.5,4)
            # let's mask our floor FROM collider
            avatarRay.node().setFromCollideMask(BitMask32.bit(1))
            avatarRay.node().setIntoCollideMask(BitMask32.allOff())
            base.cTrav.addCollider(avatarRay, self.collisionHandler)
            avatarRay.show()
            
        self.collisionHandler.addInPattern('fn-into')
        self.collisionHandler.addOutPattern('fn-out')
        self.accept('avatarRay-into', self.handleCollision)
    def handleCollision(self,entry):
        print "Collide"

these 2 lines are wrong Chiapet:

        self.collisionHandler.addInPattern('fn-into')
        self.collisionHandler.addOutPattern('fn-out')

you figure out why studying again step3 with the help of this (CollisionHandlerEvent paragraph)

PS: why do you think we should clean up these posts? they gotta stay there as a reference for other ppl that will stumble on those issues, don’t you think so?

Hi astelix,

you have done a great work! You are one of the persons, that explained me how games work. YOU ARE VERY COOL! I thank you for your work very much!

I’m working in a company in germany where I develop on embedded devices. I have skills in C (sadly not C++) and python. I’v been looking to panda3d at a long time now. But your work helped me a lot to do a private project :smiley:. Because you described how to use other necessary things (blender…). I’m looking forward to see a tutorial on how to work with gimp gg

But I have one question left. I tried to modify your “intermediate” work to see something like Command & Conquer and Warcraft 3. But I have no good idea how to show the user where it is possible to build a building. You can see this in the videos. There are always red/green quares to show where you can build or not. But I’v no idea how to do that with panda :frowning:.

Can you give me a clue there?

I’m sorry for my english. I will try to learn it better when I have time left.

man your compliments far exceed my credits but thankyou nonetheless.
Let me see if I got what you’re asking for: do you need a way to show a square (or whatever model) moving around a 3D terrain surface while moving the mouse pointer?

That’s right. I need to move a model (a house) around a 3D terrain with the mouse. The aim is to place the model to the terrain…

Is there a way to show that you can place a model to a given possition or not?

That shouldnt be too hard, my basic idea is to use collision ray, shot from camera, and then position house in place where ray hits ground, you may want to “shoot” house so it doesnt intersect with ground plane…

I guess there is also other issues to solve as i.e. not to overlap with other buildings so would also need to check bound collisions with other objects placed around to know if we could build there or not. I guess here could be better to see the terrain as a grid would be best, so there would no need of collision check but just see if the cells underneath are clear or not, using just the ray to know the terrain x,y position pointed by the mouse cursor.

Thanks :slight_smile:.

Sounds good! I’ll give it a try.

Another question is:
Is there an “official” way to post tutorials?

Don’t get me wrong… The manual is great!
But I miss the integration of other tools like Blender or Gimp. I’v spend a lot of time in reading manuals from several other pages to find out simple tasks.

your weapons are, in the order:
the panda3D manual, the panda3D reference, the official panda samples and, last but not least, this forum. There is not an allaround tutorial or magic book to learn everything - if I was able to make such a thing I were rich right now :slight_smile:
AFAIK ATM there is no other way to learn how to make stuff with panda3D.

I’m trying to use a collision event for camera collisions.
I looked at Tut-Basic-Step-4,

import direct.directbase.DirectStart
from panda3d.core import *
from direct.interval.IntervalGlobal import *

base.disableMouse() # disable default mouse controls

# hide mouse cursor, comment these 3 lines to see the cursor
props = WindowProperties()
props.setCursorHidden(True)
base.win.requestProperties(props)

# a scene
environ = loader.loadModel('environment')
environ.setScale(0.1)
environ.setZ(-5)
environ.setY(15)
environ.reparentTo(render)

###################
# CAMERA CONTROLS

# model for the camera to orbit along
model = loader.loadModel('smiley')
model.reparentTo(render)

# dummy node for camera, we will rotate the dummy node for camera rotation
parentnode = render.attachNewNode('camparent')
parentnode.reparentTo(model) # inherit transforms
parentnode.setEffect(CompassEffect.make(render)) # NOT inherit rotation

# the camera
base.cam.reparentTo(parentnode)
base.cam.lookAt(parentnode)
base.cam.setY(-10) # camera distance from model

# camera zooming
base.accept('wheel_up', lambda : base.cam.setY(base.cam.getY() + 200 * globalClock.getDt()))
base.accept('wheel_down', lambda : base.cam.setY(base.cam.getY() - 200 * globalClock.getDt()))

# global vars for camera rotation
heading = 0
pitch = 0

# camera rotation task
def thirdPersonCameraTask(task):
	global heading
	global pitch
   
	md = base.win.getPointer(0)
     
	x = md.getX()
	y = md.getY()
   
	if base.win.movePointer(0, 300, 300):
		heading = heading - (x - 300) * 0.5
		pitch = pitch - (y - 300) * 0.5
   
	parentnode.setHpr(heading, pitch,0)

	return task.cont

taskMgr.add(thirdPersonCameraTask, 'thirdPersonCameraTask')

###################
# CAMERA COLLISIONS
base.cTrav=CollisionTraverser()

# a handler
cameraFloorHandler = CollisionHandlerEvent()

# the collision geometry
floor_collide = loader.loadModel('floor-collide')
floor_collide.setScale(6)
floor_collide.setZ(-4.5)
floor_collide.reparentTo(render)
floor_collide.setTransparency(TransparencyAttrib.MAlpha)
floor_collide.setColor(0,1,1,0.5)
floor_collide.setTwoSided(True)

# retrieve the collision plane from the egg (only object in this example)
floorcollider = floor_collide.find("**/Plane")
floorcollider.node().setIntoCollideMask(BitMask32.bit(1))

# a collision sphere for camera collisions
cameraSphere = base.cam.attachNewNode(CollisionNode('cameraSphere'))
cameraSphere.node().addSolid(CollisionSphere(0, 0, 0, 3))
cameraSphere.node().setFromCollideMask(BitMask32.bit(1)) # floor
cameraSphere.node().setIntoCollideMask(BitMask32.allOff())

cameraFloorHandler.addInPattern('%fn-into-%in')
cameraFloorHandler.addAgainPattern('%fn-again-%in')

# functions to execute by panda events
def collideEventIn(entry):	
	base.cam.setY(base.cam.getY() + 2)

def collideEventAgain(entry):	
	base.cam.setY(base.cam.getY() + 2)

# panda events
base.accept('cameraSphere-into-Plane', collideEventIn)
base.accept('cameraSphere-again-Plane', collideEventAgain)

base.cTrav.addCollider(cameraSphere, cameraFloorHandler)   

  
run()

floor-collide.egg mediafire.com/?ncnvtj0ajjj
I dont get why I’m stuck with this problem :confused:

should I guess what the problem is? I see a smiley centered in the scene and moving the mouse the world rotate around that smoothly, the wheel zoom correctly the camera so I can’t see any problem. Could you tellme more about your issue?

No?

See the semitransparent blue plane? I want the camera to generate a collision event when hitting it, so camera will zoom closer (y value) to the camera parent and it won’t go below the ‘ground’.
The collision code is below the lines

###################
# CAMERA COLLISIONS

I haven’t used collision events before and had a look at your code but couldn’t find what I was doing wrong.

I ain’t enough spare time for guessing games Anon, that’s what I meant - be obvious more than cryptic so I’ll be to the issue faster.

I think the problem is in the egg plane you made - I made one from scratch and now the events are working out. Check this .blend to see what’s different from yours and let me know.

Right…

It was indeed a bad egg file… Hey, we’re all human, sorry about that :slight_smile:

no problem - happy to see the issue has gone

Hm, actually this is a bit slow… so the camera can sometimes end up below terrain.
I read this page: panda3d.org/manual/index.php/R … ng_Objects
It says I should use

object.setFluidPos(newPos)

,but in this case I modify the hpr of the object. setFluidHpr() doesn’t seem to exist.
Maybe I should use collision rays.

making a good rpg camera view is one of the most challenging things making 3d games - using rays for floors collision is the recommended way to go and for walls the collisionpusher collider. I suggest you to check intermediate step2 for that kind of stuff.

Really great work :slight_smile:
Why don’t you put a link to this thread here :wink:

thankyou Fero63 - I don’t even knew that page exists - looks a dead and obsolete page (needing a maintainer) though with no direct links in the website front pages so I guess adding new stuff there is a useless work.