To divide correctly my project, I made a class for main character and another class to manage the scene.
So, using as referece the roaming ralph sample, I saw the technique to create collisions between character and terrain for example, but like I made two classe, what I need to share between objects ?
For example, I’ll need share the CollisionHandler made in each class ?
It doesn’t matter so much about CollisionHandlers, you just need to share a CollisionTraverser between Panda objects that will collide. If they aren’t added together in the same Traverser, then they can’t ever possibly collide together.
If you want simple, you can create a CollisionTraverser and then assign it to base.cTrav. From there, Panda will take care of handling collisions in its game loop. It will call traverse per-frame and automatically reset the fluid positions.
CollisionHandlers can be assigned per object, per class, per whatever. If you want simplicity, define a single CollisionHandler and then just pass it around to all of your classes. Or you can use a CollisionHandler per class – It’s really up to what you want, and how you want to handle collisions.
Even having just one CollisionTraverser isn’t necessary. You can set up a CollisionTraverser any time, and have it collide whenever you want.
This is a common misconception, but it isn’t actually true. Remember, an “into” object doesn’t even have to be added to the Traverser at all; you only add “from” objects to the Traverser. When two objects collide, one of them is a “from” object and the other one is an “into” object; it doesn’t matter for the purposes of the collision whether the “into” object is added to a Traverser or not.
So, the only thing that really matters is that both objects are added to the same scene graph, e.g. both of them are somewhere under render. You can add either or both of them to the CollisionTraverser of your choice.
Oops, poor choice of my words. I was speaking from a purely From-centric viewpoint, ie: Two From objects in separate traversers would never generate contact points against each other.
To iterate, basically anything that has a CollisionSolid assigned to it will be considered as an Into object during a collision pass, by any CollisionTraverser that exists. (As long as, like David said, they are in the same scene graph.)
Now that I fix the problems about camera…come back again to collisions.
So…
Chicken has a little tutorial explaining the use of tags for objects (meshes I believe) to turn “on” the collision (The topic is Exporting ObjectType flags or Tags for your objects: in documentation).
Based on Ralph Roaming sample I did it (this class represent my player):
...
entries = []
for i in range(self.BillyCollisionHandler.getNumEntries()):
entry = self.BillyCollisionHandler.getEntry(i)
print entry.getName()
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() == "gramado"):
self.model.setZ(entries[0].getSurfacePoint(render).getZ())
Here a piece of my level at current state, I give a specific name, but I guess I dont give a collision for the object (in actor for this mesh for example I dont put anything).
Based on tutorial by Paulo Barbeiro, I did some piece of the entire code for the collision, but I believe doesn’t work because I dont put a handler/create collision relative to scene.
Please again I ask your help to understand.
This piece of code is relative to class of player:
Here you see the ray starting from player to down…
By mcunha98
Now the problem…here the piece of code to make (construir) the scene objeto, here the level is loaded and here I believe is need a manipulation from all objects in scene, correct ?
def construir(self):
self.worldspawn = None
if self.model_filename == None:
print "Cenario nao teve arquivo de parametro informado !"
return
if self.billy == None:
print "Billy nao foi passado para o cenario !"
return
arquivo = "level/" + self.model_filename + "/@map.egg"
print "Iniciando carregamento de " + arquivo
self.model = loader.loadModel(arquivo)
objetos = self.model.findAllMatches("**")
self.worldspawn = self.model.findAllMatches("**/worldspawn")
if self.worldspawn != None and self.worldspawn.isEmpty() == False:
self.worldspawn = self.worldspawn.getPath(0)
print "Worldspawn encontrado e Billy posicionado !"
self.ambientLight = render.attachNewNode( AmbientLight( "ambientLight" ) )
self.ambientLight.node().setColor( Vec4( .1, .1, .1, 1 ) )
#custom collisions and triggers ?!?!
for objeto in objetos:
objeto_node = objeto.node()
print "Depurando " + objeto_node.getName() + " do tipo " + str(objeto_node.getType()) + " e classe " + str(objeto_node.getClassType())
if objeto_node.getName() == "cam-pos-001":
#base.camera.setPos(objeto_node.getPos())
print "Campos001 encontrado !"
print "Finalizando carregamento de " + arquivo
self.model.reparentTo(render)
i’d sugest you create a nodepath for the player, and have the model as child to this nodepath, also attach the collision detection to this first nodepath. this way you can place the model at any height.
Actually I prefer explain again the problem before of change my code once again.
I get the collisions for the object Sphere correctly and the ray used to make the pusher action works fine too. But the problem is this…the collision works for the sphere and not for the model.
For example, the legs and the head of model enter in another objects (like houses ), there is a collision, but it work for the sphere and not for the model.
Do you believe, if I change the technique using a nodepath, will work how I want ?
I believe the sphere is the shape of your model, you have to use the appropriated solid for your model or put many solids as you wish, for instance, put solids for the head and legs.
yeah if the head of your model enters in another objects is because it does not have collision solid. You’ll have to attach one to the head.
you said your collision solids are working but the model, so the sphere represents your model, the sphere is your model. Try to scale the sphere a bit more before adding another solid.
From what I’ve seen, I think there’s something wrong in how you set up your scene.
First, make sure collisions are active on all your level meshes.
I suspect of this, since in some screens collisions were working, in others the same set up was screwed!
In the egg file there must be the {Polyset keep descend} tag,
or better if you used the octree script in chicken exporter, all the models will have a {Barrier} counterpart, invisible and optimized for collisions.
After this, try to adapt this little piece of code I took from my project:
self.model is the player’s actor.
def setUpCollision(self):
#sets up the collision solids and the Handlers
base.cTrav=CollisionTraverser("cTrav")
#staying on the ground using a vertical ray and a collisionHandlerFloor
self.floorRay=self.model.attachCollisionRay("", 0, 0, 3, 0, 0, -1,
BitMask32.bit(1), BitMask32.allOff())
#this is the cHadler that will make use of the floorRay
self.floorHandler=CollisionHandlerGravity()
self.floorHandler.setGravity(98)#magic number here
self.floorHandler.addCollider(self.floorRay, self.model)
base.cTrav.addCollider(self.floorRay, self.floorHandler)
#self.floorRay.show()#uncomment to see ray
#this sphere keeps the model from walking through walls
self.wallSphere1=self.model.attachCollisionSphere("", 0, 0, 2, 1.6,
BitMask32.bit(1),
BitMask32.allOff())
#height from self.model=2|radius=1.6
#self.wallSphere1.show()#uncomment to see sphere
#this is the handler that will check for collisions with walls
self.pusherHandler=CollisionHandlerPusher()
self.pusherHandler.addCollider(self.wallSphere1, self.model)
base.cTrav.addCollider(self.wallSphere1, self.pusherHandler)
In your code you weren’t setting CollisionBitMasks, maybe the ray was trying to collide against your other solid giving strange behaviour.
Anyway, the ray must really start from above the point it has to put on the ground, doesn’t it?