Beispiel #1
0
class RayThatCollidesWithScene:
    def __init__(self):
        self.hitters = [
            self.setup_collision_ray(offset, bitmask) for offset, bitmask in [
                (-3, BM_LEFT),
                (3, BM_RIGHT),
            ]
        ]
        self.queue = CollisionHandlerQueue()
        self.traverser = CollisionTraverser('Collision Traverser')
        self.traverser.showCollisions(base.render)
        for ray in self.hitters:
            self.traverser.add_collider(ray, self.queue)
        base.taskMgr.add(self.collide, "Collision Task")

    def setup_collision_ray(self, offset, bitmask):
        # Hitter. Do note that not every combination of object works,
        # there is a table for that in the manual.
        hitter = CollisionRay(0, 0, 0, 0, 1, 0)
        hitter_node = CollisionNode('collision_hitter')
        hitter_node.setFromCollideMask(bitmask)
        hitter_nodepath = base.render.attach_new_node(hitter_node)
        hitter_nodepath.node().addSolid(hitter)
        hitter_nodepath.set_pos(offset, -2, 0)
        hitter_nodepath.show()
        return hitter_nodepath

    def collide(self, task):
        self.traverser.traverse(render)
        for entry in self.queue.get_entries():
            print(entry)
        return task.cont
Beispiel #2
0
class SmartCar(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        # Override defaults
        self.disableMouse()
        self.setBackgroundColor(0.7, 0.7, 0.7)
        self.setFrameRateMeter(True)

        # Lights
        dlight = DirectionalLight("dlight")
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(180.0, -70.0, 0)
        self.render.setLight(dlnp)

        alight = AmbientLight("alight")
        alnp = self.render.attachNewNode(alight)
        alight.setColor(VBase4(0.4, 0.4, 0.4, 1))
        self.render.setLight(alnp)

        # Collisions
        self.cTrav = CollisionTraverser("collisionTraverser")
        self.cTrav.showCollisions(self.render)

        # Camera controls
        self.cameraController = CameraController(self, 200, math.pi / 4.0,
                                                 math.pi / 4.0)
        #self.cameraController = CameraController(self, 200, -math.pi, math.pi / 4.0)

        # Load the track
        self.track = self.loader.loadModel("models/trackMotegi")
        self.track.reparentTo(self.render)

        # Load the car
        self.car = KeyboardController(self)
Beispiel #3
0
class BulletCollision:
    def __init__(self, bullet):

        self.bullet = bullet

        self.setup_collision()
        self.queue = CollisionHandlerQueue()
        self.traverser = CollisionTraverser('Collision Traverser')
        self.traverser.showCollisions(render)
        self.traverser.add_collider(self.target_nodepath, self.queue)
        base.taskMgr.add(self.collide, "Collision Task")

    def setup_collision(self):

        self.target = CollisionSphere(0, 0, 0, 0.1)
        self.target_node = CollisionNode('collision_bullet')
        self.target_node.setFromCollideMask(ENEMIES)
        self.target_node.setIntoCollideMask(ALLIES)

        self.target_nodepath = self.bullet.model.attach_new_node(
            self.target_node)
        self.target_nodepath.node().addSolid(self.target)
        self.target_nodepath.show()

    def collide(self, task):

        self.traverser.traverse(render)

        for entry in self.queue.get_entries():

            #print("Bullet:")
            #print(entry)
            self.bullet.model.removeNode()

        return task.cont
Beispiel #4
0
class EntityCollision:
    def __init__(self, entity):

        self.entity = entity

        self.setup_collision()
        self.queue = CollisionHandlerQueue()
        self.traverser = CollisionTraverser('Collision Traverser')
        self.traverser.showCollisions(render)
        self.traverser.add_collider(self.target_nodepath, self.queue)
        base.taskMgr.add(self.collide, "Collision Task")

    def setup_collision(self):
        self.target = CollisionSphere(0, 0, 0, 1)
        self.target_node = CollisionNode('collision_entity')
        self.target_node.setFromCollideMask(ALLIES)  # unused
        self.target_node.setIntoCollideMask(ENEMIES)
        self.target_nodepath = self.entity.model.attach_new_node(
            self.target_node)
        self.target_nodepath.node().addSolid(self.target)
        self.target_nodepath.show()

    def collide(self, task):

        self.traverser.traverse(render)

        for entry in self.queue.get_entries():
            # print("Entity:")
            pos = entry.getSurfacePoint(self.entity.model)
            pos_x = pos[0]
            pos_z = pos[2]
            self.entity.spawn_particles(pos_x, pos_z)
            self.entity.life -= 1

        return task.cont
class EntityCollision:
    def __init__(self, entity):

        self.entity = entity

        self.setup_collision()
        self.queue = CollisionHandlerQueue()
        self.traverser = CollisionTraverser('Collision Traverser')
        self.traverser.showCollisions(render)
        self.traverser.add_collider(self.target_nodepath, self.queue)
        base.taskMgr.add(self.collide, "Collision Task")

    def setup_collision(self):
        self.target = CollisionSphere(0, 0, 0, 1)
        self.target_node = CollisionNode('collision_entity')
        self.target_node.setFromCollideMask(ALLIES)  # unused
        self.target_node.setIntoCollideMask(ENEMIES)
        self.target_nodepath = self.entity.model.attach_new_node(self.target_node)
        self.target_nodepath.node().addSolid(self.target)
        self.target_nodepath.show()

    def collide(self, task):

        self.traverser.traverse(render)

        for entry in self.queue.get_entries():
            # print("Entity:")
            pos = entry.getSurfacePoint(self.entity.model)
            pos_x = pos[0]
            pos_z = pos[2]
            self.entity.spawn_particles(pos_x, pos_z)
            self.entity.life -= 1

        return task.cont
class ShipCollision:
    def __init__(self, ship):

        self.ship = ship

        self.setup_collision()
        self.queue = CollisionHandlerQueue()
        self.traverser = CollisionTraverser('Collision Traverser')
        self.traverser.showCollisions(render)
        self.traverser.add_collider(self.target_nodepath, self.queue)
        base.taskMgr.add(self.collide, "Collision Task")

    def setup_collision(self):

        self.target = CollisionSphere(0, 0, 0, 0.5)
        self.target_node = CollisionNode('collision_ship')
        self.target_node.setFromCollideMask(ENEMIES)
        self.target_node.setIntoCollideMask(ALLIES)
        self.target_nodepath = self.ship.model.attach_new_node(self.target_node)
        self.target_nodepath.node().addSolid(self.target)
        #self.target_nodepath.show()

    def collide(self, task):

        self.traverser.traverse(render)

        for entry in self.queue.get_entries():
            #print("Ship:")
            #print(entry)
            self.ship.model.cleanup()
            self.ship.model.removeNode()

        return task.cont
Beispiel #7
0
class ShipCollision:
    def __init__(self, game):
        self.game = game
        self.setup_collision()
        self.queue = CollisionHandlerQueue()
        self.traverser = CollisionTraverser('Collision Traverser')
        self.traverser.showCollisions(render)
        self.traverser.add_collider(self.target_nodepath, self.queue)
        base.taskMgr.add(self.collide, "Collision Task")

    def setup_collision(self):
        self.target = CollisionSphere(0, 0, 0, 0.5)
        self.target_node = CollisionNode('collision_ship')
        self.target_node.setFromCollideMask(ENEMIES)
        self.target_node.setIntoCollideMask(ALLIES)
        self.target_nodepath = self.game.ship.model.attach_new_node(
            self.target_node)
        self.target_nodepath.node().addSolid(self.target)
        self.target_nodepath.show()

    def collide(self, task):
        self.traverser.traverse(render)
        for entry in self.queue.get_entries():
            print("Ship:")
            print(entry)
        return task.cont
class RayThatCollidesWithScene:
    def __init__(self):
        self.hitters = [self.setup_collision_ray(offset, bitmask)
                        for offset, bitmask in [
                            (-3, BM_LEFT),
                            (3, BM_RIGHT),
                       ]]
        self.queue = CollisionHandlerQueue()
        self.traverser = CollisionTraverser('Collision Traverser')
        self.traverser.showCollisions(base.render)
        for ray in self.hitters:
            self.traverser.add_collider(ray, self.queue)
        base.taskMgr.add(self.collide, "Collision Task")

    def setup_collision_ray(self, offset, bitmask):
        # Hitter. Do note that not every combination of object works,
        # there is a table for that in the manual.
        hitter = CollisionRay(0, 0, 0, 0, 1, 0)
        hitter_node = CollisionNode('collision_hitter')
        hitter_node.setFromCollideMask(bitmask)
        hitter_nodepath = base.render.attach_new_node(hitter_node)
        hitter_nodepath.node().addSolid(hitter)
        hitter_nodepath.set_pos(offset, -2, 0)
        hitter_nodepath.show()
        return hitter_nodepath

    def collide(self, task):
        self.traverser.traverse(render)
        for entry in self.queue.get_entries():
            print(entry)
        return task.cont
class RoamingRalphDemo(ShowBase):
    def __init__(self):
        # Set up the window, camera, etc.
        ShowBase.__init__(self)
        self.orbCollisionHandler = CollisionHandlerQueue()
        self.cTrav = CollisionTraverser()

        #hbPath = NodePath()

        utils3.setUpKeys(self)
        utils3.loadModels(self)
        utils3.setUpLighting(self)
        utils3.setUpFloatingSpheres(self)
        utils3.setUpRalphsShot(self)
        utils3.setUpCamera(self)
        self.healthTxt = utils3.addInstructions(.06,"Health: 100")
        self.orbTxt = utils3.addInstructions(.18,"Orbs: 0")

        self.vec = LVector3(0,1,0)#vector for pawns shot

        # Create a frame
        #frame = DirectFrame(text = "main", scale = 0.001)
        # Add button
        #bar = DirectWaitBar(text = "", value = 50, pos = (0,.4,.4))
        #bar.reparent(render)

        # Game state variables
        self.isMoving = False
        self.jumping = False
        self.vz = 0
        self.numOrbs = 0
        self.healthCount = 100

        #self.shotList = []
        taskMgr.add(self.move, "moveTask")
        #taskMgr.add(utils2.moveChris,"moveChrisTask")
        
        self.sphere = CollisionSphere(0,0,4,2)
        self.sphere2 = CollisionSphere(0,0,2,2)
        self.cnodePath = self.ralph.attachNewNode((CollisionNode('ralphColNode')))
        self.cnodePath.node().addSolid(self.sphere)
        self.cnodePath.node().addSolid(self.sphere2)
        #self.cnodePath.show()
        
        self.pusher = CollisionHandlerPusher()
        self.pusher.addCollider(self.cnodePath, self.ralph)

        #self.cTrav.addCollider(self.cnodePath, self.ralphCollisionHandler)
        self.cTrav.addCollider(self.cnodePath, self.pusher)

        ca = CollisionSphere(0,0,0,20)
        cb = self.chik.attachNewNode(CollisionNode('chikCollisionNode'))
        cb.node().addSolid(ca)
        cb.show()

        cc = CollisionSphere(3,5,12,25)
        cd = self.gianteye.attachNewNode(CollisionNode('gianteyeCollisionNode'))
        cd.node().addSolid(cc)
        cd.show()

        ci = CollisionSphere(0,0,0,2)
        coi = self.catidol.attachNewNode(CollisionNode('catidolCollisionNode'))
        coi.node().addSolid(ci)
        coi.show()

        chi = CollisionSphere(-1,3,3,3)
        chco = self.chris.attachNewNode(CollisionNode('chrisColPath'))
        chco.node().addSolid(chi)
        self.cTrav.addCollider(chco, self.orbCollisionHandler)
        #chco.show()

        self.chris.setH(90)
        self.chris.setR(-90)
        self.chris.setZ(2)

        #cbox = CollisionBox((-50,30,20),10,85,20)
        #cboxPath = self.room.attachNewNode(CollisionNode('roomSide1'))
        #cboxPath.node().addSolid(cbox)
        #cboxPath.show()

        #cbox2 = CollisionBox((200,30,20),10,85,20)
        #cboxPath2 = self.room.attachNewNode(CollisionNode('roomSide1'))
        #cboxPath2.node().addSolid(cbox2)
        #cboxPath2.show()

        #cbox3 = CollisionBox((80,-60,20),120,20,20)
        #cboxPath3 = self.room.attachNewNode(CollisionNode('roomSide1'))
        #cboxPath3.node().addSolid(cbox3)
        #cboxPath3.show()

        ct = CollisionSphere(0,0,0,1)
        cn = self.pawn.attachNewNode(CollisionNode('pawnCollisionNode'))
        cn.node().addSolid(ct)
        cn.show()

        cs2 = CollisionSphere(0,0,0,.2)
        cs2path = self.plnp.attachNewNode((CollisionNode('orbColPath')))
        cs2path.node().addSolid(cs2)
        cs2path.show()

        self.cTrav.addCollider(cs2path, self.orbCollisionHandler)

        #cs3 = CollisionSphere(0,0,0,1)
        cs3path = self.plnp2.attachNewNode((CollisionNode('orbColPath')))
        cs3path.node().addSolid(cs2)
        cs3path.show()

        chrisShotNp = self.chrisShot.attachNewNode((CollisionNode("enemyOrbColPath")))
        chrisShotNp.node().addSolid(cs2)
        chrisShotNp.show()

        self.cTrav.addCollider(cs3path, self.orbCollisionHandler)
        self.cTrav.addCollider(chrisShotNp, self.orbCollisionHandler)


        # Uncomment this line to show a visual representation of the
        # collisions occuring
        self.cTrav.showCollisions(render)

        self.chrisLastShotTime = globalClock.getFrameTime()
        self.chrisTimer = globalClock.getDt()

    # Records the state of the arrow keys
    def setKey(self, key, value):
        self.keyMap[key] = value

    # Accepts arrow keys to move either the player or the menu cursor,
    # Also deals with grid checking and collision detection
    def move(self, task):


        # Get the time that elapsed since last frame.  We multiply this with
        # the desired speed in order to find out with which distance to move
        # in order to achieve that desired speed.
        dt = globalClock.getDt()
        utils3.moveChris(self,dt)

        # If the camera-left key is pressed, move camera left.
        # If the camera-right key is pressed, move camera right.

        if self.keyMap["cam-left"]:
            self.camera.setZ(self.camera, -20 * dt)
        if self.keyMap["cam-right"]:
            self.camera.setZ(self.camera, +20 * dt)

        # save ralph's initial position so that we can restore it,
        # in case he falls off the map or runs into something.

        startpos = self.ralph.getPos()

        # If a move-key is pressed, move ralph in the specified direction.

        if self.keyMap["left"]:
            self.ralph.setH(self.ralph.getH() + 150 * dt)
            #self.camera.setX(self.camera, +15.5 * dt)
        if self.keyMap["right"]:
            self.ralph.setH(self.ralph.getH() - 150 * dt)
            #self.camera.setX(self.camera, -15.5 * dt)
        if self.keyMap["forward"]:
            self.ralph.setY(self.ralph, -35 * dt)
            #self.camera.setY(self.camera, -35 * dt)
        if self.keyMap["back"]:
            self.ralph.setY(self.ralph, +35 * dt)
            #self.camera.setY(self.camera, 35 * dt)
        if self.keyMap["c"]:
            if self.jumping is False:
            #self.ralph.setZ(self.ralph.getZ() + 100 * dt)
                self.jumping = True
                self.vz = 7

        if self.keyMap["space"]:
            self.keyMap["space"] = False
            self.shotList[self.shotCount].lpivot.setPos(self.ralph.getPos())
            self.shotList[self.shotCount].lpivot.setZ(self.ralph.getZ() + .5)
            self.shotList[self.shotCount].lpivot.setX(self.ralph.getX() - .25)

            #self.shotList.append(rShot)
            #self.lightpivot3.setPos(self.ralph.getPos())
            #self.lightpivot3.setZ(self.ralph.getZ() + .5)
            #self.lightpivot3.setX(self.ralph.getX() - .25)
            #self.myShot.setHpr(self.ralph.getHpr())
            #parent to ralph
            #node = NodePath("tmp")
            #node.setHpr(self.ralph.getHpr())
            #vec = render.getRelativeVector(node,(0,-1,0))
            #self.myShotVec = vec

            node = NodePath("tmp")
            node.setHpr(self.ralph.getHpr())
            vec = render.getRelativeVector(node,(0,-1,0))
            self.shotList[self.shotCount].vec = vec
            self.shotCount = (self.shotCount + 1) % 5


        for rs in self.shotList:
            rs.lpivot.setPos(rs.lpivot.getPos() + rs.vec * dt * 15 )
            #if shot is too far stop updating



        if self.jumping is True:
            self.vz = self.vz - 16* dt
            self.ralph.setZ(self.ralph.getZ() + self.vz * dt )
            if self.ralph.getZ() < 0:
                self.ralph.setZ(0)
                self.jumping = False
        else:
            if self.ralph.getZ() < 0:
                self.ralph.setZ(0)
            elif self.ralph.getZ() > 0:
                self.ralph.setZ(self.ralph.getZ() -7 * dt)

        # If ralph is moving, loop the run animation.
        # If he is standing still, stop the animation.
        if self.keyMap["forward"] or self.keyMap["left"] or self.keyMap["right"] or self.keyMap["c"] or self.keyMap["forward"] or self.keyMap["back"]:
            if self.isMoving is False:
                self.ralph.loop("run")
                self.isMoving = True

        else:
            if self.isMoving:
                self.ralph.stop()
                self.ralph.pose("walk", 5)
                self.isMoving = False

        # update pawns shot or set up new shot after it reaches a certain distance
        node = NodePath("tmp")
        node.setHpr(self.pawn.getHpr())
        vec = render.getRelativeVector(node,(random.random() * -0.8,random.random() + 1,0))
        self.shot.setPos(self.shot.getPos() + self.vec * dt * 10 )
        if self.shot.getY() < -15 or self.shot.getY() > 30 or self.shot.getX() < 5 or self.shot.getX() > 15:
            self.shot.setPos(self.pawn.getPos() + (0,0,0))
            self.vec = render.getRelativeVector(node,(random.random() * -0.8,random.random() + 1,0))
            self.vec = render.getRelativeVector(node,(random.random() * random.randrange(-1,2),random.random() + 1,0))

        # If the camera is too far from ralph, move it closer.
        # If the camera is too close to ralph, move it farther.
        #self.camera.lookAt(self.floater)
        camvec = self.ralph.getPos() - self.camera.getPos()
        #camvec = Vec3(0,camvec.getY(),0)
        camdist = camvec.length()
        x = self.camera.getZ()
        camvec.normalize()
        #if camdist > 6.0:
        #    self.camera.setPos(self.camera.getPos() + camvec * (camdist - 6))
        #if camdist < 6.0:
        #    self.camera.setPos(self.camera.getPos() - camvec * (6 - camdist))

        # Normally, we would have to call traverse() to check for collisions.
        # However, the class ShowBase that we inherit from has a task to do
        # this for us, if we assign a CollisionTraverser to self.cTrav.
        #self.cTrav.traverse(render)

        # Adjust camera so it stays at same height
        if self.camera.getZ() < self.ralph.getZ() + 1 or self.camera.getZ() > self.ralph.getZ() + 1:
            self.camera.setZ(self.ralph.getZ() + 1)

        # The camera should look in ralph's direction,
        # but it should also try to stay horizontal, so look at
        # a floater which hovers above ralph's head.
        self.camera.lookAt(self.floater)


        entries = list(self.orbCollisionHandler.getEntries())
        if(len(entries) > 0):
            #self.lightpivot.reparentTo(NodePath())
            for entry in self.orbCollisionHandler.getEntries():
                #print(entry)
                fromColNp = entry.getFromNodePath()
                toColNp = entry.getIntoNodePath()
                if fromColNp.getName() == "orbColPath" and toColNp.getName() == "ralphColNode":
                    fromColNp.getParent().reparentTo(NodePath())
                    self.orbTxt.destroy()
                    self.numOrbs += 1
                    str1 = "Orbs: " + str(self.numOrbs)
                    self.orbTxt = utils3.addInstructions(.18, str1)
                elif toColNp.getName() == "orbColPath" and fromColNp.getName() == "ralphColNode":
                    toColNp.getParent().reparentTo(NodePath())
                    self.orbTxt.destroy()
                    self.numOrbs += 1
                    str1 = "Orbs: " + str(self.numOrbs)
                    self.orbTxt = utils3.addInstructions(.18, str1)
                elif toColNp.getName() == "ralphOrbColPath" and fromColNp.getName() == "chrisColPath":
                    toColNp.getParent().setPos(-50,0,2)
                    self.chrisHealth = self.chrisHealth - 1
                    self.chris.setColor(1,0,0,1)
                    self.chrisHit = True
                    self.chrisRedTime = globalClock.getFrameTime()
                    #print self.chrisRedTime
                    if self.chrisHealth < 0:
                        fromColNp.getParent().removeNode()
                        self.chrisAlive = False
                elif toColNp.getName() == "chrisColPath" and fromColNp.getName() == "ralphOrbColPath":
                    fromColNp.getParent().setPos(-50,0,2)
                    self.chrisHealth = self.chrisHealth - 1
                    self.chris.setColor(1,0,0,1)
                    self.chrisHit = True
                    self.chrisRedTime = globalClock.getFrameTime()
                    #print self.chrisRedTime
                    if self.chrisHealth < 0:
                        fromColNp.getParent().removeNode()
                        self.chrisAlive = False
                        self.chrisShot.setZ(26)
                elif toColNp.getName() == "enemyOrbColPath" and fromColNp.getName() == "ralphColNode":
                    toColNp.getParent().setZ(26)
                    self.healthTxt.destroy()
                    self.healthCount -= 3
                    str1 = "Health: " + str(self.healthCount)
                    self.healthTxt = utils3.addInstructions(.06, str1)
                elif toColNp.getName() == "ralphColNode" and fromColNp.getName() == "enemyOrbColPath":
                    fromColNp.getParent().setZ(26)
                    self.healthTxt.destroy()
                    self.healthCount -= 3
                    str1 = "Health: " + str(self.healthCount)
                    self.healthTxt = utils3.addInstructions(.06, str1)



        return task.cont
Beispiel #10
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
Beispiel #11
0
class World(DirectObject):

    def __init__(self):
        
        self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0}
        base.win.setClearColor(Vec4(0,0,0,1))

        # Post the instructions

        self.title = addTitle("Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)")
        self.inst1 = addInstructions(0.95, "[ESC]: Quit")
        self.inst2 = addInstructions(0.90, "[Left Arrow]: Rotate Ralph Left")
        self.inst3 = addInstructions(0.85, "[Right Arrow]: Rotate Ralph Right")
        self.inst4 = addInstructions(0.80, "[Up Arrow]: Run Ralph Forward")
        self.inst6 = addInstructions(0.70, "[A]: Rotate Camera Left")
        self.inst7 = addInstructions(0.65, "[S]: Rotate Camera Right")
        
        # Set up the environment
        #
        # This environment model contains collision meshes.  If you look
        # in the egg file, you will see the following:
        #
        #    <Collide> { Polyset keep descend }
        #
        # This tag causes the following mesh to be converted to a collision
        # mesh -- a mesh which is optimized for collision, not rendering.
        # It also keeps the original mesh, so there are now two copies ---
        # one optimized for rendering, one for collisions.  

        self.environ = loader.loadModel("models/world")      
        self.environ.reparentTo(render)
        self.environ.setPos(0,0,0)
        
        # Create the main character, Ralph

        ralphStartPos = self.environ.find("**/start_point").getPos()
        self.ralph = Actor("models/ralph",
                                 {"run":"models/ralph-run",
                                  "walk":"models/ralph-walk"})
        self.ralph.reparentTo(render)
        self.ralph.setScale(.2)
        self.ralph.setPos(ralphStartPos)

        # Create a floater object.  We use the "floater" as a temporary
        # variable in a variety of calculations.
        
        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(render)

        # Accept the control keys for movement and rotation

        self.accept("escape", sys.exit)
        self.accept("arrow_left", self.setKey, ["left",1])
        self.accept("arrow_right", self.setKey, ["right",1])
        self.accept("arrow_up", self.setKey, ["forward",1])
        self.accept("a", self.setKey, ["cam-left",1])
        self.accept("s", self.setKey, ["cam-right",1])
        self.accept("arrow_left-up", self.setKey, ["left",0])
        self.accept("arrow_right-up", self.setKey, ["right",0])
        self.accept("arrow_up-up", self.setKey, ["forward",0])
        self.accept("a-up", self.setKey, ["cam-left",0])
        self.accept("s-up", self.setKey, ["cam-right",0])

        taskMgr.add(self.move,"moveTask")

        # Game state variables
        self.isMoving = False

        # Set up the camera
        
        base.disableMouse()
        base.camera.setPos(self.ralph.getX(),self.ralph.getY()+10,2)
        
        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  One ray will
        # start above ralph's head, and the other will start above the camera.
        # A ray may hit the terrain, or it may hit a rock or a tree.  If it
        # hits the terrain, we can detect the height.  If it hits anything
        # else, we rule that the move is illegal.

        self.cTrav = CollisionTraverser()

        self.ralphGroundRay = CollisionRay()
        self.ralphGroundRay.setOrigin(0,0,1000)
        self.ralphGroundRay.setDirection(0,0,-1)
        self.ralphGroundCol = CollisionNode('ralphRay')
        self.ralphGroundCol.addSolid(self.ralphGroundRay)
        self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol)
        self.ralphGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler)

        self.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0,0,1000)
        self.camGroundRay.setDirection(0,0,-1)
        self.camGroundCol = CollisionNode('camRay')
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.camGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol)
        self.camGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)

        # Uncomment this line to see the collision rays
        self.ralphGroundColNp.show()
        self.camGroundColNp.show()
       
        # Uncomment this line to show a visual representation of the 
        # collisions occuring
        self.cTrav.showCollisions(render)
        
        # Create some lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.3, .3, .3, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(-5, -5, -5))
        directionalLight.setColor(Vec4(1, 1, 1, 1))
        directionalLight.setSpecularColor(Vec4(1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambientLight))
        render.setLight(render.attachNewNode(directionalLight))
    
    #Records the state of the arrow keys
    def setKey(self, key, value):
        self.keyMap[key] = value
    

    # Accepts arrow keys to move either the player or the menu cursor,
    # Also deals with grid checking and collision detection
    def move(self, task):

        # If the camera-left key is pressed, move camera left.
        # If the camera-right key is pressed, move camera right.

        base.camera.lookAt(self.ralph)
        if (self.keyMap["cam-left"]!=0):
            base.camera.setX(base.camera, -20 * globalClock.getDt())
        if (self.keyMap["cam-right"]!=0):
            base.camera.setX(base.camera, +20 * globalClock.getDt())

        # save ralph's initial position so that we can restore it,
        # in case he falls off the map or runs into something.

        startpos = self.ralph.getPos()

        # If a move-key is pressed, move ralph in the specified direction.

        if (self.keyMap["left"]!=0):
            self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt())
        if (self.keyMap["right"]!=0):
            self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt())
        if (self.keyMap["forward"]!=0):
            self.ralph.setY(self.ralph, -25 * globalClock.getDt())

        # If ralph is moving, loop the run animation.
        # If he is standing still, stop the animation.

        if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0):
            if self.isMoving is False:
                self.ralph.loop("run")
                self.isMoving = True
        else:
            if self.isMoving:
                self.ralph.stop()
                self.ralph.pose("walk",5)
                self.isMoving = False

        # If the camera is too far from ralph, move it closer.
        # If the camera is too close to ralph, move it farther.

        camvec = self.ralph.getPos() - base.camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()
        camvec.normalize()
        if (camdist > 10.0):
            base.camera.setPos(base.camera.getPos() + camvec*(camdist-10))
            camdist = 10.0
        if (camdist < 5.0):
            base.camera.setPos(base.camera.getPos() - camvec*(5-camdist))
            camdist = 5.0

        # Now check for collisions.

        self.cTrav.traverse(render)

        # Adjust ralph's Z coordinate.  If ralph's ray hit terrain,
        # update his Z. If it hit anything else, or didn't hit anything, put
        # him back where he was last frame.

        entries = []
        for i in range(self.ralphGroundHandler.getNumEntries()):
            entry = self.ralphGroundHandler.getEntry(i)
            entries.append(entry)
        entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                     x.getSurfacePoint(render).getZ()))
        if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"):
            self.ralph.setZ(entries[0].getSurfacePoint(render).getZ())
        else:
            self.ralph.setPos(startpos)

        # Keep the camera at one foot above the terrain,
        # or two feet above ralph, whichever is greater.
        
        entries = []
        for i in range(self.camGroundHandler.getNumEntries()):
            entry = self.camGroundHandler.getEntry(i)
            entries.append(entry)
        entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                     x.getSurfacePoint(render).getZ()))
        if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"):
            base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0)
        if (base.camera.getZ() < self.ralph.getZ() + 2.0):
            base.camera.setZ(self.ralph.getZ() + 2.0)
            
        # The camera should look in ralph's direction,
        # but it should also try to stay horizontal, so look at
        # a floater which hovers above ralph's head.
        
        self.floater.setPos(self.ralph.getPos())
        self.floater.setZ(self.ralph.getZ() + 2.0)
        base.camera.lookAt(self.floater)

        return task.cont
Beispiel #12
0
class Character(DirectObject, XMLExportable, PropertiesTableAbstract,
                GameEntity):
    def __init__(self, attributes, showCollisions, grid_currentx,
                 grid_currenty, grid_playable_pos, parent):
        GameEntity.__init__(self, parent)  #running parent constructor

        self.movtask = 0
        self.showCollisions = showCollisions
        self.grid_currentx = grid_currentx
        self.grid_currenty = grid_currenty
        self.grid_playable_pos = grid_playable_pos
        self.attributes = attributes
        self.onPicked = ''
        self.onWalked = ''
        self.typeName = 'character'

        self.properties = {
            'url': '',
            'onWalked': '',
            'onPicked': '',
            'id': '',
            'inclination': '',
            'scale': '',
            'hitboxscale': '',
            'speed': '',
            'playable': '',
            'direction': ''
        }

        if attributes.has_key('url'):
            self.properties['url'] = attributes['url'].value
        else:
            print "WARNING: url not defined, loading placeholder"
            self.properties['url'] = 'misc/placeholder'

        if attributes.has_key('id'):
            self.properties['id'] = attributes['id'].value
        else:
            self.properties['id'] = 'all'

        if attributes.has_key('inclination'):
            self.properties['inclination'] = float(
                attributes['inclination'].value)
        else:
            self.properties['inclination'] = 30.0

        if attributes.has_key('scale'):
            self.properties['scale'] = float(attributes['scale'].value)
        else:
            self.properties['scale'] = 1.0

        if attributes.has_key('hitboxscale'):
            self.properties['hitboxscale'] = float(
                attributes['hitboxscale'].value)
        else:
            self.properties['hitboxscale'] = 1.0

        if attributes.has_key('speed'):
            self.properties['speed'] = float(attributes['speed'].value)
        else:
            self.properties['speed'] = 1.0

        #self.isNPC remains true while isPlayable is changable
        if attributes.has_key('playable'):
            self.playable = playable = attributes['playable'].value
            if self.playable == 'false':
                self.isNPC = False
                #print "setting ", self.properties['id'], " to ", self.isNPC
            else:
                self.isNPC = True
                #print "setting ", self.properties['id'], " to ", self.isNPC
        else:
            self.playable = playable = 'false'
            self.isNPC = True
        self.properties['playable'] = self.playable

        if attributes.has_key('direction'):
            self.properties['direction'] = attributes['direction'].value
        else:
            self.properties['direction'] = "down"

        if attributes.has_key('onWalked'):
            self.properties['onWalked'] = self.onWalked = attributes[
                'onWalked'].value
        else:
            self.properties['onWalked'] = self.onWalked = ""

        if attributes.has_key('onPicked'):
            self.properties['onPicked'] = self.onPicked = attributes[
                'onPicked'].value

        self.generateNode(showCollisions)

    def generateNode(self, showCollisions):
        self.destroy()

        #setting local variable
        attributes = self.attributes

        #defaulted to None
        self.pickCTrav = None

        #movement
        self.state = "still"
        self.showCollisions = showCollisions

        self.movtask = 0
        self.currentlydown = []
        self.currentlyfollowed = 0

        self.pickRequest = False

        #public props
        self.node = NodePath("characternode")
        self.node.setTwoSided(True)

        self.wtop = self.applyNearestFilter(
            loader.loadModel(
                resourceManager.getResource(self.properties['url']) +
                '/wtop.egg'))
        self.wdown = self.applyNearestFilter(
            loader.loadModel(
                resourceManager.getResource(self.properties['url']) +
                '/wdown.egg'))
        self.wleft = self.applyNearestFilter(
            loader.loadModel(
                resourceManager.getResource(self.properties['url']) +
                '/wleft.egg'))
        self.wright = self.applyNearestFilter(
            loader.loadModel(
                resourceManager.getResource(self.properties['url']) +
                '/wright.egg'))
        self.stop = self.applyNearestFilter(
            loader.loadModel(
                resourceManager.getResource(self.properties['url']) +
                '/stop.egg'))
        self.sdown = self.applyNearestFilter(
            loader.loadModel(
                resourceManager.getResource(self.properties['url']) +
                '/sdown.egg'))
        self.sleft = self.applyNearestFilter(
            loader.loadModel(
                resourceManager.getResource(self.properties['url']) +
                '/sleft.egg'))
        self.sright = self.applyNearestFilter(
            loader.loadModel(
                resourceManager.getResource(self.properties['url']) +
                '/sright.egg'))

        #Texture.FTNearest

        self.wtop.reparentTo(self.node)
        self.wdown.reparentTo(self.node)
        self.wleft.reparentTo(self.node)
        self.wright.reparentTo(self.node)
        self.stop.reparentTo(self.node)
        self.sdown.reparentTo(self.node)
        self.sleft.reparentTo(self.node)
        self.sright.reparentTo(self.node)

        self.leftdown = False
        self.rightdown = False
        self.downdown = False
        self.topdown = False

        if self.playable == "true":
            self.setPlayable(
                False)  #seems nonsense, triggered on grid.changeMap event
            self.node.setTag(
                "playable", "true"
            )  #setting this to make it recognizable from grid changeMap api
            self.setCollisions(True)
            self.setPickCollisions(True)
        else:
            self.setPlayable(False)
            self.node.setTag("playable", "false")
            self.setCollisions(False)
            self.setPickCollisions(False)

        #self.node.setX((-32/2)+0.5)
        self.node.setP(-(360 - int(self.properties['inclination'])))
        self.node.setScale(float(self.properties['scale']))
        self.node.setTransparency(TransparencyAttrib.MAlpha)

        self.lastpos = self.node.getPos()

        self.showAllSubnodes()

        #taskMgr.doMethodLater(4, self.face, 'charload'+self.properties['id'], [self.properties['direction']])
        self.face(self.properties['direction'])

        #set unique id
        self.node.setTag("id", self.properties['id'])
        #setting scripting part
        self.node.setTag("onWalked", self.onWalked)
        self.node.setTag("onPicked", self.onPicked)

        #storing a pointer of the gamenode
        self.node.setPythonTag("gamenode", self)

        self.npc_walk_stack = []
        self.npc_walk_happening = False
        self.globalLock = False

        self.setX(self.grid_currentx)
        self.setY(self.grid_currenty)

        if self.isNPC != True:
            print "attempting creation of NPC in ", self.grid_currentx, "-", self.grid_currenty

        if attributes.has_key('playable'):
            if self.isNPC != False:
                if ((self.grid_playable_pos.getX() != 0)
                        and (self.grid_playable_pos.getY() != 0)):
                    print 'GRID: moving player to ' + str(
                        self.grid_playable_pos)
                    self.setX(self.grid_playable_pos.getX())
                    self.setY(self.grid_playable_pos.getY())

        #automatic reparenting (and showing) when (re)generating node
        self.node.wrtReparentTo(self.parent.node)

    def getName(self):
        return 'Character: ' + self.properties['id']

    def xmlAttributes(self):
        return self.properties

    def xmlTypeName(self):
        return self.typeName

    '''
    Sanitize properties data to be of correct type from string
    '''

    def sanitizeProperties(self):
        #sanitizing data
        self.properties['inclination'] = float(self.properties['inclination'])
        self.properties['hitboxscale'] = float(self.properties['hitboxscale'])
        self.properties['speed'] = float(self.properties['speed'])
        self.properties['scale'] = float(self.properties['scale'])

        self.updateTilePosition()

    #interface needed by PropertiesTable
    # regenerates the node at every change
    def onPropertiesUpdated(self):
        self.sanitizeProperties()
        self.generateNode(self.showCollisions)

    #interface needed by PropertiesTable
    #TODO: implement as real interface?
    def getPropertyList(self):
        return self.properties

    #interface needed by PropertiesTable
    def setProperty(self, key, value):
        self.properties[key] = value

    def setSpeed(self, s):
        self.properties['speed'] = s

    def applyNearestFilter(self, model):
        for tex in model.findAllTextures():
            tex.setMinfilter(Texture.FT_nearest)
            tex.setMagfilter(Texture.FT_nearest)
        return model

    '''
    make the npc walk in direction for units
    '''

    def npc_push_walk(self, direction, units):
        #locking script execution
        self.globalLock = True
        script.addOneCustomLock(self)

        #start the walking
        self.npc_walk_stack.append([direction, units])
        self.npc_walk_helper()

    #apicall
    def npc_walk_helper(self):
        x = self.node.getX()
        y = self.node.getZ()

        #concurrent protection
        if self.npc_walk_happening == True:
            return

        #returning if no movement has to be performed
        if len(self.npc_walk_stack) < 0:
            return

        movement = self.npc_walk_stack.pop(0)

        direction = movement[0]
        units = movement[1]

        self.npc_targetx = x
        self.npc_targety = y
        self.npc_direction = direction

        if (direction == "down"):
            self.npc_targety = self.npc_targety - units
        elif (direction == "up"):
            self.npc_targety = self.npc_targety + units
        elif (direction == "left"):
            self.npc_targetx = self.npc_targetx - units
        elif (direction == "right"):
            self.npc_targetx = self.npc_targetx + units

        self.setAnim(direction)

        self.npc_walk_happening = True
        self.npc_movtask = taskMgr.add(self.npc_walk_task,
                                       "npc_moveCharacterTask" +
                                       self.properties['id'],
                                       uponDeath=self.npc_walk_callback)

    def npc_walk_task(self, task):
        dt = globalClock.getDt()

        if (self.npc_direction == 'left'):
            self.node.setX(self.node.getX() -
                           1 * dt * self.properties['speed'])
            currentx = self.node.getX()

            if currentx <= self.npc_targetx:
                return task.done
        if (self.npc_direction == 'right'):
            self.node.setX(self.node.getX() +
                           1 * dt * self.properties['speed'])
            currentx = self.node.getX()

            if currentx >= self.npc_targetx:
                return task.done
        if (self.npc_direction == 'up'):
            self.node.setZ(self.node.getZ() +
                           1 * dt * self.properties['speed'])
            currenty = self.node.getZ()

            if currenty >= self.npc_targety:
                return task.done
        if (self.npc_direction == 'down'):
            self.node.setZ(self.node.getZ() -
                           1 * dt * self.properties['speed'])
            currenty = self.node.getZ()

            if currenty <= self.npc_targety:
                return task.done

        return task.cont

    def npc_walk_callback(self, task):
        self.face(self.npc_direction)

        #unlocking concurrent movement protection
        self.npc_walk_happening = False

        if len(self.npc_walk_stack) > 0:
            self.npc_walk_helper()
        else:  #character ended walking, unlock
            self.globalLock = False

    '''
    write destroyfunction
    '''

    def destroy(self):
        #not accepting events
        self.ignoreAll()
        #destroying everything down
        if self.node != None:
            self.node.remove_node()
        #removing all tasks
        if self.movtask != 0:
            taskMgr.remove(self.movtask)
            self.movtask = 0

    def face(self, direction):
        if direction == "left":
            self.hideAllSubnodes()
            self.sleft.show()
        if direction == "right":
            self.hideAllSubnodes()
            self.sright.show()
        if direction == "top" or direction == "up":  #let's keep retrocompatibility
            self.hideAllSubnodes()
            self.stop.show()
        if direction == "down":
            self.hideAllSubnodes()
            self.sdown.show()

    def setCollisions(self, value):
        if value == True:
            b = self.node.getBounds().getRadius()

            self.cTrav = CollisionTraverser()

            self.collisionTube = CollisionSphere(
                b / 2, 0, b / 2, 0.035 * self.properties['hitboxscale'])
            self.collisionNode = CollisionNode('characterTube')
            self.collisionNode.addSolid(self.collisionTube)
            self.collisionNodeNp = self.node.attachNewNode(self.collisionNode)
            self.collisionHandler = CollisionHandlerQueue()
            self.cTrav.addCollider(self.collisionNodeNp, self.collisionHandler)

            if self.showCollisions == True or main.editormode:
                # Uncomment this line to see the collision rays
                self.collisionNodeNp.show()

                # Uncomment this line to show a visual representation of the
                # collisions occuring
                self.cTrav.showCollisions(render)
        else:
            b = self.node.getBounds().getRadius()
            self.collisionTube = CollisionSphere(
                b / 2, 0, b / 2, 0.035 * self.properties['hitboxscale'])

            #allowing playables to collide with npcs
            if self.isNPC == True:  #TODO: fix because it's completely f****d up
                self.collisionNode = CollisionNode('characterTube')
            else:
                self.collisionNode = CollisionNode('characterNPCTube')

            self.collisionNode.addSolid(self.collisionTube)
            self.collisionNodeNp = self.node.attachNewNode(self.collisionNode)

    #set if camera has to effectively follow the character
    #while it moves
    def setFollowedByCamera(self, value):
        #camera follow
        if value:
            if self.currentlyfollowed != True:
                customCamera.follow(self)
                self.currentlyfollowed = True
        else:
            if self.currentlyfollowed != False:
                customCamera.dontFollow()
                self.currentlyfollowed = False

    def setPickCollisions(self, value):
        if value:
            print "setting pick collisions"
            b = self.node.getBounds().getRadius()

            self.pickCTrav = CollisionTraverser()

            self.pickCollisionTube = CollisionSphere(
                b / 2, 0, b / 2, 0.035 * self.properties['hitboxscale'] + 0.01)
            self.pickCollisionNode = CollisionNode('characterPickTube')
            self.pickCollisionNode.addSolid(self.pickCollisionTube)
            self.pickCollisionNodeNp = NodePath(self.pickCollisionNode)
            self.pickCollisionNodeNp.reparentTo(self.node)
            self.pickCollisionHandler = CollisionHandlerQueue()
            self.pickCTrav.addCollider(self.pickCollisionNodeNp,
                                       self.pickCollisionHandler)

            if self.showCollisions == True:
                # Uncomment this line to see the collision rays
                self.pickCollisionNodeNp.show()

                # Uncomment this line to show a visual representation of the
                # collisions occuring
                self.pickCTrav.showCollisions(render)
        else:
            #dereferincing all pick colliders (must be done in order not to collide onto NPCs)
            self.pickCTrav = None
            self.pickCollisionTube = None
            self.pickCollisionNode = None
            self.pickCollisionNodeNp = None
            self.pickCollisionHandler = None

    #used to set playability in real time
    #useful when we want to switch context/scripted scenes
    def setPlayable(self, value):
        if self.isNPC != False:
            if value == True:
                #down events
                self.accept("arrow_left", self.arrowLeftDown)
                self.accept("arrow_right", self.arrowRightDown)
                self.accept("arrow_up", self.arrowUpDown)
                self.accept("arrow_down", self.arrowDownDown)
                #up events
                self.accept("arrow_left-up", self.arrowLeftUp)
                self.accept("arrow_right-up", self.arrowRightUp)
                self.accept("arrow_up-up", self.arrowUpUp)
                self.accept("arrow_down-up", self.arrowDownUp)
                self.accept("space", self.spaceDown)
                self.node.setTag("playable", "true")
                self.setFollowedByCamera(True)
                self.accept("pauseGameplay", self.setPlayable,
                            [False])  #can pause play
            else:
                self.ignoreAll()
                self.node.setTag("playable", "false")
                self.setFollowedByCamera(False)
                self.resetMovement()  #reset every movement happening
                self.accept("resumeGameplay", self.setPlayable,
                            [True])  #can resume play if not NPC

    #estimate loading time 4 seconds... lol... UPDATE: seems fixed in newer panda versions, inspect
    def showAllSubnodes(self):
        self.wtop.show()
        self.wdown.show()
        self.wleft.show()
        self.wright.show()
        self.stop.show()
        self.sdown.show()
        self.sleft.show()
        self.sright.show()

    def hideAllSubnodes(self):
        self.wtop.hide()
        self.wdown.hide()
        self.wleft.hide()
        self.wright.hide()
        self.stop.hide()
        self.sdown.hide()
        self.sleft.hide()
        self.sright.hide()

    def setMovement(self, value):
        if value == True:
            if self.movtask == 0:
                self.movtask = taskMgr.add(self.moveCharacter,
                                           "moveCharacterTask")
        if value == False:
            if self.movtask != 0:
                if len(self.currentlydown) == 0:
                    taskMgr.remove(self.movtask)
                    self.movtask = 0

    '''
    reset every movement actually happening
    '''

    def resetMovement(self):
        if self.leftdown == True:
            self.face("left")
        if self.rightdown == True:
            self.face("right")
        if self.downdown == True:
            self.face("down")
        if self.topdown == True:
            self.face("top")

        self.leftdown = False
        self.rightdown = False
        self.downdown = False
        self.topdown = False

        self.currentlydown = []

        self.setMovement(False)

    def setAnim(self, direction=''):
        self.hideAllSubnodes()

        if direction == '':
            if len(self.currentlydown) > 0:
                if self.currentlydown[-1] == 'left':
                    self.wleft.show()
                if self.currentlydown[-1] == 'right':
                    self.wright.show()
                if self.currentlydown[-1] == 'top':
                    self.wtop.show()
                if self.currentlydown[-1] == 'down':
                    self.wdown.show()
        else:
            if direction == 'left':
                self.wleft.show()
            if direction == 'right':
                self.wright.show()
            if direction == 'up':
                self.wtop.show()
            if direction == 'down':
                self.wdown.show()

    #pick request function
    def spaceDown(self):
        self.pickRequest = True

    #movement related functions
    def arrowLeftDown(self):
        #track key down
        self.leftdown = True
        self.setMovement(True)
        #show changes to screen
        self.currentlydown.append("left")
        self.setAnim()

    def arrowLeftUp(self):
        self.leftdown = False
        self.setMovement(False)
        #show changes to screen
        if len(self.currentlydown) == 1:
            self.hideAllSubnodes()
            self.sleft.show()
        if "left" in self.currentlydown:
            self.currentlydown.remove("left")

        if len(self.currentlydown) > 0:
            self.setAnim()

    def arrowRightDown(self):
        #track key down
        self.rightdown = True
        self.setMovement(True)
        #show changes to screen
        self.currentlydown.append("right")
        self.setAnim()

    def arrowRightUp(self):
        self.setMovement(False)
        self.rightdown = False
        #show changes to screen
        if len(self.currentlydown) == 1:
            self.hideAllSubnodes()
            self.sright.show()
        if "right" in self.currentlydown:
            self.currentlydown.remove("right")

        if len(self.currentlydown) > 0:
            self.setAnim()

    def arrowDownDown(self):
        #track key down
        self.downdown = True
        self.setMovement(True)
        #show changes to screen
        self.currentlydown.append("down")
        self.setAnim()

    def arrowDownUp(self):
        self.downdown = False
        self.setMovement(False)
        #show changes to screen
        if len(self.currentlydown) == 1:
            self.hideAllSubnodes()
            self.sdown.show()
        if "down" in self.currentlydown:
            self.currentlydown.remove("down")

        if len(self.currentlydown) > 0:
            self.setAnim()

    def arrowUpDown(self):
        #track key down
        self.topdown = True
        self.setMovement(True)
        #show changes to screen
        self.currentlydown.append("top")
        self.setAnim()

    def arrowUpUp(self):
        self.topdown = False
        self.setMovement(False)
        #show changes to screen
        if len(self.currentlydown) == 1:
            self.hideAllSubnodes()
            self.stop.show()
        if "top" in self.currentlydown:
            self.currentlydown.remove("top")
        if len(self.currentlydown) > 0:
            self.setAnim()

    def moveCharacter(self, task):
        dt = globalClock.getDt()
        if len(self.currentlydown) > 0:
            if self.currentlydown[-1] == 'left':
                self.node.setX(self.node.getX() -
                               1 * dt * self.properties['speed'])
            if self.currentlydown[-1] == 'right':
                self.node.setX(self.node.getX() +
                               1 * dt * self.properties['speed'])
            if self.currentlydown[-1] == 'top':
                self.node.setZ(self.node.getZ() +
                               1 * dt * self.properties['speed'])
            if self.currentlydown[-1] == 'down':
                self.node.setZ(self.node.getZ() -
                               1 * dt * self.properties['speed'])

        #check collisions
        if self.cTrav != None:
            self.cTrav.traverse(render)

        if self.pickCTrav != None:
            self.pickCTrav.traverse(render)

        #entries python list
        entries = list(self.collisionHandler.getEntries())
        pickentries = list(self.pickCollisionHandler.getEntries())

        for e in entries[:]:
            if e.getIntoNodePath().getName() == "characterPickTube":
                entries.remove(e)

        for e in pickentries[:]:
            if e.getIntoNodePath().getName() == "characterTube":
                pickentries.remove(e)

        if len(entries) == 0:
            self.lastpos = self.node.getPos()
        else:
            sp = entries[0].getSurfacePoint(self.node)  #surface point
            objectNode = entries[0].getIntoNodePath().getParent(
            )  #into object node
            groundNode = entries[0].getIntoNodePath()  #into object node

            if objectNode.hasTag("collideandwalk"):
                if objectNode.getTag("collideandwalk") != "yes":
                    self.node.setPos(self.lastpos)
            else:
                self.node.setPos(self.lastpos)

            #if node is a real object (not a wall)
            if objectNode.hasTag("avoidable"):
                if objectNode.getTag(
                        "avoidable"
                ) == "true":  #see if object is intelligently avoidable
                    if objectNode.hasTag("xscaled") and objectNode.hasTag(
                            "yscaled"):
                        if len(
                                self.currentlydown
                        ) > 0:  #at least 1, avoids list index out of range exception
                            if self.currentlydown[
                                    -1] == 'left' or self.currentlydown[
                                        -1] == 'right':  #TODO: fix the shiet, not always working
                                bottomObjPos = objectNode.getZ() - (
                                    float(objectNode.getTag("yscaled")) / 2)
                                topObjPos = objectNode.getZ() + (
                                    float(objectNode.getTag("yscaled")) / 2)
                                if self.node.getZ() < bottomObjPos:
                                    self.node.setZ(self.node.getZ() - 1 * dt *
                                                   self.properties['speed'])
                                if self.node.getZ() > topObjPos:
                                    self.node.setZ(self.node.getZ() + 1 * dt *
                                                   self.properties['speed'])
                                pass
                            if self.currentlydown[
                                    -1] == 'top' or self.currentlydown[
                                        -1] == 'down':
                                leftObjPos = objectNode.getX() - (
                                    float(objectNode.getTag("xscaled")) / 2)
                                rightObjPos = objectNode.getX() + (
                                    float(objectNode.getTag("xscaled")) / 2)

                                if self.node.getX() < leftObjPos:
                                    self.node.setX(self.node.getX() - 1 * dt *
                                                   self.properties['speed'])

                                if self.node.getX() > rightObjPos:
                                    self.node.setX(self.node.getX() + 1 * dt *
                                                   self.properties['speed'])
                            self.lastpos = self.node.getPos()

        for entry in entries:
            objectNode = entry.getIntoNodePath().getParent()
            onWalked = objectNode.getTag("onWalked")
            if len(onWalked) > 0:
                eval(onWalked)  #oh lol, danger detected here

        evaluatedOnce = False
        if self.pickRequest == True:
            for entry in pickentries:
                objectNode = entry.getIntoNodePath().getParent()
                onPicked = objectNode.getTag("onPicked")
                if len(onPicked) > 0 and evaluatedOnce == False:
                    eval(onPicked)  #oh lol, danger detected again here
                    evaluatedOnce = True
                else:
                    if hasattr(objectNode.getPythonTag('gamenode'), 'name'):
                        print "WARNING: picking on this object is not defined: ", objectNode.getPythonTag(
                            'gamenode').name
                        print "X: ", objectNode.getX()
                        print "Y: ", objectNode.getZ()
            self.pickRequest = False  #resetting request

        #this is needed for empty pick
        if self.pickRequest == True:
            self.pickRequest = False  #resetting request

        return Task.cont

    def getWorldPos(self):
        return self.node.getPos(render)

    def setX(self, x):
        self.node.setX(x)
        self.lastpos.setX(x)

    def setY(self, y):
        self.node.setZ(y)
        self.lastpos.setZ(y)

    #here for polymorph
    def getTileX(self):
        return self.parent.getX()

    #here for polymorph
    def getTileY(self):
        return self.parent.getY()
Beispiel #13
0
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        # relevant for DEBUG
        self.debug = True
        self.debugLabel = self.makeStatusLabel(0)
        if (self.debug):
            self.debugLabel.setText("Debug Mode ON")
        else:
            self.debugLabel.setText("Debug Mode OFF")
        self.statusLabel = self.makeStatusLabel(1)
        self.collisionLabel = self.makeStatusLabel(2)

        self.world = self.loader.loadModel("world.bam")
        self.world.reparentTo(self.render)

        # relevant for world boundaries
        self.worldsize = 1024

        self.maxspeed = 100.0
        self.startPos = Vec3(200, 200, 1)
        self.startHpr = Vec3(225, 0, 0)
        self.player = self.loader.loadModel("alliedflanker")
        self.player.setScale(.2, .2, .2)
        self.player.reparentTo(self.render)
        self.resetPlayer()

        self.startPosPartner = Vec3(200, 200, 1)
        self.startHprPartner = Vec3(225, 0, 0)
        self.partner = self.loader.loadModel("alliedflanker")
        self.partner.setScale(.2, .2, .2)
        self.partner.reparentTo(self.render)
        self.resetPartner()

        # A task to run every frame
        self.taskMgr.add(self.updateTask, "update")

        self.keyboardSetup()

        #performance (to be masked later by fog) and view:
        self.maxdistance = 400
        self.camLens.setFar(self.maxdistance)
        self.camLens.setFov(60)

        self.createEnviroment()

        # relevant for collision and DEBUG
        self.setupCollisions()
        self.textCounter = 0

        # explosion
        self.explosionModel = loader.loadModel('explosion')
        self.explosionModel.reparentTo(self.render)
        self.explosionModel.setScale(0.0)
        self.explosionModel.setLightOff()
        # only one explosion at a time:
        self.exploding = False

        self.radar

    # relevant for DEBUG
    def makeStatusLabel(self, i):
        return OnscreenText(style=2, fg=(.5,1,.5,1), pos=(-1.3,0.92-(.08*i)),\
                align=TextNode.ALeft, scale = .08, mayChange = 1)

    # relevant for collision and DEBUG
    def setupCollisions(self):
        self.collTrav = CollisionTraverser()

        self.playerGroundSphere = CollisionSphere(0, 1.5, 56, 1)
        self.playerGroundCol = CollisionNode('playerSphere')
        self.playerGroundCol.addSolid(self.playerGroundSphere)

        # bitmask
        self.playerGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.playerGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.world.setCollideMask(BitMask32.bit(0))

        # and done
        self.playerGroundColNp = self.player.attachNewNode(
            self.playerGroundCol)
        self.playerGroundHandler = CollisionHandlerQueue()
        self.collTrav.addCollider(self.playerGroundColNp,
                                  self.playerGroundHandler)

        # DEBUG
        if (self.debug == True):
            self.playerGroundColNp.show()
            self.collTrav.showCollisions(self.render)

    def keyboardSetup(self):
        self.keyMap = {
            "left": 0,
            "right": 0,
            "climb": 0,
            "fall": 0,
            "accelerate": 0,
            "decelerate": 0,
            "fire": 0
        }
        self.accept("escape", sys.exit)
        self.accept("a", self.setKey, ["accelerate", 1])
        self.accept("a-up", self.setKey, ["accelerate", 0])
        self.accept("z", self.setKey, ["decelerate", 1])
        self.accept("z-up", self.setKey, ["decelerate", 0])
        self.accept("arrow_left", self.setKey, ["left", 1])
        self.accept("arrow_left-up", self.setKey, ["left", 0])
        self.accept("arrow_right", self.setKey, ["right", 1])
        self.accept("arrow_right-up", self.setKey, ["right", 0])
        self.accept("arrow_down", self.setKey, ["climb", 1])
        self.accept("arrow_down-up", self.setKey, ["climb", 0])
        self.accept("arrow_up", self.setKey, ["fall", 1])
        self.accept("arrow_up-up", self.setKey, ["fall", 0])
        self.accept("space", self.setKey, ["fire", 1])
        self.accept("space-up", self.setKey, ["fire", 0])
        base.disableMouse()  # or updateCamera will fail

    def createEnviroment(self):
        # Fog to hide performance tweak:
        colour = (0.5, 0.5, 0.5)
        expfog = Fog("scene-wide-fog")
        expfog.setColor(*colour)
        expfog.setExpDensity(0.002)
        self.render.setFog(expfog)
        base.setBackgroundColor(*colour)

        # Our sky
        skydome = self.loader.loadModel('blue-sky-sphere')
        skydome.setEffect(CompassEffect.make(self.render))
        skydome.setScale(0.08)  # bit less than "far"

        # NOT render - you`ll fly through the sky!:
        skydome.reparentTo(self.camera)

        # Our lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.6, .6, .6, 1))
        render.setLight(render.attachNewNode(ambientLight))

        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setColor(Vec4(0.8, 0.8, 0.5, 1))
        dlnp = self.render.attachNewNode(directionalLight)
        dlnp.setPos(0, 0, 260)
        dlnp.lookAt(self.player)
        self.render.setLight(dlnp)

        self.render2d = render2d

        # image scale of 1 fills screen, position defaults to central
        Scale = 1.0 / 2.5  # decimal point is VITAL
        self.radar = OnscreenImage(image='radar.png', scale=Scale, \
                                parent=self.render2d, pos=(-0.95,0,-0.95))
        self.radar.setTransparency(TransparencyAttrib.MAlpha)
        # note the image itself and how it is centered

        hud = OnscreenImage(image='hud1.png', scale=1, \
                                parent=self.render2d, pos=(0,0,0))
        hud.setTransparency(TransparencyAttrib.MAlpha)
        self.dots = list()
        self.playerobj = OnscreenImage(image='playerdot.png', \
                                       scale=1.0/20.0,parent=self.radar)
        self.playerobj.setTransparency(TransparencyAttrib.MAlpha)

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

    def updateTask(self, task):
        self.updatePlayer()
        self.updateCamera()
        self.updateGUI(self.worldsize)
        #relevant for collision and DEBUG
        self.collTrav.traverse(self.render)
        for i in range(self.playerGroundHandler.getNumEntries()):
            entry = self.playerGroundHandler.getEntry(i)
            if (self.debug == True):
                self.collisionLabel.setText("HIT:" +
                                            str(globalClock.getFrameTime()))
            if (self.exploding == False):
                self.player.setZ(entry.getSurfacePoint(self.render).getZ() + 5)
                self.explosionSequence()
        return Task.cont

    def updatePlayer(self):
        if self.exploding == False:
            #Global Clock
            #by default, panda runs as fast as it can frame to frame
            scalefactor = (globalClock.getDt() * self.speed)
            climbfactor = scalefactor * 0.5
            bankfactor = scalefactor
            speedfactor = scalefactor * 2.9

            gravityfactor = ((self.maxspeed - self.speed) / 100.0) * 2.0

            #Climb and Fall
            if (self.keyMap["climb"] != 0 and self.speed > 0.00):
                #faster you go, quicker you climb
                self.player.setZ(self.player.getZ() + climbfactor)
                self.player.setR(self.player.getR() + climbfactor)
                #quickest return: (:avoids uncoil/unwind)
                if (self.player.getR() >= 180):
                    self.player.setR(-180)
            elif (self.keyMap["fall"] != 0 and self.speed > 0.00):
                self.player.setZ(self.player.getZ() - climbfactor)
                self.player.setR(self.player.getR() - climbfactor)
                #quickest return
                if (self.player.getR() <= -180):
                    self.player.setR(
                        180
                    )  #autoreturn - add a bit regardless to make sure it happens
            elif (self.player.getR() > 0):
                self.player.setR(self.player.getR() - (climbfactor + 0.1))
                if (self.player.getR() < 0):
                    self.player.setR(0)  #avoid jitter
            elif (self.player.getR() < 0):
                self.player.setR(self.player.getR() + (climbfactor + 0.1))
                if (self.player.getR() > 0):
                    self.player.setR(0)

            #Left and Right
            if (self.keyMap["left"] != 0 and self.speed > 0.0):
                self.player.setH(self.player.getH() + bankfactor)
                self.player.setP(self.player.getP() + bankfactor)
                #quickest return:
                if (self.player.getP() >= 180):
                    self.player.setP(-180)
            elif (self.keyMap["right"] != 0 and self.speed > 0.0):
                self.player.setH(self.player.getH() - bankfactor)
                self.player.setP(self.player.getP() - bankfactor)
                if (self.player.getP() <= -180):
                    self.player.setP(180)

            #autoreturn
            elif (self.player.getP() > 0):
                self.player.setP(self.player.getP() - (bankfactor + 0.1))
            if (self.player.getP() < 0):
                self.player.setP(0)
            elif (self.player.getP() < 0):
                self.player.setP(self.player.getP() + (bankfactor + 0.1))
            if (self.player.getP() > 0):
                self.player.setP(0)

            #throttle control
            if (self.keyMap["accelerate"] != 0):
                self.speed += 1
            if (self.speed > self.maxspeed):
                self.speed = self.maxspeed
            elif (self.keyMap["decelerate"] != 0):
                self.speed -= 1
            if (self.speed < 0.0):
                self.speed = 0.0

            #move forwards - our X/Y is inverted, see the issue

            self.player.setX(
                self.player, -speedfactor
            )  #respect max camera distance else you cannot see the floor post loop the loop!
            self.applyBoundaries()
            self.player.setZ(self.player, -gravityfactor)

    def updateGUI(self, boundingBox):
        boundingBox = boundingBox * 2
        offsetX = 0.0
        offsetZ = 0.0

        # would be fine for minimap
        self.playerobj.setX(self.player.getX() / boundingBox)
        self.playerobj.setZ(self.player.getY() / boundingBox)

        # player center
        if (self.playerobj.getX() > 0.5):
            offsetX = -(self.playerobj.getX() - 0.5)
        elif (self.playerobj.getX() < 0.5):
            offsetX = 0.5 - self.playerobj.getX()
        # else stays zero
        if (self.playerobj.getZ() > 0.5):
            offsetZ = -(self.playerobj.getZ() - 0.5)
        elif (self.playerobj.getZ() < 0.5):
            offsetZ = 0.5 - self.playerobj.getZ()

        self.playerobj.setX(self.playerobj.getX() + offsetX)
        self.playerobj.setZ(self.playerobj.getZ() + offsetZ)

        for dot in self.dots:
            dot.removeNode()  # correct way to remove from scene graph
        del self.dots[:]
        self.playerobj.setR(-self.player.getH() - 90)

        newobj = OnscreenImage(image='reddot.png',scale=1.0/60.0, \
                                   parent=self.radar)
        newobj.setTransparency(TransparencyAttrib.MAlpha)
        newobj.setX(self.partner.getX() / boundingBox)
        newobj.setZ(self.partner.getY() / boundingBox)
        newobj.setX(newobj.getX() + offsetX)
        newobj.setZ(newobj.getZ() + offsetZ)
        self.dots.append(newobj)  # so can destroy, see call above

    def applyBoundaries(self):
        if (self.player.getZ() > self.maxdistance):
            self.player.setZ(self.maxdistance)
        # should never happen once we add collision, but in case:
        elif (self.player.getZ() < 0):
            self.player.setZ(0)

        # and now the X/Y world boundaries:
        boundary = False
        if (self.player.getX() < 0):
            self.player.setX(0)
            boundary = True
        elif (self.player.getX() > self.worldsize):
            self.player.setX(self.worldsize)
            boundary = True
        if (self.player.getY() < 0):
            self.player.setY(0)
            boundary = True
        elif (self.player.getY() > self.worldsize):
            self.player.setY(self.worldsize)
            boundary = True

        # lets not be doing this every frame...
        if boundary == True and self.textCounter > 30:
            self.statusLabel.setText("STATUS: MAP END; TURN AROUND")
        elif self.textCounter > 30:
            self.statusLabel.setText("STATUS: OK")

        if self.textCounter > 30:
            self.textCounter = 0
        else:
            self.textCounter = self.textCounter + 1

    def updateCamera(self):
        #see issue content for how we calculated these:
        percent = (self.speed / self.maxspeed)
        self.camera.setPos(self.player, 19.6226 + (10 * percent), 3.8807,
                           10.2779)
        self.camera.setHpr(self.player, 94.8996, -12.6549, 1.55508)

    def resetPlayer(self):
        self.player.show()
        self.player.setPos(self.world, self.startPos)
        self.player.setHpr(self.world, self.startHpr)
        self.speed = self.maxspeed / 2

    def resetPartner(self):
        self.partner.show()
        self.partner.setPos(self.world, self.startPosPartner)
        self.partner.setHpr(self.world, self.startHprPartner)

    def explosionSequence(self):
        self.exploding = True
        self.explosionModel.setPosHpr(
            Vec3(self.player.getX(), self.player.getY(), self.player.getZ()),
            Vec3(self.player.getH(), 0, 0))
        self.player.hide()
        taskMgr.add(self.expandExplosion, 'expandExplosion')

    def expandExplosion(self, Task):
        # expand the explosion rign each frame until a certain size
        if self.explosionModel.getScale() < VBase3(60.0, 60.0, 60.0):
            factor = globalClock.getDt()
            scale = self.explosionModel.getScale()
            scale = scale + VBase3(factor * 40, factor * 40, factor * 40)
            self.explosionModel.setScale(scale)
            return Task.cont
        else:
            self.explosionModel.setScale(0)
            self.exploding = False
            self.resetPlayer()
Beispiel #14
0
class MousePicker(object):
    def __init__(self,
                 pickTag='MyPickingTag',
                 nodeName='pickRay',
                 showCollisions=False):
        self.pickTag = pickTag
        self.nodeName = nodeName
        self.showCollisions = showCollisions

    def create(self):
        self.mPickerTraverser = CollisionTraverser()
        self.mCollisionQue = CollisionHandlerQueue()

        self.mPickRay = CollisionRay()
        self.mPickRay.setOrigin(base.camera.getPos(base.render))
        self.mPickRay.setDirection(
            base.render.getRelativeVector(base.camera, Vec3(0, 1, 0)))

        #create our collison Node to hold the ray
        self.mPickNode = CollisionNode(self.nodeName)
        self.mPickNode.addSolid(self.mPickRay)

        #Attach that node to the camera since the ray will need to be positioned
        #relative to it, returns a new nodepath
        #well use the default geometry mask
        #this is inefficent but its for mouse picking only

        self.mPickNP = base.camera.attachNewNode(self.mPickNode)

        #we'll use what panda calls the "from" node.  This is reall a silly convention
        #but from nodes are nodes that are active, while into nodes are usually passive environments
        #this isnt a hard rule, but following it usually reduces processing

        #Everything to be picked will use bit 1. This way if we were doing other
        #collision we could seperate it, we use bitmasks to determine what we check other objects against
        #if they dont have a bitmask for bit 1 well skip them!
        self.mPickNode.setFromCollideMask(BitMask32(1))

        #Register the ray as something that can cause collisions
        self.mPickerTraverser.addCollider(self.mPickNP, self.mCollisionQue)

        #Setup 2D picker
        self.mPickerTraverser2D = CollisionTraverser()
        self.mCollisionQue2D = CollisionHandlerQueue()

        self.mPickNode2D = CollisionNode('2D PickNode')
        self.mPickNode2D.setFromCollideMask(BitMask32(1))
        self.mPickNode2D.setIntoCollideMask(BitMask32.allOff())

        self.mPick2DNP = base.camera2d.attachNewNode(self.mPickNode2D)

        self.mPickRay2D = CollisionRay()
        self.mPickNode2D.addSolid(self.mPickRay2D)

        self.mPickerTraverser2D.addCollider(self.mPick2DNP,
                                            self.mCollisionQue2D)

        if self.showCollisions:
            self.mPickerTraverser.showCollisions(base.render)
            self.mPickerTraverser2D.showCollisions(base.aspect2d)

    def mousePick(self, traverse=None, tag=None):
        #do we have a mouse
        if (base.mouseWatcherNode.hasMouse() == False):
            return None, None

        traverse = traverse or base.render
        tag = tag or self.pickTag

        mpos = base.mouseWatcherNode.getMouse()

        #Set the position of the ray based on the mouse position
        self.mPickRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
        self.mPickerTraverser.traverse(traverse)

        if (self.mCollisionQue.getNumEntries() > 0):
            self.mCollisionQue.sortEntries()

            for entry in self.mCollisionQue.getEntries():
                pickedObj = entry.getIntoNodePath()
                pickedObj = pickedObj.findNetTag(tag)

                if not pickedObj.isEmpty():
                    pos = entry.getSurfacePoint(base.render)
                    return pickedObj, pos

        return None, None

    def mousePick2D(self, traverse=None, tag=None, all=False):
        #do we have a mouse
        if (base.mouseWatcherNode.hasMouse() == False):
            return None, None

        traverse = traverse or base.render
        tag = tag or self.pickTag

        mpos = base.mouseWatcherNode.getMouse()

        self.mPickRay2D.setFromLens(base.cam2d.node(), mpos.getX(),
                                    mpos.getY())

        self.mPickerTraverser2D.traverse(base.aspect2d)

        if self.mCollisionQue2D.getNumEntries() > 0:
            self.mCollisionQue2D.sortEntries()

            if all:
                return [(entry.getIntoNodePath().findNetTag(tag),
                         entry.getSurfacePoint(base.aspect2d))
                        for entry in self.mCollisionQue2D.getEntries()], None
            else:
                entry = self.mCollisionQue2D.getEntry(0)
                pickedObj = entry.getIntoNodePath()

                pickedObj = pickedObj.findNetTag(tag)
                if not pickedObj.isEmpty():
                    pos = entry.getSurfacePoint(base.aspect2d)
                    return pickedObj, pos

        return None, None
Beispiel #15
0
class SpaceFlight(ShowBase):
  def __init__(self):
    ShowBase.__init__(self)
    self.text = OnscreenText \
    (
      parent = base.a2dBottomCenter,
      align=TextNode.ARight,
      fg=(1, 1, 1, 1),
      pos=(0.2, 1.),
      scale=0.1,
      shadow=(0, 0, 0, 0.5)
    )
    self.setBackgroundColor(0, 0, 0)
    self.disableMouse()
    self.fog = Fog('distanceFog')
    self.fog.setColor(0, 0, 0)
    self.fog.setExpDensity(.002)
    #
    self.queue = CollisionHandlerQueue()
    self.trav = CollisionTraverser('traverser')
    base.cTrav = self.trav
    self.loadSky()
    self.reloadGame()

    self.keyMap = {'left' : 0, 'right' : 0, 'up' : 0, 'down' : 0}
    self.gamePause = False
    #
    self.accept('escape', sys.exit)
    self.accept('p', self.pause)
    self.accept('r', self.reloadGame)
    self.accept('arrow_left', self.setKey, ['left', True])
    self.accept('arrow_right', self.setKey, ['right', True])
    self.accept('arrow_up', self.setKey, ['up', True])
    self.accept('arrow_down', self.setKey, ['down', True])
    self.accept('arrow_left-up', self.setKey, ['left', False])
    self.accept('arrow_right-up', self.setKey, ['right', False])
    self.accept('arrow_up-up', self.setKey, ['up', False])
    self.accept('arrow_down-up', self.setKey, ['down', False])
    #
    taskMgr.add(self.moveShip, 'moveShip')
    taskMgr.add(self.moveAsteroids, 'moveAsteroids')
    taskMgr.add(self.handleCollisions, 'handleCollisions')
    #
    if DEBUG:
      self.trav.showCollisions(render)
      render.find('**/ship_collision').show()
      for asteroid in render.findAllMatches('**/asteroid_collision*'):
        asteroid.show()

  def loadSky(self):
    self.sky = loader.loadModel('models/solar_sky_sphere.egg.pz')
    self.sky_tex = loader.loadTexture('models/stars_1k_tex.jpg')
    self.sky.setTexture(self.sky_tex, 1)
    self.sky.reparentTo(render)
    self.sky.setScale(500)

  def loadShip(self):
    self.ship = loader.loadModel('models/alice-scifi--fighter/fighter.egg')
    self.ship.reparentTo(render)
    self.ship.setPos(START_X, START_Y, START_Z)
    self.ship.setScale(0.25)
    # add some physics
    ship_col = self.ship.attachNewNode(CollisionNode('ship_collision'))
    col_sphere = CollisionSphere(START_X, START_Y, 0, SHIP_SPHERE_RADIUS)
    ship_col.node().addSolid(col_sphere)
    self.trav.addCollider(ship_col, self.queue)

  def spawnAsteroid(self):
    asteroid = loader.loadModel(choice(ASTEROID_SHAPES))
    asteroid_tex = loader.loadTexture('models/rock03.jpg')
    asteroid.setTexture(asteroid_tex, 1)
    asteroid.reparentTo(render)
    asteroid.setFog(self.fog)
    self.asteroids.append(asteroid)
    self.asteroids_rotation.append(randint(ASTEROID_ROTATE_MIN, ASTEROID_ROTATE_MAX))
    #
    num = len(self.asteroids) - 1
    asteroid_col = asteroid.attachNewNode(CollisionNode('asteroid_collision_%d' % num))
    col_sphere = CollisionSphere(0, 0, 0, ASTEROID_SPHERE_RADIUS)
    asteroid_col.node().addSolid(col_sphere)
    #
    asteroid.setX(randint(MIN_X, MAX_X))
    asteroid.setY(randint(ASTEROID_SPAWN_MIN_Y, ASTEROID_SPAWN_MAX_Y))
    asteroid.setZ(randint(MIN_Z, MAX_Z))

  def setKey(self, key, value):
    self.keyMap[key] = value
    if key in ['left', 'right'] and value == False:
      self.ship.setH(0)
    if key in ['up', 'down'] and value == False:
      self.ship.setP(0)

  def updateCamera(self):
    x, y, z = self.ship.getPos()
    self.camera.setPos(x, y - 40, z + 25)
    self.camera.lookAt(x, y, z + 10)

  def moveAsteroids(self, task):
    dt = globalClock.getDt()
    if not self.gamePause:
      for num, asteroid in enumerate(self.asteroids):
        asteroid.setY(asteroid.getY() - ASTEROID_SPEED * dt)
        rotation = self.asteroids_rotation[num]
        asteroid.setH(asteroid.getH() - rotation * ASTEROID_SPEED * dt)
        if asteroid.getY() < self.camera.getY() + 10:
          asteroid.setX(randint(MIN_X, MAX_X))
          asteroid.setY(randint(ASTEROID_SPAWN_MIN_Y, ASTEROID_SPAWN_MAX_Y))
          asteroid.setZ(randint(MIN_Z, MAX_Z))
    return task.cont

  def rollbackOnBoard(self, minPos, maxPos, getFunc, setFunc):
    if getFunc() < minPos:
      setFunc(minPos)
    if getFunc() > maxPos:
      setFunc(maxPos)

  def applyBound(self):
    self.rollbackOnBoard(MIN_X, MAX_X, self.ship.getX, self.ship.setX)
    self.rollbackOnBoard(MIN_Z, MAX_Z, self.ship.getZ, self.ship.setZ)

  def moveShip(self, task):
    dt = globalClock.getDt()
    if not self.gamePause:
      if self.keyMap['left']:
        self.ship.setX(self.ship.getX() - SHIP_SPEED * dt)
        self.ship.setH(TURN_SPEED)
      elif self.keyMap['right']:
        self.ship.setX(self.ship.getX() + SHIP_SPEED * dt)
        self.ship.setH(-TURN_SPEED)
      elif self.keyMap['up']:
        self.ship.setZ(self.ship.getZ() + SHIP_SPEED * dt)
        self.ship.setP(TURN_SPEED)
      elif self.keyMap['down']:
        self.ship.setZ(self.ship.getZ() - 5 * SHIP_SPEED * dt)
        self.ship.setP(-TURN_SPEED)

      self.sky.setP(self.sky.getP() - dt * 10)
      self.applyBound()
      self.updateCamera()

    return task.cont

  def handleCollisions(self, task):
    if not self.gamePause:
      for entry in self.queue.getEntries():
        node = entry.getFromNodePath()
        if node.getName() == 'ship_collision':
          self.gamePause = True
          self.text.setText('You lose :(')
    return task.cont

  def pause(self):
    self.gamePause = not self.gamePause

  def reloadGame(self):
    self.gamePause = False
    self.text.clearText()

    if hasattr(self, 'asteroids'):
      for asteroid in self.asteroids:
        asteroid.removeNode()

    self.asteroids = []
    self.asteroids_rotation = []

    if hasattr(self, 'ship'):
      self.ship.removeNode()

    self.loadShip()

    for _ in xrange(ASTEROID_MAX_CNT):
      self.spawnAsteroid()
Beispiel #16
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
class RoamingRalphDemo(ShowBase):
    def __init__(self):
        # Set up the window, camera, etc.
        ShowBase.__init__(self)
	#self.setupCD()

        # Set the background color to black
       # self.win.setClearColor((0.6, 0.6, 1.0, 1.0))
#	self.fog = Fog('myFog')
#	self.fog.setColor(0, 0, 0)
#	self.fog.setExpDensity(.05)
#	render.setFog(self.fog)	
       # This is used to store which keys are currently pressed.
        self.keyMap = {
            "left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0, "c":0, "back":0, "space":0}

        # Post the instructions
        #self.title = addTitle(
         #   "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)")
        self.inst1 = addInstructions(0.06, "[ESC]: Quit")
        self.inst2 = addInstructions(0.12, "[Left Arrow]: Rotate Ralph Left")
        self.inst3 = addInstructions(0.18, "[Right Arrow]: Rotate Ralph Right")
        self.inst4 = addInstructions(0.24, "[Up Arrow]: Run Ralph Forward")
        #self.inst6 = addInstructions(0.30, "[A]: Rotate Camera Left")
        #self.inst7 = addInstructions(0.36, "[S]: Rotate Camera Right")


        # Set up the environment
        #
        # This environment model contains collision meshes.  If you look
        # in the egg file, you will see the following:
        #
        #    <Collide> { Polyset keep descend }
        #
        # This tag causes the following mesh to be converted to a collision
        # mesh -- a mesh which is optimized for collision, not rendering.
        # It also keeps the original mesh, so there are now two copies ---
        # one optimized for rendering, one for collisions.

        self.environ = loader.loadModel("models/world")
        #self.environ.reparentTo(render)

        self.room = loader.loadModel("models/room2.egg")
        self.room.reparentTo(render)
        #self.room.setScale(.1)
        self.room.setPos(0,0,-5)
        self.room.setShaderAuto()
	#self.room.writeBamFile("myRoom1.bam")
	#self.room.setColor(1,.3,.3,1)

	self.room2 = loader.loadModel("models/abstractroom2")
        self.room2.reparentTo(render)
        self.room2.setScale(.1)
        self.room2.setPos(-12,0,0)

        # Create the main character, Ralph

        #ralphStartPos = LVecBase3F(0,0,0) #self.room.find("**/start_point").getPos()

        self.ralph = Actor("models/ralph",
                           {"run": "models/ralph-run",
                            "walk": "models/ralph-walk"})
        self.ralph.reparentTo(render)
        self.ralph.setScale(.2)
        self.ralph.setPos(0,0,0)
	#cs = CollisionSphere(0, 0, 0, 1)
	#cnodePath = self.ralph.attachNewNode(CollisionNode('cnode'))
	#cnodePath.node().addSolid(cs)
	#cnodePath.node().setPos(0,0,0)
	#cnodePath.show()	
	
	self.gianteye = loader.loadModel("models/gianteye")
	self.gianteye.reparentTo(render)
	self.gianteye.setScale(.1)
	self.gianteye.setPos(10,10,0)	
	
	#self.bluefinal = loader.loadModel("models/chrysalis")
	#self.bluefinal.reparentTo(render)
	#self.bluefinal.setScale(.1)
	#self.bluefinal.setPos(7,7,0)	
	
	#self.blue = loader.loadModel("models/blue1")
	#self.blue.reparentTo(render)
	#self.blue.setScale(.1)
	#self.blue.setPos(10,5,0)
	
	self.chik = loader.loadModel("models/chik")
	self.chik.reparentTo(render)
	self.chik.setScale(.1)
	self.chik.setPos(3,13,0)	

        self.pawn = loader.loadModel("pawn")
        self.pawn.reparentTo(render)
        self.pawn.setPos(0,0,0)

        self.shot = loader.loadModel("models/icosphere.egg")
        self.shot.reparentTo(render)
        self.shot.setScale(.5)
        self.shot.setPos(0,0,1)
        self.shot.setColor(1,.3,.3,1)

        self.myShot = loader.loadModel("models/icosphere.egg")
        #self.myShot.reparentTo(render)
        self.myShot.setScale(.1)
        self.myShot.setPos(0,0,1)
        self.myShotVec = LVector3(0,0,0)

        self.lightpivot3 = render.attachNewNode("lightpivot3")
        self.lightpivot3.setPos(0, 0, 0)
        self.lightpivot3.hprInterval(10, LPoint3(0, 0, 0)).loop()
        plight3 = PointLight('plight2')
        plight3.setColor((0, .3,0, 1))
        plight3.setAttenuation(LVector3(0.7, 0.05, 0))
        plnp3 = self.lightpivot3.attachNewNode(plight3)
        plnp3.setPos(0, 0, 0)
        self.room2.setLight(plnp3)
        self.room.setLight(plnp3)
        sphere3 = loader.loadModel("models/icosphere")
        sphere3.reparentTo(plnp3)
        sphere3.setScale(0.1)
        sphere3.setColor((0,1,0,1))

        # Create a floater object, which floats 2 units above ralph.  We
        # use this as a target for the camera to look at.

        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(self.ralph)
        self.floater.setZ(8.0)

        # Accept the control keys for movement and rotation

        self.accept("escape", sys.exit)
        self.accept("arrow_left", self.setKey, ["left", True])
        self.accept("arrow_right", self.setKey, ["right", True])
        self.accept("arrow_up", self.setKey, ["forward", True])
        self.accept("arrow_down", self.setKey, ["back", True])
        self.accept("a", self.setKey, ["cam-left", True])
        self.accept("s", self.setKey, ["cam-right", True])
        self.accept("arrow_left-up", self.setKey, ["left", False])
        self.accept("arrow_right-up", self.setKey, ["right", False])
        self.accept("arrow_up-up", self.setKey, ["forward", False])
        self.accept("arrow_down-up", self.setKey, ["back", False])
        self.accept("a-up", self.setKey, ["cam-left", False])
        self.accept("s-up", self.setKey, ["cam-right", False])

        self.accept("space", self.setKey, ["space", True])
        self.accept("space-up", self.setKey, ["space", False])

        self.accept("c",self.setKey,["c",True])
        self.accept("c-up",self.setKey,["c",False])

        taskMgr.add(self.move, "moveTask")

        # Game state variables
        self.isMoving = False
        self.jumping = False
        self.vz = 0

        # Set up the camera
        self.disableMouse()
        self.camera.setPos(self.ralph.getX(), self.ralph.getY() + 7, 3)
        self.camLens.setFov(60)

        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  One ray will
        # start above ralph's head, and the other will start above the camera.
        # A ray may hit the terrain, or it may hit a rock or a tree.  If it
        # hits the terrain, we can detect the height.  If it hits anything
        # else, we rule that the move is illegal.

        def setupCollision(self):
	    cs = CollisionSphere(0,0,2,1)
	    cnodePath = self.ralph.attachNewNode(CollisionNode('cnode'))
	    cnodePath.node().addSolid(cs)
	    cnodePath.show()
	    #for o in self.OBS:
		#ct = CollisionTube(0,0,0, 0,0,1, 0.5)
		#cn = o.attachNewNode(CollisionNode('ocnode'))
		#cn.node().addSolid(ct)
		#cn.show()
	    eyecs = CollisionSphere(0,0,4,5)
	    cnodePath = self.gianteye.attachNewNode(CollisionNode('cnode'))
	    cnodePath.node().addSolid(eyecs)
	    cnodePath.show()	 
	    eyecs = CollisionSphere(0,0,4,2)
	    cnodePath = self.chik.attachNewNode(CollisionNode('cnode'))
	    cnodePath.node().addSolid(eyecs)
	    cnodePath.show()	    
    
	    pusher = CollisionHandlerPusher()
	    pusher.addCollider(cnodePath, self.player)
	    self.cTrav = CollisionTraverser()
	    self.cTrav.add_collider(cnodePath,pusher)
	    self.cTrav.showCollisions(render)
	self.walls = self.room2.find("**/wall_collide")
	#self.walls.node().setIntoCollideMask(BitMask32.bit(0))

        self.cTrav = CollisionTraverser()
        self.ralphGroundRay = CollisionRay()
        self.ralphGroundRay.setOrigin(0, 0, 9)
        self.ralphGroundRay.setDirection(0, 0, -1)
        self.ralphGroundCol = CollisionNode('ralphRay')
        self.ralphGroundCol.addSolid(self.ralphGroundRay)
        self.ralphGroundCol.setFromCollideMask(CollideMask.bit(0))
        self.ralphGroundCol.setIntoCollideMask(CollideMask.allOff())
        self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol)
        self.ralphGroundHandler = CollisionHandlerQueue()

        self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler)	

        self.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0, 0, 9)
        self.camGroundRay.setDirection(0, 0, -1)
        self.camGroundCol = CollisionNode('camRay')
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(CollideMask.bit(0))
        self.camGroundCol.setIntoCollideMask(CollideMask.allOff())
        self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol)
        self.camGroundHandler = CollisionHandlerQueue()

        self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)

        self.sphere = CollisionSphere(0,0,4,2)
        self.sphere2 = CollisionSphere(0,0,2,2)
        self.cnodePath = self.ralph.attachNewNode((CollisionNode('cnode')))
        self.cnodePath.node().addSolid(self.sphere)
        self.cnodePath.node().addSolid(self.sphere2)
        self.cnodePath.show()
        self.pusher = CollisionHandlerPusher()
        self.pusher.addCollider(self.cnodePath, self.ralph)
        self.cTrav.add_collider(self.cnodePath, self.pusher)
	
	self.eyecs = CollisionSphere(0,0,22,25)
	self.cnodePath1 = self.gianteye.attachNewNode(CollisionNode('cnode'))
	self.cnodePath1.node().addSolid(self.eyecs)
	self.cnodePath1.show()	
	self.pusher1 = CollisionHandlerPusher()
	self.pusher1.addCollider(self.cnodePath1, self.gianteye)
	self.cTrav.add_collider(self.cnodePath1, self.pusher1)	
	self.cTrav.showCollisions(render)
	
	self.eyeGroundRay = CollisionRay()
        self.eyeGroundRay.setOrigin(0, 0, 9)
        self.eyeGroundRay.setDirection(0, 0, -1)
        self.eyeGroundCol = CollisionNode('eyeRay')
        self.eyeGroundCol.addSolid(self.eyeGroundRay)
        self.eyeGroundCol.setFromCollideMask(CollideMask.bit(0))
        self.eyeGroundCol.setIntoCollideMask(CollideMask.allOff())
        self.eyeGroundColNp = self.gianteye.attachNewNode(self.eyeGroundCol)
        self.eyeGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.eyeGroundColNp, self.eyeGroundHandler)		

	self.chikcs = CollisionSphere(0,0,11,20)
	self.cnodePath2 = self.chik.attachNewNode(CollisionNode('cnode'))
	self.cnodePath2.node().addSolid(self.chikcs)
	self.cnodePath2.show()
	self.pusher2 = CollisionHandlerPusher()
	self.pusher2.addCollider(self.cnodePath, self.chik)
	self.cTrav.add_collider(self.cnodePath, self.pusher2)	
	self.cTrav.showCollisions(render)	
	
	self.chikGroundRay = CollisionRay()
        self.chikGroundRay.setOrigin(0, 0, 9)
        self.chikGroundRay.setDirection(0, 0, -1)
        self.chikGroundCol = CollisionNode('chikRay')
        self.chikGroundCol.addSolid(self.chikGroundRay)
        self.chikGroundCol.setFromCollideMask(CollideMask.bit(0))
        self.chikGroundCol.setIntoCollideMask(CollideMask.allOff())
        self.chikGroundColNp = self.chik.attachNewNode(self.chikGroundCol)
        self.chikGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.chikGroundColNp, self.chikGroundHandler)	
	

        # Uncomment this line to see the collision rays
        self.ralphGroundColNp.show()
        self.camGroundColNp.show()
	#self.ralphroom1ColNp.show()

        # Uncomment this line to show a visual representation of the
        # collisions occuring
        #self.cTrav.showCollisions(render)

        # Create some lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.3, .3, .3, .4))
        ambientLight2 = AmbientLight("ambientLight2")
        ambientLight2.setColor((1, 1, 1, 10))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection((0, 0, -2))
        directionalLight.setColor((1, 1, 1, 1))
        directionalLight.setSpecularColor((1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambientLight))
        #self.environ.setLight(self.environ.attachNewNode(ambientLight2))
        render.setLight(render.attachNewNode(directionalLight))

        # Add a light to the scene.
        self.lightpivot = render.attachNewNode("lightpivot")
        self.lightpivot.setPos(0, 0, 1.6)
        self.lightpivot.hprInterval(20, LPoint3(360, 0, 0)).loop()
        plight = PointLight('plight')
        plight.setColor((.7, .3, 0, 1))
        plight.setAttenuation(LVector3(0.7, 0.05, 0))
        plnp = self.lightpivot.attachNewNode(plight)
        plnp.setPos(5, 0, 0)
        self.room.setLight(plnp)
        sphere = loader.loadModel("models/icosphere")
        sphere.reparentTo(plnp)
        sphere.setScale(0.1)
        sphere.setColor((1,1,0,1))

        self.lightpivot2 = render.attachNewNode("lightpivot")
        self.lightpivot2.setPos(-16, 0, 1.6)
        self.lightpivot2.hprInterval(20, LPoint3(360, 0, 0)).loop()
        plight2 = PointLight('plight2')
        plight2.setColor((0, .4,.8, 1))
        plight2.setAttenuation(LVector3(0.7, 0.05, 0))
        plnp2 = self.lightpivot2.attachNewNode(plight2)
        plnp2.setPos(5, 0, 0)
        self.room2.setLight(plnp2)
        sphere2 = loader.loadModel("models/icosphere")
        sphere2.reparentTo(plnp2)
        sphere2.setScale(0.2)
        sphere2.setColor((0,0,1,1))

        self.vec = LVector3(0,1,0) 
	
    # Records the state of the arrow keys
    def setKey(self, key, value):
        self.keyMap[key] = value

    # Accepts arrow keys to move either the player or the menu cursor,
    # Also deals with grid checking and collision detection
    def move(self, task):

        # Get the time that elapsed since last frame.  We multiply this with
        # the desired speed in order to find out with which distance to move
        # in order to achieve that desired speed.
        dt = globalClock.getDt()

        # If the camera-left key is pressed, move camera left.
        # If the camera-right key is pressed, move camera right.

        if self.keyMap["cam-left"]:
            self.camera.setZ(self.camera, -20 * dt)
        if self.keyMap["cam-right"]:
            self.camera.setZ(self.camera, +20 * dt)

        # save ralph's initial position so that we can restore it,
        # in case he falls off the map or runs into something.

        startpos = self.ralph.getPos()

        # If a move-key is pressed, move ralph in the specified direction.

        if self.keyMap["left"]:
            self.ralph.setH(self.ralph.getH() + 150 * dt)
            #self.floater.setH(self.floater.getH() + 300 * dt)
            self.camera.setX(self.camera, +15.5 * dt)
        if self.keyMap["right"]:
            self.ralph.setH(self.ralph.getH() - 150 * dt)
            self.camera.setX(self.camera, -15.5 * dt)
        if self.keyMap["forward"]:
            self.ralph.setY(self.ralph, -35 * dt)
        if self.keyMap["back"]:
            self.ralph.setY(self.ralph, +35 * dt)
        if self.keyMap["c"]:
            if self.jumping is False:
            #self.ralph.setH(self.ralph.getH() + 300 * dt)
            #self.ralph.setZ(self.ralph.getZ() + 100 * dt)
                self.jumping = True
                self.vz = 7

        if self.keyMap["space"]:
            self.lightpivot3.setPos(self.ralph.getPos())
            self.lightpivot3.setZ(self.ralph.getZ() + .5)
            self.lightpivot3.setX(self.ralph.getX() - .25)
            #self.myShot.setHpr(self.ralph.getHpr())
            #parent
            node = NodePath("tmp")
            node.setHpr(self.ralph.getHpr())
            vec = render.getRelativeVector(node,(0,-1,0))
            self.myShotVec = vec

        self.lightpivot3.setPos(self.lightpivot3.getPos() + self.myShotVec * dt * 15 )

        if self.jumping is True:
            self.vz = self.vz - 16* dt
            self.ralph.setZ(self.ralph.getZ() + self.vz * dt )
            entries = list(self.ralphGroundHandler.getEntries())
            entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())
            if len(entries) > 0 :
                if self.ralph.getZ() < 0:#entries[0].getSurfacePoint(render).getZ():
                    #self.ralph.setZ(entries[0].getSurfacePoint(render).getZ())
                    self.ralph.setZ(0)
                    self.jumping = False
        # If ralph is moving, loop the run animation.
        # If he is standing still, stop the animation.

        if self.keyMap["forward"] or self.keyMap["left"] or self.keyMap["right"] or self.keyMap["c"] or self.keyMap["forward"] or self.keyMap["back"]:
            if self.isMoving is False:
                self.ralph.loop("run")
                self.isMoving = True


        else:
            if self.isMoving:
                self.ralph.stop()
                self.ralph.pose("walk", 5)
                self.isMoving = False

        node = NodePath("tmp")
        node.setHpr(self.ralph.getHpr())
        vec = render.getRelativeVector(node,(1,0,0))

        #self.ralph.setPos(self.ralph.getPos() + vec * dt * 20)

        node = NodePath("tmp")
        #self.pawn.getH()
        node.setHpr(self.pawn.getHpr())
        vec = render.getRelativeVector(node,(random.random() * -0.8,random.random() + 1,0))
        self.shot.setPos(self.shot.getPos() + self.vec * dt * 10 )
        if self.shot.getY() < -15 or self.shot.getY() > 15 or self.shot.getX() < -15 or self.shot.getX() > 15:
            self.shot.setPos(self.pawn.getPos() + (0,0,0))
            self.vec = render.getRelativeVector(node,(random.random() * -0.8,random.random() + 1,0))
            self.vec = render.getRelativeVector(node,(random.random() * -0.8,random.random() + 1,0))

        # If the camera is too far from ralph, move it closer.
        # If the camera is too close to ralph, move it farther.

        camvec = self.ralph.getPos() - self.camera.getPos()
        #camvec.setZ(self.camera.getZ())
        camdist = camvec.length()
        x = self.camera.getZ()
        camvec.normalize()
        if camdist > 6.0:
            self.camera.setPos(self.camera.getPos() + camvec * (camdist - 6))
            camdist = 10.0
            #self.camera.setZ(self.camera, x)
        if camdist < 6.0:
            self.camera.setPos(self.camera.getPos() - camvec * (6 - camdist))
            camdist = 5.0
            #self.camera.setZ(self.camera, x)

        # Normally, we would have to call traverse() to check for collisions.
        # However, the class ShowBase that we inherit from has a task to do
        # this for us, if we assign a CollisionTraverser to self.cTrav.
        #self.cTrav.traverse(render)

        # Adjust ralph's Z coordinate.  If ralph's ray hit terrain,
        # update his Z. If it hit anything else, or didn't hit anything, put
        # him back where he was last frame.

        entries = list(self.ralphGroundHandler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())
        if self.jumping == False:
            if len(entries) > 0:# and entries[0].getIntoNode().getName() == "terrain":
                #self.ralph.setZ(entries[0].getSurfacePoint(render).getZ())
                pass
            else:
                self.ralph.setPos(startpos)

        # Keep the camera at one foot above the terrain,
        # or two feet above ralph, whichever is greater.

        entries = list(self.camGroundHandler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

        #if len(entries) > 0 and entries[0].getIntoNode().getName() == "ground":
            #self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.5)
        if self.camera.getZ() < self.ralph.getZ() + 1 or self.camera.getZ() > self.ralph.getZ() + 1:
            self.camera.setZ(self.ralph.getZ() + 1)

        #self.camera.setZ(self.ralph.getZ() + 1.5)
        #self.camera.setP(self.camera, 130)

        # The camera should look in ralph's direction,
        # but it should also try to stay horizontal, so look at
        # a floater which hovers above ralph's head.
        self.camera.lookAt(self.floater)

        return task.cont
Beispiel #18
0
class MyApp(ShowBase):
 
    def __init__(self):
        ShowBase.__init__(self)
        self.disableMouse()  
        camera.setPosHpr(0, -12, 8, 0, -35, 0)
        """
        self.environ = self.loader.loadModel("models/environment")
        # Reparent the model to render.
        self.environ.reparentTo(self.render)
        # Apply scale and position transforms on the model.
        self.environ.setScale(0.25, 0.25, 0.25)
        self.environ.setPos(-8, 42, 0)
        self.torus = loader.loadModel("torus.egg")
        self.torus.reparentTo(self.render)
        self.torus.setPos(circPos(0,1))
        self.torus.setColor(BLACK)
        self.torus.setScale(0.5,0.5,0.5)
        """
        self.setupLights()
        self.ended = False
        self.currentB = False
        self.firstTurn = True
        # Since we are using collision detection to do picking, we set it up like
        # any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  # Make a traverser
        self.pq = CollisionHandlerQueue()  # Make a handler
        # Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        # Attach that node to the camera since the ray will need to be positioned
        # relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        # Everything to be picked will use bit 1. This way if we were doing other
        # collision we could seperate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  # Make our ray
        # Add it to the collision node
        self.pickerNode.addSolid(self.pickerRay)
        # Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        self.picker.showCollisions(render)
        self.whiteTurn = True
        # Now we create the chess board and its pieces

        # We will attach all of the squares to their own root. This way we can do the
        # collision pass just on the sqaures and save the time of checking the rest
        # of the scene
        self.batonsRoot = render.attachNewNode("batonsRoot")
        self.batons = [None for i in range(9)]
        self.torus = [[None for j in range(3)] for i in range(9)]
        self.org = [[[None for j in range(3)] for i in range(3)] for i in range(3)]
        for i in range(9):
            # Load, parent, color, and position the model (a single square
            # polygon)
            self.batons[i] = loader.loadModel("bois.egg")
            self.batons[i].reparentTo(self.batonsRoot)
            self.batons[i].setPos(circPos(i,0))
            self.batons[i].setColor(0.75,0.5,0)
            self.batons[i].setScale(0.75,0.75,0.5)
            # Set the model itself to be collideable with the ray. If this model was
            # any more complex than a single polygon, you should set up a collision
            # sphere around it instead. But for single polygons this works
            # fine.
            self.batons[i].find("**/Cylinder").node().setIntoCollideMask(
                BitMask32.bit(1))
            # Set a tag on the square's node so we can look up what square this is
            # later during the collision pass
            self.batons[i].find("**/Cylinder").setTag('baton', str(i))

            # We will use this variable as a pointer to whatever piece is currently
            # in this square
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        self.accept("mouse1", self.click)
        self.accept("w", self.bestPossibleMove)
    def setupLights(self):  # This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 45, -45))
        directionalLight.setColor((0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
    def mouseTask(self, task):
        # This task deals with the highlighting and dragging based on the mouse

        # Check to see if we can access the mouse. We need it to do anything
        # else
        if self.mouseWatcherNode.hasMouse():
            # get the mouse position
            mpos = self.mouseWatcherNode.getMouse()

            # Set the position of the ray based on the mouse position
            self.pickerRay.setFromLens(self.camNode, mpos.getX(), mpos.getY())

            if self.currentB is not False:
                self.batons[self.currentB].setColor(0.75,0.5,0)
                self.currentB = False

            # Do the actual collision pass (Do it only on the squares for
            # efficiency purposes)
            self.picker.traverse(self.batonsRoot)
            if self.pq.getNumEntries() > 0:
                # if we have hit something, sort the hits so that the closest
                # is first, and highlight that node
                self.pq.sortEntries()
                self.currentB = int(self.pq.getEntry(0).getIntoNode().getTag('baton'))
                # Set the highlight on the picked square
                self.batons[self.currentB].setColor(HIGHLIGHT)
                self.currentB

        return Task.cont
    def click(self):
        if self.currentB is not False and not self.ended:
            self.addTorus(self.currentB)
    def testMorp(self, z, y, x):
        print(z,y,x)
        print([j for j in [self.org[w][y][w]for w in range(3)]if j == None])
        print([j for j in [self.org[w][y][w]for w in range(3)]if j == False])
        print(len([j for j in [self.org[w][y][w]for w in range(3)]if j == False]))
        if len([j for j in self.org[z][y] if j == None]) == 0:
            if len([j for j in self.org[z][y] if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in self.org[z][y] if j == True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j  for j in [self.org[z][w][x]for w in range(3)] if j == None]) == 0:
            if len([j  for j in [self.org[z][w][x]for w in range(3)] if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j  for j in [self.org[z][w][x]for w in range(3)] if j == True]) == 0:
                self.ended = True
                return "blackWin"
                
        if len([j  for j in [self.org[w][y][x]for w in range(3)] if j==None]) == 0:
            if len([j  for j in [self.org[w][y][x]for w in range(3)] if j==False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j  for j in [self.org[w][y][x]for w in range(3)] if j==True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j for j in [self.org[z][w][w]for w in range(3)]if j == None]) == 0:
            if len([j for j in [self.org[z][w][w]for w in range(3)]if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in [self.org[z][w][w]for w in range(3)]if j == True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j for j in [self.org[z][w][2 - w]for w in range(3)]if j == None]) == 0:
            if len([j for j in [self.org[z][w][2 - w]for w in range(3)]if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in [self.org[z][w][2 - w]for w in range(3)]if j == True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j for j in [self.org[w][w][x]for w in range(3)]if j == None]) == 0:
            if len([j for j in [self.org[w][w][x]for w in range(3)]if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in [self.org[w][w][x]for w in range(3)]if j == True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j for j in [self.org[w][2-w][x]for w in range(3)]if j == None]) == 0:
            if len([j for j in [self.org[w][2-w][x]for w in range(3)]if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in [self.org[w][2-w][x]for w in range(3)]if j == True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j for j in [self.org[w][y][w]for w in range(3)]if j == None]) == 0:
            print("wyw")
            if len([j for j in [self.org[w][y][w]for w in range(3)]if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in [self.org[w][y][w]for w in range(3)]if j == True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j for j in [self.org[2-w][y][w]for w in range(3)]if j == None]) == 0:
            if len([j for j in [self.org[2-w][y][w]for w in range(3)]if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in [self.org[2-w][y][w]for w in range(3)]if j == True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j for j in [self.org[w][w][w]for w in range(3)]if j == None]) == 0:
            if len([j for j in [self.org[w][w][w]for w in range(3)]if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in [self.org[w][w][w]for w in range(3)]if j == True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j for j in [self.org[2-w][w][w]for w in range(3)]if j == None]) == 0:
            if len([j for j in [self.org[2-w][w][w]for w in range(3)]if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in [self.org[2-w][w][w]for w in range(3)]if j == True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j for j in [self.org[w][w][2-w]for w in range(3)]if j == None]) == 0:
            if len([j for j in [self.org[w][w][2-w]for w in range(3)]if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in [self.org[w][w][2-w]for w in range(3)]if j == True]) == 0:
                self.ended = True
                return "blackWin"
        if len([j for j in [self.org[2-w][w][2-w]for w in range(3)]if j == None]) == 0:
            if len([j for j in [self.org[2-w][w][2-w]for w in range(3)]if j == False]) == 0:
                self.ended = True
                return "whiteWin"
            elif len([j for j in [self.org[2-w][w][2-w]for w in range(3)]if j == True]) == 0:
                self.ended = True
                return "blackWin"
        
            
        return "launched"
    def addTorus(self, i):
        minim = False
        for j,x in enumerate(self.torus[i]):
            if x is None:
                minim = j
                break
        if minim is not False:
            print(minim)
            print(self.whiteTurn)
            print()
            if (self.whiteTurn and not self.firstTurn) or  (self.firstTurn and not (minim == 0 and i//3 == 1 and i%3 == 1)):
                self.torus[i][minim] = loader.loadModel("torus.egg")
                self.torus[i][minim].reparentTo(self.render)
                self.torus[i][minim].setPos(circPos(i,j-1))
                self.torus[i][minim].setColor(WHITE)
                self.torus[i][minim].setScale(0.75,0.75,1.5)
                self.org[minim][i//3][i%3] = self.whiteTurn
                self.whiteTurn = not self.whiteTurn
                if self.firstTurn:
                    self.firstTurn = False
            elif not self.firstTurn:
                self.torus[i][minim] = loader.loadModel("torus.egg")
                self.torus[i][minim].reparentTo(self.render)
                self.torus[i][minim].setPos(circPos(i,j-1))
                self.torus[i][minim].setColor(BLACK)
                self.torus[i][minim].setScale(0.75,0.75,1.5)
                self.org[minim][i//3][i%3] = self.whiteTurn
                self.whiteTurn = not self.whiteTurn
            
            print(self.testMorp(minim, i//3, i%3))
    def possibleMoves(self, state, first):
        possibilities = []
        for r in range(9):
            if (((r is not 4) and first) or (not first)) and state[2][r//3][r%3] == None:
                possibilities.append(r)
        return possibilities
    def bestPossibleMove(self):
        temp = state
        for p in possibleMoves(self, state, first):
            p = 0
    def valeurBranche(self, state, first, Wturn, n):
        vblancs = 0
        vnoirs = 0
        pos = [None for p in possibleMoves(self, state, first) ]
        depth = pos
        for i,p in enumerate(possibleMoves(self, state, first)):
            tempEtat = addTorustemp(p, WTurn, state)
            temp = testMorptemp(tempEtat)
            if temp == 1 and Wturn:
                pos[i] = 1
                depth[i] = n + 1
            elif temp ==0 and Wturn:
                if first:
                    temp2 = valeurBranche(self, temp,not first, not Wturn,n+1)
                    if not (temp2[0] == 0):
                        pos[i] = -temp2[0]
                        depth[i] = temp2[1]
                    else:
                        pos[i] = 0
                        depth[i] = temp2[1]
                else:
                    temp2 = valeurBranche(self, temp, first, not Wturn,n+1)
                    if not (temp2[0] == 0):
                        pos[i] = -temp2[0]
                        depth[i] = temp2[1]
                    else :
                        pos[i] = 0
                        depth[i] = temp2[1]
            elif temp == 2 and (not Wturn):
                pos[i] = 1
            elif temp ==0 and (not Wturn):
                if first:
                    temp2 = valeurBranche(self, temp,not first, not Wturn,n+1)
                    if not (temp2[0] == 0):
                        pos[i] = -temp2[0]
                        depth[i] = temp2[1]
                    else:
                        pos[i] = 0
                        depth[i] = temp2[1]
                else:
                    temp2 = valeurBranche(self, temp, first, not Wturn,n+1)
                    if not (temp2[0] == 0):
                        pos[i] = -temp2[0]
                        depth[i] = temp2[1]
                    else :
                        pos[i] = 0
                        depth[i] = temp2[1]
            else:
                print("tu sais pas coder guillaume")
        if pos == []:
            return (0, n)
        else:
            vic = []
            zero = []
            for i,j in enumerate(pos):
                if j == 1:
                    vic.append(i)
                elif j == 0:
                    zero.append(i)
            if vic is not []:
                return 1, n
            elif zero is not []:
                dmax = 0
                for i in zero:
                    if depth[i] > dmax:
                        dmax = depth[i]
                return 0, dmax
            else:
                return -1, n
                
            
            
                
    def addTorustemp(self, i, whiteTurn, state):
        minim = False
        temp = state
        for j,x in enumerate([state[w][i//3][i%3] for w in range(3)]):
            if x is None:
                minim = j
                break
        if minim is not False:
            print(minim)
            print(whiteTurn)
            temp[minim][i//3][i%3] = whiteTurn
            return temp
    def testMorptemp(self, torg):
        for m in range(27):
            z = m//9
            y = m//3
            x = m%3
            if len([j for j in torg[z][y] if j == None]) == 0:
                if len([j for j in torg[z][y] if j == False]) == 0:
                    return 1
                elif len([j for j in torg[z][y] if j == True]) == 0:
                    return 2
            if len([j  for j in [torg[z][w][x]for w in range(3)] if j == None]) == 0:
                if len([j  for j in [torg[z][w][x]for w in range(3)] if j == False]) == 0:
                    return 1
                elif len([j  for j in [torg[z][w][x]for w in range(3)] if j == True]) == 0:
                    return 2
            if len([j  for j in [torg[w][y][x]for w in range(3)] if j==None]) == 0:
                if len([j  for j in [torg[w][y][x]for w in range(3)] if j==False]) == 0:
                    return 1
                elif len([j  for j in [torg[w][y][x]for w in range(3)] if j==True]) == 0:
                    return 2
            if len([j for j in [torg[z][w][w]for w in range(3)]if j == None]) == 0:
                if len([j for j in [torg[z][w][w]for w in range(3)]if j == False]) == 0:
                    return 1
                elif len([j for j in [torg[z][w][w]for w in range(3)]if j == True]) == 0:
                    return 2
            if len([j for j in [torg[z][w][2 - w]for w in range(3)]if j == None]) == 0:
                if len([j for j in [torg[z][w][2 - w]for w in range(3)]if j == False]) == 0:
                    return 1
                elif len([j for j in [torg[z][w][2 - w]for w in range(3)]if j == True]) == 0:
                    return 2
            if len([j for j in [torg[w][w][x]for w in range(3)]if j == None]) == 0:
                if len([j for j in [torg[w][w][x]for w in range(3)]if j == False]) == 0:
                    return 1
                elif len([j for j in [torg[w][w][x]for w in range(3)]if j == True]) == 0:
                    return 2
            if len([j for j in [torg[w][2-w][x]for w in range(3)]if j == None]) == 0:
                if len([j for j in [torg[w][2-w][x]for w in range(3)]if j == False]) == 0:
                    return 1
                elif len([j for j in [torg[w][2-w][x]for w in range(3)]if j == True]) == 0:
                    return 2
            if len([j for j in [torg[w][y][w]for w in range(3)]if j == None]) == 0:
                if len([j for j in [torg[w][y][w]for w in range(3)]if j == False]) == 0:
                    return 1
                elif len([j for j in [torg[w][y][w]for w in range(3)]if j == True]) == 0:
                    return 2
            if len([j for j in [torg[2-w][y][w]for w in range(3)]if j == None]) == 0:
                if len([j for j in [torg[2-w][y][w]for w in range(3)]if j == False]) == 0:
                    return 1
                elif len([j for j in [torg[2-w][y][w]for w in range(3)]if j == True]) == 0:
                    return 2
            if len([j for j in [torg[w][w][w]for w in range(3)]if j == None]) == 0:
                if len([j for j in [torg[w][w][w]for w in range(3)]if j == False]) == 0:
                    return 1
                elif len([j for j in [torg[w][w][w]for w in range(3)]if j == True]) == 0:
                    return 2
            if len([j for j in [torg[2-w][w][w]for w in range(3)]if j == None]) == 0:
                if len([j for j in [torg[2-w][w][w]for w in range(3)]if j == False]) == 0:
                    return 1
                elif len([j for j in [torg[2-w][w][w]for w in range(3)]if j == True]) == 0:
                    return 2
            if len([j for j in [torg[w][w][2-w]for w in range(3)]if j == None]) == 0:
                if len([j for j in [torg[w][w][2-w]for w in range(3)]if j == False]) == 0:
                    return 1
                elif len([j for j in [torg[w][w][2-w]for w in range(3)]if j == True]) == 0:
                    return 2
            if len([j for j in [torg[2-w][w][2-w]for w in range(3)]if j == None]) == 0:
                if len([j for j in [torg[2-w][w][2-w]for w in range(3)]if j == False]) == 0:
                    return 1
                elif len([j for j in [torg[2-w][w][2-w]for w in range(3)]if j == True]) == 0:
                    return 2
        
            return 0
Beispiel #19
0
class Game(DirectObject):
    def __init__(self, model):
        self.model = model

        base.setBackgroundColor(0.1, 0.1, 0.8, 1)
        base.setFrameRateMeter(True)

        base.cam.setPos(0, -20, 4)
        base.cam.lookAt(0, 0, 0)

        w = WindowProperties()
        w.setFullscreen(False)
        w.setOrigin(5, 20)
        w.setSize(865, 800)
        base.win.requestProperties(w)

        # Light
        alight = AmbientLight('ambientLight')
        alight.setColor(Vec4(0.5, 0.5, 0.5, 1))
        alightNP = render.attachNewNode(alight)

        dlight = DirectionalLight('directionalLight')
        dlight.setDirection(Vec3(1, 1, -1))
        dlight.setColor(Vec4(0.7, 0.7, 0.7, 1))
        dlightNP = render.attachNewNode(dlight)

        render.clearLight()
        render.setLight(alightNP)
        render.setLight(dlightNP)

        # Input
        self.accept('escape', self.doExit)
        self.accept('r', self.doReset)
        self.accept('f1', self.toggleWireframe)
        self.accept('f2', self.toggleTexture)
        self.accept('f3', self.toggleDebug)
        self.accept('f5', self.doScreenshot)

        inputState.watchWithModifiers('forward', 'w')
        inputState.watchWithModifiers('left', 'a')
        inputState.watchWithModifiers('reverse', 's')
        inputState.watchWithModifiers('right', 'd')
        inputState.watchWithModifiers('turnLeft', 'q')
        inputState.watchWithModifiers('turnRight', 'e')

        # Task
        taskMgr.add(self.update, 'updateWorld')

        # Physics
        self.setup()

    # _____HANDLER_____

    def doExit(self):
        self.cleanup()
        sys.exit(1)

    def endLoop(self):
        self.penalized_distance = self.distance * (numpy.exp(
            -self.time_max_steering / self.total_time))
        pickle.dump(self.penalized_distance, open('distance.p', 'wb'))
        sys.exit()
        #quit()
        #print("Distance was: ",self.distance)
        #os.execv(sys.executable,['python']+[__file__])
        #taskMgr.running = False

    def doReset(self):
        self.cleanup()
        self.setup()

    def toggleWireframe(self):
        base.toggleWireframe()

    def toggleTexture(self):
        base.toggleTexture()

    def toggleDebug(self):
        if self.debugNP.isHidden():
            self.debugNP.show()
        else:
            self.debugNP.hide()

    def doScreenshot(self):
        base.screenshot('Bullet')

    # ____TASK___

    def calculate_moves(self):
        self.y = self.model.predict(self.x)
        #print(self.y)
        self.moves = self.y > 0  #+ self.model_offset # 0.5
        #self.moves[0] = True # FIXME test

    def processInput(self, dt):
        engineForce = 0.0
        brakeForce = 0.0
        if self.moves[
                0]:  #inputState.isSet('forward'): FIXME maybe engine and brake can be linked to self.y, rectified, continuous
            engineForce = 2000.0  # 1000.
            brakeForce = 0.0

        if not self.moves[0]:  #inputState.isSet('reverse'):
            engineForce = 200.0  #0.0
            brakeForce = 100.0

        self.steering = self.y[1]
        if self.moves[1]:
            self.steering = min(self.steering, self.steeringClamp)
        if not self.moves[1]:
            self.steering = max(self.steering, -self.steeringClamp)
        """ # FIXME option may be better if self.steering is fed into self.y[3] for 4th element
    if not self.moves[2]: # enabled steering lock

        if self.moves[1]:#inputState.isSet('turnLeft'):
          self.steering += dt * self.steeringIncrement
          self.steering = min(self.steering, self.steeringClamp)

        if not self.moves[1]:#inputState.isSet('turnRight'):
          self.steering -= dt * self.steeringIncrement
          self.steering = max(self.steering, -self.steeringClamp)
    """ """
    if inputState.isSet('forward'):
      engineForce = 1000.0
      brakeForce = 0.0

    if inputState.isSet('reverse'):
      engineForce = 0.0
      brakeForce = 100.0

    if inputState.isSet('turnLeft'):
      self.steering += dt * self.steeringIncrement
      self.steering = min(self.steering, self.steeringClamp)

    if inputState.isSet('turnRight'):
      self.steering -= dt * self.steeringIncrement
      self.steering = max(self.steering, -self.steeringClamp)
    """
        # Apply steering to front wheels
        self.vehicle.setSteeringValue(self.steering, 0)
        self.vehicle.setSteeringValue(self.steering, 1)

        # Apply engine and brake to rear wheels
        self.vehicle.applyEngineForce(engineForce, 2)
        self.vehicle.applyEngineForce(engineForce, 3)
        self.vehicle.setBrake(brakeForce, 2)
        self.vehicle.setBrake(brakeForce, 3)

    def check_collisions(self):
        """pFrom = render.getRelativePoint(self.yugoNP,Point3(0,0,0))#Point3(0,0,0)
      pFrom -= Point3(0,0,pFrom[2])
      pRel = render.getRelativePoint(base.cam,self.yugoNP.getPos())  # FIXME THIS IS IT!! get rid of z component
      pRel -= Point3(0,0,pRel[2])
      p45 = Point3(pRel[0] - pRel[1], pRel[1] + pRel[0],0)
      pn45 = Point3(pRel[0] + pRel[1], pRel[1] - pRel[0],0)
      #print(render.getRelativePoint(self.yugoNP,Point3(0,0,0)))
      #print(dir(self.yugoNP))
      pTo = [pFrom + pn45, pFrom + pRel, pFrom + p45]#[pFrom + Vec3(-10,10,0)*999,pFrom + Vec3(0,10,0)*999,pFrom + Vec3(10,10,0)*999]# FIXME should be relative to front of car, getting cloe! #self.yugoNP.getPosDelta()*99999]#[Point3(-10,10,0) * 99999,Point3(0,10,0) * 99999,Point3(10,10,0) * 99999]
      #self.ray = CollisionRay(0,0,0,100,0,0)
      result = [self.world.rayTestClosest(pFrom,pt) for pt in pTo]
      #print(dir(self.yugoNP))
      #print(result.getHitPos())
      return tuple([res.getHitPos().length() for res in result])
      """#queue = CollisionHandlerQueue()
        #traverser.addCollider(fromObject, queue)
        #traverser.traverse(render)
        #queue.sortEntries()
        #for entry in queue.getEntries():
        #print(entry)
        #print(result.getHitPos())
        #if result.getNode() != None:
        #print(self.yugoNP.getPos(result.getNode()))
        #print(self.cTrav)
        self.cTrav.traverse(render)
        entries = list(self.colHandler.getEntries())
        #print(entries)
        entries.sort(key=lambda y: y.getSurfacePoint(render).getY())
        #for entry in entries:      print(entry.getFromNodePath().getName())
        if entries:  # and len(result) > 1:
            #print(entries)
            for r in entries:

                #print(r.getIntoNodePath().getName())
                if r.getIntoNodePath().getName(
                ) == 'Plane' and r.getFromNodePath().getName() == 'yugo_box':
                    self.endLoop()
                if r.getIntoNodePath().getName(
                ) == 'Plane' and r.getFromNodePath().getName() in [
                        'ray%d' % i for i in range(self.n_rays)
                ]:  #Box
                    self.ray_col_vec_dict[
                        r.getFromNodePath().getName()].append(
                            numpy.linalg.norm(
                                list(r.getSurfacePoint(
                                    r.getFromNodePath()))[:-1]))
        self.ray_col_vec_dict = {
            k: (min(self.ray_col_vec_dict[k])
                if len(self.ray_col_vec_dict[k]) >= 1 else 10000)
            for k in self.ray_col_vec_dict
        }
        self.x = numpy.array(list(self.ray_col_vec_dict.values()))
        #print(self.x)
        result = self.world.contactTest(self.yugoNP.node())
        #print(result.getNumContacts())
        #print(dir(self.yugoNP))
        #return entries

    def check_prevPos(self):
        if len(self.prevPos) > 80:
            #print(self.prevPos)
            #print(numpy.linalg.norm(self.prevPos[-1] - self.prevPos[0]))
            if numpy.linalg.norm(self.prevPos[-1] - self.prevPos[0]) < 4.5:
                #print("ERROR")
                self.endLoop()

            del self.prevPos[0:len(self.prevPos) - 80]

    def update(self, task):

        self.prevPos.append(self.yugoNP.getPos(render))
        dx = numpy.linalg.norm(self.prevPos[-1] - self.prevPos[-2])
        self.distance += dx
        self.distance_text.setText('Distance=%.3f' % (self.distance))
        #print(len(self.prevPos))

        dt = globalClock.getDt()
        self.total_time += dt
        if abs(self.steering) == abs(self.steeringClamp):
            self.time_max_steering += dt
        self.time_text.setText('TotalTime=%.3f' % (self.total_time))
        #self.time_maxsteer_text.setText('TotalTimeMaxSteer=%f'%(self.time_max_steering))
        #self.penalized_distance = self.distance*(1.-numpy.exp(-self.time_max_steering/self.total_time))
        if self.distance > 10000:
            self.endLoop()
        self.check_prevPos()
        self.speed = dx / dt
        self.speed_text.setText('Speed=%.3f' % (self.speed))

        self.check_collisions()
        self.calculate_moves()
        self.model.plot_NN()
        #self.nn_image.setImage('neural_net_vis.png')
        self.ray_col_vec_dict = {k: [] for k in self.ray_col_vec_dict}
        self.processInput(dt)
        self.world.doPhysics(dt, 10, 0.008)
        # FIXME KEEP TRACK OF TOTAL DEGREES TURNED AND PENALIZE
        #self.doReset()

        #print(dir(result[1]))
        #print(numpy.linalg.norm(list(result[1].getSurfacePoint(result[1].getFromNodePath()))[:-1]))
        #base.camera.setPos(0,-40,10)
        #print self.vehicle.getWheel(0).getRaycastInfo().isInContact()
        #print self.vehicle.getWheel(0).getRaycastInfo().getContactPointWs()

        #print self.vehicle.getChassis().isKinematic()

        return task.cont

    def cleanup(self):
        self.world = None
        self.worldNP.removeNode()

    def setup(self):
        self.worldNP = render.attachNewNode('World')
        self.distance_text = OnscreenText(
            text='Distance=0', pos=(0.75, 0.85), scale=0.08,
            mayChange=1)  #Directxxxxxx(distance='Distance=%d'%(0))
        self.speed_text = OnscreenText(
            text='Speed=0', pos=(0.75, 0.78), scale=0.08,
            mayChange=1)  #Directxxxxxx(distance='Distance=%d'%(0))
        self.time_text = OnscreenText(
            text='TotalTime=0', pos=(0.75, 0.71), scale=0.08,
            mayChange=1)  #Directxxxxxx(distance='Distance=%d'%(0))
        #self.time_maxsteer_text = OnscreenText(text='TotalTimeMaxSteer=0', pos = (0.85,0.70), scale = 0.05, mayChange=1)#Directxxxxxx(distance='Distance=%d'%(0))
        #self.nn_image = OnscreenImage(image='blank.png', pos= (0.85,0,0.15), scale=0.45) # http://dev-wiki.gestureworks.com/index.php/GestureWorksCore:Python_%26_Panda3D:_Getting_Started_II_(Hello_Multitouch)#8._Create_a_method_to_draw_touchpoint_data
        self.total_time = 0.
        self.time_max_steering = 0.
        # World
        self.debugNP = self.worldNP.attachNewNode(BulletDebugNode('Debug'))
        self.debugNP.show()

        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81))
        self.world.setDebugNode(self.debugNP.node())

        #terrain = GeoMipTerrain("mySimpleTerrain")
        #terrain.setHeightfield("./models/heightfield_2.png")
        #terrain.getRoot().reparentTo(self.worldNP)#render)
        #terrain.generate()

        # Plane
        shape = BulletPlaneShape(Vec3(0, 0, 1), 0)

        np = self.worldNP.attachNewNode(BulletRigidBodyNode('Ground'))
        np.node().addShape(shape)
        np.setPos(0, 0, -1)
        np.setCollideMask(BitMask32.allOn())

        self.world.attachRigidBody(np.node())

        #np = self.worldNP.attachNewNode(BulletRigidBodyNode('Track'))
        #np.node().setMass(5000.0)
        #np.setPos(3, 0, 10)
        #np.setCollideMask(BitMask32.allOn())#(0x0f))
        #self.track = BulletVehicle(self.world, np.node())
        #self.track.setCoordinateSystem(ZUp)
        self.track_np = loader.loadModel(
            'models/race_track_2.egg'
        )  # https://discourse.panda3d.org/t/panda3d-and-bullet-physics/15724/10
        self.track_np.setPos(-72, -7, -3.5)
        self.track_np.setScale(10)
        self.track_np.reparentTo(render)

        self.track_np.setCollideMask(BitMask32.allOn())  #(0))#.allOn())
        self.world.attachRigidBody(np.node())
        self.track_np = np
        #self.track_np.show()

        # Chassis
        shape = BulletBoxShape(Vec3(0.6, 1.4, 0.5))
        ts = TransformState.makePos(Point3(0, 0, 0.5))

        np = self.worldNP.attachNewNode(BulletRigidBodyNode('Vehicle'))
        np.node().addShape(shape, ts)
        np.setPos(0, 0, 0.05)
        np.node().setMass(800.0)
        np.node().setDeactivationEnabled(False)

        self.world.attachRigidBody(np.node())

        #np.node().setCcdSweptSphereRadius(1.0)
        #np.node().setCcdMotionThreshold(1e-7)
        self.cTrav = CollisionTraverser()
        # Vehicle
        self.vehicle = BulletVehicle(self.world, np.node())
        self.vehicle.setCoordinateSystem(ZUp)
        self.yugoNP = loader.loadModel('models/yugo/yugo.egg')
        self.yugoNP.setCollideMask(BitMask32(0))  #.allOn())
        self.yugoNP.reparentTo(np)
        self.colHandler = CollisionHandlerQueue()

        # travel distance
        self.distance = 0.
        """self.sphere = CollisionSphere(0,0,0,2)
    self.sphere_col = CollisionNode('yugo')
    self.sphere_col.addSolid(self.sphere)
    self.sphere_col.setFromCollideMask(BitMask32.allOn())
    self.sphere_col_np = self.yugoNP.attachNewNode(self.sphere_col)
    self.cTrav.addCollider(self.sphere_col_np,self.colHandler)
    self.sphere_col_np.show()"""

        self.yugo_col = CollisionNode('yugo_box')
        self.yugo_col.addSolid(CollisionBox(Point3(0, 0, 0.7), 0.9, 1.6, 0.05))
        self.yugo_col.setFromCollideMask(BitMask32(1))
        self.box_col_np = self.yugoNP.attachNewNode(self.yugo_col)
        self.cTrav.addCollider(self.box_col_np, self.colHandler)
        self.box_col_np.show()

        self.ray_col_np = {}
        self.ray_col_vec_dict = {}
        self.n_rays = self.model.shape[0]
        for i, ray_dir in enumerate(
                numpy.linspace(-numpy.pi / 4, numpy.pi / 4,
                               self.n_rays)):  # populate collision rays
            #print(ray_dir)
            self.ray = CollisionRay()
            y_dir, x_dir = numpy.cos(ray_dir), numpy.sin(ray_dir)
            self.ray.setOrigin(1.3 * x_dir, 1.3 * y_dir, 0.5)
            self.ray.setDirection(x_dir, y_dir, 0)
            self.ray_col = CollisionNode('ray%d' % (i))
            self.ray_col.addSolid(self.ray)
            self.ray_col.setFromCollideMask(
                BitMask32.allOn())  #(0x0f))#CollideMask.bit(0)
            #self.ray_col.setIntoCollideMask(CollideMask.allOff())
            self.ray_col_np['ray%d' % (i)] = self.yugoNP.attachNewNode(
                self.ray_col)
            self.cTrav.addCollider(self.ray_col_np['ray%d' % (i)],
                                   self.colHandler)
            self.ray_col_np['ray%d' % (i)].show()
            self.ray_col_vec_dict['ray%d' % (i)] = []
        self.world.attachVehicle(self.vehicle)
        self.cTrav.showCollisions(render)

        # FIXME
        base.camera.reparentTo(self.yugoNP)

        # Right front wheel
        np = loader.loadModel('models/yugo/yugotireR.egg')
        np.reparentTo(self.worldNP)
        self.addWheel(Point3(0.70, 1.05, 0.3), True, np)

        # Left front wheel
        np = loader.loadModel('models/yugo/yugotireL.egg')
        np.reparentTo(self.worldNP)
        self.addWheel(Point3(-0.70, 1.05, 0.3), True, np)

        # Right rear wheel
        np = loader.loadModel('models/yugo/yugotireR.egg')
        np.reparentTo(self.worldNP)
        self.addWheel(Point3(0.70, -1.05, 0.3), False, np)

        # Left rear wheel
        np = loader.loadModel('models/yugo/yugotireL.egg')
        np.reparentTo(self.worldNP)
        self.addWheel(Point3(-0.70, -1.05, 0.3), False, np)

        # Steering info
        self.steering = 0.0  # degree
        self.steeringClamp = 38.0  #45.0      # degree
        self.steeringIncrement = 105.0  #120.0 # degree per second

        # add previous positions
        self.prevPos = []
        self.prevPos.append(self.yugoNP.getPos(render))

        self.model_offset = 0.5 if self.model.activation == 'relu' else 0.
        # Box
        """
    for i,j in [(0,8),(-3,5),(6,-5),(8,3),(-4,-4),(0,0)]:
        shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5))
        # https://discourse.panda3d.org/t/wall-collision-help/23606
        np = self.worldNP.attachNewNode(BulletRigidBodyNode('Box'))
        np.node().setMass(1.0)
        np.node().addShape(shape)
        np.setPos(i, j, 2)
        np.setCollideMask(BitMask32.allOn())#(0x0f))

        self.world.attachRigidBody(np.node())
        self.boxNP = np
        #self.colHandler2 = CollisionHandlerQueue()


        visualNP = loader.loadModel('models/box.egg')
        visualNP.reparentTo(self.boxNP)
    #self.cTrav.addCollider(self.boxNP,self.colHandler)
    """
        """
    aNode = CollisionNode("TheRay")

    self.ray = CollisionRay()
    self.ray.setOrigin( self.yugoNP.getPos() )
    self.ray.setDirection( Vec3(0, 10, 0) )
    #self.ray.show()


    aNodePath = self.yugoNP.attachNewNode( CollisionNode("TheRay") )
    aNodePath.node().addSolid(self.ray)
    aNodePath.show()
    """
        #aNode.addSolid(self.ray)
        #self.ray = CollisionRay(0,0,0,10,0,0)
        #self.ray.reparentTo(self.yugoNP)
        #self.rayColl = CollisionNode('PlayerRay')
        #self.rayColl.addSolid(self.ray)

        #self.playerRayNode = self.yugoNP.attachNewNode( self.rayColl )
        #self.playerRayNode.show()

        #base.myTraverser.addCollider (self.playerRayNode, base.floor)
        #base.floor.addCollider( self.playerRayNode, self.yugoNP)
        """
    MyEvent=CollisionHandlerFloor()
    MyEvent.setReach(100)
    MyEvent.setOffset(15.0)

    aNode = CollisionNode("TheRay")
    ray = CollisionRay()
    ray.setOrigin( self.boxNP.getPos() )
    ray.setDirection( Vec3(10, 0, 0) )

    aNode.addSolid(ray)
    aNodePath = MyModel.attachNewNode( aNode )

    Collision = ( aNode, "TheRay" )
    Collision[0].setFromCollideMask( BitMask32.bit( 1 ) )
    """

    def addWheel(self, pos, front, np):
        wheel = self.vehicle.createWheel()

        wheel.setNode(np.node())
        wheel.setChassisConnectionPointCs(pos)
        wheel.setFrontWheel(front)

        wheel.setWheelDirectionCs(Vec3(0, 0, -1))
        wheel.setWheelAxleCs(Vec3(1, 0, 0))
        wheel.setWheelRadius(0.25)
        wheel.setMaxSuspensionTravelCm(40.0)

        wheel.setSuspensionStiffness(40.0)
        wheel.setWheelsDampingRelaxation(2.3)
        wheel.setWheelsDampingCompression(4.4)
        wheel.setFrictionSlip(100.0)
        wheel.setRollInfluence(0.1)
Beispiel #20
0
class RoamingRalphDemo(ShowBase):
    def __init__(self):
        # Set up the window, camera, etc.
        ShowBase.__init__(self)

        # Set the background color to black
        self.win.setClearColor((0, 0, 0, 1))

        # This is used to store which keys are currently pressed.
        self.keyMap = {
            "left": 0, "right": 0, "forward": 0, "back": 0, "cam-left": 0, "cam-right": 0}

        # Post the instructions
        self.title = addTitle(
            "Adventurer: 3rd Person File Manager (in progress)")
        self.inst1 = addInstructions(0.06, "[ESC]: Quit")
        self.inst2 = addInstructions(0.12, "[Arrows]: Angle Camera")
        self.inst3 = addInstructions(0.18, "[WASD]: Move")
        # Set up the environment
        #
        # This environment model contains collision meshes.  If you look
        # in the egg file, you will see the following:
        #
        #    <Collide> { Polyset keep descend }
        #
        # This tag causes the following mesh to be converted to a collision
        # mesh -- a mesh which is optimized for collision, not rendering.
        # It also keeps the original mesh, so there are now two copies ---
        # one optimized for rendering, one for collisions.

        #self.environ = loader.loadModel("models/world")
        #self.environ.reparentTo(render)

        #loader.unload_model
        startPos = Point3(0,0,0)#self.environ.find("**/start_point").getPos()
        
        # Setup controls
        self.keys = {}
        for key in ['arrow_left', 'arrow_right', 'arrow_up', 'arrow_down',
                    'a', 'd', 'w', 's']:
            self.keys[key] = 0
            self.accept(key, self.push_key, [key, 1])
            self.accept('shift-%s' % key, self.push_key, [key, 1])
            self.accept('%s-up' % key, self.push_key, [key, 0])
        #self.accept('f', self.toggleWireframe)
        #self.accept('x', self.toggle_xray_mode)
        #self.accept('b', self.toggle_model_bounds)
        self.accept('escape', __import__('sys').exit, [0])
        self.disableMouse()

        taskMgr.add(self.update, "moveTask")

        #insert test features
        #addCube(models, render, startPos + (0, 1, 0.5), 0.5)
        #addWall(models, render, startPos + (0, 1, 0.5), 30, 0.2)
        addDir(render, startPos + (0, 1, 0.5))
        
        # Game state variables
        self.isMoving = False

        # Set up the camera
        self.disableMouse()
        lens = PerspectiveLens()
        lens.setFov(60)
        lens.setNear(0.01)
        lens.setFar(1000.0)
        self.cam.node().setLens(lens)
        self.camera.setPos(startPos)
        self.heading = -95.0
        self.pitch = 0.0

        # Add collision to keept he camera in the room
        cn = CollisionNode('camera')
        cn.addSolid(CollisionSphere(0, 0, 0, 0.5))
        camColl = self.camera.attachNewNode(cn)
        self.cTrav = CollisionTraverser('camera traverser')
        self.camGroundHandler = CollisionHandlerPusher()
        self.camGroundHandler.addCollider(camColl, NodePath(self.camera))
        self.cTrav.addCollider(camColl, self.camGroundHandler)

        # Makes colliding objects show up 
        self.cTrav.showCollisions(render)
        
        # Create some lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.3, .3, .3, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection((-5, -5, -5))
        directionalLight.setColor((1, 1, 1, 1))
        directionalLight.setSpecularColor((1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambientLight))
        render.setLight(render.attachNewNode(directionalLight))


    def push_key(self, key, value):
        """Stores a value associated with a key."""
        self.keys[key] = value

    def update(self, task):
        """Updates the camera based on the keyboard input. Once this is
        done, then the CellManager's update function is called."""
        posStart = self.camera.getPos()
        delta = globalClock.getDt()
        move_x = delta * SPEED_MOVE * -self.keys['a'] + delta * SPEED_MOVE * self.keys['d']
        move_z = delta * SPEED_MOVE * self.keys['s'] + delta * SPEED_MOVE * -self.keys['w']
        self.camera.setHpr(self.heading, 0, 0)
        self.camera.setPos(self.camera, move_x, -move_z, 0)
        self.heading += (delta * 90 * self.keys['arrow_left'] +
                         delta * 90 * -self.keys['arrow_right'])
        self.pitch += (delta * 90 * self.keys['arrow_up'] +
                       delta * 90 * -self.keys['arrow_down'])
        self.camera.setHpr(self.heading, self.pitch, 0)

        # for entry in self.camGroundHandler.getEntries():
        #     if entry.getFromNode().getName() == "camera":
        #         print "Collision", posStart, self.camera.getPos()
        #         self.camera.setPos(posStart)
        #         break
        
        return task.cont
Beispiel #21
0
class Tunnel(ShowBase):
  def __init__(self):
    ShowBase.__init__(self)

    base.disableMouse()
    self.camera.setPosHpr(0, 0, 10, 0, -90, 0)
    self.setBackgroundColor(0, 0, 0)
    
    self.fog = Fog('distanceFog')
    self.fog.setColor(0, 0, 0)
    self.fog.setExpDensity(.08)
    render.setFog(self.fog)

    self.keyMap = {'left' : 0, 'right' : 0, 'up' : 0, 'down' : 0}
    #
    self.accept('escape', sys.exit)
    self.accept('arrow_left', self.setKey, ['left', True])
    self.accept('arrow_right', self.setKey, ['right', True])
    self.accept('arrow_up', self.setKey, ['up', True])
    self.accept('arrow_down', self.setKey, ['down', True])
    self.accept('arrow_left-up', self.setKey, ['left', False])
    self.accept('arrow_right-up', self.setKey, ['right', False])
    self.accept('arrow_up-up', self.setKey, ['up', False])
    self.accept('arrow_down-up', self.setKey, ['down', False])

    self.queue = CollisionHandlerQueue()
    self.trav = CollisionTraverser('traverser')
    base.cTrav = self.trav
    #
    self.makeTunnel()
    self.makeSphere()
    self.continueTunnel()
    #
    self.crystals = []
    for _ in xrange(CRYSTALS_CNT):
      self.makeRandomCrystal(randint(1, TUNNEL_CNT - 1))
    self.collisionCnt = 0
    #
    taskMgr.add(self.moveSphere, 'moveSphere')
    taskMgr.add(self.handleCollisions, 'handleCollisions')
    #
    if DEBUG:
      self.trav.showCollisions(render)
      render.find('**/sphere_collision').show()

  def makeTunnel(self):
    self.tunnel = [None] * TUNNEL_CNT
    for x in range(TUNNEL_CNT):
      self.tunnel[x] = loader.loadModel('models/tunnel')
      if x == 0:
        self.tunnel[x].reparentTo(render)
      else:
        self.tunnel[x].reparentTo(self.tunnel[x - 1])
      self.tunnel[x].setPos(0, 0, -TUNNEL_SEGMENT_LENGTH)

  def makeSphere(self):
    self.sphere = loader.loadModel('models/alice-shapes--sphere-highpoly/sphere-highpoly.egg')
    self.sphere.reparentTo(render)
    self.sphere.setScale(0.07)
    self.sphere.setZ(2)
    #
    col_node = self.sphere.attachNewNode(CollisionNode('sphere_collision'))
    col_sphere = CollisionSphere(0, 0, 2, SPHERE_RADIUS)
    col_node.node().addSolid(col_sphere)
    self.trav.addCollider(col_node, self.queue)

  def makeRandomCrystal(self, tun):
    crystal = loader.loadModel('models/bvw-f2004--purplecrystal/purplecrystal.egg')
    crystal.reparentTo(self.tunnel[tun])
    #
    pMin, pMax = LPoint3f(), LPoint3f()
    crystal.calcTightBounds(pMin, pMax)
    col_node = crystal.attachNewNode(CollisionNode('crystal_collision'))
    col_box = CollisionBox(pMin, pMax)
    col_node.node().addSolid(col_box)
    crystal.setScale(0.1)
    if DEBUG:
      col_node.show()

    pos = ['rx', '-rx', 'ry', 'down', 'up']
    rnd = choice(pos)
    Z = randint(0, 10)
    if rnd == 'rx':
      R = randint(45, 90)
      X = uniform(-2, 6)
      crystal.setR(R)
      crystal.setX(X)
    elif rnd == '-rx':
      R = randint(45, 90)
      X = uniform(-2, 8)
      crystal.setR(-R)
      crystal.setX(-X)
    elif rnd == 'ry':
      R = randint(45, 120)
      Y = uniform(2, 6)
      crystal.setR(R)
      crystal.setY(Y)
    elif rnd == '-py':
      R = randint(45, 120)
      Y = uniform(3, 8)
      crystal.setR(-R)
      crystal.setY(-Y)
    elif rnd == 'down':
      Y = uniform(1, 6)
      P = randint(70, 120)
      crystal.setY(-Y)
      crystal.setP(P)
    elif rnd == 'up':
      Y = uniform(-1, 6)
      P = randint(-130, -60)
      crystal.setY(Y)
      crystal.setP(P)
      
    crystal.setZ(Z)
    self.crystals.append(crystal)
    
  def continueTunnel(self):
    self.tunnel = self.tunnel[1:] + self.tunnel[0:1]
    self.tunnel[0].setZ(0)
    self.tunnel[0].reparentTo(render)
    self.tunnel[0].setScale(.155, .155, .305)
    self.tunnel[3].reparentTo(self.tunnel[2])
    self.tunnel[3].setZ(-TUNNEL_SEGMENT_LENGTH)
    self.tunnel[3].setScale(1)

    for child in self.tunnel[3].getChildren():
      if child.getName() == 'purplecrystal.egg':
        self.crystals.remove(child)
        child.removeNode()
        self.makeRandomCrystal(3)

    self.tunnelMove = Sequence \
    (
      LerpFunc \
      (
        self.tunnel[0].setZ,
        duration=TUNNEL_TIME,
        fromData=0,
        toData=TUNNEL_SEGMENT_LENGTH * .305
      ),
      Func(self.continueTunnel)
    )
    self.tunnelMove.start()

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

  def moveSphere(self, task):
    dt = globalClock.getDt()
    addVec = LVector3f(0, 0, 0)
    if self.keyMap['left']:
      addVec[0] -= SPHERE_SPEED * dt
    elif self.keyMap['right']:
      addVec[0] += SPHERE_SPEED * dt
    elif self.keyMap['up']:
      addVec[1] += SPHERE_SPEED * dt
    elif self.keyMap['down']:
      addVec[1] -= SPHERE_SPEED * dt
   
    if ((self.sphere.getPos() + addVec) - LPoint3f(TUNNEL_CENTER)).length() < TUNNEL_RADIUS:
      self.sphere.setPos(self.sphere.getPos() + addVec)

    return task.cont

  def handleCollisions(self, task):
    for entry in self.queue.getEntries():
      node = entry.getFromNodePath()
      if node.getName() == 'sphere_collision':
        self.collisionCnt += 1
        print 'Oops! Collision counter: %d' % self.collisionCnt
    return task.cont
Beispiel #22
0
Datei: main.py Projekt: kpj/vrfs
class MyApp(ShowBase):
    def __init__(self, path):
        ShowBase.__init__(self)
        self.verbose = False

        self.speed = 20
        self.mouse_sensitivity = .1

        self.setFrameRateMeter(True)
        #self.render.setAntialias(AntialiasAttrib.MAuto)

        self.setup_camera()
        self.setup_controls()
        self.setup_collisions()

        self.scene_node_history = []
        self.scene_node = None

        t = threading.Thread(target=self.load_directory, args=(path, ))
        t.start()

    def setup_collisions(self):
        self.coll_traverser = CollisionTraverser(
        )  # does actual work of collision detection
        self.coll_handler = CollisionHandlerQueue(
        )  # records collisions that happened

        self.selector_ray = CollisionRay(
        )  # is a CollisionSolid, which is a basic object of the collision system
        self.selector_ray.setFromLens(self.camNode, 0,
                                      0)  # point straight away from camera

        selector_node = CollisionNode(
            'mouseRay')  # encapsulates a CollisionSolid
        selector_node.addSolid(self.selector_ray)

        selector_nodepath = self.camera.attachNewNode(selector_node)
        self.coll_traverser.addCollider(selector_nodepath, self.coll_handler)

        # debug
        if self.verbose:
            self.coll_traverser.showCollisions(self.render)
            selector_nodepath.show()

    def setup_camera(self):
        self.disableMouse()

        props = WindowProperties()
        props.setCursorHidden(True)
        props.setMouseMode(WindowProperties.M_relative)
        self.win.requestProperties(props)

        self.camera.setPos(2, -20, 3)

        self.taskMgr.add(self.controlCameraTask, 'controlCameraTask')
        # self.oobe()

    def setup_controls(self):
        # keyboard
        self.accept('escape', sys.exit)

        self.accept('w', self.handle_key, ['forward', True])
        self.accept('w-up', self.handle_key, ['forward', False])

        self.accept('s', self.handle_key, ['backward', True])
        self.accept('s-up', self.handle_key, ['backward', False])

        self.accept('a', self.handle_key, ['left', True])
        self.accept('a-up', self.handle_key, ['left', False])

        self.accept('d', self.handle_key, ['right', True])
        self.accept('d-up', self.handle_key, ['right', False])

        self.accept('space', self.handle_key, ['up', True])
        self.accept('space-up', self.handle_key, ['up', False])

        self.accept('shift', self.handle_key, ['down', True])
        self.accept('shift-up', self.handle_key, ['down', False])

        self.accept('b', self.traverse_history)
        self.accept('m', self.change_speed, [10])
        self.accept('n', self.change_speed, [-10])

        self.key_map = {
            'forward': False,
            'backward': False,
            'right': False,
            'left': False,
            'up': False,
            'down': False
        }

        # mouse
        self.accept('mouse1', self.handle_mouse)

    def change_speed(self, delta):
        self.speed += delta
        print(f'New speed: {self.speed}')

    def traverse_history(self):
        if len(self.scene_node_history) > 0:
            self.scene_node.detachNode()  # remove current scene...
            self.scene_node = self.scene_node_history.pop()
            self.scene_node.reparentTo(self.render)  # ...and activate old one
        else:
            print('History is empty')

    def handle_key(self, key, value):
        self.key_map[key] = value

    def handle_mouse(self):
        # check collisions
        self.coll_traverser.traverse(self.render)
        if self.coll_handler.getNumEntries() > 0:
            self.coll_handler.sortEntries()  # sort by distance
            pickedObj = self.coll_handler.getEntry(0).getIntoNodePath()

            pickedObj = pickedObj.findNetTag('canCollide')
            if not pickedObj.isEmpty():
                func = pickedObj.getPythonTag('callback')
                func()

    def load_directory(self, path):
        # save old scene
        if self.scene_node is not None:
            self.scene_node_history.append(self.scene_node)
            self.scene_node.detachNode()

        # create new scene under dummy node
        dummy = self.render.attachNewNode('dummy')

        # generate layout
        x = 0
        y = 0
        step = 3

        filenum = len(os.listdir(path))
        sidelen = int(np.ceil(np.sqrt(filenum)))
        idx_list = list(np.ndindex((sidelen, sidelen)))
        assert len(idx_list) >= filenum, f'{filenum} < {len(idx_list)}'

        for (i, j), entry in zip(idx_list, os.scandir(path)):
            print(f'Parsing "{entry.name}":', end=' ')
            x, y = i * step, j * step
            pos = (x, 0, y)

            if entry.is_dir():
                if not entry.name.startswith('.'):
                    e = DirectoryEntity(self, dummy, entry.path, pos)
                    e.build()
                print('directory')
                continue

            general_type, _ = mimetypes.guess_type(entry.path)
            if general_type is None:
                ErrorEntity(self, dummy, entry.path, pos).build()
                print('error')
                continue

            type_, subtype = general_type.split('/')
            print(type_, subtype)

            Entity = {
                'image': ImageEntity,
                'text': TextEntity
            }.get(type_, None)
            if Entity is None:
                Entity = {'pdf': PdfEntity}.get(subtype, None)
            if Entity is None:
                try:
                    TextEntity(self, dummy, entry.path, pos).build()
                except:
                    ErrorEntity(self, dummy, entry.path, pos).build()
            else:
                Entity(self, dummy, entry.path, pos).build()

        # self.render.ls()
        self.scene_node = dummy

    def controlCameraTask(self, task):
        md = self.win.getPointer(0)
        x = md.getX()
        y = md.getY()

        self.camera.setH(x * self.mouse_sensitivity)
        self.camera.setP(y * self.mouse_sensitivity)

        dt = globalClock.getDt()  # is magically available from panda3d
        if self.key_map['forward']:
            self.camera.setPos(self.camera, 0, self.speed * dt, 0)
        if self.key_map['backward']:
            self.camera.setPos(self.camera, 0, -self.speed * dt, 0)
        if self.key_map['left']:
            self.camera.setPos(self.camera, -self.speed * dt / 2, 0, 0)
        if self.key_map['right']:
            self.camera.setPos(self.camera, self.speed * dt / 2, 0, 0)
        if self.key_map['up']:
            self.camera.setPos(self.camera, 0, 0, self.speed * dt / 2)
        if self.key_map['down']:
            self.camera.setPos(self.camera, 0, 0, -self.speed * dt / 2)

        if self.verbose:
            self.coll_traverser.traverse(self.render)

        return Task.cont
Beispiel #23
0
class MousePicker(object):
    def __init__(self, pickTag="MyPickingTag", nodeName="pickRay", showCollisions=False):
        self.pickTag = pickTag
        self.nodeName = nodeName
        self.showCollisions = showCollisions

    def create(self):
        self.mPickerTraverser = CollisionTraverser()
        self.mCollisionQue = CollisionHandlerQueue()

        self.mPickRay = CollisionRay()
        self.mPickRay.setOrigin(base.camera.getPos(base.render))
        self.mPickRay.setDirection(base.render.getRelativeVector(base.camera, Vec3(0, 1, 0)))

        # create our collison Node to hold the ray
        self.mPickNode = CollisionNode(self.nodeName)
        self.mPickNode.addSolid(self.mPickRay)

        # Attach that node to the camera since the ray will need to be positioned
        # relative to it, returns a new nodepath
        # well use the default geometry mask
        # this is inefficent but its for mouse picking only

        self.mPickNP = base.camera.attachNewNode(self.mPickNode)

        # we'll use what panda calls the "from" node.  This is reall a silly convention
        # but from nodes are nodes that are active, while into nodes are usually passive environments
        # this isnt a hard rule, but following it usually reduces processing

        # Everything to be picked will use bit 1. This way if we were doing other
        # collision we could seperate it, we use bitmasks to determine what we check other objects against
        # if they dont have a bitmask for bit 1 well skip them!
        self.mPickNode.setFromCollideMask(BitMask32(1))

        # Register the ray as something that can cause collisions
        self.mPickerTraverser.addCollider(self.mPickNP, self.mCollisionQue)

        # Setup 2D picker
        self.mPickerTraverser2D = CollisionTraverser()
        self.mCollisionQue2D = CollisionHandlerQueue()

        self.mPickNode2D = CollisionNode("2D PickNode")
        self.mPickNode2D.setFromCollideMask(BitMask32(1))
        self.mPickNode2D.setIntoCollideMask(BitMask32.allOff())

        self.mPick2DNP = base.camera2d.attachNewNode(self.mPickNode2D)

        self.mPickRay2D = CollisionRay()
        self.mPickNode2D.addSolid(self.mPickRay2D)

        self.mPickerTraverser2D.addCollider(self.mPick2DNP, self.mCollisionQue2D)

        if self.showCollisions:
            self.mPickerTraverser.showCollisions(base.render)
            self.mPickerTraverser2D.showCollisions(base.aspect2d)

    def mousePick(self, traverse=None, tag=None):
        # do we have a mouse
        if base.mouseWatcherNode.hasMouse() == False:
            return None, None

        traverse = traverse or base.render
        tag = tag or self.pickTag

        mpos = base.mouseWatcherNode.getMouse()

        # Set the position of the ray based on the mouse position
        self.mPickRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
        self.mPickerTraverser.traverse(traverse)

        if self.mCollisionQue.getNumEntries() > 0:
            self.mCollisionQue.sortEntries()

            for entry in self.mCollisionQue.getEntries():
                pickedObj = entry.getIntoNodePath()
                pickedObj = pickedObj.findNetTag(tag)

                if not pickedObj.isEmpty():
                    pos = entry.getSurfacePoint(base.render)
                    return pickedObj, pos

        return None, None

    def mousePick2D(self, traverse=None, tag=None, all=False):
        # do we have a mouse
        if base.mouseWatcherNode.hasMouse() == False:
            return None, None

        traverse = traverse or base.render
        tag = tag or self.pickTag

        mpos = base.mouseWatcherNode.getMouse()

        self.mPickRay2D.setFromLens(base.cam2d.node(), mpos.getX(), mpos.getY())

        self.mPickerTraverser2D.traverse(base.aspect2d)

        if self.mCollisionQue2D.getNumEntries() > 0:
            self.mCollisionQue2D.sortEntries()

            if all:
                return (
                    [
                        (entry.getIntoNodePath().findNetTag(tag), entry.getSurfacePoint(base.aspect2d))
                        for entry in self.mCollisionQue2D.getEntries()
                    ],
                    None,
                )
            else:
                entry = self.mCollisionQue2D.getEntry(0)
                pickedObj = entry.getIntoNodePath()

                pickedObj = pickedObj.findNetTag(tag)
                if not pickedObj.isEmpty():
                    pos = entry.getSurfacePoint(base.aspect2d)
                    return pickedObj, pos

        return None, None
Beispiel #24
0
class Game(DirectObject):
    def __init__(self, model):
        self.model = model
        base.setBackgroundColor(0.1, 0.1, 0.8, 1)
        base.setFrameRateMeter(True)

        base.cam.setPos(0, -20, 4)
        base.cam.lookAt(0, 0, 0)

        # Light
        alight = AmbientLight('ambientLight')
        alight.setColor(Vec4(0.5, 0.5, 0.5, 1))
        alightNP = render.attachNewNode(alight)

        dlight = DirectionalLight('directionalLight')
        dlight.setDirection(Vec3(1, 1, -1))
        dlight.setColor(Vec4(0.7, 0.7, 0.7, 1))
        dlightNP = render.attachNewNode(dlight)

        render.clearLight()
        render.setLight(alightNP)
        render.setLight(dlightNP)

        # Input
        self.accept('escape', self.doExit)
        self.accept('r', self.doReset)
        self.accept('f1', self.toggleWireframe)
        self.accept('f2', self.toggleTexture)
        self.accept('f3', self.toggleDebug)
        self.accept('f5', self.doScreenshot)

        inputState.watchWithModifiers('forward', 'w')
        inputState.watchWithModifiers('left', 'a')
        inputState.watchWithModifiers('reverse', 's')
        inputState.watchWithModifiers('right', 'd')
        inputState.watchWithModifiers('turnLeft', 'q')
        inputState.watchWithModifiers('turnRight', 'e')

        # Task
        taskMgr.add(self.update, 'updateWorld')

        # Physics
        self.setup()

    # _____HANDLER_____

    def doExit(self):
        self.cleanup()
        sys.exit(1)

    def doReset(self):
        self.cleanup()
        self.setup()

    def toggleWireframe(self):
        base.toggleWireframe()

    def toggleTexture(self):
        base.toggleTexture()

    def toggleDebug(self):
        if self.debugNP.isHidden():
            self.debugNP.show()
        else:
            self.debugNP.hide()

    def doScreenshot(self):
        base.screenshot('Bullet')

    # ____TASK___

    def calculate_moves(self):
        self.y = self.model.predict(self.x)
        self.moves = self.y > 0  # 0.5

    def processInput(self, dt):
        engineForce = 0.0
        brakeForce = 0.0
        if self.moves[0]:  #inputState.isSet('forward'):
            engineForce = 1000.0
            brakeForce = 0.0

        if not self.moves[0]:  #inputState.isSet('reverse'):
            engineForce = 0.0
            brakeForce = 100.0

        if self.moves[1]:  #inputState.isSet('turnLeft'):
            self.steering += dt * self.steeringIncrement
            self.steering = min(self.steering, self.steeringClamp)

        if not self.moves[1]:  #inputState.isSet('turnRight'):
            self.steering -= dt * self.steeringIncrement
            self.steering = max(self.steering, -self.steeringClamp)
        """
    if inputState.isSet('forward'):
      engineForce = 1000.0
      brakeForce = 0.0

    if inputState.isSet('reverse'):
      engineForce = 0.0
      brakeForce = 100.0

    if inputState.isSet('turnLeft'):
      self.steering += dt * self.steeringIncrement
      self.steering = min(self.steering, self.steeringClamp)

    if inputState.isSet('turnRight'):
      self.steering -= dt * self.steeringIncrement
      self.steering = max(self.steering, -self.steeringClamp)
    """
        # Apply steering to front wheels
        self.vehicle.setSteeringValue(self.steering, 0)
        self.vehicle.setSteeringValue(self.steering, 1)

        # Apply engine and brake to rear wheels
        self.vehicle.applyEngineForce(engineForce, 2)
        self.vehicle.applyEngineForce(engineForce, 3)
        self.vehicle.setBrake(brakeForce, 2)
        self.vehicle.setBrake(brakeForce, 3)

    def raycast(self):
        """pFrom = render.getRelativePoint(self.yugoNP,Point3(0,0,0))#Point3(0,0,0)
      pFrom -= Point3(0,0,pFrom[2])
      pRel = render.getRelativePoint(base.cam,self.yugoNP.getPos())  # FIXME THIS IS IT!! get rid of z component
      pRel -= Point3(0,0,pRel[2])
      p45 = Point3(pRel[0] - pRel[1], pRel[1] + pRel[0],0)
      pn45 = Point3(pRel[0] + pRel[1], pRel[1] - pRel[0],0)
      #print(render.getRelativePoint(self.yugoNP,Point3(0,0,0)))
      #print(dir(self.yugoNP))
      pTo = [pFrom + pn45, pFrom + pRel, pFrom + p45]#[pFrom + Vec3(-10,10,0)*999,pFrom + Vec3(0,10,0)*999,pFrom + Vec3(10,10,0)*999]# FIXME should be relative to front of car, getting cloe! #self.yugoNP.getPosDelta()*99999]#[Point3(-10,10,0) * 99999,Point3(0,10,0) * 99999,Point3(10,10,0) * 99999]
      #self.ray = CollisionRay(0,0,0,100,0,0)
      result = [self.world.rayTestClosest(pFrom,pt) for pt in pTo]
      #print(dir(self.yugoNP))
      #print(result.getHitPos())
      return tuple([res.getHitPos().length() for res in result])
      """#queue = CollisionHandlerQueue()
        #traverser.addCollider(fromObject, queue)
        #traverser.traverse(render)
        #queue.sortEntries()
        #for entry in queue.getEntries():
        #print(entry)
        #print(result.getHitPos())
        #if result.getNode() != None:
        #print(self.yugoNP.getPos(result.getNode()))
        #print(self.cTrav)
        self.cTrav.traverse(render)
        entries = list(self.colHandler.getEntries())
        entries.sort(key=lambda y: y.getSurfacePoint(render).getY())
        #for entry in entries:      print(entry.getFromNodePath().getName())
        if entries:  # and len(result) > 1:
            for r in entries:
                if r.getIntoNodePath().getName(
                ) == 'Box' and r.getFromNodePath().getName() in [
                        'ray%d' % i for i in range(3)
                ]:
                    self.ray_col_vec_dict[
                        r.getFromNodePath().getName()].append(
                            numpy.linalg.norm(
                                list(r.getSurfacePoint(
                                    r.getFromNodePath()))[:-1]))
        self.ray_col_vec_dict = {
            k: (min(self.ray_col_vec_dict[k])
                if len(self.ray_col_vec_dict[k]) >= 1 else 10000)
            for k in self.ray_col_vec_dict
        }
        self.x = numpy.array(list(self.ray_col_vec_dict.values()))
        #return entries

    def update(self, task):

        dt = globalClock.getDt()

        self.raycast()
        self.calculate_moves()
        self.ray_col_vec_dict = {k: [] for k in self.ray_col_vec_dict}
        self.processInput(dt)
        self.world.doPhysics(dt, 10, 0.008)

        #print(dir(result[1]))
        #print(numpy.linalg.norm(list(result[1].getSurfacePoint(result[1].getFromNodePath()))[:-1]))
        #base.camera.setPos(0,-40,10)
        #print self.vehicle.getWheel(0).getRaycastInfo().isInContact()
        #print self.vehicle.getWheel(0).getRaycastInfo().getContactPointWs()

        #print self.vehicle.getChassis().isKinematic()

        return task.cont

    def cleanup(self):
        self.world = None
        self.worldNP.removeNode()

    def setup(self):
        self.worldNP = render.attachNewNode('World')

        # World
        self.debugNP = self.worldNP.attachNewNode(BulletDebugNode('Debug'))
        self.debugNP.show()

        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81))
        self.world.setDebugNode(self.debugNP.node())

        #terrain = GeoMipTerrain("mySimpleTerrain")
        #terrain.setHeightfield("./models/heightfield_2.png")
        #terrain.getRoot().reparentTo(self.worldNP)#render)
        #terrain.generate()

        # Plane
        shape = BulletPlaneShape(Vec3(0, 0, 1), 0)

        np = self.worldNP.attachNewNode(BulletRigidBodyNode('Ground'))
        np.node().addShape(shape)
        np.setPos(0, 0, -1)
        np.setCollideMask(BitMask32.allOn())

        self.world.attachRigidBody(np.node())

        np = self.worldNP.attachNewNode(BulletRigidBodyNode('Track'))
        np.node().setMass(5000.0)
        np.setPos(3, 0, 10)
        np.setCollideMask(BitMask32.allOn())  #(0x0f))
        #self.track = BulletVehicle(self.world, np.node())
        #self.track.setCoordinateSystem(ZUp)
        self.track_np = loader.loadModel('models/race_track.egg')
        self.track_np.setScale(100)
        self.track_np.reparentTo(np)

        self.track_np.setCollideMask(BitMask32.allOn())
        self.world.attachRigidBody(np.node())
        self.track_np = np
        #self.track_np.show()

        # Chassis
        shape = BulletBoxShape(Vec3(0.6, 1.4, 0.5))
        ts = TransformState.makePos(Point3(0, 0, 0.5))

        np = self.worldNP.attachNewNode(BulletRigidBodyNode('Vehicle'))
        np.node().addShape(shape, ts)
        np.setPos(0, 0, 1)
        np.node().setMass(800.0)
        np.node().setDeactivationEnabled(False)

        self.world.attachRigidBody(np.node())

        #np.node().setCcdSweptSphereRadius(1.0)
        #np.node().setCcdMotionThreshold(1e-7)
        self.cTrav = CollisionTraverser()
        # Vehicle
        self.vehicle = BulletVehicle(self.world, np.node())
        self.vehicle.setCoordinateSystem(ZUp)
        self.yugoNP = loader.loadModel('models/yugo/yugo.egg')
        self.yugoNP.reparentTo(np)
        self.colHandler = CollisionHandlerQueue()
        self.ray_col_np = {}
        self.ray_col_vec_dict = {}
        for ray_dir in range(-1, 2):  # populate collision rays
            self.ray = CollisionRay()
            self.ray.setOrigin(ray_dir, 0.5, 0.5)
            self.ray.setDirection(ray_dir, 1, 0)
            self.ray_col = CollisionNode('ray%d' % (ray_dir + 1))
            self.ray_col.addSolid(self.ray)
            self.ray_col.setFromCollideMask(
                BitMask32.allOn())  #(0x0f))#CollideMask.bit(0)
            #self.ray_col.setIntoCollideMask(CollideMask.allOff())
            self.ray_col_np['ray%d' %
                            (ray_dir + 1)] = self.yugoNP.attachNewNode(
                                self.ray_col)
            self.cTrav.addCollider(self.ray_col_np['ray%d' % (ray_dir + 1)],
                                   self.colHandler)
            self.ray_col_np['ray%d' % (ray_dir + 1)].show()
            self.ray_col_vec_dict['ray%d' % (ray_dir + 1)] = []
        self.world.attachVehicle(self.vehicle)
        self.cTrav.showCollisions(render)

        # FIXME
        base.camera.reparentTo(self.yugoNP)

        # Right front wheel
        np = loader.loadModel('models/yugo/yugotireR.egg')
        np.reparentTo(self.worldNP)
        self.addWheel(Point3(0.70, 1.05, 0.3), True, np)

        # Left front wheel
        np = loader.loadModel('models/yugo/yugotireL.egg')
        np.reparentTo(self.worldNP)
        self.addWheel(Point3(-0.70, 1.05, 0.3), True, np)

        # Right rear wheel
        np = loader.loadModel('models/yugo/yugotireR.egg')
        np.reparentTo(self.worldNP)
        self.addWheel(Point3(0.70, -1.05, 0.3), False, np)

        # Left rear wheel
        np = loader.loadModel('models/yugo/yugotireL.egg')
        np.reparentTo(self.worldNP)
        self.addWheel(Point3(-0.70, -1.05, 0.3), False, np)

        # Steering info
        self.steering = 0.0  # degree
        self.steeringClamp = 45.0  # degree
        self.steeringIncrement = 120.0  # degree per second

        # Box
        for i, j in [(0, 8), (-3, 5), (6, -5), (8, 3), (-4, -4)]:
            shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5))
            # https://discourse.panda3d.org/t/wall-collision-help/23606
            np = self.worldNP.attachNewNode(BulletRigidBodyNode('Box'))
            np.node().setMass(1.0)
            np.node().addShape(shape)
            np.setPos(i, j, 2)
            np.setCollideMask(BitMask32.allOn())  #(0x0f))

            self.world.attachRigidBody(np.node())
            self.boxNP = np
            #self.colHandler2 = CollisionHandlerQueue()

            visualNP = loader.loadModel('models/box.egg')
            visualNP.reparentTo(self.boxNP)
        #self.cTrav.addCollider(self.boxNP,self.colHandler)
        """
    aNode = CollisionNode("TheRay")

    self.ray = CollisionRay()
    self.ray.setOrigin( self.yugoNP.getPos() )
    self.ray.setDirection( Vec3(0, 10, 0) )
    #self.ray.show()


    aNodePath = self.yugoNP.attachNewNode( CollisionNode("TheRay") )
    aNodePath.node().addSolid(self.ray)
    aNodePath.show()
    """
        #aNode.addSolid(self.ray)
        #self.ray = CollisionRay(0,0,0,10,0,0)
        #self.ray.reparentTo(self.yugoNP)
        #self.rayColl = CollisionNode('PlayerRay')
        #self.rayColl.addSolid(self.ray)

        #self.playerRayNode = self.yugoNP.attachNewNode( self.rayColl )
        #self.playerRayNode.show()

        #base.myTraverser.addCollider (self.playerRayNode, base.floor)
        #base.floor.addCollider( self.playerRayNode, self.yugoNP)
        """
    MyEvent=CollisionHandlerFloor()
    MyEvent.setReach(100)
    MyEvent.setOffset(15.0)

    aNode = CollisionNode("TheRay")
    ray = CollisionRay()
    ray.setOrigin( self.boxNP.getPos() )
    ray.setDirection( Vec3(10, 0, 0) )

    aNode.addSolid(ray)
    aNodePath = MyModel.attachNewNode( aNode )

    Collision = ( aNode, "TheRay" )
    Collision[0].setFromCollideMask( BitMask32.bit( 1 ) )
    """

    def addWheel(self, pos, front, np):
        wheel = self.vehicle.createWheel()

        wheel.setNode(np.node())
        wheel.setChassisConnectionPointCs(pos)
        wheel.setFrontWheel(front)

        wheel.setWheelDirectionCs(Vec3(0, 0, -1))
        wheel.setWheelAxleCs(Vec3(1, 0, 0))
        wheel.setWheelRadius(0.25)
        wheel.setMaxSuspensionTravelCm(40.0)

        wheel.setSuspensionStiffness(40.0)
        wheel.setWheelsDampingRelaxation(2.3)
        wheel.setWheelsDampingCompression(4.4)
        wheel.setFrictionSlip(100.0)
        wheel.setRollInfluence(0.1)
Beispiel #25
0
class Moving(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        # This is used to store which keys are currently pressed.
        self.keyMap = {
            "left": 0, "right": 0, "forward": 0, "back": 0, "up": 0}

        # Set up the environment
        #
        # This environment model contains collision meshes.  If you look
        # in the egg file, you will see the following:
        #
        #    <Collide> { Polyset keep descend }
        #
        # This tag causes the following mesh to be converted to a collision
        # mesh -- a mesh which is optimized for collision, not rendering.
        # It also keeps the original mesh, so there are now two copies ---
        # one optimized for rendering, one for collisions.

        self.environ = loader.loadModel("EggMod/SandPlan.egg")
        self.environ.reparentTo(render)
        self.environ.setScale(20)

        StartPos = LVector3(0,0,94)
        self.movint = loader.loadModel("EggMod/HailPar.egg")
        self.movint.reparentTo(render)
        self.movint.setScale(2)
        self.movint.setPos(StartPos + (0, 0, 0.5))


        # Accept the control keys for movement and rotation

        self.accept("escape", sys.exit)
        self.accept("arrow_left", self.setKey, ["left", True])
        self.accept("arrow_right", self.setKey, ["right", True])
        self.accept("arrow_up", self.setKey, ["forward", True])
        self.accept("arrow_down", self.setKey, ["back", True])
        self.accept("f", self.setKey, ["up", True])       
        self.accept("arrow_left-up", self.setKey, ["left", False])
        self.accept("arrow_right-up", self.setKey, ["right", False])
        self.accept("arrow_up-up", self.setKey, ["forward", False])
        self.accept("arrow_down-up", self.setKey, ["back", False])
        self.accept("f-up", self.setKey, ["up", False])
        
        self.mopan=Pmango()
        
        self.alin = LinearEulerIntegrator()
        self.mopan.attachLinearIntegrator(self.alin)
        self.arin = AngularEulerIntegrator()
        self.mopan.attachAngularIntegrator(self.arin)
        
        taskMgr.add(self.move, "moveTask")


        self.cTrav = CollisionTraverser()
        #base.cTrav.setRespectPrevTransform(True)
        

        self.actMove = NodePath("ActMove")
        self.actMove.reparentTo(render)
        self.an = ActorNode("BMova")
        self.anp = self.actMove.attachNewNode(self.an)
        

        
        self.mopan.attachPhysicalNode(self.an)
        self.movint.reparentTo(self.anp)

        self.anp.node().getPhysicsObject().setMass(1)
        #self.an.getPhysicsObject().setTerminalVelocity(1.0)

        self.dvi=0
        self.grava=ForceNode('GravAll')
        self.grar=render.attachNewNode(self.grava)
        self.grdi=LinearVectorForce(0.0,-0.0,-8.0)
        #self.grdi.setMassDependent(1)
        self.grava.addForce(self.grdi)  #Forces have to be added to force nodes and to
        # a physics manager
         
        self.mopan.addLinearForce(self.grdi)

        
        self.BMoveBalance = CollisionSphere(0, 0, -7.0, 1)
        self.BMoveBalanceNode = CollisionNode('BMove')
        self.BMoveBalanceNode.addSolid(self.BMoveBalance)
        

        self.BMoveBalancePath = self.movint.attachNewNode(self.BMoveBalanceNode)
        self.DinGro = PhysicsCollisionHandler()
        self.DinGro.setStaticFrictionCoef(1)
        self.DinGro.setDynamicFrictionCoef(2)
        self.DinGro.setAlmostStationarySpeed(0.1)

        self.DinGro.addCollider(self.BMoveBalancePath,self.anp) #Colliders use nodepaths for collisions instead of nodes
        self.cTrav.addCollider(self.BMoveBalancePath, self.DinGro)

        # Uncomment this line to see the collision rays
        self.BMoveBalancePath.show()

        # Uncomment this line to show a visual representation of the
        # collisions occuring
        self.cTrav.showCollisions(render)

        # Create some lighting
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection((-5, -5, -5))
        render.setLight(render.attachNewNode(directionalLight))        


    # Records the state of the arrow keys
    def setKey(self, key, value):
        self.keyMap[key] = value

    # Accepts arrow keys to move either the player or the menu cursor,
    # Also deals with grid checking and collision detection

    def move(self, task):
        # Get the time that elapsed since last frame.  We multiply this with
        # the desired speed in order to find out with which distance to move
        # in order to achieve that desired speed.
        dt = globalClock.getDt()
        self.dvi+=dt
        self.anr=self.an.getPhysicsObject()

        print(self.anr.getVelocity())

        if dt<=.2:
            self.mopan.doPhysics(dt)
    
        if self.keyMap["left"]:
            self.movint.setH(self.movint.getH() + 200 * dt)
        if self.keyMap["right"]:
            self.movint.setH(self.movint.getH() - 200 * dt)
        if self.keyMap["forward"]:
            self.movint.setFluidY(self.movint, -25 * dt)          
        if self.keyMap["back"]:
            self.movint.setFluidY(self.movint, 25 * dt)
        if self.keyMap["up"]:
            self.movint.setFluidZ(self.movint, 25 * dt)

        # Normally, we would have to call traverse() to check for collisions.
        # However, the class ShowBase that we inherit from has a task to do
        # this for us, if we assign a CollisionTraverser to self.cTrav.
        #self.cTrav.traverse(render)
        

        return task.cont
Beispiel #26
0
class PandaHW(ShowBase):

    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()
    def collEvent(self, entry):
        print "Collide event", entry
    # A task is a procedure that is called every frame
    def spinCameraTask(self, task):
        rotation_speed = 20
        invert_camY = True
        w, h = self.getSize()
        if base.mouseWatcherNode.hasMouse():
            cx = base.mouseWatcherNode.getMouseX()
            cy = base.mouseWatcherNode.getMouseY()
            self.camAlpha -= cx * rotation_speed
            self.camBeta  -= (cy * rotation_speed) * (-1 if invert_camY else 1)
        for win in self.winList:
            if win.hasPointer(0):
                win.movePointer(0,w/2,h/2)
        self.pandaActor.setHpr(self.camAlpha, self.camBeta, 0.)
        self.camera.setHpr(180., -self.camBeta, 0.)
        return Task.cont
    def moveCameraTask(self, task):
        walk_speed = 1
        newX = self.pandaActor.getX()
        newY = self.pandaActor.getY()
        newZ = self.pandaActor.getZ()
        if self.moving:
            self.pandaActor.loop("walk")
        else:
            self.pandaActor.stop()
        if 1 in self.moving: # Forward
            newX -= sin(degtorad(self.camAlpha)) * walk_speed
            newY += cos(degtorad(self.camAlpha)) * walk_speed
            newZ += sin(degtorad(self.camBeta))  * walk_speed
        if 2 in self.moving: # Backward
            newX += sin(degtorad(self.camAlpha)) * walk_speed
            newY -= cos(degtorad(self.camAlpha)) * walk_speed
            newZ -= sin(degtorad(self.camBeta))  * walk_speed
        if 3 in self.moving: # left
            newX -= cos(degtorad(self.camAlpha)) * walk_speed
            newY -= sin(degtorad(self.camAlpha)) * walk_speed
        if 4 in self.moving: # right
            newX += cos(degtorad(self.camAlpha)) * walk_speed
            newY += sin(degtorad(self.camAlpha)) * walk_speed
        newZ -= self.playerFallingSpeed
        #if newZ >= (self.playerAltitude - 0.1) and newZ <= (self.playerAltitude + 0.1) and not self.jumping: # Tolerance
        #    newZ = self.playerAltitude
        self.pandaActor.setPos(newX, newY, newZ)
        self.player.pos = VBase3(newX, newY, newZ)
        return Task.cont
    def move(self, direction):
        if direction < 0 and -direction in self.moving:
            self.moving.remove(-direction)
        else:
            self.moving.append(direction)
    def playerGravity(self, task):
        self.player.simulate(task.time)
        self.pandaActor.setPos(self.player.pos)
        z = self.player.pos.getZ()
        pa = self.playerAltitude
        if self.jumping and z >= (pa - 0.1) and z <= (pa + 0.1): # Tolerance
            self.inJump = True
            self.player.vel = VBase3(0, 0, 0.05)
            self.player.force = VBase3(0, 0, 0)
        return Task.cont
    def jump(self, jumping = True):
        self.jumping = jumping
    def keyBoardSetup( self ):
        self.accept("escape", sys.exit )
        key_directions = {
            "arrow_up": 1, "z" : 1,
            "arrow_down": 2, "s" : 2,
            "arrow_left": 3, "q" : 3,
            "arrow_right": 4, "d" : 4,
            }
        for key_name, direction in key_directions.items():
            self.accept(key_name, self.move, [direction])
            self.accept("%s-up" % (key_name,), self.move, [-direction])
        self.accept("space", self.jump, [True])
        self.accept("space-up", self.jump, [False])
Beispiel #27
0
class MyApp(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)

        ################
        #Terrain
        ################

        #######
        #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.environ = loader.loadModel("models/environment")
        self.environ.setScale(.25, .25, .25)
        self.environ.reparentTo(render)
        self.environ.setCollideMask(BitMask32.bit(0))

        ################
        #Game objects 
        ################

        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.setPythonTag("moving", False)
        self.pandaActor.setCollideMask(BitMask32.allOff())
        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.last_mouse_y = self.win.getPointer(0).getY()

        ################
        #Physics
        ################


        base.enableParticles()

        self.avatarNP=base.render.attachNewNode(ActorNode("actor"))
        # Sets up the mass. Note that in this scenario, mass is not taken into consideration.
        self.avatarNP.node().getPhysicsObject().setMass(100.)
        self.avatarNP.setPos(0,0,0)
        # Parent our avatar to the ready to go physics node
        self.pandaActor.reparentTo(self.avatarNP)

        gravityFN=ForceNode('world-forces')
        gravityFNP=render.attachNewNode(gravityFN)
        gravityForce=LinearVectorForce(0,0,-.1)
        gravityForce.setMassDependent(False)
        gravityFN.addForce(gravityForce)
        # Attach it to the global physics manager
        base.physicsMgr.addLinearForce(gravityForce)

        base.physicsMgr.attachPhysicalNode(self.avatarNP.node())

        ################
        #Collisions
        ################

        self.cTrav = CollisionTraverser()
        self.cTrav.showCollisions(base.render)

        self.pandaGroundRay = CollisionSphere(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.avatarNP.attachNewNode(self.pandaGroundRayNode)
        self.pandaGroundRayNodepath.show()
        self.pandaGroundCollisionHandler = PhysicsCollisionHandler()
        self.pandaGroundCollisionHandler.addCollider(self.pandaGroundRayNodepath, self.avatarNP)
        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)

        ################
        #Camera
        ################

        self.disableMouse()

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

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

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

        ################
        #Events
        ################

        self.taskMgr.add(self.gameLoop, "gameLoop", 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()

    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 gameLoop(self, task):

        dt = globalClock.getDt()

        #self.avatarNP.setY(self.avatarNP, 10 * dt)

        if self.keys["w"]: self.avatarNP.setZ(self.avatarNP, 5 * dt)

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

        if self.keys["a"]: self.avatarNP.setX(self.avatarNP, -5 * dt)

        if self.keys["d"]: self.avatarNP.setX(self.avatarNP, 5 * dt)

        #Mouse-based viewpoint rotation

        mouse_pos = self.win.getPointer(0)

        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

        #self.cam.setP(0)

        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.avatarNP.setH(self.avatarYawRot)
        self.cam.setH(self.avatarYawRot)
        self.cam.setP(-self.avatarPitchRot)

        xy_plane_cam_dist = self.cam_away*cos(radians(self.avatarPitchRot))

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

        print self.camera.getPos()
        self.cam.setPos(self.avatarNP.getX() + cam_x_adjust, self.avatarNP.getY() - cam_y_adjust, 
                        self.avatarNP.getZ() + cam_z_adjust)

        print self.avatarNP.getPos()

        #self.cam.setP(self.x)
        #self.x += .01

        #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
Beispiel #28
0
    def __init__(self):
        ShowBase.__init__(self)

        mySound = base.loader.loadSfx("sfx/tank_with_radar.ogg")
        self.mainShot_snd = base.loader.loadSfx("sfx/mainShot.ogg")
        self.enemyShot_snd = base.loader.loadSfx("sfx/enemyShot.ogg")
        self.enemyTankExplosion_snd = base.loader.loadSfx(
            "sfx/enemyTankExplosion.ogg")

        device_list = self.devices.getDevices()
        for device in device_list:
            print(device.device_class)
            # if device.device_class == DeviceClass.flight_stick:
            #    print("Have Joy stick")

        # render.setDepthTest(False)
        self.camLens.setFov(50)
        render.setAntialias(AntialiasAttrib.MLine)

        base.setBackgroundColor(0, 0, 0)
        base.disableMouse()
        props = WindowProperties()
        # props.setCursorHidden(True)
        base.win.requestProperties(props)

        # Load the environment models
        self.ground = self.loader.loadModel("models/ground_bl.egg")

        self.tank = self.loader.loadModel("models/tank_bl.egg")
        self.tank.setRenderModeWireframe()

        self.ground.setRenderModeWireframe()
        self.ground.setScale(100, 100, 1)

        # tank as lines
        #   set up explosion variables
        #   explosion intervals added in renderTanks() method
        for t in tanks_list:
            tanks_dict[t]["explosion"] = Parallel(
                name="Tank{}-Explosion".format(t))

        # group node for all enemy tanks
        self.tank_group = render.attachNewNode("Tanks")
        self.renderTanks(self.tank_group)

        # tank rounds
        with open('models/tank_round.json', "r") as f:
            data = json.load(f)
        lines = create_lineSegs_object(data, 0)
        lines.setThickness(3)

        gn_round = lines.create()
        np_round = NodePath(gn_round)

        self.tank_round = []
        #
        self.tank_round.append(render.attachNewNode("tank-round"))
        np_round.instanceTo(self.tank_round[0])
        # self.tank_round[0].hide()
        self.tank_round[0].setColorScale(0.3, 0.3, 1.0, 1.0)
        self.tank_round[0].setPos(0, 20, -0.2 - 10)
        self.tank_round[0].setHpr(self.tank_round[0], 0, 90, 0)
        self.tank_round[0].setScale(0.2, 0.2, 0.2)
        self.tank_round[0].reparentTo(camera)

        # render enemy tank round
        for t in tanks_list:
            tanks_dict[t]["round"] = render.attachNewNode(
                "tank{}-round".format(t))
            np_round.instanceTo(tanks_dict[t]["round"])
            tanks_dict[t]["round"].setPos(-0.4, 0, 1.61325)
            tanks_dict[t]["round"].setHpr(tanks_dict[t]["round"], 0, 0, 90)
            tanks_dict[t]["round"].setScale(0.14, 0.14, 0.14)
            tanks_dict[t]["round"].reparentTo(tanks_dict[t]["tank"])

        #
        # new mountain method
        self.render_mountains()

        ####################
        # collisions       #
        ####################
        print(CollisionNode.getDefaultCollideMask())

        # Initialize collision Handler
        self.collHandEvent = CollisionHandlerEvent()
        self.collHandEvent.addInPattern('into-%in')

        # collision spheres enemy tank
        for t in tanks_list:
            cs = CollisionSphere(0, 0, 0.9, tanks_dict[t]["coll_rad"])
            cnodePath = tanks_dict[t]["tank"].attachNewNode(
                CollisionNode('cTank' + t))
            cnodePath.node().addSolid(cs)

            if DEBUG:
                # cnodePath.show()
                pass
        self.tank_group.setCollideMask(BitMask32(0x10))

        # print(self.tank_group.getCollideMask())
        # print(tanks_dict['1']["tank"].getCollideMask())

        # collision sphere for round of main tank
        cs = CollisionSphere(0, 0, 0, 1)
        tr_cnodePath = self.tank_round[0].attachNewNode(
            CollisionNode('cTankRound'))
        tr_cnodePath.node().addSolid(cs)

        # collision spheres for enemy tank rounds
        cs = CollisionSphere(0, 0, 0, 1)
        for t in tanks_list:
            np = tanks_dict[t]["round"].attachNewNode(
                CollisionNode('ceTankRound' + t))
            np.node().addSolid(cs)
            np.node().setFromCollideMask(BitMask32(0x20))
            # np.show()

        # collision sphere main tank
        cs = CollisionSphere(0, 0, 0, 1)
        np = self.camera.attachNewNode(CollisionNode('cmTank'))
        np.node().addSolid(cs)
        # np.show()

        # Initialise Traverser
        traverser = CollisionTraverser('Main Traverser')
        if DEBUG:
            traverser.showCollisions(render)
        base.cTrav = traverser

        # from objects
        traverser.addCollider(tr_cnodePath, self.collHandEvent)

        np_list = render.findAllMatches("**/ceTankRound*")
        for np in np_list:
            traverser.addCollider(np, self.collHandEvent)

        # grid
        grid_lines = procedural_grid(-1000, 500, -1000, 500, 50)
        grid_lines.setThickness(1)
        node = grid_lines.create()
        self.grid = NodePath(node)
        self.grid.setColorScale(0.15, 0.2, 0.15, 1.0)
        self.grid.setPos(0, 0, -0.2)

        alight = AmbientLight('ambientLight')
        alight.setColor(Vec4(0, 0, 0, 0))  # ambient light is dim red
        # alightNP = self.render.attachNewNode(alight)

        # render sight
        self.render_sight()

        # Tasks
        for t in tanks_list:
            tanks_dict[t]["move"] = True

        self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
        self.taskMgr.add(self.moveTanksTask, "MoveTanksTask")
        self.taskMgr.add(self.moveTask, "MoveTask")
        self.taskMgr.add(self.enemy_shoot_task, "EnemyShoot")

        # base.messenger.toggleVerbose()

        self.accept('space', self.shoot)
        self.accept('space-up', self.shot_clear)
        self.accept('shot-done', self.reset_shot)

        self.accept('into-' + 'cmTank', self.struck)
        for t in tanks_list:
            self.accept('into-' + 'cTank' + t, self.tank0_round_hit)
            self.accept('explosion{}-done'.format(t),
                        self.explosion_cleanup,
                        extraArgs=[t])
            self.accept('shot{}-done'.format(t),
                        self.enemy_reset_shot,
                        extraArgs=[t])

        # on-screen text
        vect = self.camera.getHpr()
        self.textObject = OnscreenText(text=str(vect[0]),
                                       pos=(-0.5, -0.9),
                                       scale=(0.03, 0.05),
                                       fg=(0.4, 1.0, 0.4, 1),
                                       mayChange=True)
        self.textObject.reparentTo(self.render2d)

        mySound.setLoop(True)
        mySound.play()
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
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
Beispiel #31
0
class Game(ShowBase):
    def __init__(self):
        # Set up the window, camera, etc.
        ShowBase.__init__(self)

        # Set the background color to black
        self.win.setClearColor(BACKGROUND_COLOR)

        # Set up the environment
        #
        # This environment model contains collision meshes.  If you look
        # in the egg file, you will see the following:
        #
        #    <Collide> { Polyset keep descend }
        #
        # This tag causes the following mesh to be converted to a collision
        # mesh -- a mesh which is optimized for collision, not rendering.
        # It also keeps the original mesh, so there are now two copies ---
        # one optimized for rendering, one for collisions.

        self.environ = loader.loadModel("models/world")
        self.environ.reparentTo(render)

        # Create the main character

        playerStartPos = self.environ.find("**/start_point").getPos()
        self.player = Actor("models/player", {"run": "models/player-run", "walk": "models/player-walk"})
        self.player.reparentTo(render)
        self.player.setScale(0.2)
        self.player.setPos(playerStartPos + (0, 0, 0.5))

        # Create a floater object, which floats 2 units above player.  We
        # use this as a target for the camera to look at.

        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(self.player)
        self.floater.setZ(CAMERA_TARGET_HEIGHT_DELTA)

        self.first_person = False

        def key_dn(name):
            return lambda: self.setKey(name, True)

        def key_up(name):
            return lambda: self.setKey(name, False)

        def quit():
            self.destroy()

        def toggle_first():
            self.first_person = not self.first_person

        # Accept the control keys for movement and rotation
        key_map = [
            # key              command        action                   help
            # ---              -------        ------                   ----
            ("escape", "esc", lambda: quit(), "[ESC]: Quit"),
            ("arrow_left", "left", key_dn("left"), "[Left Arrow]: Rotate Left"),
            ("arrow_left-up", "left", key_up("left"), None),
            ("arrow_right", "right", key_dn("right"), "[Right Arrow]: Rotate Right"),
            ("arrow_right-up", "right", key_up("right"), None),
            ("arrow_up", "forward", key_dn("forward"), "[Up Arrow]: Run Forward"),
            ("arrow_up-up", "forward", key_up("forward"), None),
            ("arrow_down", "backward", key_dn("backward"), "[Down Arrow]: Run Backward"),
            ("arrow_down-up", "backward", key_up("backward"), None),
            ("a", "cam-left", key_dn("cam-left"), "[A]: Rotate Camera Left"),
            ("a-up", "cam-left", key_up("cam-left"), None),
            ("s", "cam-right", key_dn("cam-right"), "[S]: Rotate Camera Right"),
            ("s-up", "cam-right", key_up("cam-right"), None),
            ("f", "first-pers", lambda: toggle_first(), "[F]: Toggle first-person"),
        ]
        self.keyMap = {}
        inst = Instructions()
        for key, command, action, description in key_map:
            if command:
                self.setKey(command, False)
            self.accept(key, action)
            if description:
                inst.add(description)

        taskMgr.add(self.move, "moveTask")

        # Game state variables
        self.isMoving = False

        # Set up the camera
        self.disableMouse()
        self.camera.setPos(self.player.getX(), self.player.getY() + 10, 2)

        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  One ray will
        # start above player's head, and the other will start above the camera.
        # A ray may hit the terrain, or it may hit a rock or a tree.  If it
        # hits the terrain, we can detect the height.  If it hits anything
        # else, we rule that the move is illegal.
        self.cTrav = CollisionTraverser()

        self.playerGroundRay = CollisionRay()
        self.playerGroundRay.setOrigin(0, 0, 9)
        self.playerGroundRay.setDirection(0, 0, -1)
        self.playerGroundCol = CollisionNode("playerRay")
        self.playerGroundCol.addSolid(self.playerGroundRay)
        self.playerGroundCol.setFromCollideMask(CollideMask.bit(0))
        self.playerGroundCol.setIntoCollideMask(CollideMask.allOff())
        self.playerGroundColNp = self.player.attachNewNode(self.playerGroundCol)
        self.playerGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.playerGroundColNp, self.playerGroundHandler)

        self.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0, 0, 9)
        self.camGroundRay.setDirection(0, 0, -1)
        self.camGroundCol = CollisionNode("camRay")
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(CollideMask.bit(0))
        self.camGroundCol.setIntoCollideMask(CollideMask.allOff())
        self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol)
        self.camGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)

        # Uncomment this line to see the collision rays
        self.playerGroundColNp.show()
        self.camGroundColNp.show()

        # Uncomment this line to show a visual representation of the
        # collisions occuring
        self.cTrav.showCollisions(render)

        # Create some lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((0.3, 0.3, 0.3, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection((-5, -5, -5))
        directionalLight.setColor((1, 1, 1, 1))
        directionalLight.setSpecularColor((1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambientLight))
        render.setLight(render.attachNewNode(directionalLight))

    # Records the state of the arrow keys
    def setKey(self, key, value):
        self.keyMap[key] = value

    # Accepts arrow keys to move either the player or the menu cursor,
    # Also deals with grid checking and collision detection
    def move(self, task):

        # Get the time that elapsed since last frame.  We multiply this with
        # the desired speed in order to find out with which distance to move
        # in order to achieve that desired speed.
        dt = globalClock.getDt()

        # If the camera-left key is pressed, move camera left.
        # If the camera-right key is pressed, move camera right.

        if self.keyMap["cam-left"]:
            self.camera.setX(self.camera, -20 * dt)
        if self.keyMap["cam-right"]:
            self.camera.setX(self.camera, +20 * dt)

        # save player's initial position so that we can restore it,
        # in case he falls off the map or runs into something.

        startpos = self.player.getPos()

        # If a move-key is pressed, move player in the specified direction.

        if self.keyMap["left"]:
            self.player.setH(self.player.getH() + 300 * dt)
        if self.keyMap["right"]:
            self.player.setH(self.player.getH() - 300 * dt)
        if self.keyMap["forward"]:
            self.player.setY(self.player, -25 * dt)
        if self.keyMap["backward"]:
            self.player.setY(self.player, 25 * dt)

        # If player is moving, loop the run animation.
        # If he is standing still, stop the animation.

        if self.keyMap["forward"] or self.keyMap["backward"] or self.keyMap["left"] or self.keyMap["right"]:
            if self.isMoving is False:
                self.player.loop("run")
                self.isMoving = True
        else:
            if self.isMoving:
                self.player.stop()
                self.player.pose("walk", 5)
                self.isMoving = False

        # If the camera is too far from player, move it closer.
        # If the camera is too close to player, move it farther.

        if self.first_person:
            self.camera.setPos(self.player.getPos())
        else:
            camvec = self.player.getPos() - self.camera.getPos()
            camvec.setZ(0)
            camdist = camvec.length()
            camvec.normalize()
            if camdist > CAMERA_DISTANCE_MAX:
                self.camera.setPos(self.camera.getPos() + camvec * (camdist - int(CAMERA_DISTANCE_MAX)))
                camdist = CAMERA_DISTANCE_MAX
                if camdist < CAMERA_DISTANCE_MIN:
                    self.camera.setPos(self.camera.getPos() - camvec * (int(CAMERA_DISTANCE_MIN) - camdist))
                    camdist = CAMERA_DISTANCE_MIN

        # Normally, we would have to call traverse() to check for collisions.
        # However, the class ShowBase that we inherit from has a task to do
        # this for us, if we assign a CollisionTraverser to self.cTrav.
        self.cTrav.traverse(render)

        # Adjust player's Z coordinate.  If player's ray hit terrain,
        # update his Z. If it hit anything else, or didn't hit anything, put
        # him back where he was last frame.

        entries = list(self.playerGroundHandler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

        if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain":
            self.player.setZ(entries[0].getSurfacePoint(render).getZ())
        else:
            self.player.setPos(startpos)

        # Keep the camera at one foot above the terrain,
        # or two feet above player, whichever is greater.

        entries = list(self.camGroundHandler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

        if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain":
            self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + CAMERA_POSITION_HEIGHT_DELTA_MIN)
        if self.camera.getZ() < self.player.getZ() + CAMERA_POSITION_HEIGHT_DELTA_MAX:
            self.camera.setZ(self.player.getZ() + CAMERA_POSITION_HEIGHT_DELTA_MAX)

        # The camera should look in player's direction,
        # but it should also try to stay horizontal, so look at
        # a floater which hovers above player's head.
        self.camera.lookAt(self.floater)

        return task.cont
Beispiel #32
0
class Game(ShowBase):
    def __init__(self):
        # Set up the window, camera, etc.
        ShowBase.__init__(self)

        # Set the background color to black
        self.win.setClearColor(BACKGROUND_COLOR)

        # Set up the environment
        #
        # This environment model contains collision meshes.  If you look
        # in the egg file, you will see the following:
        #
        #    <Collide> { Polyset keep descend }
        #
        # This tag causes the following mesh to be converted to a collision
        # mesh -- a mesh which is optimized for collision, not rendering.
        # It also keeps the original mesh, so there are now two copies ---
        # one optimized for rendering, one for collisions.

        self.environ = loader.loadModel("models/world")
        self.environ.reparentTo(render)

        # Create the main character

        playerStartPos = self.environ.find("**/start_point").getPos()
        self.player = Actor("models/player",
                           {"run": "models/player-run",
                            "walk": "models/player-walk"})
        self.player.reparentTo(render)
        self.player.setScale(.2)
        self.player.setPos(playerStartPos + (0, 0, 0.5))

        # Create a floater object, which floats 2 units above player.  We
        # use this as a target for the camera to look at.

        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(self.player)
        self.floater.setZ(CAMERA_TARGET_HEIGHT_DELTA)

        self.first_person = False

        def key_dn(name):
            return lambda: self.setKey(name, True)
        def key_up(name):
            return lambda: self.setKey(name, False)
        def quit():
            self.destroy()
        def toggle_first():
            self.first_person = not self.first_person
        # Accept the control keys for movement and rotation
        key_map = [
            # key              command        action                   help
            # ---              -------        ------                   ----
            ("escape",         "esc",         lambda: quit(),          '[ESC]: Quit'),
            ("arrow_left",     'left',        key_dn("left"),          "[Left Arrow]: Rotate Left"),
            ("arrow_left-up",  'left',        key_up("left"),          None),
            ("arrow_right",    'right',       key_dn("right"),         "[Right Arrow]: Rotate Right"),
            ("arrow_right-up", 'right',       key_up("right"),         None),
            ("arrow_up",       'forward',     key_dn("forward"),       "[Up Arrow]: Run Forward"),
            ("arrow_up-up",    'forward',     key_up("forward"),       None),
            ("arrow_down",     'backward',    key_dn("backward"),      "[Down Arrow]: Run Backward"),
            ("arrow_down-up",  'backward',    key_up("backward"),      None),
            ("a",              'cam-left',    key_dn("cam-left"),      "[A]: Rotate Camera Left"),
            ("a-up",           'cam-left',    key_up("cam-left"),      None),
            ("s",              'cam-right',   key_dn("cam-right"),     "[S]: Rotate Camera Right"),
            ("s-up",           'cam-right',   key_up("cam-right"),     None),
            ('f',              'first-pers',  lambda: toggle_first(),  '[F]: Toggle first-person'),
            ]
        self.keyMap = {}
        inst = Instructions()
        for key, command, action, description in key_map:
            if command:
                self.setKey(command, False)
            self.accept(key, action)
            if description:
                inst.add(description)

        taskMgr.add(self.move, "moveTask")

        # Game state variables
        self.isMoving = False

        # Set up the camera
        self.disableMouse()
        self.camera.setPos(self.player.getX(), self.player.getY() + 10, 2)

        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  One ray will
        # start above player's head, and the other will start above the camera.
        # A ray may hit the terrain, or it may hit a rock or a tree.  If it
        # hits the terrain, we can detect the height.  If it hits anything
        # else, we rule that the move is illegal.
        self.cTrav = CollisionTraverser()

        self.playerGroundRay = CollisionRay()
        self.playerGroundRay.setOrigin(0, 0, 9)
        self.playerGroundRay.setDirection(0, 0, -1)
        self.playerGroundCol = CollisionNode('playerRay')
        self.playerGroundCol.addSolid(self.playerGroundRay)
        self.playerGroundCol.setFromCollideMask(CollideMask.bit(0))
        self.playerGroundCol.setIntoCollideMask(CollideMask.allOff())
        self.playerGroundColNp = self.player.attachNewNode(self.playerGroundCol)
        self.playerGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.playerGroundColNp, self.playerGroundHandler)

        self.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0, 0, 9)
        self.camGroundRay.setDirection(0, 0, -1)
        self.camGroundCol = CollisionNode('camRay')
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(CollideMask.bit(0))
        self.camGroundCol.setIntoCollideMask(CollideMask.allOff())
        self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol)
        self.camGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)

        # Uncomment this line to see the collision rays
        self.playerGroundColNp.show()
        self.camGroundColNp.show()

        # Uncomment this line to show a visual representation of the
        # collisions occuring
        self.cTrav.showCollisions(render)

        # Create some lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.3, .3, .3, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection((-5, -5, -5))
        directionalLight.setColor((1, 1, 1, 1))
        directionalLight.setSpecularColor((1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambientLight))
        render.setLight(render.attachNewNode(directionalLight))

    # Records the state of the arrow keys
    def setKey(self, key, value):
        self.keyMap[key] = value

    # Accepts arrow keys to move either the player or the menu cursor,
    # Also deals with grid checking and collision detection
    def move(self, task):

        # Get the time that elapsed since last frame.  We multiply this with
        # the desired speed in order to find out with which distance to move
        # in order to achieve that desired speed.
        dt = globalClock.getDt()

        # If the camera-left key is pressed, move camera left.
        # If the camera-right key is pressed, move camera right.

        if self.keyMap["cam-left"]:
            self.camera.setX(self.camera, -20 * dt)
        if self.keyMap["cam-right"]:
            self.camera.setX(self.camera, +20 * dt)

        # save player's initial position so that we can restore it,
        # in case he falls off the map or runs into something.

        startpos = self.player.getPos()

        # If a move-key is pressed, move player in the specified direction.

        if self.keyMap["left"]:
            self.player.setH(self.player.getH() + 300 * dt)
        if self.keyMap["right"]:
            self.player.setH(self.player.getH() - 300 * dt)
        if self.keyMap["forward"]:
            self.player.setY(self.player, -25 * dt)
        if self.keyMap["backward"]:
            self.player.setY(self.player, 25 * dt)

        # If player is moving, loop the run animation.
        # If he is standing still, stop the animation.

        if self.keyMap["forward"] or self.keyMap["backward"] or self.keyMap["left"] or self.keyMap["right"]:
            if self.isMoving is False:
                self.player.loop("run")
                self.isMoving = True
        else:
            if self.isMoving:
                self.player.stop()
                self.player.pose("walk", 5)
                self.isMoving = False

        # If the camera is too far from player, move it closer.
        # If the camera is too close to player, move it farther.

        if self.first_person:
            self.camera.setPos(self.player.getPos())
        else:
            camvec = self.player.getPos() - self.camera.getPos()
            camvec.setZ(0)
            camdist = camvec.length()
            camvec.normalize()
            if camdist > CAMERA_DISTANCE_MAX:
                self.camera.setPos(self.camera.getPos() + camvec * (camdist - int(CAMERA_DISTANCE_MAX)))
                camdist = CAMERA_DISTANCE_MAX
                if camdist < CAMERA_DISTANCE_MIN:
                    self.camera.setPos(self.camera.getPos() - camvec * (int(CAMERA_DISTANCE_MIN) - camdist))
                    camdist = CAMERA_DISTANCE_MIN

        # Normally, we would have to call traverse() to check for collisions.
        # However, the class ShowBase that we inherit from has a task to do
        # this for us, if we assign a CollisionTraverser to self.cTrav.
        self.cTrav.traverse(render)

        # Adjust player's Z coordinate.  If player's ray hit terrain,
        # update his Z. If it hit anything else, or didn't hit anything, put
        # him back where he was last frame.

        entries = list(self.playerGroundHandler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

        if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain":
            self.player.setZ(entries[0].getSurfacePoint(render).getZ())
        else:
            self.player.setPos(startpos)

        # Keep the camera at one foot above the terrain,
        # or two feet above player, whichever is greater.

        entries = list(self.camGroundHandler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

        if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain":
            self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + CAMERA_POSITION_HEIGHT_DELTA_MIN)
        if self.camera.getZ() < self.player.getZ() + CAMERA_POSITION_HEIGHT_DELTA_MAX:
            self.camera.setZ(self.player.getZ() + CAMERA_POSITION_HEIGHT_DELTA_MAX)

        # The camera should look in player's direction,
        # but it should also try to stay horizontal, so look at
        # a floater which hovers above player's head.
        self.camera.lookAt(self.floater)

        return task.cont
Beispiel #33
0
class TutorialGame(ShowBase):
    def __init__(self):
        # call superclass init (no implicit chaining)
        ShowBase.__init__(self)

        ######### load player model
        self.player = loader.loadModel("panda")
        self.player.setScale(0.1)
        self.player.reparentTo(render)
        self.player.setY(10)

        ######### move camera for tilted overhead view
        base.disableMouse()
        base.camera.setPos(0, -10, 10)
        base.camera.lookAt(self.player)

        ######### load "obstacle" model
        self.obs = loader.loadModel("models/box")
        self.obs.setScale(0.1)

        # re-use same model for multiple objects
        self.OBS = []
        for i in range(0, 4):
            n = render.attachNewNode("Obstacle")
            self.obs.instanceTo(n)
            n.reparentTo(render)
            n.setPos(-1.5 + random.random() * 8.0, 8.5 + random.random() * 8.0,
                     0)
            self.OBS.append(n)

        ######### add directional light
        dlight = DirectionalLight('dlight')
        dlight.setColor((1, 1, 1, 1))
        self.dlnp = render.attachNewNode(dlight)

        render.setLight(self.dlnp)
        dlight.setDirection(LVector3(-0.8, 0, 0))

        ######### setup other systems
        self.setupInput()
        self.setupCollision()

        # pre-frame update
        taskMgr.add(self.update, "update")

# helper for taking in input

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

    def setupInput(self):
        self.keyMap = {"left": 0, "right": 0, "fwd": 0, "back": 0}

        # this sets values in keyMap to True when keys are pressed
        self.accept("escape", sys.exit)
        self.accept("w", self.setKey, ["fwd", True])
        self.accept("a", self.setKey, ["left", True])
        self.accept("s", self.setKey, ["back", True])
        self.accept("d", self.setKey, ["right", True])

        # this sets values in keyMap to False when keys are released
        self.accept("w-up", self.setKey, ["fwd", False])
        self.accept("a-up", self.setKey, ["left", False])
        self.accept("s-up", self.setKey, ["back", False])
        self.accept("d-up", self.setKey, ["right", False])

    def setupCollision(self):
        cs = CollisionSphere(0, 0, 0, 10)
        cnodePath = self.player.attachNewNode(CollisionNode('cnode'))
        cnodePath.node().addSolid(cs)
        cnodePath.show()
        for o in self.OBS:
            ct = CollisionBox(0, 1, 1, 0.5)
            cn = o.attachNewNode(CollisionNode('ocnode'))
            cn.node().addSolid(ct)
            cn.show()
        pusher = CollisionHandlerPusher()
        pusher.addCollider(cnodePath, self.player)
        self.cTrav = CollisionTraverser()
        self.cTrav.addCollider(cnodePath, pusher)
        self.cTrav.showCollisions(render)

    # move the player based on the keyMap input
    def update(self, task):
        dt = globalClock.getDt()

        # user input
        if self.keyMap["fwd"]:
            self.player.setY(self.player.getY() + SPEED * dt)
        if self.keyMap["back"]:
            self.player.setY(self.player.getY() - SPEED * dt)
        if self.keyMap["left"]:
            self.player.setX(self.player.getX() - SPEED * dt)
        if self.keyMap["right"]:
            self.player.setX(self.player.getX() + SPEED * dt)

        return task.cont
Beispiel #34
0
class TheWorld(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.params = {
            "mouse_x": 0,
            "mouse_y": 0,
        }

        self.disableMouse()
        self.cmd_mgr = commandmgr.TheWorldCommandMgr(self)
        util.hidden_relative_mouse(self)
        for cmd_str, cmd_fn in self.cmd_mgr.mapping.items():
            self.accept(cmd_str, cmd_fn)

        # environment
        self.setBackgroundColor(.0, .0, .0, 1)

        # # ground
        self.ground_cube = self.loader.loadModel("cuby.gltf")
        self.ground_cube.setColor(1, 1, 1, 1)
        ground_cube_size = Vec3(2, 2, .4)
        self.ground_cube.setScale(ground_cube_size)

        self.ground = self.render.attachNewNode("ground")

        grid_size = 5
        grid_max = grid_size - 1
        dist = 8
        grid_coordinates = itertools.product(range(grid_size),
                                             range(grid_size))

        def normalize(x_y):
            x, y = x_y
            return (x - grid_max / 2) * dist, (y - grid_max / 2) * dist

        for x, y in map(normalize, grid_coordinates):
            placeholder = self.ground.attachNewNode("placeholder")
            placeholder.setPos(x, y, -ground_cube_size.z)
            self.ground_cube.instanceTo(placeholder)

            # collision ground
            coll_node = CollisionNode(f"ground_{x}_{y}")
            coll_node.setFromCollideMask(CollideMask.allOff())
            coll_node.setIntoCollideMask(CollideMask.bit(0))
            nodepath = placeholder.attachNewNode(coll_node)
            nodepath.node().addSolid(
                CollisionBox(Point3(0, 0, 0), ground_cube_size.x,
                             ground_cube_size.y, ground_cube_size.z))

        # lighting
        ambient_light = AmbientLight("ambient_light")
        ambient_light.setColor((.2, .2, .2, 1))
        alight = self.render.attachNewNode(ambient_light)
        self.render.setLight(alight)

        # actor
        self.actor_obj = Actor(self, self.render, "cuby.gltf")
        self.actor = self.actor_obj.node
        self.actor.setColor(cube_color)

        # # collision actor
        self.cTrav = CollisionTraverser('traverser')
        self.cTrav.showCollisions(self.actor)

        self.actor_coll = CollisionNode('actor')
        self.actor_coll.addSolid(CollisionBox(Point3(0, 0, 0), 1, 1, 1))
        self.actor_coll.setFromCollideMask(CollideMask.bit(0))
        self.actor_coll.setIntoCollideMask(CollideMask.allOff())
        self.actor_coll_np = self.actor.attachNewNode(self.actor_coll)
        self.pusher = CollisionHandlerPusher()

        self.pusher.addCollider(self.actor_coll_np, self.actor)
        self.cTrav.addCollider(self.actor_coll_np, self.pusher)

        # lighting
        self.centerlight_np = self.render.attachNewNode("basiclightcenter")
        self.centerlight_np.hprInterval(4, (360, 0, 0)).loop()

        d, h = 8, 1
        self.basic_point_light((-d, 0, h), (.0, .0, .7, 1), "left_light")
        self.basic_point_light((d, 0, h), (.0, .7, 0, 1), "right_light")
        self.basic_point_light((0, d, h), (.7, .0, .0, 1), "front_light")
        self.basic_point_light((0, -d, h), (1, 1, 1, 1), "back_light")

        self.actor_stater = Stater(self.actor)
        self.cmd_mgr.set_actor_stater(self.actor_stater)
        self.actor_mover = Mover(self, self.actor_obj, self.actor_stater)

        self.camera.wrtReparentTo(self.actor)
        self.camera.setPos(Vec3(0, 4, 1).normalized() * cam_dist)
        self.camera.lookAt(0, 0, 0)

        self.taskMgr.add(self.update_params, "paramsTask")
        self.taskMgr.add(self.actor_mover.execute, "moveTask")
        self.taskMgr.add(self.log, "logTask")

        self.render.setShaderAuto()

    def update_params(self, task):
        if self.mouseWatcherNode.hasMouse():
            self.params["mouse_x"] = self.mouseWatcherNode.getMouseX()
            self.params["mouse_y"] = self.mouseWatcherNode.getMouseY()
            self.win.movePointer(0,
                                 self.win.getProperties().getXSize() // 2,
                                 self.win.getProperties().getYSize() // 2)
        self.params["actor_pos"] = self.actor.getPos()
        return Task.cont

    def log(self, task):
        return Task.cont

    def basic_point_light(self,
                          position,
                          color,
                          name,
                          attenuation=(1, 0, 0.02)):
        light = PointLight(name)
        light.setColor(color)
        light.setAttenuation(attenuation)
        # light.setShadowCaster(True)
        # light.getLens().setNearFar(5, 20)
        plight = self.centerlight_np.attachNewNode(light)
        plight.setPos(position)
        self.render.setLight(plight)

        light_cube = self.loader.loadModel("cuby.gltf")
        light_cube.reparentTo(plight)
        light_cube.setScale(0.25)
        material = Material()
        material.setEmission(color)
        light_cube.setMaterial(material)
Beispiel #35
0
class PandaPath(ShowBase):
    def __init__(self):
        # Set up the window, camera, etc.
        ShowBase.__init__(self)

        # Set the background color to black
        self.win.setClearColor((0, 0, 0, 1))

        # This is used to store which keys are currently pressed.
        self.key_map = {"left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0}

        # Post the Instruction
        self.title = add_title("Panda 3D Demo")

        # Instructions
        self.inst1 = add_instructions(0.06, "[ESC]: Quit")
        self.inst2 = add_instructions(0.12, "[Left Arrow]: Rotate Left")
        self.inst3 = add_instructions(0.18, "[Right Arrow]: Rotate Ralph Right")
        self.inst4 = add_instructions(0.24, "[Up Arrow]: Run Ralph Forward")
        # self.inst6 = add_instructions(0.30, "[A]: Rotate Camera Left")
        # self.inst7 = add_instructions(0.36, "[S]: Rotate Camera Right")

        # Load the Environment Model
        self.environ = self.loader.loadModel(ENVIRONMENT)
        # Reparent the model to the render controller
        self.environ.reparentTo(render)

        # Apply scale and position transform on the model
        # self.environ.setScale(0.25, 0.25, 0.25)
        # self.environ.setPos(-8, 42, 0)

        # Create the Main Character
        # Load and transform the panda actor
        ralph_start_pos = self.environ.find("**/start_point").getPos()
        self.ralph = Actor(RALPH_ACTOR, RALPH_ACTIONS)

        # self.ralph.setScale(0.005, 0.005, 0.005)
        self.ralph.reparentTo(render)
        # Loop it's animation
        self.ralph.setScale(0.2)
        self.ralph.setPos(ralph_start_pos + (0, 0, 0.5))
        # self.ralph.loop("walk")

        # Create a floater object, which floats 2 units above rlaph. We use this as a target for the camera to look at
        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(self.ralph)
        # 2 Units above Ralph
        self.floater.setZ(2.0)

        # Configure the Camera
        # Add the spin camera taks procedure to the taks manager
        # self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")

        # Accept certain control keys
        self.accept("escape", sys.exit)
        self.accept("arrow_left", self.set_key, ["left", True])
        self.accept("arrow_right", self.set_key, ["right", True])
        self.accept("arrow_up", self.set_key, ["forward", True])
        self.accept("a", self.set_key, ["cam-left", True])
        self.accept("s", self.set_key, ["cam-right", True])
        self.accept("arrow_left-up", self.set_key, ["left", False])
        self.accept("arrow_right-up", self.set_key, ["right", False])
        self.accept("arrow_up-up", self.set_key, ["forward", False])
        self.accept("a-up", self.set_key, ["cam-left", False])
        self.accept("s-up", self.set_key, ["cam-right", False])

        # Game States
        taskMgr.add(self.move, "moveTask")
        self.is_moving = False

        self.disableMouse()
        self.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 2)
        self.camera.lookAt(self.floater)

        """
        Detect the height of hte terrain by creating a collision ray and casting it down towards the terrain.

        One ray will start above ralph's head and the other will start above the camera.
        A ray may hit the terrain, or it may hit a rock or a tree.
        If it hits the terrain we ca ndetect the height.

        If it hits anything else, we rule that the move is illegal.
        """
        self.cTrav = CollisionTraverser()

        # Create a vector, it's location is at the top of ralph's head
        self.ralph_ground_ray = CollisionRay()
        self.ralph_ground_ray.setOrigin(0, 0, 9)  # Top of ralph's head
        self.ralph_ground_ray.setDirection(0, 0, -1)  # Points -Z axis

        # Create a Collision node
        self.ralph_ground_col = CollisionNode("ralph_ray")  # Give the node a name
        self.ralph_ground_col.addSolid(self.ralph_ground_ray)  # the vector from ralph's head to the ground is solid
        self.ralph_ground_col.setFromCollideMask(CollideMask.bit(0))  # ??
        self.ralph_ground_col.setIntoCollideMask(
            CollideMask.allOff()
        )  # ?? This seems like it defines the behavior of ray
        self.ralph_ground_col_np = self.ralph.attachNewNode(self.ralph_ground_col)  # Attach the ray to ralph
        self.ralph_ground_handler = (
            CollisionHandlerQueue()
        )  # I think that when a collision occurs it sends through this
        self.cTrav.addCollider(self.ralph_ground_col_np, self.ralph_ground_handler)  # Attach the collision

        """
        Attach the a camera ray to the camera
        """
        self.cam_ground_ray = CollisionRay()
        self.cam_ground_ray.setOrigin(0, 0, 9)
        self.cam_ground_ray.setDirection(0, 0, -1)
        self.cam_ground_col = CollisionNode("camera_ray")
        self.cam_ground_col.addSolid(self.cam_ground_ray)
        self.cam_ground_col.setFromCollideMask(CollideMask.bit(0))
        self.cam_ground_col.setIntoCollideMask(CollideMask.allOff())
        self.cam_ground_col_np = self.camera.attachNewNode(self.cam_ground_col)
        self.cam_ground_handler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.cam_ground_col_np, self.cam_ground_handler)

        # Uncomment the following lines to view the rays
        self.ralph_ground_col_np.show()
        self.cam_ground_col_np.show()

        # Uncomment this line to show a visual representation of the Collision occuring
        self.cTrav.showCollisions(render)

        # Create some lighting
        ambient_light = AmbientLight("ambient_light")
        ambient_light.setColor((0.3, 0.3, 0.3, 1))
        directional_light = DirectionalLight("directional_light")
        directional_light.setDirection((-5, -5, -5))
        directional_light.setColor((1, 1, 1, 1))
        directional_light.setSpecularColor((1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambient_light))
        render.setLight(render.attachNewNode(directional_light))

        # Add Cube
        X_OFFSET = 0
        Y_OFFSET = -3
        Z_OFFSET = 1

        CUBE_SIZE = 2

        x, y, z = ralph_start_pos
        x += X_OFFSET
        y += Y_OFFSET
        z += Z_OFFSET

        # make_cube(x, y, z, CUBE_SIZE)

    def set_key(self, key, value):
        self.key_map[key] = value

    def move(self, task):
        dt = globalClock.getDt()
        # print "DT: %f" % dt

        # ****: Movement
        # Get Ralph's position before we do anything to it
        start_pos = self.ralph.getPos()

        # User wants to turn
        if self.key_map["left"]:
            self.ralph.setH(self.ralph.getH() + 300 * dt)
        if self.key_map["right"]:
            self.ralph.setH(self.ralph.getH() - 300 * dt)

        # Perform a move forward
        if self.key_map["forward"]:
            self.ralph.setY(self.ralph, -25 * dt)

        # ****: Animation
        if self.key_map["forward"] or self.key_map["left"] or self.key_map["right"]:
            if not self.is_moving:
                self.ralph.loop("run")
                self.is_moving = True

        else:
            if self.is_moving:
                self.ralph.stop()
                self.ralph.pose("walk", 5)
                self.is_moving = False

        # ****: Camera Movement
        if self.key_map["cam-left"]:
            self.camera.setX(self.camera, -20 * dt)
        elif self.key_map["cam-right"]:
            self.camera.setX(self.camera, +20 * dt)

        # If the camera is too far from ralph, move it closer
        # If the camera is too close to ralph, move it farther
        camvec = self.ralph.getPos() - self.camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()
        camvec.normalize()
        if camdist > 10.0:
            self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10))
            camdist = 10.0
        if camdist < 5.0:
            self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist))
            camdist - 5.0

        # ****: Collision
        """
        Normally, we would have to call traverse() to check for collisions.

        However, the class ShowBase that we inherit from has a task to do this for us

        If we assign a CollisionTraverser to self.cTrav

        Adjust ralph's Z coordinate. If ralph's ray hit terrain update his Z.

        If it hit anything else, or didn't hit anything put him back where he was last frame.
        """

        entries = list(self.ralph_ground_handler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())
        # print "Entry count: %d" % len(entries)

        if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain":
            self.ralph.setZ(entries[0].getSurfacePoint(render).getZ())
        else:
            self.ralph.setPos(start_pos)

        # Keep the camera at one foot above the terrain or two feet above ralph, whichever is greater
        entries = list(self.cam_ground_handler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

        if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain":
            self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0)
        if self.camera.getZ() < self.ralph.getZ() + 2.0:
            self.camera.setZ(self.ralph.getZ() + 2.0)

        """
        The camera should look in rlaphs direction, but it should also try to stay horizontal so look at a
        floater which hovers above ralph's head
        """
        self.camera.lookAt(self.floater)
        return task.cont
Beispiel #36
0
class Grabber(object):
    def __init__( self, levitNP):
        """ A widget to position, rotate, and scale Panda 3D Models and Actors
            * handleM1 decides what to do with a mouse1 click
            -- object selection by calling handleSelection when the grabModel is inactive (hidden)
            -- object manipulation by calling handleManipulationSetup (sets the stage for and launches the dragTask)

            isHidden() when nothing is selected
            isDragging means not running collision checks for selection setup and LMB is pressed

            call handleM1 from another class to push control up
            in the program hierarchy (remove inner class calls)
        """
        # TODO remove selection functionality from grabber and put it in a selector class
        self.levitorNP = levitNP  # TODO remove this and use barebonesNP
        self.selected = None
        self.initialize()

    def initialize(self):
        """Reset everything except LevitorNP and selected, also called inside __init__"""
        self.notify = DirectNotify().newCategory('grabberErr')
        self.currPlaneColNorm = Vec3(0.0)
        self.isCameraControlOn = False
        self.isDragging = False
        self.isMultiselect = False
        self.grabScaleFactor = .075
        self.currTransformDir = Point3(0.0)
        self.interFrameMousePosition = Point3(0.0)
        self.init3DemVal = Point3(0.0)
        # initCommVal holds the value before a command operation has taken place
        self.initialCommandTrgVal = None
        # To load the grabber model, this climbs up the absolute path to /barebones/ to gain access to the model folder
        self.grabModelNP = loader.loadModel(Filename.fromOsSpecific(
                                            ntpath.split( ntpath.split(inspect.stack()[0][1])[0] )[0])
                                            + '/EditorModels/widget')
        self.grabModelNP.setPos(0.0, 0.0, 0.0)
        self.grabModelNP.setBin("fixed", 40)
        self.grabModelNP.setDepthTest(False)
        self.grabModelNP.setDepthWrite(False)
        self.transformOpEnum = Enum('rot, scale, trans')
        self.currTransformOperation = None
        # TODO For readability, use this enum in the nested if/else as was the original intent.
        self.grabInd = Enum('xRot, yRot, zRot, xScaler, yScaler, zScaler, xTrans, yTrans, zTrans, xyTrans, xzTrans, zyTrans, grabCore')
        grbrNodLst = [self.grabModelNP.find("**/XRotator;+h-s-i"),       # 0
                       self.grabModelNP.find("**/YRotator;+h-s-i"),      # 1
                       self.grabModelNP.find("**/ZRotator;+h-s-i"),      # 2 end rotate
                       self.grabModelNP.find("**/XScaler;+h-s-i"),       # 3
                       self.grabModelNP.find("**/YScaler;+h-s-i"),       # 4
                       self.grabModelNP.find("**/ZScaler;+h-s-i"),       # 5 end scale
                       self.grabModelNP.find("**/XTranslator;+h-s-i"),   # 6
                       self.grabModelNP.find("**/YTranslator;+h-s-i"),   # 7
                       self.grabModelNP.find("**/ZTranslator;+h-s-i"),   # 8 end translate / end single dir operations
                       self.grabModelNP.find("**/XYTranslator;+h-s-i"),  # 9
                       self.grabModelNP.find("**/XZTranslator;+h-s-i"),  # 10
                       self.grabModelNP.find("**/ZYTranslator;+h-s-i"),  # 11 end bi-directional operations
                       self.grabModelNP.find("**/WidgetCore;+h-s-i")]    # 12
        #Mat4.yToZUpMat()  # change coordinate to z up
        grbrNodLst[12].getParent().setHprScale(0, 0, 0, 1, 1, -1)
        self.grabModelNP.setPythonTag('grabberRoot', grbrNodLst)
        self.grabModelNP.reparentTo(BBGlobalVars.bareBonesObj.levitorNP)
        self.grabModelNP.hide()
        #self.grabIntoBitMask = COLLISIONMASKS
        self.grabModelNP.setCollideMask(COLLISIONMASKS['default'])
        self.grabModelNP.setPythonTag('grabber', self)

        ##############################################################################
        # This whole section is the basics for setting up mouse selection
        # --The mouse events are added in the events section (next)

        # Create the collision node for the picker ray to add traverser as a 'from' collider
        self.grabberColNode = CollisionNode('grabberMouseRay')
        # Set the collision bitmask
        # TODO: define collision bitmask (let user define thiers? likely not)
        self.defaultBitMask = GeomNode.getDefaultCollideMask()
        self.grabberColNode.setFromCollideMask(self.defaultBitMask)
        self.grabberRayColNP = camera.attachNewNode(self.grabberColNode)
        # Create the grabberRay and add it to the picker CollisionNode
        self.grabberRay = CollisionRay(0.0, 0.0, 0.0,
                                       0.0, 1.0, 0.0)
        self.grabberRayNP = self.grabberColNode.addSolid(self.grabberRay)
        # create a collision queue for the traverser
        self.colHandlerQueue = CollisionHandlerQueue()
        # Create collision traverser
        self.colTraverser = CollisionTraverser('grabberTraverser')
        # Set the collision traverser's 'fromObj' and handler
        # e.g. trav.addCollider( fromObj, handler )
        self.colTraverser.addCollider(self.grabberRayColNP, self.colHandlerQueue)


        ############################################################
        # setup event handling with the messenger
        # URGENT remove all of this messenger code throughout Grabber, especially the camera control
        # disable the mouse when the ~ is pressed (w/o shift)
        self.disableCamera()                            # disable camera control by the mouse
        messenger.accept('`', self, self.enableCamera)  # enable camera control when the ~ key is pressed w/o shift
        messenger.accept('`-up', self, self.disableCamera)  # disable camera control when the ~ key is released

        # handle mouse selection/deselection & manipulating the scene
        messenger.accept('mouse1', self, self.handleM1, persistent=1)  # deselect in event handler

        taskMgr.add(self.scaleGrabber, 'scaleGrabber')
        # ////////////////////////////////////////////////////////////////////
        # comment out: good for debug info
        #taskMgr.add(self.watchMouseColl, name='grabberDebug')
        #this is only good for seeing types and hierarchy
        #self.grabModelNP.ls()
        #render.ls()
        # self.frames = 0  #remove
        # self.axis = loader.loadModel("zup-axis")
        # self.axis.reparentTo(self.grabModelNP)
        # self.axis.setScale(.15)
        # self.axis.setPos(0.0)
        # self.grabModelNP.append( 'newAttrib', self)
        # setattr( self.grabModelNP, 'newAttrib', self)


    def prepareForPickle(self):
        self.colTraverser = None     # Traversers are not picklable
        self.defaultBitMask = None   # BitMasks "..."
        # self.grabIntoBitMask = None  # "..."
        self.colHandlerQueue = None  # CollisonHandlerQueue "..."
        self.grabModelNP.removeNode()
        self.grabModelNP = None
        taskMgr.remove('scaleGrabber')


    def recoverFromPickle(self):
        self.initialize()
        if self.selected is not None:
            self.grabModelNP.setPos(render, self.selected.getPos(render))
            self.grabModelNP.show()
        print "grabber sel ", self.selected, " isHidden() ", self.grabModelNP.isHidden(), '\n'
        taskMgr.add(self.scaleGrabber, 'scaleGrabber')

    #### May use to gain control over pickling.
    # def __repr__(self): # for pickling purposes
    #     if self.colTraverser:
    #         self.colTraverser = None
    #
    #     dictrepr = dict.__repr__(self.__dict__)
    #     dictrepr = '%r(%r)' % (type(self).__name__, dictrepr)
    #     print dictrepr  # REMOVE
    #     return dictrepr


    def watchMouseColl(self, task):
        """ This exists for debugging purposes to perpetually watch mouse collisions.
        """
        # TODO make this highlight objects under the mouse for predictable object selection/grabber operations
        self.colTraverser.showCollisions(render)
        if base.mouseWatcherNode.hasMouse() and False == self.isCameraControlOn:
            # This gives the screen coordinates of the mouse.
            mPos = base.mouseWatcherNode.getMouse()
            # This makes the ray's origin the camera and makes the ray point
            # to the screen coordinates of the mouse.
            self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY())
            # traverses the graph for collisions
            self.colTraverser.traverse(render)
        return task.cont


    def scaleGrabber(self, task):
        if self.grabModelNP.isHidden():
            return task.cont
        coreLst = self.grabModelNP.getPythonTag('grabberRoot')
        camPos = self.grabModelNP.getRelativePoint(self.grabModelNP, camera.getPos())

        if camPos.z >= 0:        # 1-4
            if camPos.x > 0.0 <= camPos.y:    # quad 1
                coreLst[12].getParent().setScale( 1, 1, -1)

            elif camPos.x < 0.0 <= camPos.y:  # quad 2
                coreLst[12].getParent().setScale( -1, 1, -1)

            elif camPos.x < 0.0 >= camPos.y:  # quad 3
                coreLst[12].getParent().setScale( -1, -1, -1)

            elif camPos.x > 0.0 >= camPos.y:  # quad 4
                coreLst[12].getParent().setScale( 1, -1, -1)

            else:
                self.notify.warning("if-else default, scaleGrabber cam.z > 0")

        else:      # 5-8
            if camPos.x > 0.0 <= camPos.y:    # quad 5
                coreLst[12].getParent().setScale( 1, 1, 1)

            elif camPos.x < 0.0 <= camPos.y:  # quad 6
                coreLst[12].getParent().setScale( -1, 1, 1)

            elif camPos.x < 0.0 >= camPos.y:  # quad 7
                coreLst[12].getParent().setScale( -1, -1, 1)

            elif camPos.x > 0.0 >= camPos.y:  # quad 8
                coreLst[12].getParent().setScale( 1, -1, 1)

            else:
                self.notify.warning("if-else default, scaleGrabber cam.z z < 0")


        distToCam = (camera.getPos() - render.getRelativePoint(BBGlobalVars.currCoordSysNP, self.grabModelNP.getPos())).length()
        self.grabModelNP.setScale(self.grabScaleFactor * distToCam,
                                  self.grabScaleFactor * distToCam,
                                  self.grabScaleFactor * distToCam)
        # keep the position identical to the selection
        # for when outside objects like undo/redo move selected
        self.grabModelNP.setPos(render, self.selected.getPos(render))
        return task.cont

    # TODO find a way to move camera control to a proper camera handler, perhaps move these to a global
    def enableCamera(self):
        self.isCameraControlOn = True
        PanditorEnableMouseFunc()

    def disableCamera(self):
        self.isCameraControlOn = False
        PanditorDisableMouseFunc()


    def handleM3(self):
        """Deselect the selected object."""
        if not self.grabModelNP.isHidden() and not self.isCameraControlOn:
            # if the grab model is in the scene and the camera is not in control
            if base.mouseWatcherNode.hasMouse() and not self.isDragging:
                # we're ignoring accidental mouse3 clicks while dragging here with not isDragging
                self.selected = None              # empty the selected, will be turned back on once something's selected
                messenger.ignore('mouse3', self)  # turn the deselect event off
                self.grabModelNP.hide()           # hide the grab model and set it back to render's pos
                self.grabModelNP.setPos(0.0)


    def handleM1Up(self):
        """Stop dragging the selected object."""
        taskMgr.remove('mouse1Dragging')
        self.isDragging = False
        self.currTransformOperation = None  # NOTE other references have been added, but no other object references them
        # record the mouse1 operation
        BBGlobalVars.undoHandler.record(self.selected, CommandUndo([self.initialCommandTrgVal],
                                                                    self.selected.setMat, self.selected.getMat(render)))
        messenger.ignore('mouse1-up', self)


    def handleM1(self):
        """Decides how to handle a mouse1 click."""
        if self.isCameraControlOn:
            return

        if base.mouseWatcherNode.hasMouse():
            # give the grabber first chance
            if self.grabModelNP.isHidden():
                # no collisions w/ grabber or nothing selected
                # handle selection with scene objects
                self.handleSelection()

            elif not self.isDragging:
                # The grabber is in place but not dragging. Get ready to drag.
                self.handleManipulationSetup()  # it'll call self.handleSelection() if no collision w/ grabber
                # TODO (if warranted) make self.handleManipulationSetup() return false if no col w/ grabber, call selection here instead


    def handleManipulationSetup(self):
        """Sets up all the attributes needed for the mouse dragging task."""
        # This makes the ray's origin the camera and makes the ray point
        # to the screen coordinates of the mouse.
        if self.isDragging:
            return
        camVec = self.grabModelNP.getRelativeVector(self.grabModelNP, camera.getPos())
        mPos = base.mouseWatcherNode.getMouse()
        self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY())
        self.colTraverser.traverse(self.grabModelNP)  # look for collisions on the grabber

        if not self.isCameraControlOn and self.colHandlerQueue.getNumEntries() > 0 and not self.grabModelNP.isHidden():
            # see if collided with the grabber if not handle re or multi selection
            self.colHandlerQueue.sortEntries()
            grabberObj = self.colHandlerQueue.getEntry(0).getIntoNodePath()
            grabberLst = self.grabModelNP.getPythonTag('grabberRoot')  # see __init__

            # the index gives the operations rot < 3 scale < 6 trans < 9 trans2D < 12
            # mod index gives axis 0 == x, 1 == y, 2 == z
            ind = -1
            for i in range(0, 13):
                if grabberObj == grabberLst[i]:
                    ind = i
                    grabberObj = grabberLst[i]
            # ensure we are not picking ourselves, ahem, the grabber
            assert(not self.grabModelNP.isAncestorOf(self.selected))
            mPos3D = Point3(0.0)
            xVec = Vec3(1, 0, 0)
            yVec = Vec3(0, 1, 0)
            zVec = Vec3(0, 0, 1)
            # TODO: ??? break this up into translate rotate and scale function to make it readable
            if -1 < ind < 3:             # rotate
                if ind % 3 == 0:    # x
                    self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.rot,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))
                elif ind % 3 == 1:  # y
                    self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.rot,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))
                else:               # z
                    self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.rot,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))

            elif ind < 6:                 # scale
                if ind % 3 == 0:    # x
                    self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.scale,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))
                elif ind % 3 == 1:  # y
                    # self.currTransformDir = Point3( 0.0, 1.0, 0.0)
                    self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.scale,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))
                else:               # z
                    # self.currTransformDir = Point3( 0.0, 0.0, 1.0)
                    self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.scale,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))

            elif ind < 9:                 # translate
                if ind % 3 == 0:    # x
                    # if the camera's too flat to the collision plane bad things happen
                    if camVec.angleDeg( zVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, zVec):
                        self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec)

                    elif self.getMousePlaneIntersect(mPos3D, yVec):
                        self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.trans, mPos3D, yVec)

                elif ind % 3 == 1:  # y
                    if camVec.angleDeg( zVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, zVec):
                        self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec)

                    elif self.getMousePlaneIntersect(mPos3D, xVec):
                        self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, xVec)

                else:               # z
                    if camVec.angleDeg( yVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, yVec):
                        self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, yVec)

                    elif self.getMousePlaneIntersect(mPos3D, xVec):
                        self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, xVec)

            elif ind < 12:            # translate 2D
                if ind % 3 == 0:    # xy
                    if self.getMousePlaneIntersect(mPos3D, zVec):
                        self.initializeManipVars(Point3(1.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec)

                elif ind % 3 == 1:  # xz
                    if self.getMousePlaneIntersect(mPos3D, yVec):
                        self.initializeManipVars(Point3(1.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, yVec)
                else:               # zy
                    if self.getMousePlaneIntersect(mPos3D, xVec):
                        self.initializeManipVars(Point3(0.0, 1.0, 1.0), self.transformOpEnum.trans, mPos3D, xVec)

            elif ind == 12:  # scale in three directions
                self.initializeManipVars(Point3(1.0, 1.0, 1.0), self.transformOpEnum.scale,
                                         Point3(mPos.getX(), mPos.getY(), 0.0))

            else:
                self.notify.warning("Grabber Err: no grabber collision when col entries > 0 AND grabber not hidden")

            # Save initial value for save/undo.
            # The end result of the operation is sent to the undo handler on mouse up event.
            if self.selected:
                self.initialCommandTrgVal = self.selected.getMat(render)
        else:
            # no collisions w/ grabber or nothing selected
            # handle reselection or multi-selection (not yet implemented) with other scene obj
            self.handleSelection()


    def handleSelection(self):
        if self.isDragging:
            return

        # First check that the mouse is not outside the screen.
        if base.mouseWatcherNode.hasMouse() and False == self.isCameraControlOn:

            self.grabberColNode.setFromCollideMask(self.defaultBitMask)
            # This gives the screen coordinates of the mouse.
            mPos = base.mouseWatcherNode.getMouse()

            # This makes the ray's origin the camera and makes the ray point
            # to the screen coordinates of the mouse.
            self.colHandlerQueue.clearEntries()
            self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY())
            self.colTraverser.traverse(render)  # look for collisions

            if self.colHandlerQueue.getNumEntries() > 0:
                self.colHandlerQueue.sortEntries()
                grabbedObj = self.colHandlerQueue.getEntry(0).getIntoNodePath()
                if not grabbedObj.findNetTag('pickable').isEmpty():
                    grabbedObj = grabbedObj.findNetTag('pickable')
                    self.selected = grabbedObj
                    self.grabModelNP.setPos(render,
                                            grabbedObj.getPos(render).x,
                                            grabbedObj.getPos(render).y,
                                            grabbedObj.getPos(render).z)
                    self.grabModelNP.show()
                    messenger.accept('mouse3', self, self.handleM3)

    def handleDragging(self, task):
        """ Does the actual work of manipulating objects,
            once the needed attributes have been setup by handleManipulationSetup().
        """

        if not self.isDragging:
            return task.done
        mPos3D = Point3(0.0)
        #
        # This section handles the actual translating rotating or scale after it's been set up in mouse1SetupManip...()
        # ONLY one operation is preformed per frame
        if self.currTransformOperation == self.transformOpEnum.trans:
            # 1st translation, rotation's section is at next elif
            if self.getMousePlaneIntersect(mPos3D, self.currPlaneColNorm):

                # get the difference between the last mouse and this frames mouse
                selectedNewPos = mPos3D - self.interFrameMousePosition
                # store this frames mouse
                self.interFrameMousePosition = mPos3D
                # add the difference to the selected object's pos
                self.selected.setPos(render, self.selected.getPos(render).x + self.currTransformDir.x * selectedNewPos.x,
                                             self.selected.getPos(render).y + self.currTransformDir.y * selectedNewPos.y,
                                             self.selected.getPos(render).z + self.currTransformDir.z * selectedNewPos.z)

                self.grabModelNP.setPos(render, self.selected.getPos(render))

        elif self.currTransformOperation == self.transformOpEnum.rot:
            # 2nd rotation, followed finally by scaling
            # if operating on the z-axis, use the y (vertical screen coordinates otherwise use x (horizontal)
            mPos = base.mouseWatcherNode.getMouse()
            #rotMag = 0.0
            if self.currTransformDir == Vec3( 0.0, 0.0, 1.0):
                rotMag = (mPos.x - self.interFrameMousePosition.x) * 1000
            else:
                rotMag = (self.interFrameMousePosition.y - mPos.y) * 1000

            initPos = self.selected.getPos()
            initPar = self.selected.getParent()
            self.selected.wrtReparentTo(render)
            self.selected.setMat(self.selected.getMat() * Mat4.rotateMat(rotMag, self.currTransformDir))
            self.selected.wrtReparentTo(initPar)
            self.selected.setPos(initPos)

            self.interFrameMousePosition = Point3(mPos.x, mPos.y, 0.0)

        elif self.currTransformOperation == self.transformOpEnum.scale:
            # 3rd and final is scaling
            mPos = base.mouseWatcherNode.getMouse()
            # TODO: make dragging away from the object larger and to the object smaller (not simply left right up down)
            # td The problem with this MAY come if negative, mirrored, scaling is implemented.

            # if operating on the z-axis, use the y (vertical screen coordinates otherwise use x (horizontal)
            if self.currTransformDir == Point3( 0.0, 0.0, 1.0):
                sclMag = (mPos.y - self.interFrameMousePosition.y) * 5.5
            elif self.currTransformDir == Point3( 0.0, 1.0, 0.0):
                sclMag = (mPos.x - self.interFrameMousePosition.x) * 5.5
            else:
                sclMag = (self.interFrameMousePosition.x - mPos.x) * 5.5

            # This is the line that prevents scaling past the origin. Flipping the faces doesn't seem to work.
            if -0.0001 < sclMag < 0.0001:
                sclMag = 0.000001

            # create a dummy node to parent to and position such that applying scale to it will scale selected properly
            dummy = self.levitorNP.attachNewNode('dummy')
            initScl = dummy.getScale()
            # Don't forget the parent. Selected needs put back in place
            initPar = self.selected.getParent()
            initPos = self.selected.getPos()
            self.selected.wrtReparentTo(dummy)

            dummy.setScale(initScl.x + sclMag * self.currTransformDir.x,
                           initScl.y + sclMag * self.currTransformDir.y,
                           initScl.z + sclMag * self.currTransformDir.z)

            # reset selected's parent then destroy dummy
            self.selected.wrtReparentTo(initPar)
            self.selected.setPos(initPos)
            dummy.removeNode()
            dummy = None

            self.interFrameMousePosition = Point3( mPos.x, mPos.y, 0.0)
        else:
            self.notify.error("Err: Dragging with invalid curTransformOperation enum in handleDragging")

        return task.cont  # ended by handleM1Up(), the mouse1-up event handler


    def initializeManipVars(self, transformDir, transformOp, mPos3D, planeNormVec=None):
        self.currTransformDir = transformDir
        self.currPlaneColNorm = planeNormVec  # set the norm for the collision plane to be used in mouse1Dragging
        self.interFrameMousePosition = mPos3D
        self.currTransformOperation = transformOp
        self.isDragging = True
        taskMgr.add(self.handleDragging, 'mouse1Dragging')
        messenger.accept('mouse1-up', self, self.handleM1Up)


    def getMousePlaneIntersect(self, mPos3Dref, normVec):
        mPos = base.mouseWatcherNode.getMouse()
        plane = Plane(normVec, self.grabModelNP.getPos())
        nearPoint = Point3()
        farPoint = Point3()
        base.camLens.extrude(mPos, nearPoint, farPoint)
        if plane.intersectsLine(mPos3Dref,
            render.getRelativePoint(camera, nearPoint),
            render.getRelativePoint(camera, farPoint)):
            return True
        return False



    def destroy(self):
        raise NotImplementedError('Make sure messenger etc are cleared of refs and the model node is deleted')
        self.grabModelNP.clearPythonTag('grabberRoot')
        self.grabModelNP.clearPythonTag('grabber')
        self.grabModelNP = None
        messenger.ignoreAll(self)
Beispiel #37
0
class PandaPath(ShowBase):
    def __init__(self):
        #Set up the window, camera, etc.
        ShowBase.__init__(self)

        #Set the background color to black
        self.win.setClearColor((0, 0, 0, 1))

        # This is used to store which keys are currently pressed.
        self.key_map = {
            "left": 0,
            "right": 0,
            "forward": 0,
            "cam-left": 0,
            "cam-right": 0
        }

        #Post the Instruction
        self.title = add_title("Panda 3D Demo")

        #Instructions
        self.inst1 = add_instructions(0.06, "[ESC]: Quit")
        self.inst2 = add_instructions(0.12, "[Left Arrow]: Rotate Left")
        self.inst3 = add_instructions(0.18,
                                      "[Right Arrow]: Rotate Ralph Right")
        self.inst4 = add_instructions(0.24, "[Up Arrow]: Run Ralph Forward")
        #self.inst6 = add_instructions(0.30, "[A]: Rotate Camera Left")
        #self.inst7 = add_instructions(0.36, "[S]: Rotate Camera Right")

        #Load the Environment Model
        self.environ = self.loader.loadModel(ENVIRONMENT)
        #Reparent the model to the render controller
        self.environ.reparentTo(render)

        #Apply scale and position transform on the model
        #self.environ.setScale(0.25, 0.25, 0.25)
        #self.environ.setPos(-8, 42, 0)

        #Create the Main Character
        #Load and transform the panda actor
        ralph_start_pos = self.environ.find("**/start_point").getPos()
        self.ralph = Actor(RALPH_ACTOR, RALPH_ACTIONS)

        #self.ralph.setScale(0.005, 0.005, 0.005)
        self.ralph.reparentTo(render)
        #Loop it's animation
        self.ralph.setScale(0.2)
        self.ralph.setPos(ralph_start_pos + (0, 0, 0.5))
        #self.ralph.loop("walk")

        #Create a floater object, which floats 2 units above rlaph. We use this as a target for the camera to look at
        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(self.ralph)
        #2 Units above Ralph
        self.floater.setZ(2.0)

        #Configure the Camera
        #Add the spin camera taks procedure to the taks manager
        #self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")

        #Accept certain control keys
        self.accept("escape", sys.exit)
        self.accept("arrow_left", self.set_key, ["left", True])
        self.accept("arrow_right", self.set_key, ["right", True])
        self.accept("arrow_up", self.set_key, ["forward", True])
        self.accept("a", self.set_key, ["cam-left", True])
        self.accept("s", self.set_key, ["cam-right", True])
        self.accept("arrow_left-up", self.set_key, ["left", False])
        self.accept("arrow_right-up", self.set_key, ["right", False])
        self.accept("arrow_up-up", self.set_key, ["forward", False])
        self.accept("a-up", self.set_key, ["cam-left", False])
        self.accept("s-up", self.set_key, ["cam-right", False])

        #Game States
        taskMgr.add(self.move, "moveTask")
        self.is_moving = False

        self.disableMouse()
        self.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 2)
        self.camera.lookAt(self.floater)
        '''
        Detect the height of hte terrain by creating a collision ray and casting it down towards the terrain.

        One ray will start above ralph's head and the other will start above the camera.
        A ray may hit the terrain, or it may hit a rock or a tree.
        If it hits the terrain we ca ndetect the height.

        If it hits anything else, we rule that the move is illegal.
        '''
        self.cTrav = CollisionTraverser()

        #Create a vector, it's location is at the top of ralph's head
        self.ralph_ground_ray = CollisionRay()
        self.ralph_ground_ray.setOrigin(0, 0, 9)  # Top of ralph's head
        self.ralph_ground_ray.setDirection(0, 0, -1)  # Points -Z axis

        #Create a Collision node
        self.ralph_ground_col = CollisionNode(
            'ralph_ray')  # Give the node a name
        self.ralph_ground_col.addSolid(
            self.ralph_ground_ray
        )  # the vector from ralph's head to the ground is solid
        self.ralph_ground_col.setFromCollideMask(CollideMask.bit(0))  # ??
        self.ralph_ground_col.setIntoCollideMask(CollideMask.allOff(
        ))  # ?? This seems like it defines the behavior of ray
        self.ralph_ground_col_np = self.ralph.attachNewNode(
            self.ralph_ground_col)  #Attach the ray to ralph
        self.ralph_ground_handler = CollisionHandlerQueue(
        )  #I think that when a collision occurs it sends through this
        self.cTrav.addCollider(
            self.ralph_ground_col_np,
            self.ralph_ground_handler)  #Attach the collision
        '''
        Attach the a camera ray to the camera
        '''
        self.cam_ground_ray = CollisionRay()
        self.cam_ground_ray.setOrigin(0, 0, 9)
        self.cam_ground_ray.setDirection(0, 0, -1)
        self.cam_ground_col = CollisionNode("camera_ray")
        self.cam_ground_col.addSolid(self.cam_ground_ray)
        self.cam_ground_col.setFromCollideMask(CollideMask.bit(0))
        self.cam_ground_col.setIntoCollideMask(CollideMask.allOff())
        self.cam_ground_col_np = self.camera.attachNewNode(self.cam_ground_col)
        self.cam_ground_handler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.cam_ground_col_np, self.cam_ground_handler)

        #Uncomment the following lines to view the rays
        self.ralph_ground_col_np.show()
        self.cam_ground_col_np.show()

        #Uncomment this line to show a visual representation of the Collision occuring
        self.cTrav.showCollisions(render)

        # Create some lighting
        ambient_light = AmbientLight("ambient_light")
        ambient_light.setColor((0.3, 0.3, 0.3, 1))
        directional_light = DirectionalLight("directional_light")
        directional_light.setDirection((-5, -5, -5))
        directional_light.setColor((
            1,
            1,
            1,
            1,
        ))
        directional_light.setSpecularColor((1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambient_light))
        render.setLight(render.attachNewNode(directional_light))

        #Add Cube
        X_OFFSET = 0
        Y_OFFSET = -3
        Z_OFFSET = 1

        CUBE_SIZE = 2

        x, y, z = ralph_start_pos
        x += X_OFFSET
        y += Y_OFFSET
        z += Z_OFFSET

        #make_cube(x, y, z, CUBE_SIZE)

    def set_key(self, key, value):
        self.key_map[key] = value

    def move(self, task):
        dt = globalClock.getDt()
        #print "DT: %f" % dt

        #****: Movement
        #Get Ralph's position before we do anything to it
        start_pos = self.ralph.getPos()

        #User wants to turn
        if self.key_map["left"]:
            self.ralph.setH(self.ralph.getH() + 300 * dt)
        if self.key_map["right"]:
            self.ralph.setH(self.ralph.getH() - 300 * dt)

        #Perform a move forward
        if self.key_map["forward"]:
            self.ralph.setY(self.ralph, -25 * dt)

        #****: Animation
        if self.key_map["forward"] or self.key_map["left"] or self.key_map[
                "right"]:
            if not self.is_moving:
                self.ralph.loop("run")
                self.is_moving = True

        else:
            if self.is_moving:
                self.ralph.stop()
                self.ralph.pose("walk", 5)
                self.is_moving = False

        #****: Camera Movement
        if self.key_map["cam-left"]:
            self.camera.setX(self.camera, -20 * dt)
        elif self.key_map["cam-right"]:
            self.camera.setX(self.camera, +20 * dt)

        #If the camera is too far from ralph, move it closer
        #If the camera is too close to ralph, move it farther
        camvec = self.ralph.getPos() - self.camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()
        camvec.normalize()
        if camdist > 10.0:
            self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10))
            camdist = 10.0
        if camdist < 5.0:
            self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist))
            camdist - 5.0

        #****: Collision
        """
        Normally, we would have to call traverse() to check for collisions.

        However, the class ShowBase that we inherit from has a task to do this for us

        If we assign a CollisionTraverser to self.cTrav

        Adjust ralph's Z coordinate. If ralph's ray hit terrain update his Z.

        If it hit anything else, or didn't hit anything put him back where he was last frame.
        """

        entries = list(self.ralph_ground_handler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())
        #print "Entry count: %d" % len(entries)

        if len(entries) > 0 and entries[0].getIntoNode().getName(
        ) == "terrain":
            self.ralph.setZ(entries[0].getSurfacePoint(render).getZ())
        else:
            self.ralph.setPos(start_pos)

        #Keep the camera at one foot above the terrain or two feet above ralph, whichever is greater
        entries = list(self.cam_ground_handler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

        if len(entries) > 0 and entries[0].getIntoNode().getName(
        ) == "terrain":
            self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0)
        if self.camera.getZ() < self.ralph.getZ() + 2.0:
            self.camera.setZ(self.ralph.getZ() + 2.0)
        """
        The camera should look in rlaphs direction, but it should also try to stay horizontal so look at a
        floater which hovers above ralph's head
        """
        self.camera.lookAt(self.floater)
        return task.cont