def loadCollisions(self):
     sphere = CollisionSphere(0, 0, 0, 1)
     sphere.setTangible(0)
     node = CollisionNode(self.uniqueName('collectableCollNode'))
     node.addSolid(sphere)
     node.setCollideMask(CIGlobals.WallBitmask)
     self.collSensorNodePath = self.attachNewNode(node)
     ray = CollisionRay(0.0, 0.0, CollisionHandlerRayStart, 0.0, 0.0, -1.0)
     rayNode = CollisionNode(self.uniqueName('collectableRayNode'))
     rayNode.addSolid(ray)
     rayNode.setFromCollideMask(CIGlobals.FloorBitmask)
     rayNode.setIntoCollideMask(BitMask32.allOff())
     self.collRayNodePath = self.attachNewNode(rayNode)
     lifter = CollisionHandlerFloor()
     lifter.addCollider(self.collRayNodePath, self)
     base.cTrav.addCollider(self.collRayNodePath, lifter)
Esempio n. 2
0
class Physics:
    def __init__(self):
        self.rayCTrav = CollisionTraverser("collision traverser for ray tests")
        #self.pusher = PhysicsCollisionHandler()
        self.pusher = CollisionHandlerPusher()
        self.pusher.addInPattern('%fn-in-%in')
        self.pusher.addOutPattern('%fn-out-%in')
        self.pusher.addInPattern('%fn-in')
        self.pusher.addOutPattern('%fn-out')

    def startPhysics(self):
        #self.actorNode = ActorNode("playerPhysicsControler")
        #base.physicsMgr.attachPhysicalNode(self.actorNode)
        #self.actorNode.getPhysicsObject().setMass(self.player_mass)
        #self.mainNode = render.attachNewNode(self.actorNode)
        self.mainNode = render.attachNewNode("CharacterColliders")
        self.reparentTo(self.mainNode)

        charCollisions = self.mainNode.attachNewNode(CollisionNode(self.char_collision_name))
        #charCollisions.node().addSolid(CollisionSphere(0, 0, self.player_height/4.0, self.player_height/4.0))
        #charCollisions.node().addSolid(CollisionSphere(0, 0, self.player_height/4.0*3.05, self.player_height/4.0))
        charCollisions.node().addSolid(CollisionSphere(0, 0, self.player_height/2.0, self.player_height/4.0))
        charCollisions.node().setIntoCollideMask(BitMask32(0x80))  # 1000 0000
        if self.show_collisions:
            charCollisions.show()
        self.pusher.addCollider(charCollisions, self.mainNode)
        base.cTrav.addCollider(charCollisions, self.pusher)

        charFFootCollisions = self.attachNewNode(CollisionNode("floor_ray"))
        charFFootCollisions.node().addSolid(CollisionRay(0, 0, 0.5, 0, 0, -1))
        #charFFootCollisions.node().addSolid(CollisionSegment((0, 0, 0.2), (0, 0, -1)))
        charFFootCollisions.node().setIntoCollideMask(BitMask32.allOff())
        charFFootCollisions.node().setFromCollideMask(BitMask32(0x7f))  # 0111 1111
        if self.show_collisions:
            charFFootCollisions.show()

        self.floor_handler = CollisionHandlerFloor()
        self.floor_handler.addCollider(charFFootCollisions, self.mainNode)
        #self.floor_handler.setOffset(0)
        self.floor_handler.setMaxVelocity(5)
        base.cTrav.addCollider(charFFootCollisions, self.floor_handler)

        self.accept("{}-in".format(self.char_collision_name), self.checkCharCollisions)

        self.raytest_segment = CollisionSegment(0, 1)
        self.raytest_np = render.attachNewNode(CollisionNode("testRay"))
        self.raytest_np.node().addSolid(self.raytest_segment)
        self.raytest_np.node().setIntoCollideMask(BitMask32.allOff())
        self.raytest_np.node().setFromCollideMask(BitMask32(0x7f))  # 0111 1111
        if self.show_collisions:
            self.raytest_np.show()

        self.raytest_queue = CollisionHandlerQueue()
        self.rayCTrav.addCollider(self.raytest_np, self.raytest_queue)

    def stopPhysics(self):
        self.raytest_segment.removeNode()
        self.pusher.clearColliders()
        self.floor_handler.clearColliders()
        self.rayCTrav.clearColliders()

    def updatePlayerPos(self, speed, heading, dt):
        if heading is not None:
            self.mainNode.setH(camera, heading)
            self.mainNode.setP(0)
            self.mainNode.setR(0)
        self.mainNode.setFluidPos(self.mainNode, speed)
        self.doStep()

    def checkCharCollisions(self, args):
        self.doStep()

    def doStep(self):
        # do the step height check
        tmpNP = self.mainNode.attachNewNode("temporary")
        tmpNP.setPos(self.mainNode, 0, 0, -self.stepheight)
        pointA = self.mainNode.getPos(render)
        pointA.setZ(pointA.getZ() + self.player_height/1.8)
        pointB = tmpNP.getPos(render)
        if pointA == pointB: return
        char_step_collision = self.getFirstCollisionInLine(pointA, pointB)
        tmpNP.removeNode()
        if char_step_collision is not None:
            self.mainNode.setFluidZ(char_step_collision.getZ())
            return True
        return False

    def getFirstCollisionInLine(self, pointA, pointB):
        """A simple raycast check which will return the first collision point as
        seen from point A towards pointB"""
        self.raytest_segment.setPointA(pointA)
        self.raytest_segment.setPointB(pointB)
        self.rayCTrav.traverse(render)
        self.raytest_queue.sortEntries()
        pos = None
        if self.raytest_queue.getNumEntries() > 0:
            pos = self.raytest_queue.getEntry(0).getSurfacePoint(render)
        return pos
Esempio n. 3
0
class Physics:
    def __init__(self):
        self.rayCTrav = CollisionTraverser("collision traverser for ray tests")
        #self.pusher = PhysicsCollisionHandler()
        self.pusher = CollisionHandlerPusher()
        self.pusher.addInPattern('%fn-in-%in')
        self.pusher.addOutPattern('%fn-out-%in')
        self.pusher.addInPattern('%fn-in')
        self.pusher.addOutPattern('%fn-out')

    def startPhysics(self):
        #self.actorNode = ActorNode("playerPhysicsControler")
        #base.physicsMgr.attachPhysicalNode(self.actorNode)
        #self.actorNode.getPhysicsObject().setMass(self.player_mass)
        #self.mainNode = render.attachNewNode(self.actorNode)
        self.mainNode = render.attachNewNode("CharacterColliders")
        self.reparentTo(self.mainNode)

        charCollisions = self.mainNode.attachNewNode(
            CollisionNode(self.char_collision_name))
        #charCollisions.node().addSolid(CollisionSphere(0, 0, self.player_height/4.0, self.player_height/4.0))
        #charCollisions.node().addSolid(CollisionSphere(0, 0, self.player_height/4.0*3.05, self.player_height/4.0))
        charCollisions.node().addSolid(
            CollisionSphere(0, 0, self.player_height / 2.0,
                            self.player_height / 4.0))
        charCollisions.node().setIntoCollideMask(BitMask32(0x80))  # 1000 0000
        if self.show_collisions:
            charCollisions.show()
        self.pusher.addCollider(charCollisions, self.mainNode)
        base.cTrav.addCollider(charCollisions, self.pusher)

        charFFootCollisions = self.attachNewNode(CollisionNode("floor_ray"))
        charFFootCollisions.node().addSolid(CollisionRay(0, 0, 0.5, 0, 0, -1))
        #charFFootCollisions.node().addSolid(CollisionSegment((0, 0, 0.2), (0, 0, -1)))
        charFFootCollisions.node().setIntoCollideMask(BitMask32.allOff())
        charFFootCollisions.node().setFromCollideMask(
            BitMask32(0x7f))  # 0111 1111
        if self.show_collisions:
            charFFootCollisions.show()

        self.floor_handler = CollisionHandlerFloor()
        self.floor_handler.addCollider(charFFootCollisions, self.mainNode)
        #self.floor_handler.setOffset(0)
        self.floor_handler.setMaxVelocity(5)
        base.cTrav.addCollider(charFFootCollisions, self.floor_handler)

        self.accept("{}-in".format(self.char_collision_name),
                    self.checkCharCollisions)

        self.raytest_segment = CollisionSegment(0, 1)
        self.raytest_np = render.attachNewNode(CollisionNode("testRay"))
        self.raytest_np.node().addSolid(self.raytest_segment)
        self.raytest_np.node().setIntoCollideMask(BitMask32.allOff())
        self.raytest_np.node().setFromCollideMask(BitMask32(0x7f))  # 0111 1111
        if self.show_collisions:
            self.raytest_np.show()

        self.raytest_queue = CollisionHandlerQueue()
        self.rayCTrav.addCollider(self.raytest_np, self.raytest_queue)

    def stopPhysics(self):
        self.raytest_segment.removeNode()
        self.pusher.clearColliders()
        self.floor_handler.clearColliders()
        self.rayCTrav.clearColliders()

    def updatePlayerPos(self, speed, heading, dt):
        if heading is not None:
            self.mainNode.setH(camera, heading)
            self.mainNode.setP(0)
            self.mainNode.setR(0)
        self.mainNode.setFluidPos(self.mainNode, speed)
        self.doStep()

    def checkCharCollisions(self, args):
        self.doStep()

    def doStep(self):
        # do the step height check
        tmpNP = self.mainNode.attachNewNode("temporary")
        tmpNP.setPos(self.mainNode, 0, 0, -self.stepheight)
        pointA = self.mainNode.getPos(render)
        pointA.setZ(pointA.getZ() + self.player_height / 1.8)
        pointB = tmpNP.getPos(render)
        if pointA == pointB: return
        char_step_collision = self.getFirstCollisionInLine(pointA, pointB)
        tmpNP.removeNode()
        if char_step_collision is not None:
            self.mainNode.setFluidZ(char_step_collision.getZ())
            return True
        return False

    def getFirstCollisionInLine(self, pointA, pointB):
        """A simple raycast check which will return the first collision point as
        seen from point A towards pointB"""
        self.raytest_segment.setPointA(pointA)
        self.raytest_segment.setPointB(pointB)
        self.rayCTrav.traverse(render)
        self.raytest_queue.sortEntries()
        pos = None
        if self.raytest_queue.getNumEntries() > 0:
            pos = self.raytest_queue.getEntry(0).getSurfacePoint(render)
        return pos
Esempio n. 4
0
    def __init__(self):
        messenger.toggleVerbose()

        ShowBase.__init__(self)

        self.environ = self.loader.loadModel("models/falcon")
        self.environ.reparentTo(self.render)
        self.environ.setScale(0.25, 0.25, 0.25)
        self.environ.setPos(-8, 42, 0)

        self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
        self.taskMgr.add(self.moveCameraTask, "MoveCameraTask")
        self.taskMgr.add(self.playerGravity, "PlayerGravity")
        #self.taskMgr.add(self.collTask, "CollisionTask")


        self.pandaActor = Actor("models/panda-model",
                                {"walk": "models/panda-walk4"})
        self.pandaActor.setScale(0.005, 0.005, 0.005)
        self.pandaActor.setPos(0, 0, 10)
        self.pandaActor.reparentTo(self.render)

        # Initialize the collision traverser.
        self.cTrav = CollisionTraverser()
        self.cTrav.showCollisions(self.render)
         
        # Initialize the Pusher collision handler.
        pusher = CollisionHandlerPusher()
 
        # Create a collision node for this object.
        cNode = CollisionNode('panda')
        # Attach a collision sphere solid to the collision node.
        cNode.addSolid(CollisionSphere(0, 0, 0, 600))
        # Attach the collision node to the object's model.
        pandaC = self.pandaActor.attachNewNode(cNode)
        # Set the object's collision node to render as visible.
        pandaC.show()
 
        # Create a collsion node for this object.
        cNode = CollisionNode('environnement')
        # Attach a collision sphere solid to the collision node.
        cNode.addSolid(CollisionSphere(-1.3, 19, 0.5, 2.5))
        cNode.addSolid(CollisionPlane(Plane(Vec3(0,0,1), Point3(0,0,0.2))))
        # Attach the collision node to the object's model.
        environC = self.environ.attachNewNode(cNode)
        # Set the object's collision node to render as visible.
        environC.show()
 
        # Add the Pusher collision handler to the collision traverser.
        self.cTrav.addCollider(pandaC, pusher)
        # Add the 'frowney' collision node to the Pusher collision handler.
        pusher.addCollider(pandaC, self.environ, base.drive.node())
         
        fromObject = self.pandaActor.attachNewNode(CollisionNode('colNode'))
        fromObject.node().addSolid(CollisionRay(0, 0, 0, 0, 0, -1))
        lifter = CollisionHandlerFloor()
        lifter.addCollider(fromObject, self.pandaActor)
        self.cTrav.addCollider(pandaC, lifter)

        # Have the 'smiley' sphere moving to help show what is happening.
        #frowney.posInterval(5, Point3(5, 25, 0), startPos=Point3(-5, 25, 0), fluid=1).loop()
 
        #self.stuff = Actor("models/panda-model")
        #self.stuff.setScale(0.005, 0.005, 0.005)
        #self.stuff.setPos(-1.3, 19., 0.5)
        #self.stuff.reparentTo(self.render)

#        cTrav = CollisionTraverser()
#        ceh = CollisionHandlerQueue()
#        #ceh.addInPattern('%fn-into-%in')
#        #ceh.addAgainPattern('%fn-again-%in')
#        #ceh.addOutPattern('%fn-outof-%in')
#        self.pandaColl = self.pandaActor.attachNewNode(CollisionNode('cnode'))
#        self.pandaColl.node().addSolid(CollisionSphere(self.pandaActor.getChild( 0 ).getBounds( ).getCenter(), 400))
#        self.pandaColl.show()
#        cTrav.addCollider( self.pandaColl, ceh )
#        self.cTrav = cTrav
#        self.cTrav.showCollisions(self.render)
#        self.queue = ceh
#        cs = CollisionSphere(-1.3, 19, 0.5, 2.5)
#        pl = CollisionPlane(Plane(Vec3(0,0,1), Point3(0,0,0.2)))
#        # ray = CollisionRay(self.pandaActor.getPos(), Vec3(0,0,-1))
#        cnodePath = self.render.attachNewNode(CollisionNode('cnode'))
#        # rayNodePath = self.render.attachNewNode(CollisionNode('raynode'))
#        cnodePath.node().addSolid(cs)
#        cnodePath.node().addSolid(pl)
#        # rayNodePath.node().addSolid(ray)
#        cnodePath.show()
#        # rayNodePath.show()
#        #rayNodePath.reparentTo(self.pandaActor)
        #self.accept('car-into-rail', handleRailCollision)
        #cTrav.addCollider(cnodePath, ceh)

        self.camera.reparentTo(self.pandaActor)
        self.camera.setPos(0., 1050., 1000.)

        self.camAlpha = 180
        self.camBeta = 0
        self.moving = []
        self.playerAltitude = 0
        self.jumping = False
        self.inJump = False
        self.playerFallingSpeed = 0
        self.player = Mass(80)
        base.useDrive()
        #base.disableMouse( ) # disable the default camera controls that are created for us
        self.keyBoardSetup()
Esempio n. 5
0
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.seeNode = self.render.attachNewNode("see")

        self.cam.reparentTo(self.seeNode)
        self.cam.setPos(0, 0, 5)

        self.fpscamera = fpscontroller.FpsController(self, self.seeNode)
        self.fpscamera.setFlyMode(True)

        self.prevPos = self.fpscamera.getPos()
        self.prevInto = None
        self.info = self.genLabelText("Position: <unknown>", 4)

        self.makeInstructions()
        self.initCollisions()

        self.leftColor = LVecBase4i(224, 224, 64, 255)
        self.rightColor = LVecBase4i(64, 224, 224, 255)

        self.isDrawing = False
        self.toggleDrawing()

        self.accept("escape", sys.exit)  # Escape quits
        self.accept("enter", self.toggleDrawing)

    def initCollisions(self):
        # Initialize the collision traverser.
        self.cTrav = CollisionTraverser()

        self.cTrav.showCollisions(self.render)

        #         self.cQueue = CollisionHandlerQueue()

        # Initialize the Pusher collision handler.
        # self.pusher = CollisionHandlerPusher()
        self.pusher = CollisionHandlerFloor()

        ### player

        print DirectNotifyGlobal.directNotify.getCategories()
        # Create a collsion node for this object.
        playerNode = CollisionNode("player")
        playerNode.addSolid(CollisionSphere(0, 0, 0, 1))

        #         playerNode.setFromCollideMask(BitMask32.bit(0))
        #         playerNode.setIntoCollideMask(BitMask32.allOn())

        # Attach the collision node to the object's model.
        self.playerC = self.fpscamera.player.attachNewNode(playerNode)
        # Set the object's collision node to render as visible.
        self.playerC.show()

        # Add the 'player' collision node to the Pusher collision handler.
        # self.pusher.addCollider(self.playerC, self.fpscamera.player)
        # self.pusher.addCollider(playerC, self.fpscamera.player)

    #         self.cTrav.addCollider(self.playerC, self.cQueue)

    def toggleDrawing(self):
        self.isDrawing = not self.isDrawing

        if self.isDrawing:
            self.drawText.setText("Enter: Turn off drawing")
            self.fpscamera.setFlyMode(True)
            self.prevPos = None

            self.cTrav.removeCollider(self.playerC)
            self.pusher.removeCollider(self.playerC)

            self.removeTask("updatePhysics")
            self.addTask(self.drawHere, "drawHere")

            self.geomNode = GeomNode("geomNode")
            self.geomNodePath = self.render.attachNewNode(self.geomNode)

            self.geomNodePath.setTwoSided(True)

            # apparently p3tinydisplay needs this
            self.geomNodePath.setColorOff()

            # Create a collision node for this object.
            self.floorCollNode = CollisionNode("geom")

            #             self.floorCollNode.setFromCollideMask(BitMask32.bit(0))
            #             self.floorCollNode.setIntoCollideMask(BitMask32.allOn())

            # Attach the collision node to the object's model.
            floorC = self.geomNodePath.attachNewNode(self.floorCollNode)
            # Set the object's collision node to render as visible.
            floorC.show()

            # self.pusher.addCollider(floorC, self.geomNodePath)

            self.newVertexData()

            self.newGeom()

        else:
            self.drawText.setText("Enter: Turn on drawing")
            self.removeTask("drawHere")
            if self.prevPos:
                self.completePath()

            self.fpscamera.setFlyMode(True)

            self.drive.setPos(self.fpscamera.getPos())

            self.cTrav.addCollider(self.playerC, self.pusher)
            self.pusher.addCollider(self.playerC, self.fpscamera.player)

            self.taskMgr.add(self.updatePhysics, "updatePhysics")

    def newVertexData(self):
        fmt = GeomVertexFormat.getV3c4()
        #         fmt = GeomVertexFormat.getV3n3c4()
        self.vertexData = GeomVertexData("path", fmt, Geom.UHStatic)
        self.vertexWriter = GeomVertexWriter(self.vertexData, "vertex")
        #         self.normalWriter = GeomVertexWriter(self.vertexData, 'normal')
        self.colorWriter = GeomVertexWriter(self.vertexData, "color")

    def newGeom(self):
        self.triStrips = GeomTristrips(Geom.UHDynamic)
        self.geom = Geom(self.vertexData)
        self.geom.addPrimitive(self.triStrips)

    def makeInstructions(self):
        OnscreenText(text="Draw Path by Walking", style=1, fg=(1, 1, 0, 1), pos=(0.5, -0.95), scale=0.07)

        self.drawText = self.genLabelText("", 0)
        self.genLabelText("Walk (W/S/A/D), Jump=Space, Look=PgUp/PgDn", 1)
        self.genLabelText("  (hint, go backwards with S to see your path immediately)", 2)
        self.genLabelText("ESC: Quit", 3)

    def genLabelText(self, text, i):
        return OnscreenText(text=text, pos=(-1.3, 0.95 - 0.05 * i), fg=(1, 1, 0, 1), align=TextNode.ALeft, scale=0.05)

    def drawHere(self, task):
        pos = self.fpscamera.getPos()
        self.info.setText(
            "Position: {0}, {1}, {2} at {3} by {4}".format(
                int(pos.x * 100) / 100.0,
                int(pos.y * 100) / 100.0,
                int(pos.z) / 100.0,
                self.fpscamera.getHeading(),
                self.fpscamera.getLookAngle(),
            )
        )

        prevPos = self.prevPos

        if not prevPos:
            self.prevPos = pos

        elif (pos - prevPos).length() > 1:
            self.drawQuadTo(prevPos, pos, 2)

            row = self.vertexWriter.getWriteRow()
            numPrims = self.triStrips.getNumPrimitives()
            if numPrims == 0:
                primVerts = row
            else:
                primVerts = row - self.triStrips.getPrimitiveEnd(numPrims - 1)

            if primVerts >= 4:
                self.triStrips.closePrimitive()

                if row >= 256:
                    print "Packing and starting anew"
                    newGeom = True
                    self.geom.unifyInPlace(row, False)
                else:
                    newGeom = False

                self.completePath()

                if newGeom:
                    self.newVertexData()

                self.newGeom()
                if not newGeom:
                    self.triStrips.addConsecutiveVertices(row - 2, 2)
                else:
                    self.drawQuadTo(prevPos, pos, 2)

            self.leftColor[1] += 63
            self.rightColor[2] += 37

            self.prevPos = pos

        return task.cont

    def drawLineTo(self, pos, color):
        self.vertexWriter.addData3f(pos.x, pos.y, pos.z)
        #         self.normalWriter.addData3f(0, 0, 1)
        self.colorWriter.addData4i(color)

        self.triStrips.addNextVertices(1)

    def drawQuadTo(self, a, b, width):
        """ a (to) b are vectors defining a line bisecting a new quad. """
        into = b - a
        if abs(into.x) + abs(into.y) < 1:
            if not self.prevInto:
                return
            into = self.prevInto
            print into
        else:
            into.normalize()

        # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space

        if self.vertexWriter.getWriteRow() == 0:
            self.drawQuadRow(a, into, width)

        self.drawQuadRow(b, into, width)

        self.prevInto = into

    def drawQuadRow(self, a, into, width):
        """ a defines a point, with 'into' being the normalized direction. """

        # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space

        aLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z)
        aRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z)

        row = self.vertexWriter.getWriteRow()

        self.vertexWriter.addData3f(aLeft)
        self.vertexWriter.addData3f(aRight)

        #         self.normalWriter.addData3f(Vec3(0, 0, 1))
        #         self.normalWriter.addData3f(Vec3(0, 0, 1))

        self.colorWriter.addData4i(self.leftColor)
        self.colorWriter.addData4i(self.rightColor)

        self.triStrips.addConsecutiveVertices(row, 2)

    def completePath(self):
        self.geomNode.addGeom(self.geom)

        if self.triStrips.getNumPrimitives() == 0:
            return

        floorMesh = CollisionFloorMesh()

        tris = self.triStrips.decompose()
        p = 0
        vertexReader = GeomVertexReader(self.vertexData, "vertex")
        for i in range(tris.getNumPrimitives()):
            v0 = tris.getPrimitiveStart(i)
            ve = tris.getPrimitiveEnd(i)
            if v0 < ve:
                vertexReader.setRow(tris.getVertex(v0))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                vertexReader.setRow(tris.getVertex(v0 + 1))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                vertexReader.setRow(tris.getVertex(v0 + 2))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                floorMesh.addTriangle(p, p + 1, p + 2)
                p += 3

        self.floorCollNode.addSolid(floorMesh)

    def updatePhysics(self, task):
        pos = self.fpscamera.getPos()
        self.info.setText(
            "Position: {0}, {1}, {2}".format(int(pos.x * 100) / 100.0, int(pos.y * 100) / 100.0, int(pos.z) / 100.0)
        )
        return task.cont
Esempio n. 6
0
class PlayerBase(DirectObject):
    def __init__(self):
        # Player Model setup
        self.player = Actor("Player",
                            {"Run":"Player-Run",
                            "Sidestep":"Player-Sidestep",
                            "Idle":"Player-Idle"})
        self.player.setBlend(frameBlend = True)
        self.player.setPos(0, 0, 0)
        self.player.pose("Idle", 0)
        self.player.reparentTo(render)
        self.player.hide()

        self.footstep = base.audio3d.loadSfx('footstep.ogg')
        self.footstep.setLoop(True)
        base.audio3d.attachSoundToObject(self.footstep, self.player)

        # Create a brush to paint on the texture
        splat = PNMImage("../data/Splat.png")
        self.colorBrush = PNMBrush.makeImage(splat, 6, 6, 1)

        CamMask = BitMask32.bit(0)
        AvBufMask = BitMask32.bit(1)
        self.avbuf = None
        if base.win:
            self.avbufTex = Texture('avbuf')
            self.avbuf = base.win.makeTextureBuffer('avbuf', 256, 256, self.avbufTex, True)
            cam = Camera('avbuf')
            cam.setLens(base.camNode.getLens())
            self.avbufCam = base.cam.attachNewNode(cam)
            dr = self.avbuf.makeDisplayRegion()
            dr.setCamera(self.avbufCam)
            self.avbuf.setActive(False)
            self.avbuf.setClearColor((1, 0, 0, 1))
            cam.setCameraMask(AvBufMask)
            base.camNode.setCameraMask(CamMask)

            # avbuf renders everything it sees with the gradient texture.
            tex = loader.loadTexture('gradient.png')
            np = NodePath('np')
            np.setTexture(tex, 100)
            np.setColor((1, 1, 1, 1), 100)
            np.setColorScaleOff(100)
            np.setTransparency(TransparencyAttrib.MNone, 100)
            np.setLightOff(100)
            cam.setInitialState(np.getState())
            #render.hide(AvBufMask)

        # Setup a texture stage to paint on the player
        self.paintTs = TextureStage('paintTs')
        self.paintTs.setMode(TextureStage.MDecal)
        self.paintTs.setSort(10)
        self.paintTs.setPriority(10)

        self.tex = Texture('paint_av_%s'%id(self))

        # Setup a PNMImage that will hold the paintable texture of the player
        self.imageSizeX = 64
        self.imageSizeY = 64
        self.p = PNMImage(self.imageSizeX, self.imageSizeY, 4)
        self.p.fill(1)
        self.p.alphaFill(0)
        self.tex.load(self.p)
        self.tex.setWrapU(self.tex.WMClamp)
        self.tex.setWrapV(self.tex.WMClamp)

        # Apply the paintable texture to the avatar
        self.player.setTexture(self.paintTs, self.tex)

        # team
        self.playerTeam = ""
        # A lable that will display the players team
        self.lblTeam = DirectLabel(
            scale = 1,
            pos = (0, 0, 3),
            frameColor = (0, 0, 0, 0),
            text = "TEAM",
            text_align = TextNode.ACenter,
            text_fg = (0,0,0,1))
        self.lblTeam.reparentTo(self.player)
        self.lblTeam.setBillboardPointEye()

        # basic player values
        self.maxHits = 3
        self.currentHits = 0
        self.isOut = False

        self.TorsorControl = self.player.controlJoint(None,"modelRoot","Torsor")

        # setup the collision detection
        # wall and object collision
        self.playerSphere = CollisionSphere(0, 0, 1, 1)
        self.playerCollision = self.player.attachNewNode(CollisionNode("playerCollision%d"%id(self)))
        self.playerCollision.node().addSolid(self.playerSphere)
        base.pusher.addCollider(self.playerCollision, self.player)
        base.cTrav.addCollider(self.playerCollision, base.pusher)
        # foot (walk) collision
        self.playerFootRay = self.player.attachNewNode(CollisionNode("playerFootCollision%d"%id(self)))
        self.playerFootRay.node().addSolid(CollisionRay(0, 0, 2, 0, 0, -1))
        self.playerFootRay.node().setIntoCollideMask(0)
        self.lifter = CollisionHandlerFloor()
        self.lifter.addCollider(self.playerFootRay, self.player)
        base.cTrav.addCollider(self.playerFootRay, self.lifter)

        # Player weapon setup
        self.gunAttach = self.player.exposeJoint(None, "modelRoot", "WeaponSlot_R")
        self.color = LPoint3f(1, 1, 1)
        self.gun = Gun(id(self))
        self.gun.reparentTo(self.gunAttach)
        self.gun.hide()
        self.gun.setColor(self.color)

        self.hud = None

        # Player controls setup
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0}
        # screen sizes
        self.winXhalf = base.win.getXSize() / 2
        self.winYhalf = base.win.getYSize() / 2
        self.mouseSpeedX = 0.1
        self.mouseSpeedY = 0.1
        # AI controllable variables
        self.AIP = 0.0
        self.AIH = 0.0

        self.movespeed = 5.0

        self.userControlled = False

        self.accept("Bulet-hit-playerCollision%d" % id(self), self.hit)
        self.accept("window-event", self.recalcAspectRatio)

    def runBase(self):
        self.player.show()
        self.gun.show()
        taskMgr.add(self.move, "moveTask%d"%id(self), priority=-4)

    def stopBase(self):
        taskMgr.remove("moveTask%d"%id(self))
        self.ignoreAll()
        self.gun.remove()
        self.footstep.stop()
        base.audio3d.detachSound(self.footstep)
        self.player.delete()

    def setKey(self, key, value):
        self.keyMap[key] = value

    def setPos(self, pos):
        self.player.setPos(pos)

    def setColor(self, color=LPoint3f(0,0,0)):
        self.color = color
        self.gun.setColor(color)
        c = (color[0], color[1], color[2], 1.0)
        self.lblTeam["text_fg"] = c

    def setTeam(self, team):
        self.playerTeam = team
        self.lblTeam["text"] = team


    def shoot(self, shotVec=None):
        self.gun.shoot(shotVec)
        if self.hud != None:
            self.hud.updateAmmo(self.gun.maxAmmunition, self.gun.ammunition)

    def reload(self):
        self.gun.reload()
        if self.hud != None:
            self.hud.updateAmmo(self.gun.maxAmmunition, self.gun.ammunition)

    def recalcAspectRatio(self, window):
        self.winXhalf = window.getXSize() / 2
        self.winYhalf = window.getYSize() / 2

    def hit(self, entry, color):
        self.currentHits += 1

        # Create a brush to paint on the texture
        splat = PNMImage("../data/Splat.png")
        splat = splat * LColorf(color[0], color[1], color[2], 1.0)
        self.colorBrush = PNMBrush.makeImage(splat, 6, 6, 1)

        self.paintAvatar(entry)

        if self.currentHits >= self.maxHits:
            base.messenger.send("GameOver-player%d" % id(self))
            self.isOut = True

    def __paint(self, s, t):
        """ Paints a point on the avatar at texture coordinates (s, t). """
        x = (s * self.p.getXSize())
        y = ((1.0 - t) * self.p.getYSize())

        # Draw in color directly on the avatar
        p1 = PNMPainter(self.p)
        p1.setPen(self.colorBrush)
        p1.drawPoint(x, y)

        self.tex.load(self.p)
        self.tex.setWrapU(self.tex.WMClamp)
        self.tex.setWrapV(self.tex.WMClamp)

        self.paintDirty = True

    def paintAvatar(self, entry):
        """ Paints onto an avatar.  Returns true on success, false on
        failure (because there are no avatar pixels under the mouse,
        for instance). """

        # First, we have to render the avatar in its false-color
        # image, to determine which part of its texture is under the
        # mouse.
        if not self.avbuf:
            return False

        #mpos = base.mouseWatcherNode.getMouse()
        mpos = entry.getSurfacePoint(self.player)
        ppos = entry.getSurfacePoint(render)

        self.player.showThrough(BitMask32.bit(1))
        self.avbuf.setActive(True)
        base.graphicsEngine.renderFrame()
        self.player.show(BitMask32.bit(1))
        self.avbuf.setActive(False)

        # Now we have the rendered image in self.avbufTex.
        if not self.avbufTex.hasRamImage():
            print "Weird, no image in avbufTex."
            return False
        p = PNMImage()
        self.avbufTex.store(p)
        ix = int((1 + mpos.getX()) * p.getXSize() * 0.5)
        iy = int((1 - mpos.getY()) * p.getYSize() * 0.5)
        x = 1
        if ix >= 0 and ix < p.getXSize() and iy >= 0 and iy < p.getYSize():
            s = p.getBlue(ix, iy)
            t = p.getGreen(ix, iy)
            x = p.getRed(ix, iy)
        if x > 0.5:
            # Off the avatar.
            return False

        # At point (s, t) on the avatar's map.

        self.__paint(s, t)
        return True

    def move(self, task):
        if self is None: return task.done
        if self.userControlled:
            if not base.mouseWatcherNode.hasMouse(): return task.cont
            self.pointer = base.win.getPointer(0)
            mouseX = self.pointer.getX()
            mouseY = self.pointer.getY()

            if base.win.movePointer(0, self.winXhalf, self.winYhalf):
                p = self.TorsorControl.getP() + (mouseY - self.winYhalf) * self.mouseSpeedY
                if p <-80:
                    p = -80
                elif p > 90:
                    p = 90
                self.TorsorControl.setP(p)

                h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX
                if h <-360:
                    h = 360
                elif h > 360:
                    h = -360
                self.player.setH(h)
        else:
            self.TorsorControl.setP(self.AIP)
            self.player.setH(self.AIH)

        forward =  self.keyMap["forward"] != 0
        backward = self.keyMap["backward"] != 0

        if self.keyMap["left"] != 0:
            if self.player.getCurrentAnim() != "Sidestep" and not (forward or backward):
                self.player.loop("Sidestep")
                self.player.setPlayRate(5, "Sidestep")
            self.player.setX(self.player, self.movespeed * globalClock.getDt())
        elif self.keyMap["right"] != 0:
            if self.player.getCurrentAnim() != "Sidestep" and not (forward or backward):
                self.player.loop("Sidestep")
                self.player.setPlayRate(5, "Sidestep")
            self.player.setX(self.player, -self.movespeed * globalClock.getDt())
        else:
            self.player.stop("Sidestep")
        if forward:
            if self.player.getCurrentAnim() != "Run":
                self.player.loop("Run")
                self.player.setPlayRate(5, "Run")
            self.player.setY(self.player, -self.movespeed * globalClock.getDt())
        elif backward:
            if self.player.getCurrentAnim() != "Run":
                self.player.loop("Run")
                self.player.setPlayRate(-5, "Run")
            self.player.setY(self.player, self.movespeed * globalClock.getDt())
        else:
            self.player.stop("Run")

        if not (self.keyMap["left"] or self.keyMap["right"] or
                self.keyMap["forward"] or self.keyMap["backward"] or
                self.player.getCurrentAnim() == "Idle"):
            self.player.loop("Idle")
            self.footstep.stop()
        else:
            self.footstep.play()

        return task.cont
class SmartCamera:
    UPDATE_TASK_NAME = 'update_smartcamera'
    notify = directNotify.newCategory('SmartCamera')

    def __init__(self):
        self.cTrav = CollisionTraverser('cam_traverser')
        base.pushCTrav(self.cTrav)
        self.cTrav.setRespectPrevTransform(1)
        self.default_pos = None
        self.parent = None
        self.initialized = False
        self.started = False
        self.camFloorRayNode = None
        self.ccRay2 = None
        self.ccRay2Node = None
        self.ccRay2NodePath = None
        self.ccRay2BitMask = None
        self.ccRay2MoveNodePath = None
        self.camFloorCollisionBroadcaster = None
        self.notify.debug('SmartCamera initialized!')
        return

    def lerpCameraFov(self, fov, time):
        taskMgr.remove('cam-fov-lerp-play')
        oldFov = base.camLens.getHfov()
        if abs(fov - oldFov) > 0.1:

            def setCamFov(fov):
                base.camLens.setMinFov(fov / (4.0 / 3.0))

            self.camLerpInterval = LerpFunctionInterval(setCamFov, fromData=oldFov, toData=fov, duration=time, name='cam-fov-lerp')
            self.camLerpInterval.start()

    def setCameraFov(self, fov):
        self.fov = fov
        if not (self.isPageDown or self.isPageUp):
            base.camLens.setMinFov(self.fov / (4.0 / 3.0))

    def initCameraPositions(self):
        camHeight = max(base.localAvatar.getHeight(), 3.0)
        nrCamHeight = base.localAvatar.getHeight()
        heightScaleFactor = camHeight * 0.3333333333
        defLookAt = Point3(0.0, 1.5, camHeight)
        self.firstPersonCamPos = Point3(0.0, 0.7, nrCamHeight * 5.0)
        scXoffset = 3.0
        scPosition = (Point3(scXoffset - 1, -10.0, camHeight + 5.0), Point3(scXoffset, 2.0, camHeight))
        self.cameraPositions = [
         (Point3(0.0, -9.0 * heightScaleFactor, camHeight),
          defLookAt,
          Point3(0.0, camHeight, camHeight * 4.0),
          Point3(0.0, camHeight, camHeight * -1.0),
          0),
         (
          Point3(0.0, 0.7, camHeight),
          defLookAt,
          Point3(0.0, camHeight, camHeight * 1.33),
          Point3(0.0, camHeight, camHeight * 0.66),
          1),
         (
          Point3(5.7 * heightScaleFactor, 7.65 * heightScaleFactor, camHeight + 2.0),
          Point3(0.0, 1.0, camHeight),
          Point3(0.0, 1.0, camHeight * 4.0),
          Point3(0.0, 1.0, camHeight * -1.0),
          0),
         (
          Point3(0.0, 8.65 * heightScaleFactor, camHeight),
          Point3(0.0, 1.0, camHeight),
          Point3(0.0, 1.0, camHeight * 4.0),
          Point3(0.0, 1.0, camHeight * -1.0),
          0),
         (
          Point3(0.0, -24.0 * heightScaleFactor, camHeight + 4.0),
          defLookAt,
          Point3(0.0, 1.5, camHeight * 4.0),
          Point3(0.0, 1.5, camHeight * -1.0),
          0),
         (
          Point3(0.0, -12.0 * heightScaleFactor, camHeight + 4.0),
          defLookAt,
          Point3(0.0, 1.5, camHeight * 4.0),
          Point3(0.0, 1.5, camHeight * -1.0),
          0)]

    def pageUp(self):
        if not base.localAvatar.avatarMovementEnabled:
            return
        if not self.isPageUp:
            self.isPageDown = 0
            self.isPageUp = 1
            self.lerpCameraFov(70, 0.6)
            self.setCameraPositionByIndex(self.cameraIndex)
        else:
            self.clearPageUpDown()

    def pageDown(self):
        if not base.localAvatar.avatarMovementEnabled:
            return
        if not self.isPageDown:
            self.isPageUp = 0
            self.isPageDown = 1
            self.lerpCameraFov(70, 0.6)
            self.setCameraPositionByIndex(self.cameraIndex)
        else:
            self.clearPageUpDown()

    def clearPageUpDown(self):
        if self.isPageDown or self.isPageUp:
            self.lerpCameraFov(self.fov, 0.6)
            self.isPageDown = 0
            self.isPageUp = 0
            self.setCameraPositionByIndex(self.cameraIndex)

    def nextCameraPos(self, forward):
        if not base.localAvatar.avatarMovementEnabled:
            return
        self.__cameraHasBeenMoved = 1
        if forward:
            self.cameraIndex += 1
            if self.cameraIndex > len(self.cameraPositions) - 1:
                self.cameraIndex = 0
        else:
            self.cameraIndex -= 1
            if self.cameraIndex < 0:
                self.cameraIndex = len(self.cameraPositions) - 1
        self.setCameraPositionByIndex(self.cameraIndex)

    def setCameraPositionByIndex(self, index):
        self.notify.debug('switching to camera position %s' % index)
        self.setCameraSettings(self.cameraPositions[index])

    def setCameraSettings(self, camSettings):
        self.setIdealCameraPos(camSettings[0])
        if self.isPageUp and self.isPageDown or not self.isPageUp and not self.isPageDown:
            self.__cameraHasBeenMoved = 1
            self.setLookAtPoint(camSettings[1])
        else:
            if self.isPageUp:
                self.__cameraHasBeenMoved = 1
                self.setLookAtPoint(camSettings[2])
            else:
                if self.isPageDown:
                    self.__cameraHasBeenMoved = 1
                    self.setLookAtPoint(camSettings[3])
                else:
                    self.notify.error('This case should be impossible.')
        self.__disableSmartCam = camSettings[4]
        if self.__disableSmartCam:
            self.putCameraFloorRayOnAvatar()
            self.cameraZOffset = 0.0

    def set_default_pos(self, pos):
        self.default_pos = pos

    def get_default_pos(self):
        return self.default_pos

    def set_parent(self, parent):
        self.parent = parent

    def get_parent(self):
        return self.parent

    def getVisibilityPoint(self):
        return Point3(0.0, 0.0, base.localAvatar.getHeight())

    def setLookAtPoint(self, la):
        self.__curLookAt = Point3(la)

    def getLookAtPoint(self):
        return Point3(self.__curLookAt)

    def setIdealCameraPos(self, pos):
        self.__idealCameraPos = Point3(pos)
        self.updateSmartCameraCollisionLineSegment()

    def getIdealCameraPos(self):
        return Point3(self.__idealCameraPos)

    def getCompromiseCameraPos(self):
        if self.__idealCameraObstructed == 0:
            compromisePos = self.getIdealCameraPos()
        else:
            visPnt = self.getVisibilityPoint()
            idealPos = self.getIdealCameraPos()
            distance = Vec3(idealPos - visPnt).length()
            ratio = self.closestObstructionDistance / distance
            compromisePos = idealPos * ratio + visPnt * (1 - ratio)
            liftMult = 1.0 - ratio * ratio
            compromisePos = Point3(compromisePos[0], compromisePos[1], compromisePos[2] + base.localAvatar.getHeight() * 0.4 * liftMult)
        compromisePos.setZ(compromisePos[2] + self.cameraZOffset)
        return compromisePos

    def updateSmartCameraCollisionLineSegment(self):
        pointB = self.getIdealCameraPos()
        pointA = self.getVisibilityPoint()
        vectorAB = Vec3(pointB - pointA)
        lengthAB = vectorAB.length()
        if lengthAB > 0.001:
            self.ccLine.setPointA(pointA)
            self.ccLine.setPointB(pointB)

    def initializeSmartCamera(self):
        self.__idealCameraObstructed = 0
        self.closestObstructionDistance = 0.0
        self.cameraIndex = 0
        self.cameraPositions = []
        self.auxCameraPositions = []
        self.cameraZOffset = 0.0
        self.setGeom(render)
        self.__onLevelGround = 0
        self.__camCollCanMove = 0
        self.__disableSmartCam = 0
        self.initializeSmartCameraCollisions()
        self._smartCamEnabled = False
        self.isPageUp = 0
        self.isPageDown = 0
        self.fov = CIGlobals.DefaultCameraFov

    def enterFirstPerson(self):
        self.stop_smartcamera()
        if hasattr(self.get_parent(), 'toon_head'):
            head = self.get_parent().toon_head
            camera.reparentTo(head)
        camera.setPos(0, -0.35, 0)
        camera.setHpr(0, 0, 0)

    def exitFirstPerson(self):
        self.initialize_smartcamera()
        self.initialize_smartcamera_collisions()
        self.start_smartcamera()

    def putCameraFloorRayOnAvatar(self):
        self.camFloorRayNode.setPos(base.localAvatar, 0, 0, 5)

    def putCameraFloorRayOnCamera(self):
        self.camFloorRayNode.setPos(self.ccSphereNodePath, 0, 0, 0)

    def recalcCameraSphere(self):
        nearPlaneDist = base.camLens.getNear()
        hFov = base.camLens.getHfov()
        vFov = base.camLens.getVfov()
        hOff = nearPlaneDist * math.tan(deg2Rad(hFov / 2.0))
        vOff = nearPlaneDist * math.tan(deg2Rad(vFov / 2.0))
        camPnts = [Point3(hOff, nearPlaneDist, vOff),
         Point3(-hOff, nearPlaneDist, vOff),
         Point3(hOff, nearPlaneDist, -vOff),
         Point3(-hOff, nearPlaneDist, -vOff),
         Point3(0.0, 0.0, 0.0)]
        avgPnt = Point3(0.0, 0.0, 0.0)
        for camPnt in camPnts:
            avgPnt = avgPnt + camPnt

        avgPnt = avgPnt / len(camPnts)
        sphereRadius = 0.0
        for camPnt in camPnts:
            dist = Vec3(camPnt - avgPnt).length()
            if dist > sphereRadius:
                sphereRadius = dist

        avgPnt = Point3(avgPnt)
        self.ccSphereNodePath.setPos(avgPnt)
        self.ccSphereNodePath2.setPos(avgPnt)
        self.ccSphere.setRadius(sphereRadius)

    def setGeom(self, geom):
        self.__geom = geom

    def initializeSmartCameraCollisions(self):
        if self.initialized:
            return
        self.ccTrav = CollisionTraverser('LocalAvatar.ccTrav')
        self.ccLine = CollisionSegment(0.0, 0.0, 0.0, 1.0, 0.0, 0.0)
        self.ccLineNode = CollisionNode('ccLineNode')
        self.ccLineNode.addSolid(self.ccLine)
        self.ccLineNodePath = base.localAvatar.attachNewNode(self.ccLineNode)
        self.ccLineBitMask = CIGlobals.CameraBitmask
        self.ccLineNode.setFromCollideMask(self.ccLineBitMask)
        self.ccLineNode.setIntoCollideMask(BitMask32.allOff())
        self.camCollisionQueue = CollisionHandlerQueue()
        self.ccTrav.addCollider(self.ccLineNodePath, self.camCollisionQueue)
        self.ccSphere = CollisionSphere(0, 0, 0, 1)
        self.ccSphereNode = CollisionNode('ccSphereNode')
        self.ccSphereNode.addSolid(self.ccSphere)
        self.ccSphereNodePath = base.camera.attachNewNode(self.ccSphereNode)
        self.ccSphereNode.setFromCollideMask(CIGlobals.CameraBitmask)
        self.ccSphereNode.setIntoCollideMask(BitMask32.allOff())
        self.camPusher = CollisionHandlerPusher()
        self.camPusher.addCollider(self.ccSphereNodePath, base.camera)
        self.camPusher.setCenter(base.localAvatar)
        self.ccPusherTrav = CollisionTraverser('LocalAvatar.ccPusherTrav')
        self.ccSphere2 = self.ccSphere
        self.ccSphereNode2 = CollisionNode('ccSphereNode2')
        self.ccSphereNode2.addSolid(self.ccSphere2)
        self.ccSphereNodePath2 = base.camera.attachNewNode(self.ccSphereNode2)
        self.ccSphereNode2.setFromCollideMask(CIGlobals.CameraBitmask)
        self.ccSphereNode2.setIntoCollideMask(BitMask32.allOff())
        self.camPusher2 = CollisionHandlerPusher()
        self.ccPusherTrav.addCollider(self.ccSphereNodePath2, self.camPusher2)
        self.camPusher2.addCollider(self.ccSphereNodePath2, base.camera)
        self.camPusher2.setCenter(base.localAvatar)
        self.camFloorRayNode = base.localAvatar.attachNewNode('camFloorRayNode')
        self.ccRay = CollisionRay(0.0, 0.0, 0.0, 0.0, 0.0, -1.0)
        self.ccRayNode = CollisionNode('ccRayNode')
        self.ccRayNode.addSolid(self.ccRay)
        self.ccRayNodePath = self.camFloorRayNode.attachNewNode(self.ccRayNode)
        self.ccRayBitMask = CIGlobals.FloorBitmask
        self.ccRayNode.setFromCollideMask(self.ccRayBitMask)
        self.ccRayNode.setIntoCollideMask(BitMask32.allOff())
        self.ccTravFloor = CollisionTraverser('LocalAvatar.ccTravFloor')
        self.camFloorCollisionQueue = CollisionHandlerQueue()
        self.ccTravFloor.addCollider(self.ccRayNodePath, self.camFloorCollisionQueue)
        self.ccTravOnFloor = CollisionTraverser('LocalAvatar.ccTravOnFloor')
        self.ccRay2 = CollisionRay(0.0, 0.0, 0.0, 0.0, 0.0, -1.0)
        self.ccRay2Node = CollisionNode('ccRay2Node')
        self.ccRay2Node.addSolid(self.ccRay2)
        self.ccRay2NodePath = self.camFloorRayNode.attachNewNode(self.ccRay2Node)
        self.ccRay2BitMask = CIGlobals.FloorBitmask
        self.ccRay2Node.setFromCollideMask(self.ccRay2BitMask)
        self.ccRay2Node.setIntoCollideMask(BitMask32.allOff())
        self.ccRay2MoveNodePath = hidden.attachNewNode('ccRay2MoveNode')
        self.camFloorCollisionBroadcaster = CollisionHandlerFloor()
        self.camFloorCollisionBroadcaster.setInPattern('on-floor')
        self.camFloorCollisionBroadcaster.setOutPattern('off-floor')
        self.camFloorCollisionBroadcaster.addCollider(self.ccRay2NodePath, self.ccRay2MoveNodePath)
        self.cTrav.addCollider(self.ccRay2NodePath, self.camFloorCollisionBroadcaster)
        self.initialized = True

    def deleteSmartCameraCollisions(self):
        del self.ccTrav
        del self.ccLine
        del self.ccLineNode
        self.ccLineNodePath.removeNode()
        del self.ccLineNodePath
        del self.camCollisionQueue
        del self.ccRay
        del self.ccRayNode
        self.ccRayNodePath.removeNode()
        del self.ccRayNodePath
        del self.ccRay2
        del self.ccRay2Node
        self.ccRay2NodePath.removeNode()
        del self.ccRay2NodePath
        self.ccRay2MoveNodePath.removeNode()
        del self.ccRay2MoveNodePath
        del self.ccTravOnFloor
        del self.ccTravFloor
        del self.camFloorCollisionQueue
        del self.camFloorCollisionBroadcaster
        del self.ccSphere
        del self.ccSphereNode
        self.ccSphereNodePath.removeNode()
        del self.ccSphereNodePath
        del self.camPusher
        del self.ccPusherTrav
        del self.ccSphere2
        del self.ccSphereNode2
        self.ccSphereNodePath2.removeNode()
        del self.ccSphereNodePath2
        del self.camPusher2
        self.initialized = False

    def startUpdateSmartCamera(self):
        if self.started:
            return
        self.__floorDetected = 0
        self.__cameraHasBeenMoved = 1
        self.recalcCameraSphere()
        self.__instantaneousCamPos = camera.getPos()
        self.cTrav.addCollider(self.ccSphereNodePath, self.camPusher)
        self.ccTravOnFloor.addCollider(self.ccRay2NodePath, self.camFloorCollisionBroadcaster)
        self.__disableSmartCam = 0
        self.__lastPosWrtRender = camera.getPos(render) + 1
        self.__lastHprWrtRender = camera.getHpr(render) + 1
        taskName = base.localAvatar.taskName('updateSmartCamera')
        taskMgr.remove(taskName)
        taskMgr.add(self.updateSmartCamera, taskName, priority=47)
        self.started = True

    def stopUpdateSmartCamera(self):
        self.cTrav.removeCollider(self.ccSphereNodePath)
        self.ccTravOnFloor.removeCollider(self.ccRay2NodePath)
        taskName = base.localAvatar.taskName('updateSmartCamera')
        taskMgr.remove(taskName)
        camera.setPos(self.getIdealCameraPos())
        self.started = False

    def updateSmartCamera(self, task):
        if not self.__camCollCanMove and not self.__cameraHasBeenMoved:
            if self.__lastPosWrtRender == camera.getPos(render):
                if self.__lastHprWrtRender == camera.getHpr(render):
                    return Task.cont
        self.__cameraHasBeenMoved = 0
        self.__lastPosWrtRender = camera.getPos(render)
        self.__lastHprWrtRender = camera.getHpr(render)
        self.__idealCameraObstructed = 0
        if not self.__disableSmartCam:
            self.ccTrav.traverse(self.__geom)
            if self.camCollisionQueue.getNumEntries() > 0:
                try:
                    self.camCollisionQueue.sortEntries()
                    self.handleCameraObstruction(self.camCollisionQueue.getEntry(0))
                except AssertionError:
                    pass

            if not self.__onLevelGround:
                self.handleCameraFloorInteraction()
        if not self.__idealCameraObstructed:
            self.nudgeCamera()
        if not self.__disableSmartCam:
            self.ccPusherTrav.traverse(self.__geom)
            self.putCameraFloorRayOnCamera()
        self.ccTravOnFloor.traverse(self.__geom)
        return Task.cont

    def positionCameraWithPusher(self, pos, lookAt):
        camera.setPos(pos)
        self.ccPusherTrav.traverse(self.__geom)
        camera.lookAt(lookAt)

    def nudgeCamera(self):
        CLOSE_ENOUGH = 0.1
        curCamPos = self.__instantaneousCamPos
        curCamHpr = camera.getHpr()
        targetCamPos = self.getCompromiseCameraPos()
        targetCamLookAt = self.getLookAtPoint()
        posDone = 0
        if Vec3(curCamPos - targetCamPos).length() <= CLOSE_ENOUGH:
            camera.setPos(targetCamPos)
            posDone = 1
        camera.setPos(targetCamPos)
        camera.lookAt(targetCamLookAt)
        targetCamHpr = camera.getHpr()
        hprDone = 0
        if Vec3(curCamHpr - targetCamHpr).length() <= CLOSE_ENOUGH:
            hprDone = 1
        if posDone and hprDone:
            return
        lerpRatio = 0.15
        lerpRatio = 1 - pow(1 - lerpRatio, globalClock.getDt() * 30.0)
        self.__instantaneousCamPos = targetCamPos * lerpRatio + curCamPos * (1 - lerpRatio)
        if self.__disableSmartCam or not self.__idealCameraObstructed:
            newHpr = targetCamHpr * lerpRatio + curCamHpr * (1 - lerpRatio)
        else:
            newHpr = targetCamHpr
        camera.setPos(self.__instantaneousCamPos)
        camera.setHpr(newHpr)

    def popCameraToDest(self):
        newCamPos = self.getCompromiseCameraPos()
        newCamLookAt = self.getLookAtPoint()
        self.positionCameraWithPusher(newCamPos, newCamLookAt)
        self.__instantaneousCamPos = camera.getPos()

    def handleCameraObstruction(self, camObstrCollisionEntry):
        collisionPoint = camObstrCollisionEntry.getSurfacePoint(self.ccLineNodePath)
        collisionVec = Vec3(collisionPoint - self.ccLine.getPointA())
        distance = collisionVec.length()
        self.__idealCameraObstructed = 1
        self.closestObstructionDistance = distance
        self.popCameraToDest()

    def handleCameraFloorInteraction(self):
        self.putCameraFloorRayOnCamera()
        self.ccTravFloor.traverse(self.__geom)
        if self.__onLevelGround:
            return
        if self.camFloorCollisionQueue.getNumEntries() == 0:
            return
        self.camFloorCollisionQueue.sortEntries()
        camObstrCollisionEntry = self.camFloorCollisionQueue.getEntry(0)
        camHeightFromFloor = camObstrCollisionEntry.getSurfacePoint(self.ccRayNodePath)[2]
        self.cameraZOffset = camera.getPos()[2] + camHeightFromFloor
        if self.cameraZOffset < 0:
            self.cameraZOffset = 0
        if self.__floorDetected == 0:
            self.__floorDetected = 1
            self.popCameraToDest()
Esempio n. 8
0
class MyApp(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)
 
        self.disableMouse()

        self.cam_away = 20
        self.cam_elevation = 5
        self.rot_rate = .5

        self.cam_dist = (self.cam_away**2 + self.cam_elevation**2) ** .5

        #######
        self.environ = GeoMipTerrain("terrain")
        self.environ.setHeightfield("../terrain/first.png")
        self.environ.setColorMap("../terrain/first-c.png")
        self.environ.generate()
        self.environ.getRoot().setScale(1, 1, 100)
        self.environ.getRoot().setPos(0, 0, 0)
        self.environ.getRoot().reparentTo(render)
        self.environ.getRoot().setName("terrain")
        self.environ.getRoot().setCollideMask(BitMask32.bit(0))
        #######

        self.pandaActor = Actor("models/panda",
                                {"walk": "models/panda-walk"})
        self.pandaActor.setScale(.5, .5, .5)
        self.pandaActor.setHpr(180, 0, 0)
        self.pandaActor.setPos(50, 50, 50)
        self.pandaActor.reparentTo(render)
        self.pandaActor.setPythonTag("moving", False)
        self.avatarYawRot = 0
        self.avatarPitchRot = 0

        #self.teapot = loader.loadModel("models/teapot")
        #self.teapot.setScale(1, 1, 1)
        #self.teapot.setPos(60, 60, 50)
        #self.teapot.reparentTo(render)

        self.cam.setHpr(0, 0, 0)
 
        self.taskMgr.add(self.updateTerrain, "update terrain", priority = 35)

        self.keys = {"w" : 0, "s" : 0, "a" : 0, "d" : 0}

        self.accept("w", self.setKey, ["w", 1])
        self.accept("w-up", self.setKey, ["w", 0])
        self.accept("s", self.setKey, ["s", 1])
        self.accept("s-up", self.setKey, ["s", 0])
        self.accept("a", self.setKey, ["a", 1])
        self.accept("a-up", self.setKey, ["a", 0])
        self.accept("d", self.setKey, ["d", 1])
        self.accept("d-up", self.setKey, ["d", 0])
        self.accept("wheel_up", self.zoomCamera, [-1])
        self.accept("wheel_down", self.zoomCamera, [1])

        self.accept('window-event', self.handleWindowEvent)

        props = WindowProperties()
        props.setCursorHidden(True) 
        base.win.requestProperties(props)

        self.last_mouse_x = self.win.getPointer(0).getX()
        #self.last_mouse_y = self.win.getPointer(0).getY()

        self.cTrav = CollisionTraverser()

        self.pandaGroundRay = CollisionRay(0,0,0,0,0,1)
        self.pandaGroundRayNode = CollisionNode('pandaGroundRay')
        self.pandaGroundRayNode.addSolid(self.pandaGroundRay)
        self.pandaGroundRayNode.setFromCollideMask(BitMask32.bit(0))
        self.pandaGroundRayNode.setIntoCollideMask(BitMask32.allOff())
        self.pandaGroundRayNodepath = self.pandaActor.attachNewNode(self.pandaGroundRayNode)
        self.pandaGroundRayNodepath.show()
        self.pandaGroundCollisionHandler = CollisionHandlerFloor()
        self.pandaGroundCollisionHandler.addCollider(self.pandaGroundRayNodepath, self.pandaActor)
        self.cTrav.addCollider(self.pandaGroundRayNodepath, self.pandaGroundCollisionHandler)

        #self.teapotRay = CollisionSphere(0,0,0,5)
        #self.teapotGroundCol = CollisionNode('teapotRay')
        #self.teapotGroundCol.addSolid(self.teapotRay)
        #self.teapotGroundCol.setFromCollideMask(BitMask32.allOff())
        #self.teapotGroundCol.setIntoCollideMask(BitMask32.bit(0))
        #self.teapotGroundColNp = self.teapot.attachNewNode(self.teapotGroundCol)
        #self.teapotGroundHandler = CollisionHandlerQueue()
        #self.cTrav.addCollider(self.teapotGroundColNp, self.teapotGroundHandler)

    def setKey(self, key, value):

        self.keys[key] = value

    def handleWindowEvent(self, window=None):

        wp = window.getProperties()

        self.win_center_x = wp.getXSize() / 2
        self.win_center_y = wp.getYSize() / 2

    def zoomCamera(self, direction):

        self.cam_away += direction

    def updateTerrain(self, task):

        dt = globalClock.getDt()

        self.pandaActor.setY(self.pandaActor, -50 * dt)

        if self.keys["w"]: self.pandaActor.setZ(self.pandaActor, 20 * dt)

        if self.keys["s"]: self.pandaActor.setZ(self.pandaActor, -20 * dt)

        if self.keys["a"]: self.pandaActor.setX(self.pandaActor, 20 * dt)

        if self.keys["d"]: self.pandaActor.setX(self.pandaActor, -20 * dt)

        mouse_pos = self.win.getPointer(0)

        #Mouse-based viewpoint rotation

        current_mouse_x = mouse_pos.getX()
        #current_mouse_y = mouse_pos.getY()

        mouse_shift_x = current_mouse_x - self.last_mouse_x
        #mouse_shift_y = current_mouse_y - self.last_mouse_y

        self.last_mouse_x = current_mouse_x
        #self.last_mouse_y = current_mouse_y

        if current_mouse_x == 0 or current_mouse_x >= (self.win_center_x * 1.5):

            base.win.movePointer(0, self.win_center_x, self.win_center_y)
            self.last_mouse_x = self.win_center_x

        #if current_mouse_y == 0 or current_mouse_y >= (self.win_center_y * 1.5):

        #    base.win.movePointer(0, self.win_center_x, self.win_center_y)
        #    self.last_mouse_y = self.win_center_y

        yaw_shift = -((mouse_shift_x) * self.rot_rate)
        #pitch_shift = -((mouse_shift_y) * self.rot_rate)

        self.avatarYawRot += yaw_shift
        #self.avatarPitchRot += pitch_shift

        self.pandaActor.setH(self.pandaActor, yaw_shift)
        self.cam.setH(self.cam, yaw_shift)

        cam_x_adjust = self.cam_away*sin(radians(self.avatarYawRot))  
        cam_y_adjust = self.cam_away*cos(radians(self.avatarYawRot))

        self.cam.setPos(self.pandaActor.getX() + cam_x_adjust, self.pandaActor.getY() - cam_y_adjust, 
                        self.pandaActor.getZ() + self.cam_elevation)






        #self.cTrav.traverse(render)

        #entries = []

        #for i in range(self.pandaGroundCollisionHandler.getNumEntries()):

        #    entry = self.pandaGroundCollisionHandler.getEntry(i)
        #    entries.append(entry)

        #for entry in entries:

        #    print entry.getIntoNode().getName()

        #    if entry.getIntoNode().getName() == "terrain":

        #        print "shiet"

        #        self.pandaActor.setZ(entry.getSurfacePoint(render).getZ())

        return Task.cont
Esempio n. 9
0
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.seeNode = self.render.attachNewNode('see')

        self.cam.reparentTo(self.seeNode)
        self.cam.setPos(0, 0, 5)

        self.fpscamera = fpscontroller.FpsController(self, self.seeNode)
        self.fpscamera.setFlyMode(True)
        self.fpscamera.setMouseLook(True)

        self.prevPos = self.fpscamera.getPos()
        self.prevInto = None

        self.makeInstructions()
        self.info = self.genLabelText("Position: <unknown>", 2)

        self.initCollisions()

        self.leftColor = LVecBase4i(224, 224, 64, 255)
        self.rightColor = LVecBase4i(64, 224, 224, 255)

        self.isDrawing = False
        self.toggleDrawing()

        self.accept("escape", sys.exit)  #Escape quits
        self.accept("enter", self.toggleDrawing)

    def initCollisions(self):
        # Initialize the collision traverser.
        self.cTrav = CollisionTraverser()

        self.cTrav.showCollisions(self.render)

        # Initialize the Pusher collision handler.
        self.pusher = CollisionHandlerFloor()

        ### player

        # Create a collsion node for this object.
        playerNode = CollisionNode('player')
        playerNode.addSolid(CollisionSphere(0, 0, 0, 1))

        # Attach the collision node to the object's model.
        self.playerC = self.fpscamera.player.attachNewNode(playerNode)
        # Set the object's collision node to render as visible.
        self.playerC.show()

    def toggleDrawing(self):
        self.isDrawing = not self.isDrawing

        if self.isDrawing:
            self.instructionText.setText(
                'Enter: Generate Tunnel from Movement')

            self.fpscamera.setFlyMode(True)
            self.prevPos = None

            # self.cTrav.remosveCollider(self.playerC)

            self.removeTask('updatePhysics')
            self.addTask(self.drawHere, 'drawHere')

            self.geomNode = GeomNode('geomNode')
            self.geomNodePath = self.render.attachNewNode(self.geomNode)

            self.geomNodePath.setTwoSided(True)

            # apparently p3tinydisplay needs this
            self.geomNodePath.setColorOff()

            # Create a collision node for this object.
            self.floorCollNode = CollisionNode('geom')

            # Attach the collision node to the object's model.
            floorC = self.geomNodePath.attachNewNode(self.floorCollNode)
            # Set the object's collision node to render as visible.
            floorC.show()

            self.newVertexData()

            self.newGeom()

        else:
            self.instructionText.setText('Enter: Record Movement for Tunnel')

            self.removeTask('drawHere')
            if self.prevPos:
                #self.completePath()
                self.completeTunnelPath()

            self.fpscamera.setFlyMode(True)

            self.drive.setPos(self.fpscamera.getPos())

            self.cTrav.addCollider(self.playerC, self.pusher)
            self.pusher.addCollider(self.playerC, self.fpscamera.player)

            self.taskMgr.add(self.updatePhysics, 'updatePhysics')

    def newVertexData(self):
        fmt = GeomVertexFormat.getV3c4()
        #         fmt = GeomVertexFormat.getV3n3c4()
        self.vertexData = GeomVertexData("path", fmt, Geom.UHStatic)
        self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex')
        #         self.normalWriter = GeomVertexWriter(self.vertexData, 'normal')
        self.colorWriter = GeomVertexWriter(self.vertexData, 'color')

    def newGeom(self):
        self.triStrips = GeomTristrips(Geom.UHDynamic)
        self.geom = Geom(self.vertexData)
        self.geom.addPrimitive(self.triStrips)

    def makeInstructions(self):
        OnscreenText(text="Draw Path by Walking (WSAD/space/mouselook)",
                     style=1,
                     fg=(1, 1, 0, 1),
                     pos=(0.5, -0.95),
                     scale=.07)
        self.genLabelText("ESC: Quit", 0)
        self.instructionText = self.genLabelText("", 1)

    def genLabelText(self, text, i):
        return OnscreenText(text=text,
                            pos=(-1.3, .95 - .05 * i),
                            fg=(1, 1, 0, 1),
                            align=TextNode.ALeft,
                            scale=.05)

    def drawHere(self, task):
        pos = self.fpscamera.getPos()
        self.info.setText("Position: {0}, {1}, {2} at {3} by {4}".format(
            int(pos.x * 100) / 100.,
            int(pos.y * 100) / 100.,
            int(pos.z) / 100., self.fpscamera.getHeading(),
            self.fpscamera.getLookAngle()))

        prevPos = self.prevPos

        if not prevPos:
            self.prevPos = pos

        elif (pos - prevPos).length() >= 1:
            #             self.extendPathQuad(prevPos, pos, 2)
            self.extendPathTunnel(prevPos, pos, 3)

            self.leftColor[1] += 63
            self.rightColor[2] += 37

            self.prevPos = pos

        return task.cont

    def extendPathQuad(self, prevPos, pos, width):
        self.drawQuadTo(prevPos, pos, width)

        row = self.vertexWriter.getWriteRow()
        numPrims = self.triStrips.getNumPrimitives()
        if numPrims == 0:
            primVerts = row
        else:
            primVerts = row - self.triStrips.getPrimitiveEnd(numPrims - 1)

        if primVerts >= 4:
            self.triStrips.closePrimitive()

            if row >= 256:
                print "Packing and starting anew"
                newGeom = True
                self.geom.unifyInPlace(row, False)
            else:
                newGeom = False

            self.completeQuadPath()

            if newGeom:
                self.newVertexData()

            self.newGeom()
            if newGeom:
                self.drawQuadTo(prevPos, pos, width)
            else:
                self.triStrips.addConsecutiveVertices(row - 2, 2)

    def extendPathTunnel(self, prevPos, pos, width):
        self.drawTunnelTo(prevPos, pos, width)

    def drawLineTo(self, pos, color):
        self.vertexWriter.addData3f(pos.x, pos.y, pos.z)
        #         self.normalWriter.addData3f(0, 0, 1)
        self.colorWriter.addData4i(color)

        self.triStrips.addNextVertices(1)

        return 1

    def drawQuadTo(self, a, b, width):
        """ a (to) b are vectors defining a line bisecting a new quad. """
        into = (b - a)
        if abs(into.x) + abs(into.y) < 1:
            # ensure that if we jump in place, we don't get a thin segment
            if not self.prevInto:
                return
            into = self.prevInto
        else:
            into.normalize()

        # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space

        if self.vertexWriter.getWriteRow() == 0:
            self.drawQuadRow(a, into, width)

        verts = self.drawQuadRow(b, into, width)

        self.prevInto = into

        return verts

    def drawQuadRow(self, a, into, width):
        """ a defines a point, with 'into' being the normalized direction. """

        # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space

        aLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z)
        aRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z)

        row = self.vertexWriter.getWriteRow()

        self.vertexWriter.addData3f(aLeft)
        self.vertexWriter.addData3f(aRight)

        #         self.normalWriter.addData3f(Vec3(0, 0, 1))
        #         self.normalWriter.addData3f(Vec3(0, 0, 1))

        self.colorWriter.addData4i(self.leftColor)
        self.colorWriter.addData4i(self.rightColor)

        self.triStrips.addConsecutiveVertices(row, 2)

        return 2

    def drawTunnelTo(self, a, b, width):
        """ a (to) b are vectors defining a line bisecting a new tunnel segment. """
        into = (b - a)
        if abs(into.x) + abs(into.y) < 1:
            # ensure that if we jump in place, we don't get a thin segment
            if not self.prevInto:
                return
            into = self.prevInto
        else:
            into.normalize()

        # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space

        if self.vertexWriter.getWriteRow() == 0:
            self.drawTunnelBoundary(a, into, width)

        row = self.vertexWriter.getWriteRow()
        verts = self.drawTunnelBoundary(b, into, width)
        totalVerts = self.drawTunnelRow(row, verts)

        self.prevInto = into

        return totalVerts

    def drawTunnelBoundary(self, a, into, width):
        """ a defines a point, with 'into' being the normalized direction. """

        aLowLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z)
        aLowRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z)
        aHighRight = Vec3(a.x + into.y * width, a.y - into.x * width,
                          a.z + width * 3)
        aHighLeft = Vec3(a.x - into.y * width, a.y + into.x * width,
                         a.z + width * 3)

        self.vertexWriter.addData3f(aLowLeft)
        self.vertexWriter.addData3f(aLowRight)
        self.vertexWriter.addData3f(aHighRight)
        self.vertexWriter.addData3f(aHighLeft)

        self.colorWriter.addData4i(self.leftColor)
        self.colorWriter.addData4i(self.rightColor)
        self.colorWriter.addData4i(self.leftColor)
        self.colorWriter.addData4i(self.rightColor)

        return 4

    def drawTunnelRowX(self, row, verts):
        # BOTTOM: bottom-left, new-bottom-left, bottom-right, new-bottom-right
        self.triStrips.addConsecutiveVertices(row - verts + 0, 1)
        self.triStrips.addConsecutiveVertices(row + 0, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 1, 1)
        self.triStrips.addConsecutiveVertices(row + 1, 1)
        self.triStrips.closePrimitive()
        # RIGHT: (new-bottom-right) bottom-right, new-top-right, top-right
        self.triStrips.addConsecutiveVertices(row + 1, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 1, 1)
        self.triStrips.addConsecutiveVertices(row + 2, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 2, 1)
        self.triStrips.closePrimitive()
        # TOP: top-left, new top-right, new top-left
        self.triStrips.addConsecutiveVertices(row - verts + 2, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
        self.triStrips.addConsecutiveVertices(row + 2, 1)
        self.triStrips.addConsecutiveVertices(row + 3, 1)
        self.triStrips.closePrimitive()
        # LEFT: (new top-left) new bottom-left, top-left, bottom-left, new-bottom-left
        self.triStrips.addConsecutiveVertices(row + 3, 1)
        self.triStrips.addConsecutiveVertices(row + 0, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 0, 1)
        self.triStrips.closePrimitive()

        return verts * 4

    def drawTunnelRow(self, row, verts):
        #         # clockwise for the inside of the tunnel
        #         # TOP: new-top-left, top-left, new-top-right, top-right
        #         self.triStrips.addConsecutiveVertices(row + 3, 1)
        #         self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
        #         self.triStrips.addConsecutiveVertices(row + 2, 1)
        #         self.triStrips.addConsecutiveVertices(row - verts + 2, 1)
        #         # RIGHT: new-bottom-right, bottom-right
        #         self.triStrips.addConsecutiveVertices(row + 1, 1)
        #         self.triStrips.addConsecutiveVertices(row - verts + 1, 1)
        #         # BOTTOM: new-bottom-left, bottom-left
        #         self.triStrips.addConsecutiveVertices(row, 1)
        #         self.triStrips.addConsecutiveVertices(row - verts, 1)
        #         # LEFT: new top-left, top-left
        #         self.triStrips.addConsecutiveVertices(row + 3, 1)
        #         self.triStrips.addConsecutiveVertices(row - verts + 3, 1)

        # TOP: new-top-left, top-left, new-top-right, top-right
        self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
        self.triStrips.addConsecutiveVertices(row + 3, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 2, 1)
        self.triStrips.addConsecutiveVertices(row + 2, 1)
        # RIGHT: new-bottom-right, bottom-right
        self.triStrips.addConsecutiveVertices(row - verts + 1, 1)
        self.triStrips.addConsecutiveVertices(row + 1, 1)
        # BOTTOM: new-bottom-left, bottom-left
        self.triStrips.addConsecutiveVertices(row - verts, 1)
        self.triStrips.addConsecutiveVertices(row, 1)
        # LEFT: new top-left, top-left
        self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
        self.triStrips.addConsecutiveVertices(row + 3, 1)

        self.triStrips.closePrimitive()

        return verts * 4

    def completeQuadPath(self):
        self.geomNode.addGeom(self.geom)

        if self.triStrips.getNumPrimitives() == 0:
            return

        floorMesh = CollisionFloorMesh()
        vertexReader = GeomVertexReader(self.vertexData, 'vertex')
        tris = self.triStrips.decompose()
        print "Decomposed prims:", tris.getNumPrimitives()
        p = 0
        for i in range(tris.getNumPrimitives()):
            v0 = tris.getPrimitiveStart(i)
            ve = tris.getPrimitiveEnd(i)
            if v0 < ve:
                vertexReader.setRow(tris.getVertex(v0))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                vertexReader.setRow(tris.getVertex(v0 + 1))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                vertexReader.setRow(tris.getVertex(v0 + 2))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                floorMesh.addTriangle(p, p + 1, p + 2)
                p += 3

        self.floorCollNode.addSolid(floorMesh)

    def completeTunnelPath(self):
        self.geomNode.addGeom(self.geom)

        if self.triStrips.getNumPrimitives() == 0:
            return

        floorMesh = CollisionFloorMesh()
        vertexReader = GeomVertexReader(self.vertexData, 'vertex')

        print "Original prims:", self.triStrips.getNumPrimitives()

        p = 0
        for i in range(self.triStrips.getNumPrimitives()):
            v0 = self.triStrips.getPrimitiveStart(i)
            ve = self.triStrips.getPrimitiveEnd(i)
            j = v0 + 4

            # add the bottom triangles
            vertexReader.setRow(self.triStrips.getVertex(j))
            floorMesh.addVertex(Point3(vertexReader.getData3f()))
            vertexReader.setRow(self.triStrips.getVertex(j + 1))
            floorMesh.addVertex(Point3(vertexReader.getData3f()))
            vertexReader.setRow(self.triStrips.getVertex(j + 2))
            floorMesh.addVertex(Point3(vertexReader.getData3f()))
            floorMesh.addTriangle(p, p + 1, p + 2)

            vertexReader.setRow(self.triStrips.getVertex(j + 3))
            floorMesh.addVertex(Point3(vertexReader.getData3f()))
            floorMesh.addTriangle(p + 1, p + 3, p + 2)

            p += 4

        # this adds every triangle, but is not appropriate for a closed path


#         tris = self.triStrips.decompose()
#         print "Decomposed prims:",tris.getNumPrimitives()
#         p = 0
#         for i in range(tris.getNumPrimitives()):
#             v0 = tris.getPrimitiveStart(i)
#             ve = tris.getPrimitiveEnd(i)
#             if v0 < ve:
#                 vertexReader.setRow(tris.getVertex(v0))
#                 floorMesh.addVertex(Point3(vertexReader.getData3f()))
#                 vertexReader.setRow(tris.getVertex(v0+1))
#                 floorMesh.addVertex(Point3(vertexReader.getData3f()))
#                 vertexReader.setRow(tris.getVertex(v0+2))
#                 floorMesh.addVertex(Point3(vertexReader.getData3f()))
#                 floorMesh.addTriangle(p, p+1, p+2)
#                 p += 3

        self.floorCollNode.addSolid(floorMesh)

    def updatePhysics(self, task):
        pos = self.fpscamera.getPos()

        self.info.setText("Position: {0}, {1}, {2}".format(
            int(pos.x * 100) / 100.,
            int(pos.y * 100) / 100.,
            int(pos.z) / 100.))

        return task.cont
Esempio n. 10
0
class Player(FSM, DirectObject):
    NormalMode = "Normal"
    FightMode = "Fight"

    GAMEPADMODE = "Gamepad"
    MOUSEANDKEYBOARD = "MouseAndKeyboard"

    def __init__(self):
        FSM.__init__(self, "FSM-Player")
        random.seed()

        #
        # PLAYER CONTROLS AND CAMERA
        #
        self.player = Actor(
            "Character",
            {
                "Idle": "Character-Idle",
                "Run": "Character-Run",
                "Activate": "Character-Activate",
                "Death": "Character-Death",
                "Jump": "Character-Jump",
                "Hit": "Character-Hit",
                "Fight_Attack": "Character-FightAttack",
                "Fight_Idle": "Character-FightIdle",
                "Fight_Left": "Character-FightLeft",
                "Fight_Right": "Character-FightRight",
            },
        )
        self.player.setBlend(frameBlend=True)
        # the initial cam distance
        self.fightCamDistance = 3.0
        # the next two vars will set the min and max distance the cam can have
        # to the node it is attached to
        self.maxCamDistance = 4.0
        self.minCamDistance = 1.2
        # the initial cam distance
        self.camDistance = (self.maxCamDistance - self.minCamDistance) / 2.0 + self.minCamDistance
        # the next two vars set the min and max distance on the Z-Axis to the
        # node the cam is attached to
        self.maxCamHeightDist = 3.0
        self.minCamHeightDist = 1.5
        # the average camera height
        self.camHeightAvg = (self.maxCamHeightDist - self.minCamHeightDist) / 2.0 + self.minCamHeightDist
        # an invisible object which will fly above the player and will be used to
        # track the camera on it
        self.camFloater = NodePath(PandaNode("playerCamFloater"))
        self.camFloater.setPos(0, 0, 1.5)
        self.camFloater.reparentTo(self.player)
        # screen sizes
        self.winXhalf = base.win.getXSize() / 2
        self.winYhalf = base.win.getYSize() / 2
        # Interval for the jump animation
        self.jumpInterval = None
        self.jumpstartFloater = NodePath(PandaNode("jumpstartFloater"))
        self.jumpstartFloater.reparentTo(render)
        self.deathComplete = None
        # Joystick/Gamepad support
        self.hasJoystick = False
        if gamepadSupport:
            # initialize controls
            joysticks = [pygame.joystick.Joystick(x) for x in range(pygame.joystick.get_count())]
            if len(joysticks) > 0:
                self.mainJoystick = joysticks[0]
                self.mainJoystick.init()
                self.hasJoystick = True

        #
        # WEAPONS AND ACCESSORIES
        #
        self.RightHandAttach = self.player.exposeJoint(None, "modelRoot", "HandAttach_R")
        self.spear = loader.loadModel("Spear")
        self.spear.setP(90)
        self.spear.setR(180)
        self.spear.reparentTo(self.RightHandAttach)
        self.LeftHandAttach = self.player.exposeJoint(None, "modelRoot", "HandAttach_L")
        self.shield = loader.loadModel("Shield")
        self.shield.setZ(0.05)
        self.shield.setH(-90)
        self.shield.reparentTo(self.LeftHandAttach)

        #
        # PLAYER COLLISION DETECTION AND PHYSICS
        #
        self.playerSphere = CollisionSphere(0, 0, 0.8, 0.7)
        self.playerCollision = self.player.attachNewNode(CollisionNode("playerCollision"))
        self.playerCollision.node().addSolid(self.playerSphere)
        base.pusher.addCollider(self.playerCollision, self.player)
        base.cTrav.addCollider(self.playerCollision, base.pusher)
        # The foot collision checks
        self.footRay = CollisionRay(0, 0, 0, 0, 0, -1)
        self.playerFootRay = self.player.attachNewNode(CollisionNode("playerFootCollision"))
        self.playerFootRay.node().addSolid(self.footRay)
        self.playerFootRay.node().setIntoCollideMask(0)
        self.lifter = CollisionHandlerFloor()
        self.lifter.addCollider(self.playerFootRay, self.player)
        self.lifter.setMaxVelocity(5)
        base.cTrav.addCollider(self.playerFootRay, self.lifter)
        # a collision segment slightly in front of the player to check for jump ledges
        self.jumpCheckSegment = CollisionSegment(0, -0.2, 0.5, 0, -0.2, -2)
        self.playerJumpRay = self.player.attachNewNode(CollisionNode("playerJumpCollision"))
        self.playerJumpRay.node().addSolid(self.jumpCheckSegment)
        self.playerJumpRay.node().setIntoCollideMask(0)
        self.jumper = CollisionHandlerEvent()
        self.jumper.addOutPattern("%fn-out")
        base.cTrav.addCollider(self.playerJumpRay, self.jumper)
        # a collision segment to check attacks
        self.attackCheckSegment = CollisionSegment(0, 0, 1, 0, -1.3, 1)
        self.playerAttackRay = self.player.attachNewNode(CollisionNode("playerAttackCollision"))
        self.playerAttackRay.node().addSolid(self.attackCheckSegment)
        self.playerAttackRay.node().setIntoCollideMask(0)
        self.attackqueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.playerAttackRay, self.attackqueue)

        #
        # SOUNDEFFECTS
        #
        self.footstep = loader.loadSfx("Footstep.ogg")
        self.footstep.setLoop(True)
        self.footstep.setPlayRate(1.5)
        self.footstep.setVolume(0.5)
        self.spearAttackSfx = loader.loadSfx("SpearAttack.ogg")
        self.spearAttackSfx.setVolume(0.5)

    #
    # START/STOP
    #
    def start(self, startPoint):
        self.player.setPos(startPoint.getPos())
        self.player.setHpr(startPoint.getHpr())
        self.player.reparentTo(render)
        self.jumpstartFloater.setPos(self.player.getPos())

        self.keyMap = {"horizontal": 0, "vertical": 0}

        self.health = 3
        self.trackedEnemy = None
        # this mode will be used to determine in which move mode the player currently is
        self.mode = Player.NormalMode
        # the initial cam height
        self.camHeight = self.camHeightAvg
        # a time to keep the cam zoom at a specific speed independent of
        # current framerate
        self.camElapsed = 0.0
        self.mouseSpeedX = 15.0 * base.mouseSensitivity
        self.mouseSpeedY = 0.2 * base.mouseSensitivity
        self.speed = 1.0

        self.camCenterEvents = ["centerCam", "home", "q"]
        self.camZoomInEvents = ["zoomIn", "+", "wheel_up"]
        self.camZoomOutEvents = ["zoomOut", "-", "wheel_down"]
        self.actionEvents = ["doAction", "enter", "e"]

        self.accept("arrow_left", self.setKey, ["horizontal", 1])
        self.accept("arrow_right", self.setKey, ["horizontal", -1])
        self.accept("arrow_up", self.setKey, ["vertical", -1])
        self.accept("arrow_down", self.setKey, ["vertical", 1])
        self.accept("arrow_left-up", self.setKey, ["horizontal", 0])
        self.accept("arrow_right-up", self.setKey, ["horizontal", 0])
        self.accept("arrow_up-up", self.setKey, ["vertical", 0])
        self.accept("arrow_down-up", self.setKey, ["vertical", 0])
        self.accept("a", self.setKey, ["horizontal", 1])
        self.accept("d", self.setKey, ["horizontal", -1])
        self.accept("w", self.setKey, ["vertical", -1])
        self.accept("s", self.setKey, ["vertical", 1])
        self.accept("a-up", self.setKey, ["horizontal", 0])
        self.accept("d-up", self.setKey, ["horizontal", 0])
        self.accept("w-up", self.setKey, ["vertical", 0])
        self.accept("s-up", self.setKey, ["vertical", 0])
        for event in self.camCenterEvents:
            self.acceptOnce(event, self.center)
        for event in self.camZoomInEvents:
            self.acceptOnce(event, self.zoom, [True])
        for event in self.camZoomOutEvents:
            self.acceptOnce(event, self.zoom, [False])
        for event in self.actionEvents:
            self.acceptOnce(event, self.request, ["Action"])
        self.accept("ActionDone", self.request, ["Idle"])

        self.accept("playerJumpCollision-out", self.jump)

        taskMgr.add(self.move, "task_movement", priority=-10)
        taskMgr.add(self.updateCam, "task_camActualisation", priority=-4)

        if self.hasJoystick:
            taskMgr.add(self.gamepadLoop, "task_gamepad_loop", priority=-5)

        camera.setPos(self.player, 0, self.camDistance, self.camHeightAvg)

        self.hasJumped = False
        self.isActionmove = False

        self.request("Idle")

    def stop(self):
        taskMgr.remove("task_movement")
        taskMgr.remove("task_camActualisation")
        taskMgr.remove("task_gamepad_loop")
        self.ignoreAll()
        self.player.hide()

    def cleanup(self):
        self.stop()
        if self.deathComplete is not None:
            self.deathComplete.finish()
        if self.jumpInterval is not None:
            self.jumpInterval.finish()
        self.spear.removeNode()
        self.shield.removeNode()
        self.player.cleanup()
        self.player.removeNode()
        self.jumpstartFloater.removeNode()
        self.camFloater.removeNode()

    #
    # BASIC FUNCTIONS
    #
    def die(self):
        self.health -= 1
        base.messenger.send("setHealth", [self.health])
        self.request("Death")

    def heal(self):
        if self.health >= 3:
            return
        self.health += 1
        base.messenger.send("setHealth", [self.health])

    def hit(self):
        self.health -= 1
        base.messenger.send("setHealth", [self.health])
        if self.health == 0:
            self.request("Death")
        else:
            self.request("Hit")

    def resetPlayerPos(self):
        self.player.setPos(self.jumpstartFloater.getPos())
        self.jumper.clear()
        self.request("Idle")

    def gameOver(self):
        base.messenger.send("GameOver", ["loose"])

    def enterFightMode(self, trackedEnemy):
        self.trackedEnemy = trackedEnemy
        self.mode = Player.FightMode
        base.messenger.send("EnterFightMode")

    def exitFightMode(self):
        self.trackedEnemy = None
        self.mode = Player.NormalMode
        base.messenger.send("ExitFightMode")

    def gamepadLoop(self, task):
        joymap = {0: "doAction", 5: "centerCam", 6: "zoomIn", 4: "zoomOut", 9: "escape"}
        for event in pygame.event.get():
            for button in range(self.mainJoystick.get_numbuttons()):
                if button in joymap and self.mainJoystick.get_button(button):
                    base.messenger.send(joymap[button])
            if event.type == pygame.JOYAXISMOTION:
                for axis in range(self.mainJoystick.get_numaxes()):
                    axisChange = 0.0
                    axisChange = self.mainJoystick.get_axis(axis)
                    if axis == 0:
                        self.setKey("horizontal", -axisChange)
                    if axis == 1:
                        self.setKey("vertical", axisChange)
        return task.cont

    def setAnimationSpeed(self, requestedState):
        if requestedState == "Run":
            self.player.setPlayRate(3 * self.speed, "Run")
        elif requestedState == "RunReverse":
            self.player.setPlayRate(-3 * self.speed, "Run")
        elif requestedState == "FightLeft":
            self.player.setPlayRate(2 * self.speed, "Fight_Left")
        elif requestedState == "FightRight":
            self.player.setPlayRate(2 * self.speed, "Fight_Right")

    #
    # MOVE FUNCTIONS
    #
    def setKey(self, key, value):
        self.keyMap[key] = value

    def move(self, task):
        dt = globalClock.getDt()
        resetMouse = False

        def resetMouse():
            if base.controlType == Player.MOUSEANDKEYBOARD:
                base.win.movePointer(0, self.winXhalf, self.winYhalf)

        if self.player.getAnimControl("Hit").isPlaying() or self.player.getAnimControl("Death").isPlaying():
            resetMouse()
            return task.cont
        if self.deathComplete is not None:
            if self.deathComplete.isPlaying():
                resetMouse()
                return task.cont
        if self.jumpInterval is not None:
            if self.jumpInterval.isPlaying():
                resetMouse()
                return task.cont
        if self.isActionmove:
            resetMouse()
            return task.cont

        if self.mode == Player.NormalMode:
            self.__normalMove(dt)
        else:
            self.__fightMove(dt)
        return task.cont

    def __normalMove(self, dt):
        requestState = "Idle"
        move = False
        if self.keyMap["horizontal"] != 0:
            requestState = "Run"
            move = True
        if self.keyMap["vertical"] != 0:
            requestState = "Run"
            move = True
        if move and base.controlType == Player.GAMEPADMODE:
            movementVec = Vec3(self.keyMap["horizontal"], self.keyMap["vertical"], 0)
            self.speed = max(abs(self.keyMap["horizontal"]), abs(self.keyMap["vertical"]))
            angle = math.atan2(-movementVec.getX(), movementVec.getY())
            rotation = angle * (180.0 / math.pi)
            self.player.setH(camera, rotation)
            self.player.setP(0)
            self.player.setR(0)
            self.player.setPos(self.player, (0, -2 * self.speed * dt, 0))
        elif base.controlType == Player.MOUSEANDKEYBOARD:
            if not base.mouseWatcherNode.hasMouse():
                return
            self.pointer = base.win.getPointer(0)
            mouseX = self.pointer.getX()
            mouseY = self.pointer.getY()

            if base.win.movePointer(0, self.winXhalf, self.winYhalf):
                z = camera.getZ() + (mouseY - self.winYhalf) * self.mouseSpeedY * dt
                camera.setZ(z)

                h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX * dt
                if h < -360:
                    h = 360
                elif h > 360:
                    h = -360
                self.player.setH(h)
                if move:
                    self.player.setPos(
                        self.player, (2 * dt * self.keyMap["horizontal"], 2 * dt * self.keyMap["vertical"], 0)
                    )
                self.center()
        if self.state != requestState:
            self.request(requestState)
        self.setAnimationSpeed(requestState)

    def __fightMove(self, dt):
        if self.trackedEnemy == None:
            return
        requestState = "Idle"
        self.player.lookAt(self.trackedEnemy)
        self.player.setH(self.player, 180)
        if self.keyMap["horizontal"] > 0:
            self.player.setX(self.player, 2 * self.speed * dt)
            requestState = "FightLeft"
        elif self.keyMap["horizontal"] < 0:
            self.player.setX(self.player, -2 * self.speed * dt)
            requestState = "FightRight"
        elif self.keyMap["vertical"] < 0:
            self.player.setY(self.player, -2 * self.speed * dt)
            requestState = "Run"
        elif self.keyMap["vertical"] > 0:
            self.player.setY(self.player, 2 * self.speed * dt)
            requestState = "RunReverse"
        if self.state != requestState:
            self.request(requestState)
        self.setAnimationSpeed(requestState)

    def jump(self, extraArg):
        intoName = extraArg.getIntoNode().getName().lower()
        if not "floor" in intoName and not "plate" in intoName:
            return
        # setup the projectile interval
        startPos = self.player.getPos()
        self.jumpstartFloater.setPos(self.player, 0, 0.5, 0)
        tempFloater = NodePath(PandaNode("tempJumpFloater"))
        tempFloater.setPos(self.player, 0, -3.2, 0.1)
        endPos = tempFloater.getPos()
        tempFloater.removeNode()
        self.jumpInterval = ProjectileInterval(
            self.player, startPos=startPos, endPos=endPos, duration=1.5, gravityMult=0.25
        )
        self.request("Jump")
        self.jumpInterval.start()

    #
    # CAMERA FUNCTIONS
    #
    def updateCam(self, task):
        if self.mode == Player.NormalMode:
            self.__normalCam()
        else:
            self.__fightCam()
        return task.cont

    def zoom(self, zoomIn):

        # Camera Movement Updates
        camvec = self.player.getPos() - camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()

        zoom = 0
        if zoomIn:
            if camdist > self.minCamDistance + 0.5:
                zoom = 0.5
            for event in self.camZoomInEvents:
                self.acceptOnce(event, self.zoom, [True])
        else:
            if camdist < self.maxCamDistance - 0.5:
                zoom = -0.5
            for event in self.camZoomOutEvents:
                self.acceptOnce(event, self.zoom, [False])
        camera.setPos(camera, 0, zoom, 0)

    def center(self):
        # Camera Movement Updates
        camvec = self.player.getPos() - camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()
        # get the cameras current offset to the player model on the z-axis
        offsetZ = camera.getZ() - self.player.getZ()
        camera.setPos(self.player, 0, camdist, offsetZ)
        for event in self.camCenterEvents:
            self.acceptOnce(event, self.center)

    def __normalCam(self):
        """This function will check the min and max distance of the camera to
        the defined model and will correct the position if the cam is to close
        or to far away"""

        # Camera Movement Updates
        camvec = self.player.getPos() - camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()
        camvec.normalize()

        # If far from player start following
        if camdist > self.maxCamDistance:
            camera.setPos(camera.getPos() + camvec * (camdist - self.maxCamDistance))
            camdist = self.maxCamDistance

        # If player to close move cam backwards
        if camdist < self.minCamDistance:
            camera.setPos(camera.getPos() - camvec * (self.minCamDistance - camdist))
            camdist = self.minCamDistance

        # get the cameras current offset to the player model on the z-axis
        offsetZ = camera.getZ() - self.player.getZ()
        # check if the camera is within the min and max z-axis offset
        if offsetZ < self.minCamHeightDist:
            camera.setZ(self.player.getZ() + self.minCamHeightDist)
            offsetZ = self.minCamHeightDist
        elif offsetZ > self.maxCamHeightDist:
            camera.setZ(self.player.getZ() + self.maxCamHeightDist)
            offsetZ = self.maxCamHeightDist

        if offsetZ != self.camHeightAvg and not base.controlType == Player.MOUSEANDKEYBOARD:
            # if we are not moving up or down, set the cam to an average position
            if offsetZ != self.camHeightAvg:
                if offsetZ > self.camHeightAvg:
                    # the cam is higher then the average cam height above the player
                    # so move it slowly down
                    camera.setZ(camera.getZ() - 5 * globalClock.getDt())
                    newOffsetZ = camera.getZ() - self.player.getZ()
                    # check if the cam has reached the desired offset
                    if newOffsetZ < self.camHeightAvg:
                        # set the cam z position to exactly the desired offset
                        camera.setZ(self.player.getZ() + self.camHeightAvg)
                else:
                    # the cam is lower then the average cam height above the player
                    # so move it slowly up
                    camera.setZ(camera.getZ() + 5 * globalClock.getDt())
                    newOffsetZ = camera.getZ() - self.player.getZ()
                    # check if the cam has reached the desired offset
                    if newOffsetZ > self.camHeightAvg:
                        # set the cam z position to exactly the desired offset
                        camera.setZ(self.player.getZ() + self.camHeightAvg)

        camera.lookAt(self.camFloater)

    def __fightCam(self):
        """This function will check the min and max distance of the camera to
        the defined model and will correct the position if the cam is to close
        or to far away"""
        camera.setX(self.player, 0)
        camera.setY(self.player, self.fightCamDistance)
        camera.setZ(0.5)

        camera.lookAt(self.camFloater)

    #
    # FSM FUNCTIONS
    #
    def enterIdle(self):
        if self.mode == Player.NormalMode:
            self.player.loop("Idle")
            self.footstep.stop()
        elif self.mode == Player.FightMode:
            self.player.loop("Fight_Idle")
            self.footstep.stop()

    def enterRun(self):
        self.player.loop("Run")
        self.footstep.play()

    def enterRunReverse(self):
        self.player.loop("Run")
        self.footstep.play()

    def enterAction(self):
        if self.player.getAnimControl("Hit").isPlaying() or self.player.getAnimControl("Death").isPlaying():
            self.__exitAction()
            return
        self.isActionmove = True
        if self.mode == Player.NormalMode:
            self.__enterActivate()
        elif self.mode == Player.FightMode:
            self.__enterFightAttack()
        self.accept("ActionDone", self.__exitAction)

    def __exitAction(self):
        self.isActionmove = False
        for event in self.actionEvents:
            self.acceptOnce(event, self.request, ["Action"])

    def __enterActivate(self):
        activateAnim = self.player.actorInterval("Activate", playRate=3)
        activateAnim.setDoneEvent("ActionDone")
        activateAnim.start()
        base.messenger.send("Player_Activate")
        self.footstep.stop()

    def enterDeath(self):
        self.footstep.stop()
        deathAnim = self.player.actorInterval("Death")
        deathComplete = None
        if self.health == 0:
            self.deathComplete = Sequence(deathAnim, Wait(2), Func(self.gameOver))
        else:
            self.deathComplete = Sequence(deathAnim, Wait(2), Func(self.resetPlayerPos))
        self.deathComplete.start()

    def enterJump(self):
        self.player.play("Jump")
        self.footstep.stop()

    def enterHit(self):
        self.player.setPlayRate(4, "Hit")
        self.player.play("Hit")
        self.footstep.stop()

    def __enterFightAttack(self):
        attackAnim = self.player.actorInterval("Fight_Attack", playRate=3)
        attackAnim.setDoneEvent("ActionDone")
        attackAnim.start()
        self.spearAttackSfx.play()
        for i in range(self.attackqueue.getNumEntries()):
            entry = self.attackqueue.getEntry(i)
            into = entry.getIntoNode()
            if "golemHitField" in into.getName():
                if random.random() > 0.15:
                    base.messenger.send("HitEnemy")
        self.footstep.stop()

    def enterFightLeft(self):
        self.player.loop("Fight_Left")
        self.footstep.play()

    def enterFightRight(self):
        self.player.loop("Fight_Right")
        self.footstep.play()
Esempio n. 11
0
class MyApp(ShowBase):
    def __init__(self):

        ShowBase.__init__(self)

        self.disableMouse()

        self.cam_away = 20
        self.cam_elevation = 5
        self.rot_rate = .5

        self.cam_dist = (self.cam_away**2 + self.cam_elevation**2)**.5

        #######
        self.environ = GeoMipTerrain("terrain")
        self.environ.setHeightfield("../terrain/first.png")
        self.environ.setColorMap("../terrain/first-c.png")
        self.environ.generate()
        self.environ.getRoot().setScale(1, 1, 100)
        self.environ.getRoot().setPos(0, 0, 0)
        self.environ.getRoot().reparentTo(render)
        self.environ.getRoot().setName("terrain")
        self.environ.getRoot().setCollideMask(BitMask32.bit(0))
        #######

        self.pandaActor = Actor("models/panda", {"walk": "models/panda-walk"})
        self.pandaActor.setScale(.5, .5, .5)
        self.pandaActor.setHpr(180, 0, 0)
        self.pandaActor.setPos(50, 50, 50)
        self.pandaActor.reparentTo(render)
        self.pandaActor.setPythonTag("moving", False)
        self.avatarYawRot = 0
        self.avatarPitchRot = 0

        #self.teapot = loader.loadModel("models/teapot")
        #self.teapot.setScale(1, 1, 1)
        #self.teapot.setPos(60, 60, 50)
        #self.teapot.reparentTo(render)

        self.cam.setHpr(0, 0, 0)

        self.taskMgr.add(self.updateTerrain, "update terrain", priority=35)

        self.keys = {"w": 0, "s": 0, "a": 0, "d": 0}

        self.accept("w", self.setKey, ["w", 1])
        self.accept("w-up", self.setKey, ["w", 0])
        self.accept("s", self.setKey, ["s", 1])
        self.accept("s-up", self.setKey, ["s", 0])
        self.accept("a", self.setKey, ["a", 1])
        self.accept("a-up", self.setKey, ["a", 0])
        self.accept("d", self.setKey, ["d", 1])
        self.accept("d-up", self.setKey, ["d", 0])
        self.accept("wheel_up", self.zoomCamera, [-1])
        self.accept("wheel_down", self.zoomCamera, [1])

        self.accept('window-event', self.handleWindowEvent)

        props = WindowProperties()
        props.setCursorHidden(True)
        base.win.requestProperties(props)

        self.last_mouse_x = self.win.getPointer(0).getX()
        #self.last_mouse_y = self.win.getPointer(0).getY()

        self.cTrav = CollisionTraverser()

        self.pandaGroundRay = CollisionRay(0, 0, 0, 0, 0, 1)
        self.pandaGroundRayNode = CollisionNode('pandaGroundRay')
        self.pandaGroundRayNode.addSolid(self.pandaGroundRay)
        self.pandaGroundRayNode.setFromCollideMask(BitMask32.bit(0))
        self.pandaGroundRayNode.setIntoCollideMask(BitMask32.allOff())
        self.pandaGroundRayNodepath = self.pandaActor.attachNewNode(
            self.pandaGroundRayNode)
        self.pandaGroundRayNodepath.show()
        self.pandaGroundCollisionHandler = CollisionHandlerFloor()
        self.pandaGroundCollisionHandler.addCollider(
            self.pandaGroundRayNodepath, self.pandaActor)
        self.cTrav.addCollider(self.pandaGroundRayNodepath,
                               self.pandaGroundCollisionHandler)

        #self.teapotRay = CollisionSphere(0,0,0,5)
        #self.teapotGroundCol = CollisionNode('teapotRay')
        #self.teapotGroundCol.addSolid(self.teapotRay)
        #self.teapotGroundCol.setFromCollideMask(BitMask32.allOff())
        #self.teapotGroundCol.setIntoCollideMask(BitMask32.bit(0))
        #self.teapotGroundColNp = self.teapot.attachNewNode(self.teapotGroundCol)
        #self.teapotGroundHandler = CollisionHandlerQueue()
        #self.cTrav.addCollider(self.teapotGroundColNp, self.teapotGroundHandler)

    def setKey(self, key, value):

        self.keys[key] = value

    def handleWindowEvent(self, window=None):

        wp = window.getProperties()

        self.win_center_x = wp.getXSize() / 2
        self.win_center_y = wp.getYSize() / 2

    def zoomCamera(self, direction):

        self.cam_away += direction

    def updateTerrain(self, task):

        dt = globalClock.getDt()

        self.pandaActor.setY(self.pandaActor, -50 * dt)

        if self.keys["w"]: self.pandaActor.setZ(self.pandaActor, 20 * dt)

        if self.keys["s"]: self.pandaActor.setZ(self.pandaActor, -20 * dt)

        if self.keys["a"]: self.pandaActor.setX(self.pandaActor, 20 * dt)

        if self.keys["d"]: self.pandaActor.setX(self.pandaActor, -20 * dt)

        mouse_pos = self.win.getPointer(0)

        #Mouse-based viewpoint rotation

        current_mouse_x = mouse_pos.getX()
        #current_mouse_y = mouse_pos.getY()

        mouse_shift_x = current_mouse_x - self.last_mouse_x
        #mouse_shift_y = current_mouse_y - self.last_mouse_y

        self.last_mouse_x = current_mouse_x
        #self.last_mouse_y = current_mouse_y

        if current_mouse_x == 0 or current_mouse_x >= (self.win_center_x *
                                                       1.5):

            base.win.movePointer(0, self.win_center_x, self.win_center_y)
            self.last_mouse_x = self.win_center_x

        #if current_mouse_y == 0 or current_mouse_y >= (self.win_center_y * 1.5):

        #    base.win.movePointer(0, self.win_center_x, self.win_center_y)
        #    self.last_mouse_y = self.win_center_y

        yaw_shift = -((mouse_shift_x) * self.rot_rate)
        #pitch_shift = -((mouse_shift_y) * self.rot_rate)

        self.avatarYawRot += yaw_shift
        #self.avatarPitchRot += pitch_shift

        self.pandaActor.setH(self.pandaActor, yaw_shift)
        self.cam.setH(self.cam, yaw_shift)

        cam_x_adjust = self.cam_away * sin(radians(self.avatarYawRot))
        cam_y_adjust = self.cam_away * cos(radians(self.avatarYawRot))

        self.cam.setPos(self.pandaActor.getX() + cam_x_adjust,
                        self.pandaActor.getY() - cam_y_adjust,
                        self.pandaActor.getZ() + self.cam_elevation)

        #self.cTrav.traverse(render)

        #entries = []

        #for i in range(self.pandaGroundCollisionHandler.getNumEntries()):

        #    entry = self.pandaGroundCollisionHandler.getEntry(i)
        #    entries.append(entry)

        #for entry in entries:

        #    print entry.getIntoNode().getName()

        #    if entry.getIntoNode().getName() == "terrain":

        #        print "shiet"

        #        self.pandaActor.setZ(entry.getSurfacePoint(render).getZ())

        return Task.cont
Esempio n. 12
0
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.seeNode = self.render.attachNewNode('see')

        self.cam.reparentTo(self.seeNode)
        self.cam.setPos(0, 0, 5)

        self.fpscamera = fpscontroller.FpsController(self, self.seeNode)
        self.fpscamera.setFlyMode(True)

        self.prevPos = self.fpscamera.getPos()
        self.prevInto = None
        self.info = self.genLabelText("Position: <unknown>", 4)

        self.makeInstructions()
        self.initCollisions()

        self.leftColor = LVecBase4i(224, 224, 64, 255)
        self.rightColor = LVecBase4i(64, 224, 224, 255)

        self.isDrawing = False
        self.toggleDrawing()

        self.accept("escape", sys.exit)  #Escape quits
        self.accept("enter", self.toggleDrawing)

    def initCollisions(self):
        # Initialize the collision traverser.
        self.cTrav = CollisionTraverser()

        self.cTrav.showCollisions(self.render)

        #         self.cQueue = CollisionHandlerQueue()

        # Initialize the Pusher collision handler.
        #self.pusher = CollisionHandlerPusher()
        self.pusher = CollisionHandlerFloor()

        ### player

        print DirectNotifyGlobal.directNotify.getCategories()
        # Create a collsion node for this object.
        playerNode = CollisionNode('player')
        playerNode.addSolid(CollisionSphere(0, 0, 0, 1))

        #         playerNode.setFromCollideMask(BitMask32.bit(0))
        #         playerNode.setIntoCollideMask(BitMask32.allOn())

        # Attach the collision node to the object's model.
        self.playerC = self.fpscamera.player.attachNewNode(playerNode)
        # Set the object's collision node to render as visible.
        self.playerC.show()

        # Add the 'player' collision node to the Pusher collision handler.
        #self.pusher.addCollider(self.playerC, self.fpscamera.player)
        #self.pusher.addCollider(playerC, self.fpscamera.player)


#         self.cTrav.addCollider(self.playerC, self.cQueue)

    def toggleDrawing(self):
        self.isDrawing = not self.isDrawing

        if self.isDrawing:
            self.drawText.setText("Enter: Turn off drawing")
            self.fpscamera.setFlyMode(True)
            self.prevPos = None

            self.cTrav.removeCollider(self.playerC)
            self.pusher.removeCollider(self.playerC)

            self.removeTask('updatePhysics')
            self.addTask(self.drawHere, 'drawHere')

            self.geomNode = GeomNode('geomNode')
            self.geomNodePath = self.render.attachNewNode(self.geomNode)

            self.geomNodePath.setTwoSided(True)

            # apparently p3tinydisplay needs this
            self.geomNodePath.setColorOff()

            # Create a collision node for this object.
            self.floorCollNode = CollisionNode('geom')

            #             self.floorCollNode.setFromCollideMask(BitMask32.bit(0))
            #             self.floorCollNode.setIntoCollideMask(BitMask32.allOn())

            # Attach the collision node to the object's model.
            floorC = self.geomNodePath.attachNewNode(self.floorCollNode)
            # Set the object's collision node to render as visible.
            floorC.show()

            #self.pusher.addCollider(floorC, self.geomNodePath)

            self.newVertexData()

            self.newGeom()

        else:
            self.drawText.setText("Enter: Turn on drawing")
            self.removeTask('drawHere')
            if self.prevPos:
                self.completePath()

            self.fpscamera.setFlyMode(True)

            self.drive.setPos(self.fpscamera.getPos())

            self.cTrav.addCollider(self.playerC, self.pusher)
            self.pusher.addCollider(self.playerC, self.fpscamera.player)

            self.taskMgr.add(self.updatePhysics, 'updatePhysics')

    def newVertexData(self):
        fmt = GeomVertexFormat.getV3c4()
        #         fmt = GeomVertexFormat.getV3n3c4()
        self.vertexData = GeomVertexData("path", fmt, Geom.UHStatic)
        self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex')
        #         self.normalWriter = GeomVertexWriter(self.vertexData, 'normal')
        self.colorWriter = GeomVertexWriter(self.vertexData, 'color')

    def newGeom(self):
        self.triStrips = GeomTristrips(Geom.UHDynamic)
        self.geom = Geom(self.vertexData)
        self.geom.addPrimitive(self.triStrips)

    def makeInstructions(self):
        OnscreenText(text="Draw Path by Walking",
                     style=1,
                     fg=(1, 1, 0, 1),
                     pos=(0.5, -0.95),
                     scale=.07)

        self.drawText = self.genLabelText("", 0)
        self.genLabelText("Walk (W/S/A/D), Jump=Space, Look=PgUp/PgDn", 1)
        self.genLabelText(
            "  (hint, go backwards with S to see your path immediately)", 2)
        self.genLabelText("ESC: Quit", 3)

    def genLabelText(self, text, i):
        return OnscreenText(text=text,
                            pos=(-1.3, .95 - .05 * i),
                            fg=(1, 1, 0, 1),
                            align=TextNode.ALeft,
                            scale=.05)

    def drawHere(self, task):
        pos = self.fpscamera.getPos()
        self.info.setText("Position: {0}, {1}, {2} at {3} by {4}".format(
            int(pos.x * 100) / 100.,
            int(pos.y * 100) / 100.,
            int(pos.z) / 100., self.fpscamera.getHeading(),
            self.fpscamera.getLookAngle()))

        prevPos = self.prevPos

        if not prevPos:
            self.prevPos = pos

        elif (pos - prevPos).length() > 1:
            self.drawQuadTo(prevPos, pos, 2)

            row = self.vertexWriter.getWriteRow()
            numPrims = self.triStrips.getNumPrimitives()
            if numPrims == 0:
                primVerts = row
            else:
                primVerts = row - self.triStrips.getPrimitiveEnd(numPrims - 1)

            if primVerts >= 4:
                self.triStrips.closePrimitive()

                if row >= 256:
                    print "Packing and starting anew"
                    newGeom = True
                    self.geom.unifyInPlace(row, False)
                else:
                    newGeom = False

                self.completePath()

                if newGeom:
                    self.newVertexData()

                self.newGeom()
                if not newGeom:
                    self.triStrips.addConsecutiveVertices(row - 2, 2)
                else:
                    self.drawQuadTo(prevPos, pos, 2)

            self.leftColor[1] += 63
            self.rightColor[2] += 37

            self.prevPos = pos

        return task.cont

    def drawLineTo(self, pos, color):
        self.vertexWriter.addData3f(pos.x, pos.y, pos.z)
        #         self.normalWriter.addData3f(0, 0, 1)
        self.colorWriter.addData4i(color)

        self.triStrips.addNextVertices(1)

    def drawQuadTo(self, a, b, width):
        """ a (to) b are vectors defining a line bisecting a new quad. """
        into = (b - a)
        if abs(into.x) + abs(into.y) < 1:
            if not self.prevInto:
                return
            into = self.prevInto
            print into
        else:
            into.normalize()

        # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space

        if self.vertexWriter.getWriteRow() == 0:
            self.drawQuadRow(a, into, width)

        self.drawQuadRow(b, into, width)

        self.prevInto = into

    def drawQuadRow(self, a, into, width):
        """ a defines a point, with 'into' being the normalized direction. """

        # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space

        aLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z)
        aRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z)

        row = self.vertexWriter.getWriteRow()

        self.vertexWriter.addData3f(aLeft)
        self.vertexWriter.addData3f(aRight)

        #         self.normalWriter.addData3f(Vec3(0, 0, 1))
        #         self.normalWriter.addData3f(Vec3(0, 0, 1))

        self.colorWriter.addData4i(self.leftColor)
        self.colorWriter.addData4i(self.rightColor)

        self.triStrips.addConsecutiveVertices(row, 2)

    def completePath(self):
        self.geomNode.addGeom(self.geom)

        if self.triStrips.getNumPrimitives() == 0:
            return

        floorMesh = CollisionFloorMesh()

        tris = self.triStrips.decompose()
        p = 0
        vertexReader = GeomVertexReader(self.vertexData, 'vertex')
        for i in range(tris.getNumPrimitives()):
            v0 = tris.getPrimitiveStart(i)
            ve = tris.getPrimitiveEnd(i)
            if v0 < ve:
                vertexReader.setRow(tris.getVertex(v0))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                vertexReader.setRow(tris.getVertex(v0 + 1))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                vertexReader.setRow(tris.getVertex(v0 + 2))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                floorMesh.addTriangle(p, p + 1, p + 2)
                p += 3

        self.floorCollNode.addSolid(floorMesh)

    def updatePhysics(self, task):
        pos = self.fpscamera.getPos()
        self.info.setText("Position: {0}, {1}, {2}".format(
            int(pos.x * 100) / 100.,
            int(pos.y * 100) / 100.,
            int(pos.z) / 100.))
        return task.cont
Esempio n. 13
0
class Maleficium(ShowBase):
    def __init__(self):
        compressedTextures = ConfigVariableString('compressed-textures','1') # Compresses Textures on load (increases loadtime / framerate)
        ShowBase.__init__(self)
        
        ## Debug Values (True/False)
        self.fpsMeter = True
        
        debug.checkDebugSettings(self)

        self.KeyBindings()

        ## Load World
        world.load('prisonCrater')

        ## Add Player to World
        self.playerBox = NodePath('player')
        self.player = Actor("data/models/hm.bam",
                            {"run":"data/models/hm-run.bam",
                             "idle":"data/models/hm.bam"})
        self.player.reparentTo(self.playerBox)
        self.player.setScale(.01)
        self.playerBox.reparentTo(render)
        self.isMoving = False

        ## Create Camera
        base.disableMouse()
        self.cameratarget = self.render.attachNewNode('Camera Target')
        base.camera.setPos(self.playerBox.getX(),self.playerBox.getY()+20,self.playerBox.getZ()+5)
        self.cameratarget.setPos(self.playerBox.getX(),self.playerBox.getY(),self.playerBox.getZ()+6)
        self.radius = 10
        self.XYAngle = .028
        self.ZAngle = .01

        ## Set Up Ground Collisions
        ## Player Collision
        base.cTrav = CollisionTraverser()
        self.ColHandler = CollisionHandlerFloor()       
        self.colGroundRay = CollisionNode('colGroundRay')
        self.colGroundRay.addSolid(CollisionRay(0,0,2,0,0,-1))
        self.playerCol = self.playerBox.attachNewNode(self.colGroundRay)
        base.cTrav.addCollider(self.playerCol,self.ColHandler)
        self.ColHandler.addCollider(self.playerCol,self.playerBox)
                                       
        ## Add main Game Loop to taskmanager
        taskMgr.add(self.gameLoop,'mainLoop')


    ### Input Structure; Coded by Darren Kent (Modeled after Roaming-Ralph by Ryan Myers)
    def KeyBindings(self):
        ## Setup Map
        self.startRightClick = True
        
        self.keyMap = {
            "forward":0,
            "backward":0,
            "turn_left":0,
            "turn_right":0,
            "strafe_left":0,
            "strafe_right":0,
            "cam_up":0,
            "cam_down":0,
            "cam_right":0,
            "cam_left":0,
            "zoom_in":0,
            "zoom_out":0,
            "right_click":0,
            "wheel_zoom_in":0,
            "wheel_zoom_out":0,
            }

        ## Accept Keys
        self.accept('escape',sys.exit)
        self.accept('w', self.setKey, ['forward',1])
        self.accept('w-up', self.setKey, ['forward',0])
        self.accept('s', self.setKey, ['backward',1])
        self.accept('s-up', self.setKey, ['backward',0])
        self.accept('a', self.setKey, ['turn_left',1])
        self.accept('a-up', self.setKey, ['turn_left',0])
        self.accept('d', self.setKey, ['turn_right',1])
        self.accept('d-up', self.setKey, ['turn_right',0])
        self.accept('q', self.setKey, ['strafe_left',1])
        self.accept('q-up', self.setKey, ['strafe_left',0])
        self.accept('e', self.setKey, ['strafe_right',1])
        self.accept('e-up', self.setKey, ['strafe_right',0])
        self.accept('arrow_up', self.setKey, ['cam_down',1])
        self.accept('arrow_up-up', self.setKey, ['cam_down',0])
        self.accept('arrow_down', self.setKey, ['cam_up',1])
        self.accept('arrow_down-up', self.setKey, ['cam_up',0])
        self.accept('arrow_right', self.setKey, ['cam_right',1])
        self.accept('arrow_right-up', self.setKey, ['cam_right',0])
        self.accept('arrow_left', self.setKey, ['cam_left',1])
        self.accept('arrow_left-up', self.setKey, ['cam_left',0])
        self.accept('[', self.setKey, ['zoom_in',1])
        self.accept('[-up', self.setKey, ['zoom_in',0])
        self.accept(']', self.setKey, ['zoom_out',1])
        self.accept(']-up', self.setKey, ['zoom_out',0])

        ## Accept Mouse
        self.accept('mouse3',self.setKey, ['right_click',1])
        self.accept('mouse3-up',self.setKey, ['right_click',0])
        self.accept('wheel_up',self.setKey, ['wheel_zoom_in',1])
        self.accept('wheel_down',self.setKey, ['wheel_zoom_out',1])

    ### Set Key Presses; Coded by Darren Kent (Modeled after Roaming-Ralph by Ryan Myers)
    def setKey(self,key,value):
        self.keyMap[key] = value        
            


    ### Main Game Loop; Coded by Darren Kent
    def gameLoop(self,task):

        ## Keyboard Camera Controls
        if (self.keyMap["cam_left"]!=0):
            self.XYAngle += .002
        if (self.keyMap["cam_right"]!=0):
            self.XYAngle -= .002
        if (self.keyMap["cam_up"] != 0):
            if self.ZAngle <= .045:
                self.ZAngle += .001
        if (self.keyMap["cam_down"] != 0):
            if self.ZAngle >= .002:
                self.ZAngle -= .001
        if (self.keyMap["zoom_in"] != 0):
            if self.radius >= 4:
                self.radius -= 1
                self.setRadius = self.radius
        if (self.keyMap["zoom_out"] != 0):
            if self.radius <= 40:
                self.radius += 1
                self.setRadius = self.radius
                
        ## Mouse Camera Controls
        if (self.keyMap["right_click"]!=0):
            if self.startRightClick == True:
                self.startRightClick = False
                self.tempMouseX = base.mouseWatcherNode.getMouseX()
                self.tempMouseY = base.mouseWatcherNode.getMouseY()
                self.tempXAngle = self.XYAngle
                self.tempZAngle = self.ZAngle
                self.tempPlayerH = self.playerBox.getH()
            elif self.startRightClick == False:
                Ztemp = self.tempZAngle + (base.mouseWatcherNode.getMouseY() - self.tempMouseY) / 20
                self.XYAngle = self.tempXAngle - (base.mouseWatcherNode.getMouseX() - self.tempMouseX) / 20
                if Ztemp >= .045:
                    Ztemp = .045
                if Ztemp <= 0.002:
                    Ztemp = 0.002
                self.ZAngle = Ztemp
        else:
            self.startRightClick = True
       
        if (self.keyMap["wheel_zoom_in"] != 0):
            if self.radius >= 7:
                self.radius -= 3
                self.setRadius = self.radius
        if (self.keyMap["wheel_zoom_out"] != 0):
            if self.radius <= 38:
                self.radius += 2
                self.setRadius = self.radius
        self.setKey("wheel_zoom_out",0)
        self.setKey("wheel_zoom_in", 0)

        ## Reposition Camera
        x = self.cameratarget.getX() + self.radius * math.sin(math.degrees(self.ZAngle)) * math.cos(math.degrees(self.XYAngle))
        y = self.cameratarget.getY() + self.radius * math.sin(math.degrees(self.ZAngle)) * math.sin(math.degrees(self.XYAngle))
        z = self.cameratarget.getZ() + self.radius * math.cos(math.degrees(self.ZAngle))
        base.camera.setPos(x,y,z)
        base.camera.lookAt(self.cameratarget)
        self.cameratarget.setPos(self.playerBox.getX(),self.playerBox.getY(),self.playerBox.getZ()+6)


        ## Keyboard Movement Controls
        if (self.keyMap["turn_left"]!=0):
            self.playerBox.setH(self.playerBox.getH() + 200 * globalClock.getDt())
        if (self.keyMap["turn_right"]!=0):
            self.playerBox.setH(self.playerBox.getH() - 200 * globalClock.getDt())
        if (self.keyMap["strafe_left"]!=0):
            self.playerBox.setX(self.playerBox, +20 * globalClock.getDt())
        if (self.keyMap["strafe_right"]!=0):
            self.playerBox.setX(self.playerBox, -20 * globalClock.getDt())
        if (self.keyMap["forward"]!=0):
            self.playerBox.setY(self.playerBox, -25 * globalClock.getDt())
        if (self.keyMap["backward"] != 0):
            self.playerBox.setY(self.playerBox, +15 * globalClock.getDt())

        if (self.keyMap["forward"]!=0):
            if self.isMoving == False:
                self.player.setPlayRate(2.5,'run')
                self.player.loop('run')
                self.isMoving = True
        else:
            if self.isMoving:
                self.player.setPlayRate(1,'idle')
                self.player.loop('idle')
                self.isMoving = False

        ## Check Collisions
            

        return task.cont
Esempio n. 14
0
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.seeNode = self.render.attachNewNode('see')
         
        self.cam.reparentTo(self.seeNode)
        self.cam.setPos(0, 0, 5)
        
        self.fpscamera = fpscontroller.FpsController(self, self.seeNode)
        self.fpscamera.setFlyMode(True)
        self.fpscamera.setMouseLook(True)
        
        self.prevPos = self.fpscamera.getPos()
        self.prevInto = None
        
        self.makeInstructions()
        self.info = self.genLabelText("Position: <unknown>", 2)

        self.initCollisions()

        self.leftColor = LVecBase4i(224, 224, 64, 255)
        self.rightColor = LVecBase4i(64, 224, 224, 255)
        
        self.isDrawing = False
        self.toggleDrawing()
        
        self.accept("escape", sys.exit)            #Escape quits
        self.accept("enter", self.toggleDrawing)

    def initCollisions(self):
        # Initialize the collision traverser.
        self.cTrav = CollisionTraverser()
        
        self.cTrav.showCollisions(self.render)
        
        # Initialize the Pusher collision handler.
        self.pusher = CollisionHandlerFloor()
                
        ### player
        
        # Create a collsion node for this object.
        playerNode = CollisionNode('player')
        playerNode.addSolid(CollisionSphere(0, 0, 0, 1))
        
        # Attach the collision node to the object's model.
        self.playerC = self.fpscamera.player.attachNewNode(playerNode)
        # Set the object's collision node to render as visible.
        self.playerC.show()
         

    def toggleDrawing(self):
        self.isDrawing = not self.isDrawing
        
        if self.isDrawing:
            self.instructionText.setText('Enter: Generate Tunnel from Movement')

            self.fpscamera.setFlyMode(True)
            self.prevPos = None

            # self.cTrav.remosveCollider(self.playerC)
            
            self.removeTask('updatePhysics')
            self.addTask(self.drawHere, 'drawHere')
            
            self.geomNode = GeomNode('geomNode')
            self.geomNodePath = self.render.attachNewNode(self.geomNode)
            
            self.geomNodePath.setTwoSided(True)
            
            
            # apparently p3tinydisplay needs this
            self.geomNodePath.setColorOff()

            # Create a collision node for this object.
            self.floorCollNode = CollisionNode('geom')

            # Attach the collision node to the object's model.
            floorC = self.geomNodePath.attachNewNode(self.floorCollNode)
            # Set the object's collision node to render as visible.
            floorC.show()

            self.newVertexData()
            
            self.newGeom()

        else:
            self.instructionText.setText('Enter: Record Movement for Tunnel')

            self.removeTask('drawHere')
            if self.prevPos:
                #self.completePath()
                self.completeTunnelPath()
            
            self.fpscamera.setFlyMode(True)
            
            self.drive.setPos(self.fpscamera.getPos())

            self.cTrav.addCollider(self.playerC, self.pusher)
            self.pusher.addCollider(self.playerC, self.fpscamera.player)

            self.taskMgr.add(self.updatePhysics, 'updatePhysics')

    def newVertexData(self):
        fmt = GeomVertexFormat.getV3c4()
#         fmt = GeomVertexFormat.getV3n3c4()
        self.vertexData = GeomVertexData("path", fmt, Geom.UHStatic)
        self.vertexWriter = GeomVertexWriter(self.vertexData, 'vertex')
#         self.normalWriter = GeomVertexWriter(self.vertexData, 'normal')
        self.colorWriter = GeomVertexWriter(self.vertexData, 'color')

    def newGeom(self):
        self.triStrips = GeomTristrips(Geom.UHDynamic)
        self.geom = Geom(self.vertexData)
        self.geom.addPrimitive(self.triStrips)
        
        
    def makeInstructions(self):
        OnscreenText(text="Draw Path by Walking (WSAD/space/mouselook)",
                          style=1, fg=(1,1,0,1),
                          pos=(0.5,-0.95), scale = .07)
        self.genLabelText("ESC: Quit", 0)
        self.instructionText = self.genLabelText("", 1)
        
    def genLabelText(self, text, i):
        return OnscreenText(text = text, pos = (-1.3, .95-.05*i), fg=(1,1,0,1),
                      align = TextNode.ALeft, scale = .05)

    def drawHere(self, task):
        pos = self.fpscamera.getPos()
        self.info.setText("Position: {0}, {1}, {2} at {3} by {4}".format(int(pos.x*100)/100., int(pos.y*100)/100., int(pos.z)/100., 
                                                                  self.fpscamera.getHeading(), self.fpscamera.getLookAngle()))
        
        prevPos = self.prevPos
        
        if not prevPos:
            self.prevPos = pos
            
        elif (pos - prevPos).length() >= 1:
#             self.extendPathQuad(prevPos, pos, 2)
            self.extendPathTunnel(prevPos, pos, 3)
                    
            self.leftColor[1] += 63
            self.rightColor[2] += 37
            
            self.prevPos = pos
        
        return task.cont

    def extendPathQuad(self, prevPos, pos, width):
        self.drawQuadTo(prevPos, pos, width)

        row = self.vertexWriter.getWriteRow()
        numPrims = self.triStrips.getNumPrimitives()
        if numPrims == 0:
            primVerts = row
        else:
            primVerts = row - self.triStrips.getPrimitiveEnd(numPrims-1)

        if primVerts >= 4:
            self.triStrips.closePrimitive()

            if row >= 256:
                print "Packing and starting anew"
                newGeom = True
                self.geom.unifyInPlace(row, False)
            else:
                newGeom = False
                
            self.completeQuadPath()

            if newGeom:                
                self.newVertexData()
                                
            self.newGeom()
            if newGeom:
                self.drawQuadTo(prevPos, pos, width)
            else:
                self.triStrips.addConsecutiveVertices(row - 2, 2)
            
        
    def extendPathTunnel(self, prevPos, pos, width):
        self.drawTunnelTo(prevPos, pos, width)

    def drawLineTo(self, pos, color):
        self.vertexWriter.addData3f(pos.x, pos.y, pos.z)
#         self.normalWriter.addData3f(0, 0, 1)
        self.colorWriter.addData4i(color)
        
        self.triStrips.addNextVertices(1)
        
        return 1
            
    def drawQuadTo(self, a, b, width):
        """ a (to) b are vectors defining a line bisecting a new quad. """
        into = (b - a)
        if abs(into.x) + abs(into.y) < 1:
            # ensure that if we jump in place, we don't get a thin segment
            if not self.prevInto:
                return
            into = self.prevInto
        else:
            into.normalize()
        
        # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space
        
        if self.vertexWriter.getWriteRow() == 0:
            self.drawQuadRow(a, into, width)        
        
        verts = self.drawQuadRow(b, into, width)

        self.prevInto = into
        
        return verts

    def drawQuadRow(self, a, into, width):
        """ a defines a point, with 'into' being the normalized direction. """
        
        # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space
        
        aLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z)
        aRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z)
        
        row = self.vertexWriter.getWriteRow()
        
        self.vertexWriter.addData3f(aLeft)
        self.vertexWriter.addData3f(aRight)
        
#         self.normalWriter.addData3f(Vec3(0, 0, 1))
#         self.normalWriter.addData3f(Vec3(0, 0, 1))
        
        self.colorWriter.addData4i(self.leftColor)
        self.colorWriter.addData4i(self.rightColor)
        
        self.triStrips.addConsecutiveVertices(row, 2)

        return 2
            
    def drawTunnelTo(self, a, b, width):
        """ a (to) b are vectors defining a line bisecting a new tunnel segment. """
        into = (b - a)
        if abs(into.x) + abs(into.y) < 1:
            # ensure that if we jump in place, we don't get a thin segment
            if not self.prevInto:
                return
            into = self.prevInto
        else:
            into.normalize()
        
        # the perpendicular of (a,b) is (-b,a); we want the path to be "flat" in Z=space
        
        if self.vertexWriter.getWriteRow() == 0:
            self.drawTunnelBoundary(a, into, width)        
            
        row = self.vertexWriter.getWriteRow()
        verts = self.drawTunnelBoundary(b, into, width)        
        totalVerts = self.drawTunnelRow(row, verts)        
        
        self.prevInto = into
        
        return totalVerts

    def drawTunnelBoundary(self, a, into, width):
        """ a defines a point, with 'into' being the normalized direction. """
        
        aLowLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z)
        aLowRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z)
        aHighRight = Vec3(a.x + into.y * width, a.y - into.x * width, a.z + width * 3)
        aHighLeft = Vec3(a.x - into.y * width, a.y + into.x * width, a.z + width * 3)
        
        self.vertexWriter.addData3f(aLowLeft)
        self.vertexWriter.addData3f(aLowRight)
        self.vertexWriter.addData3f(aHighRight)
        self.vertexWriter.addData3f(aHighLeft)
        
        self.colorWriter.addData4i(self.leftColor)
        self.colorWriter.addData4i(self.rightColor)
        self.colorWriter.addData4i(self.leftColor)
        self.colorWriter.addData4i(self.rightColor)
        
        return 4
    
    def drawTunnelRowX(self, row, verts):
        # BOTTOM: bottom-left, new-bottom-left, bottom-right, new-bottom-right
        self.triStrips.addConsecutiveVertices(row - verts + 0, 1)
        self.triStrips.addConsecutiveVertices(row + 0, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 1, 1)
        self.triStrips.addConsecutiveVertices(row + 1, 1)
        self.triStrips.closePrimitive()
        # RIGHT: (new-bottom-right) bottom-right, new-top-right, top-right
        self.triStrips.addConsecutiveVertices(row + 1, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 1, 1)
        self.triStrips.addConsecutiveVertices(row + 2, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 2, 1)
        self.triStrips.closePrimitive()
        # TOP: top-left, new top-right, new top-left
        self.triStrips.addConsecutiveVertices(row - verts + 2, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
        self.triStrips.addConsecutiveVertices(row + 2, 1)
        self.triStrips.addConsecutiveVertices(row + 3, 1)
        self.triStrips.closePrimitive()
        # LEFT: (new top-left) new bottom-left, top-left, bottom-left, new-bottom-left
        self.triStrips.addConsecutiveVertices(row + 3, 1)
        self.triStrips.addConsecutiveVertices(row + 0, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 0, 1)
        self.triStrips.closePrimitive()
        
        return verts * 4
    
    def drawTunnelRow(self, row, verts):
#         # clockwise for the inside of the tunnel
#         # TOP: new-top-left, top-left, new-top-right, top-right
#         self.triStrips.addConsecutiveVertices(row + 3, 1)
#         self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
#         self.triStrips.addConsecutiveVertices(row + 2, 1)
#         self.triStrips.addConsecutiveVertices(row - verts + 2, 1)
#         # RIGHT: new-bottom-right, bottom-right
#         self.triStrips.addConsecutiveVertices(row + 1, 1)
#         self.triStrips.addConsecutiveVertices(row - verts + 1, 1)
#         # BOTTOM: new-bottom-left, bottom-left
#         self.triStrips.addConsecutiveVertices(row, 1)
#         self.triStrips.addConsecutiveVertices(row - verts, 1)
#         # LEFT: new top-left, top-left
#         self.triStrips.addConsecutiveVertices(row + 3, 1)
#         self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
        
        # TOP: new-top-left, top-left, new-top-right, top-right
        self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
        self.triStrips.addConsecutiveVertices(row + 3, 1)
        self.triStrips.addConsecutiveVertices(row - verts + 2, 1)
        self.triStrips.addConsecutiveVertices(row + 2, 1)
        # RIGHT: new-bottom-right, bottom-right
        self.triStrips.addConsecutiveVertices(row - verts + 1, 1)
        self.triStrips.addConsecutiveVertices(row + 1, 1)
        # BOTTOM: new-bottom-left, bottom-left
        self.triStrips.addConsecutiveVertices(row - verts, 1)
        self.triStrips.addConsecutiveVertices(row, 1)
        # LEFT: new top-left, top-left
        self.triStrips.addConsecutiveVertices(row - verts + 3, 1)
        self.triStrips.addConsecutiveVertices(row + 3, 1)

        self.triStrips.closePrimitive()
        
        return verts * 4
        
    def completeQuadPath(self):
        self.geomNode.addGeom(self.geom)
        
        if self.triStrips.getNumPrimitives() == 0:
            return
        
        floorMesh = CollisionFloorMesh()
        vertexReader = GeomVertexReader(self.vertexData, 'vertex') 
        tris = self.triStrips.decompose()
        print "Decomposed prims:",tris.getNumPrimitives()
        p = 0
        for i in range(tris.getNumPrimitives()):
            v0 = tris.getPrimitiveStart(i)
            ve = tris.getPrimitiveEnd(i)
            if v0 < ve:
                vertexReader.setRow(tris.getVertex(v0))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                vertexReader.setRow(tris.getVertex(v0+1))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                vertexReader.setRow(tris.getVertex(v0+2))
                floorMesh.addVertex(Point3(vertexReader.getData3f()))
                floorMesh.addTriangle(p, p+1, p+2)
                p += 3
        
        self.floorCollNode.addSolid(floorMesh)
        

    def completeTunnelPath(self):
        self.geomNode.addGeom(self.geom)
        
        if self.triStrips.getNumPrimitives() == 0:
            return
        
        floorMesh = CollisionFloorMesh()
        vertexReader = GeomVertexReader(self.vertexData, 'vertex') 
        
        print "Original prims:",self.triStrips.getNumPrimitives()
        
        p = 0
        for i in range(self.triStrips.getNumPrimitives()):
            v0 = self.triStrips.getPrimitiveStart(i)
            ve = self.triStrips.getPrimitiveEnd(i)
            j = v0 + 4
            
            # add the bottom triangles
            vertexReader.setRow(self.triStrips.getVertex(j))
            floorMesh.addVertex(Point3(vertexReader.getData3f()))
            vertexReader.setRow(self.triStrips.getVertex(j+1))
            floorMesh.addVertex(Point3(vertexReader.getData3f()))
            vertexReader.setRow(self.triStrips.getVertex(j+2))
            floorMesh.addVertex(Point3(vertexReader.getData3f()))
            floorMesh.addTriangle(p, p+1, p+2)
            
            vertexReader.setRow(self.triStrips.getVertex(j+3))
            floorMesh.addVertex(Point3(vertexReader.getData3f()))
            floorMesh.addTriangle(p+1, p+3, p+2)

            p += 4
        
        # this adds every triangle, but is not appropriate for a closed path
#         tris = self.triStrips.decompose()
#         print "Decomposed prims:",tris.getNumPrimitives()
#         p = 0
#         for i in range(tris.getNumPrimitives()):
#             v0 = tris.getPrimitiveStart(i)
#             ve = tris.getPrimitiveEnd(i)
#             if v0 < ve:
#                 vertexReader.setRow(tris.getVertex(v0))
#                 floorMesh.addVertex(Point3(vertexReader.getData3f()))
#                 vertexReader.setRow(tris.getVertex(v0+1))
#                 floorMesh.addVertex(Point3(vertexReader.getData3f()))
#                 vertexReader.setRow(tris.getVertex(v0+2))
#                 floorMesh.addVertex(Point3(vertexReader.getData3f()))
#                 floorMesh.addTriangle(p, p+1, p+2)
#                 p += 3
        
        self.floorCollNode.addSolid(floorMesh)
        
    
          
    def updatePhysics(self, task):
        pos = self.fpscamera.getPos()

        self.info.setText("Position: {0}, {1}, {2}".format(int(pos.x*100)/100., int(pos.y*100)/100., int(pos.z)/100.))

        return task.cont