def replaceCollisionPolysWithPlanes(self, model): newCollisionNode = PM.CollisionNode('collisions') newCollideMask = PM.BitMask32(0) planes = [] collList = model.findAllMatches('**/+CollisionNode') if not collList: collList = [model] for cnp in collList: cn = cnp.node() if not isinstance(cn, PM.CollisionNode): self.notify.warning('Not a collision node: %s' % repr(cnp)) break newCollideMask = newCollideMask | cn.getIntoCollideMask() for i in range(cn.getNumSolids()): solid = cn.getSolid(i) if isinstance(solid, PM.CollisionPolygon): plane = PM.Plane(solid.getPlane()) planes.append(plane) else: self.notify.warning('Unexpected collision solid: %s' % repr(solid)) newCollisionNode.addSolid(plane) newCollisionNode.setIntoCollideMask(newCollideMask) threshold = 0.1 planes.sort(lambda p1, p2: p1.compareTo(p2, threshold)) lastPlane = None for plane in planes: if lastPlane == None or plane.compareTo(lastPlane, threshold) != 0: cp = PM.CollisionPlane(plane) newCollisionNode.addSolid(cp) lastPlane = plane return PM.NodePath(newCollisionNode)
def RebuildGeomNodesToColPolys(incomingNodes): """ Converts GeomNodes into CollisionPolys in a straight 1-to-1 conversion Returns a new NodePath containing the CollisionNodes """ parent = pm.NodePath('cGeomConversionParent') for c in incomingNodes: gni = 0 geomNode = c.node() for g in range(geomNode.getNumGeoms()): geom = geomNode.getGeom(g).decompose() vdata = geom.getVertexData() vreader = pm.GeomVertexReader(vdata, 'vertex') cChild = pm.CollisionNode('cGeom-%s-gni%i' % (c.getName(), gni)) gni += 1 for p in range(geom.getNumPrimitives()): prim = geom.getPrimitive(p) for p2 in range(prim.getNumPrimitives()): s = prim.getPrimitiveStart(p2) e = prim.getPrimitiveEnd(p2) v = [] for vi in range(s, e): vreader.setRow(prim.getVertex(vi)) v.append(vreader.getData3f()) colPoly = pm.CollisionPolygon(*v) cChild.addSolid(colPoly) parent.attachNewNode(cChild) return parent
def privGotSpec(self, levelSpec): DistCogdoLevelGame.privGotSpec(self, levelSpec) levelMgr = self.getEntity(LevelConstants.LevelMgrEntId) self.endVault = levelMgr.geom self.endVault.reparentTo(self.geomRoot) self.endVault.findAllMatches('**/MagnetArms').detach() self.endVault.findAllMatches('**/Safes').detach() self.endVault.findAllMatches('**/MagnetControlsAll').detach() cn = self.endVault.find('**/wallsCollision').node() cn.setIntoCollideMask(OTPGlobals.WallBitmask | ToontownGlobals.PieBitmask | PM.BitMask32.lowerOn(3) << 21) walls = self.endVault.find('**/RollUpFrameCillison') walls.detachNode() self.evWalls = self.replaceCollisionPolysWithPlanes(walls) self.evWalls.reparentTo(self.endVault) self.evWalls.stash() floor = self.endVault.find('**/EndVaultFloorCollision') floor.detachNode() self.evFloor = self.replaceCollisionPolysWithPlanes(floor) self.evFloor.reparentTo(self.endVault) self.evFloor.setName('floor') plane = PM.CollisionPlane( PM.Plane(PM.Vec3(0, 0, 1), PM.Point3(0, 0, -50))) planeNode = PM.CollisionNode('dropPlane') planeNode.addSolid(plane) planeNode.setCollideMask(ToontownGlobals.PieBitmask) self.geomRoot.attachNewNode(planeNode)
def privGotSpec(self, levelSpec): DistCogdoLevelGame.privGotSpec(self, levelSpec) levelMgr = self.getEntity(LevelConstants.LevelMgrEntId) self.endVault = levelMgr.geom self.endVault.reparentTo(self.geomRoot) # Clear out unneeded backstage models from the EndVault, if # they're in the file. self.endVault.findAllMatches('**/MagnetArms').detach() self.endVault.findAllMatches('**/Safes').detach() self.endVault.findAllMatches('**/MagnetControlsAll').detach() # Flag the collisions in the end vault so safes and magnets # don't try to go through the wall. cn = self.endVault.find('**/wallsCollision').node() cn.setIntoCollideMask(OTPGlobals.WallBitmask | ToontownGlobals.PieBitmask | (PM.BitMask32.lowerOn(3) << 21)) # Find all the wall polygons and replace them with planes, # which are solid, so there will be zero chance of safes or # toons slipping through a wall. walls = self.endVault.find('**/RollUpFrameCillison') walls.detachNode() self.evWalls = self.replaceCollisionPolysWithPlanes(walls) self.evWalls.reparentTo(self.endVault) # Initially, these new planar walls are stashed, so they don't # cause us trouble in the intro movie or in battle one. We # will unstash them when we move to battle three. self.evWalls.stash() # Also replace the floor polygon with a plane, and rename it # so we can detect a collision with it. floor = self.endVault.find('**/EndVaultFloorCollision') floor.detachNode() self.evFloor = self.replaceCollisionPolysWithPlanes(floor) self.evFloor.reparentTo(self.endVault) self.evFloor.setName('floor') # Also, put a big plane across the universe a few feet below # the floor, to catch things that fall out of the world. plane = PM.CollisionPlane( PM.Plane(PM.Vec3(0, 0, 1), PM.Point3(0, 0, -50))) planeNode = PM.CollisionNode('dropPlane') planeNode.addSolid(plane) planeNode.setCollideMask(ToontownGlobals.PieBitmask) self.geomRoot.attachNewNode(planeNode)
def fromCol(parent, handler, type, mask=P.BitMask32.allOn()): """Setup a from collision solid. Last I checked CollisionPolygon 's and CollisionTube 's can't be used as from solids. If you pass one, it won't hit anything""" nodepath = parent.attachNewNode(P.CollisionNode('frmcol')) nodepath.node().addSolid(type) #add the solid to the new collisionNode nodepath.node().setFromCollideMask(mask) #allow selective masking nodepath.setCollideMask(P.BitMask32.allOff()) #it's a from solid only. ####uncomment this line to make the collision solid visible: ##nodepath.show() base.cTrav.addCollider(nodepath, handler) #add to the traverser try: #the next line doesn't work on queues. (not necessary) handler.addCollider(nodepath, parent) #keep the ward out of trouble except: pass #Don't care. This method needs to work on queues too. return nodepath #we might need the new CollisionNode again later.
def enterLoaded(self): DistCogdoLevelGameAI.enterLoaded(self) self.scene = PM.NodePath('scene') cn = PM.CollisionNode('walls') cs = PM.CollisionSphere(0, 0, 0, 13) cn.addSolid(cs) cs = PM.CollisionInvSphere(0, 0, 0, 42) cn.addSolid(cs) self.attachNewNode(cn) for i in xrange(CogdoGameConsts.MaxPlayers): crane = DistCogdoCraneAI(self.air, self, i) crane.generateWithRequired(self.zoneId) self._cranes[i] = crane for i in xrange(len(self._moneyBags)): mBag = DistCogdoCraneMoneyBagAI(self.air, self, i) mBag.generateWithRequired(self.zoneId) self._moneyBags[i] = mBag
def replaceCollisionPolysWithPlanes(self, model): newCollisionNode = PM.CollisionNode('collisions') newCollideMask = PM.BitMask32(0) planes = [] collList = model.findAllMatches('**/+CollisionNode') if not collList: collList = [model] for cnp in collList: cn = cnp.node() if not isinstance(cn, PM.CollisionNode): self.notify.warning("Not a collision node: %s" % (repr(cnp))) break newCollideMask = newCollideMask | cn.getIntoCollideMask() for i in range(cn.getNumSolids()): solid = cn.getSolid(i) if isinstance(solid, PM.CollisionPolygon): # Save the plane defined by this polygon plane = PM.Plane(solid.getPlane()) planes.append(plane) else: self.notify.warning("Unexpected collision solid: %s" % (repr(solid))) newCollisionNode.addSolid(plane) newCollisionNode.setIntoCollideMask(newCollideMask) # Now sort all of the planes and remove the nonunique ones. # We can't use traditional dictionary-based tricks, because we # want to use Plane.compareTo(), not Plane.__hash__(), to make # the comparison. threshold = 0.1 planes.sort(lambda p1, p2: p1.compareTo(p2, threshold)) lastPlane = None for plane in planes: if lastPlane == None or plane.compareTo(lastPlane, threshold) != 0: cp = PM.CollisionPlane(plane) newCollisionNode.addSolid(cp) lastPlane = plane return PM.NodePath(newCollisionNode)
def __init__(self, pos=None, color=(0.6, 0.8, 0.5, 1), scale=12, h=8, size=33, trees=0.7): # Initialise primary NodePath which everything else is parented to if pos is None: pos = P.Vec3(0, 0, 0) self.pos = pos self.prime = P.NodePath('Terrain primary NodePath') self.prime.setPos(self.pos) # Create terrain models (rendering and collision) self.tnp, self.collnp = makeTerrain(size=size, h=h) self.tnp.reparentTo(self.prime) self.tnp.setColor(*color) self.tnp.setScale(scale) # Shift the collision terrain a bit so rays from trees hit self.collnp.setPos(self.collnp, .0001, .0001, 0) self.collnp.setCollideMask(C.floorMASK) # All trees in the scene are parented to one NodePath for flattening self.trees = self.prime.attachNewNode(P.PandaNode('trees')) self.treesColl = self.prime.attachNewNode(P.CollisionNode('treesColl')) self.treesColl.node().setIntoCollideMask(offMASK) self.treesColl.node().setFromCollideMask(obstacleMASK) #self.treesColl.show() vehicleCTrav.addCollider(self.treesColl, obstacleHandler) # Initialise trees img = greenNoise(imgSize=(size, size), scale=0.25) for x in range(0, size - 1): for y in range(0, size - 1): if img.getGreen(x, y) > trees: treepos = P.Vec3(x * scale + 0.5 * scale, y * scale + 0.5 * scale, 50) tree = Tree(pos=treepos) tree.prime.reparentTo(self.trees) taskMgr.add(self.flatten, "Terrain flatten task")
def __init__(self, pos=None): """Initialise the tree.""" # Models and CollisionSolids are parented to one prime NodePath if pos is None: pos = P.Vec3(0, 0, 0) self.pos = pos self.prime = P.NodePath('tree') self.prime.setPos(self.pos) dir = "models/trees" # FIXME: hardcoded models dir # Choose a random model from dir and load it. trees = [ f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f)) and f.endswith('.egg') ] tree = random.choice(trees) self.np = loadModel(os.path.join(dir, tree), self.prime) # TODO: Give each tree a random orientation # Initialise the Tree's CollisionRay which is used with a # CollisionHandlerQueue to find the height of the terrain below the # tree and move the tree to that height (see self.step) self.raynp = self.prime.attachNewNode(P.CollisionNode('colNode')) self.raynp.node().addSolid(P.CollisionRay(0, 0, 3, 0, 0, -1)) self.handler = P.CollisionHandlerQueue() cTrav.addCollider(self.raynp, self.handler) #self.raynp.show() # We only want our CollisionRay to collide with the collision # geometry of the terrain, se we set a mask here. self.raynp.node().setFromCollideMask(C.floorMASK) self.raynp.node().setIntoCollideMask(C.offMASK) # Add a task for this Tree to the global task manager. taskMgr.add(self.step, "Tree step task")
def __init__(self): """Initialise the scene.""" # Show the framerate base.setFrameRateMeter(True) # Initialise terrain: # Make 4 terrain nodepath objects with different hilliness values # and arrange them side-by-side in a 2x2 grid, giving a big terrain # with variable hilly and flat areas. color = (0.6, 0.8, 0.5, 1) # Bright green-ish scale = 12 height = 18 # FIXME: For now we are raising the terrain so it # floats above the sea to prevent lakes from # appearing (but you still get them sometimes) t1 = Terrain(color=color, scale=scale, trees=0.7, pos=P.Point3(0, 0, height)) t1.prime.reparentTo(render) t2 = Terrain(color=color, scale=scale, h=24, pos=P.Point3(32 * scale, 0, height), trees=0.5) t2.prime.reparentTo(render) t3 = Terrain(color=color, scale=scale, h=16, pos=P.Point3(32 * scale, 32 * scale, height), trees=0.3) t3.prime.reparentTo(render) t4 = Terrain(color=color, scale=scale, h=2, pos=P.Point3(0, 32 * scale, height), trees=0.9) t4.prime.reparentTo(render) #tnp1.setPos(tnp1,-32,-32,terrainHeight) # Initialise sea sea = Sea() # Initialise skybox. self.box = loader.loadModel("models/skybox/space_sky_box.x") self.box.setScale(6) self.box.reparentTo(render) # Initialise characters self.characters = [] self.player = C.Character(model='models/eve', run='models/eve-run', walk='models/eve-walk') self.player.prime.setZ(100) self.player._pos = SteerVec(32 * 12 + random.random() * 100, 32 * 12 + random.random() * 100) self.player.maxforce = 0.4 self.player.maxspeed = 0.55 EdgeScreenTracker(self.player.prime, dist=200) # Setup camera for i in range(0, 11): self.characters.append(C.Character()) self.characters[i].prime.setZ(100) self.characters[i].wander() self.characters[i].maxforce = 0.3 self.characters[i].maxspeed = 0.2 self.characters[i]._pos = SteerVec(32 * 12 + random.random() * 100, 32 * 12 + random.random() * 100) C.setContainer( ContainerSquare(pos=SteerVec(32 * 12, 32 * 12), radius=31 * 12)) #C.toggleAnnotation() # Initialise keyboard controls. self.accept("c", C.toggleAnnotation) self.accept("escape", sys.exit) # Setup CollisionRay and CollisionHandlerQueue for mouse picking. self.pickerQ = P.CollisionHandlerQueue() self.picker = camera.attachNewNode( P.CollisionNode('Picker CollisionNode')) self.picker.node().addSolid(P.CollisionRay()) # We want the picker ray to collide with the floor and nothing else. self.picker.node().setFromCollideMask(C.floorMASK) self.picker.setCollideMask(P.BitMask32.allOff()) base.cTrav.addCollider(self.picker, self.pickerQ) try: handler.addCollider(self.picker, camera) except: pass self.accept('mouse1', self.onClick) # Set the far clipping plane to be far enough away that we can see the # skybox. base.camLens.setFar(10000) # Initialise lighting self.alight = AmbientLight('alight') self.alight.setColor(VBase4(0.35, 0.35, 0.35, 1)) self.alnp = render.attachNewNode(self.alight) render.setLight(self.alnp) self.dlight = DirectionalLight('dlight') self.dlight.setColor(VBase4(0.4, 0.4, 0.4, 1)) self.dlnp = render.attachNewNode(self.dlight) self.dlnp.setHpr(45, -45, 0) render.setLight(self.dlnp) self.plight = PointLight('plight') self.plight.setColor(VBase4(0.8, 0.8, 0.5, 1)) self.plnp = render.attachNewNode(self.plight) self.plnp.setPos(160, 160, 50) self.slight = Spotlight('slight') self.slight.setColor(VBase4(1, 1, 1, 1)) lens = PerspectiveLens() self.slight.setLens(lens) self.slnp = render.attachNewNode(self.slight) self.slnp.setPos(-20, -20, 20) self.slnp.lookAt(50, 50, 0) # Initialise some scene-wide exponential fog colour = (0.5, 0.8, 0.8) self.expfog = Fog("Scene-wide exponential Fog object") self.expfog.setColor(*colour) self.expfog.setExpDensity(0.0005) render.setFog(self.expfog) base.setBackgroundColor(*colour) # Add a task for this Plant to the global task manager. self.stepcount = 0 taskMgr.add(self.step, "Plant step task")