Panda3d Collisions made simple

you know guys: it is all written - the problem is it is written by an Italian pretending to write English. :wink:
anyhow MMichaud, drozzy is right about to not rush while peeking this stuff - the panda3D manual itself, in the first page point very clearly this:

I’m a 20y skilled programmer and I’d found difficult to put my feet into this stuff nonetheless - not much about to understand what a python or even C++ line of code means, but rather all the knowledge that turn around a game engine - a huge lot of stuff to know. So my friends take your time, read carefully and don’t rush is a lesson to learn quick if you wanna learn quickly. (what a pun)
But keep digging an pointing any stuff you find off here though - I’ll try to make my best to fix it for you - provided to have enough spare time of course.

Hey, I’m on step6.py, and I found this line:

collisionHandler.addAgainPattern(
  "ray_again_all%(""rays"")fh%(""balls"")ih"
)

Please don’t tell me you put the “” empty quotes there just to keep me awake??? Or are they needed? Looks like an empty string … and could be replaced with:

collisionHandler.addAgainPattern(
  "ray_again_all%(rays)fh%(balls)ih"
)

which works.

I am still not sure what the part before the first % is - the “ray_again_all”. Or how that string is built up… I looked at the manual - but they show no examples. Any way you can expand on that?

Hm… I think I am beginning to understand this stuff…
If you specify a pattern like this:

%(rays)ft-into-%(balls)it

it means look for any colliders that are in the groups “rays” and “balls” respectively, and substitute these strings with the actual tag values.
So it will match if a ray “ray1” collides with a ball “smiley”, and will use these values in forming the function name: ray1-into-smiley.

On the other hand if you got something like this:

some_name%(rays)fh%(balls)ih

it will still match a collision between “ray1” and “smiley” ball, but it will no longer use these specific tag names in the collision. It will just use whatever string is left-over after you remove all the special characters. So in the above case it will be just: some_name.

I find this wierd. Maybe someone can enlighten me.
How come this:

and this:

does the same thing? Notice the lack of node().
It seems like both PandaNode and NodePath both have setTag() methods…

can’t get your question - you may for sure set and read a tag for both kind of nodes but what do you need to know about that?

Well, I want to know which one I should set the tag on.
collider_path or collider_path.node()?
And does it make a difference?

I guess should be clear to you setTag() is simply a way to make a node or nodepath carry on a string value to be read somewhere in your application - which one you’ll decide to apply - either on nodepath or on a pandanode - it’s up to you and your code logic. What I’m not sure to understand is if you found something strange related with the subject on my code or is outside that.

No, this is just a general question, unrelated to the tutorial.

I was just surprised that it worked when I changed it… anyways thanks.

It is true that both NodePath and PandaNode have a setTag() method. They both do the same thing–the NodePath.setTag() method is a pass-through to the PandaNode.setTag() method. It’s just there as a convenience.

In fact, (almost) all of the NodePath methods are technically just conveniences–(almost) anything you can do with a NodePath, you can do with the underlying PandaNode, but sometimes the PandaNode interface is a lot clumsier. The exceptions are the methods that have to do with a particular instance of a PandaNode, which is the main reason we have a NodePath class in the first place.

David

Thanks.
Also this video kinda helps:
video.google.com/videoplay?docid … 4529&hl=en

I say kinda cause I can’t see 90% of the board :wink:

hey astelix, so I am on step8 now, and I’ve been following your code, but for some reason I don’t get any object being spawned. I didn’t complete the whole tutorial code - but I think I left out the friction functions only.

Mabye somebody can point out something really obvious to me? Here is the code:

import direct.directbase.DirectStart
import random

from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *

loadPrcFileData("", """syn-video 0""")

import snipstuff

base.cam.setPos(0, -30, 10)
base.cam.lookAt((0,0,4))

base.cTrav = CollisionTraverser()
# this is what "simulates" our physics
base.enableParticles()

collisionHandler = PhysicsCollisionHandler()

collisionPlane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0,0,0)))
plane = base.render.attachNewNode(CollisionNode('planecnode'))
plane.node().addSolid(collisionPlane)
plane.show()

# Affect everything below render by this force node
globalForcesForceNode = ForceNode('world-forces')
globalForces = base.render.attachNewNode(globalForcesForceNode)

# set linear downward on Z force
globalForcesGravity = LinearVectorForce(0, 0, -9.81)
globalForcesForceNode.addForce(globalForcesGravity)

# physics manager created when we called base.enableParticles()
base.physicsMgr.addLinearForce(globalForcesGravity)

def phyball_dispenser(modelname, scale=1.):
  ball = NodePath(PandaNode('phisicsball'))
  ballActor = ActorNode('ballactornode')
  ballActorNP = ball.attachNewNode(ballActor)
  ballModel = loader.loadModel(modelname)
  ballModel.reparentTo(ballActorNP)
  ballModel.setScale(scale)

  ballCollider = ballActorNP.attachNewNode(CollisionNode('ballcnode'))
  ballCollider.node().addSolid(CollisionSphere(0, 0, 0, 1*scale))

  base.physicsMgr.attachPhysicalNode(ballActor)

  collisionHandler.addCollider(ballCollider, ballActorNP)
  base.cTrav.addCollider(ballCollider, collisionHandler)
  ball.reparentTo(base.render)
  return ball

smiley = phyball_dispenser('smiley')

def object_dispenser(num):
  def create_object():
    phyball = phyball_dispenser(random.choice(['frowney', 'watermelon']))
    pos = (random.uniform(-1,1), random.uniform(-.5, .5), 30)
    phyball.setPos(pos)
    
  creates = []
  for i in range(num):
    creates.append(Func(create_object))
    creates.append(Wait(.24))
  Sequence(*creates)

snipstuff.DO.accept('r', object_dispenser, [30])

run()

Also, I don’t understand what the function acce() does. Especially the second line with ‘-repeat’ business:

def acce(k,h,p):
    snipstuff.DO.accept(k,h,p)
    snipstuff.DO.accept(k+'-repeat', h, p)

Thanks!

here you go:

  #creates = []
  #for i in range(num):
    #creates.append(Func(create_object))
    #creates.append(Wait(.24))
  #Sequence(*creates)
  seq=Sequence()
  for i in range(num):
    seq.append(Func(create_object))
    seq.append(Wait(.24))
  seq.start()

as said in the comment:

#** just an helper function - never mind
def acce(k,h,p):

if you don’t get it that’s not an issue, just forget it right now, it is unimportant for the tutorial.

Ok so i have been working through collisions and I understand it much better but i think im missing something. When I try to use your intermediate #2 to integrate it into my project I run into a problem. The colliders get made but they wont collide with each other but when i run it without bitmask though they have no problem colliding with the ground. here is my code (Partialy from your code partially from the manual)

one thing you may notice is that I use a seperate bitmask for the mesh and for the collider sphere this is so I can use my mouse functions but it dosnt appear to be my problem.

class ActorClass(DirectObject):
    def __init__(self):
    
        base.cTrav=CollisionTraverser() #added for collisions
        self.collisionHandler = CollisionHandlerPusher() #added for collisions
        base.cTrav.showCollisions(base.render)
        #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 = []
        self.InnerCollider = []
        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])
            cNode = CollisionNode('smiley'+str(i))
            cNode.addSolid(CollisionSphere(0, 0, 0, 1.1))
            self.InnerCollider.append(self.InnerSphere[i].attachNewNode(cNode))
            self.InnerCollider[i].show()
            self.InnerCollider[i].setCollideMask(BitMask32.bit(1))
            cNode.setCollideMask(BitMask32.bit(1))
            base.cTrav.addCollider(self.InnerCollider[i], self.collisionHandler)
            self.collisionHandler.addCollider(self.InnerCollider[i], self.InnerSphere[i], base.drive.node())
            self.InnerSphere[i].setCollideMask(BitMask32.bit(0))

If I got your excerpt, looks you are trying to use an actor directly as an INTO collide object but that I don’t think is legitimate for the panda3d collision system - you gotta use at least a model if not a collide node. Revise your code to add another collide to act as a into collider or try to use innercollider for this purtpose playing with masks using setIntoCollideMask and setFromCollideMask methods.

That may be what my code is doing but that isnt what i wanted maybe you can show me where this is happening
the plan was to use the current collider as the from and into so colliders cannot cross paths. If this is not posssible i can create a second one but I think this should be possible. I also have the actor setup with a mask but thats just so my mouse ray can find him. So that is what my above code should do but I have no idea where it went horibbly, horibbly wrong.

explain to me what you’re trying to do and I’ll possibly provide you some code to do it, cos actually your goal is quite foggy for me

OK what im trying to do is:
I have an “unknown” amount of guys loading from a csv file (anywhere from 1 to 30) and i need to take there collision objects (all with the same name) and make it so they cannot run into each other (or walls later). Cause right now they can occupy the same spot not good… Thats pretty much what i need to do.

heh, you put it so simple but for what I’m seeing you’re going to do lately, I guess it is a bit more than that. Correct me if I’m wrong but, aren’t you trying to make a bunch of actors laying around a geomipmap terrain driven by the new pandaAI library? If it is so I guess we’d to work it out deeper than just having some collisions bouncing each other. Anyhow, my best guess is to assign a ray to use as FROM collider (acting as the actor’s eye) shifted ahead the actor’s nose of a certain distance and a sphere surrounding the actor as INTO with the same mask as walls. Use then a collisionevent collision handler to detect each collision an read inside the event handler function the collision normal off the into object, to use as the direction to face the from object involved in the collision (to run away from the other object - whichever would be). Unfortunately I ain’t coded a thing exactly lioke that before but I guess you should put that up together easily taking pieces of code off intermediate/step3.py (the from ray, the into sphere and the collision event stuff). Another thing you may dig is this one, where you’ll find a sphere bouncing with walls and other objects - even if use the physics collision handler it is closer to what you need.
Let me know how it goes.

astelix

You apear to know my game better than I do lol. But your right I will give your idea a try and see how it goes although it maybe something to add to the advanced or intermediate when im done as I suspect alot of new Panda Games will now use PandaAI in some form or another

if you’ll be willing to share your code, that will be quite a great addition to this tutorial I’ll do indeed
keep up!