Hello I was wondering how to make an object collide with some things and not others, I’ll show you my code thwn explain in more detail.
import direct.directbase.DirectStart
from panda3d.core import CollisionTraverser,CollisionNode
from panda3d.core import CollisionHandlerQueue,CollisionRay, CollisionSphere, CollisionHandlerPusher
from panda3d.core import Filename,AmbientLight,DirectionalLight
from panda3d.core import PandaNode,NodePath,Camera,TextNode
from panda3d.core import Vec3,Vec4,BitMask32
from direct.gui.OnscreenText import OnscreenText
from direct.actor.Actor import Actor
from direct.showbase.DirectObject import DirectObject
import random, sys, os, math
class World(object, DirectObject):
def __init__(self):
# get the centre of the window
self.winXhalf = base.win.getXSize()/2 # get the X size, then halve it.
self.winYhalf = base.win.getYSize()/2 # get the Y size, then halve it.
# define the traverser and our collision handlers
base.cTrav = CollisionTraverser() # traverser
pusher = CollisionHandlerPusher() # collison handler pusher
self.manGroundHandler = CollisionHandlerQueue() # collision handler queue
# set the base win colour to (0,0,0,1) (black)
base.win.setClearColor(Vec4(0,0,0,1))
# load up environment
self.terrain = loader.loadModel('models/world')
self.terrain.reparentTo(render)
self.terrain.setPos(0,0,0)
# Create the main character, man
manStartPos = self.terrain.find("**/start_point").getPos()
self.man = loader.loadModel('frowney') # load frowney as our model that we move around
self.man.reparentTo(render)
self.man.setScale(.1)
self.man.setPos(manStartPos) # set his start pos to "manStartPos" whixh we defined ealier
# add a collision solid to "man"
Cnode = CollisionNode('man') # define a Cnode and name it "man"
Cnode.addSolid(CollisionSphere(0,0,0,1)) # add a collision sphere solid to "Cnode"
Cman = self.man.attachNewNode(Cnode) # attach the collision solid to "man"
# Create a floater object. We use the "floater" as a temporary
# variable in a variety of calculations.
self.floater = NodePath(PandaNode("floater"))
self.floater.reparentTo(render)
# a tonne of variables that we will use later
speed = 25
Forward = Vec3(0,speed*2,0)
Back = Vec3(0,-speed,0)
Left = Vec3(-speed,0,0)
Right = Vec3(speed,0,0)
Stop = Vec3(0)
self.walk = Stop
self.strife = Stop
# accept all the controls
self.accept( "escape",sys.exit ) # close window
self.accept( "s" , self.__setattr__,["walk",Back] ) # walk back
self.accept( "w" , self.__setattr__,["walk",Forward]) # walk forward
self.accept( "s-up" , self.__setattr__,["walk",Stop] )
self.accept( "w-up" , self.__setattr__,["walk",Stop] )
self.accept( "a" , self.__setattr__,["strife",Left]) # walk left
self.accept( "d" , self.__setattr__,["strife",Right] ) # walk right
self.accept( "a-up" , self.__setattr__,["strife",Stop] )
self.accept( "d-up" , self.__setattr__,["strife",Stop] )
taskMgr.add(self.move, 'move-task')
# Game state variables
self.isMoving = False
# Set up the camera
base.disableMouse() # disables default camera controls
base.camera.reparentTo(self.man) # reparent the camera to "man"
base.camera.setPos(0, 5, 2) # set the position of the camera relative to "man"
base.camLens.setNearFar(1.1,1000)
# We will detect the height of the terrain by creating a collision
# ray and casting it downward toward the terrain. One ray will
# start above ralph's head, and the other will start above the camera.
# A ray may hit the terrain, or it may hit a rock or a tree. If it
# hits the terrain, we can detect the height. If it hits anything
# else, we rule that the move is illegal.
self.manGroundRay = CollisionRay() # define a collision ray
self.manGroundRay.setOrigin(0,0,1000) # set the origin
self.manGroundRay.setDirection(0,0,-1) # set the direction
self.manGroundCol = CollisionNode('manRay') # define a collision node
self.manGroundCol.addSolid(self.manGroundRay) # add a solid to the collision node
self.manGroundCol.setFromCollideMask(BitMask32.bit(0)) # set a from bitmask
self.manGroundCol.setIntoCollideMask(BitMask32.allOff())# set an into bitmask
self.manGroundColNp = self.man.attachNewNode(self.manGroundCol) #attach "manGroundCol" to "man"
base.cTrav.addCollider(self.manGroundColNp, self.manGroundHandler) # add "man" to the traverser
base.cTrav.showCollisions(render) # show the collisions
base.cTrav.addCollider(Cman, pusher) # add the man's collision solid to the traverser
pusher.addCollider(Cman, self.man, base.drive.node()) # add the man's collison solid to the pusher collision handler
def move(self, task):
# move
dt=globalClock.getDt() # get the global clock
# mouse
md = base.win.getPointer(0) # calls the mouse
x = md.getX()
y = md.getY()
# makes it so that when the mouse moves the camera moves
if base.win.movePointer(0, self.winXhalf, self.winYhalf):
self.man.setH(self.man, (x - self.winXhalf)*-0.1)
base.camera.setP( clampScalar(-90,90, base.camera.getP() - (y - self.winYhalf)*0.1) )
# move where the keys set it
moveVec=(self.walk+self.strife)*dt # horizontal
self.man.setFluidPos(self.man,moveVec)
# Now check for collisions.
base.cTrav.traverse(render)
# Adjust man's Z coordinate. If man's ray hit terrain,
# update his Z. If it hit anything else, or didn't hit anything, put
# him back where he was last frame.
# get man's current pos
startpos = self.man.getPos()
entries = []
for i in range(self.manGroundHandler.getNumEntries()):
entry = self.manGroundHandler.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() == "terrain"):
self.man.setZ(entries[0].getSurfacePoint(render).getZ())
else:
self.man.setPos(startpos)
return task.cont
w = World()
run()
Okay so I have it so that “man” can walk around on uneven terrain but what what happens is when I add a collision sphere I collide with the collision mesh that’s around the world model and stops me cause I’ve added man to the pusherhandler which I will use later for other objects. So what I need is to say to the program that I don’t want to collide with the mesh around the world model but I want to collide with everything else.
And there was another thing that didn’t make sense to me in the roaming-ralph tutorial what does this mean
for i in range(self.manGroundHandler.getNumEntries()):
I don’t get the “for i in range” bit can someone please help by explaining this to me
And now just one more thing you may notice that if you take away the collision sphere around man it will he will walk around like on uneven terrain but when he collides with say a rock or tree the collision ray knows it’s colliding with it but the model just goes through/over it so can someone please point out the bit of code in the roaming-ralph tutorial that makes him Ralph stop when he hits a tree/rock
thanks.