예제 #1
0
파일: ViewPort.py 프로젝트: Astron/panda3d
  def makePerspective(parent):
    v = Viewport('persp', parent)
    v.camPos = Point3(-19, -19, 19)
    v.camLookAt = Point3(0, 0, 0)

    v.grid = DirectGrid(parent=render)
    collPlane = CollisionNode('PerspGridCol')
    collPlane.addSolid(CollisionPlane(Plane(0, 0, 1, 0)))
    #oldBitmask = collPlane.getIntoCollideMask()
    #collPlane.setIntoCollideMask(BitMask32.bit(21)|oldBitmask)
    collPlane.setIntoCollideMask(BitMask32.bit(21))
    v.collPlane = NodePath(collPlane)
    v.collPlane.reparentTo(v.grid)

    collPlane2 = CollisionNode('PerspGridCol2')
    collPlane2.addSolid(CollisionPlane(Plane(0, 0, -1, 0)))
    #oldBitmask = collPlane2.getIntoCollideMask()
    #collPlane2.setIntoCollideMask(BitMask32.bit(21)|oldBitmask)
    collPlane2.setIntoCollideMask(BitMask32.bit(21))
    v.collPlane2 = NodePath(collPlane2)
    v.collPlane2.reparentTo(v.grid)

    #v.grid.gridBack.findAllMatches("**/+GeomNode")[0].setName("_perspViewGridBack")
    LE_showInOneCam(v.grid, 'persp')
    return v
예제 #2
0
파일: battle.py 프로젝트: Allexit/tgc-game
    def __init__(self, nick):
        self.player = player.Player(nick=nick)
        self.controller = controller.ClientController(self.player)
        self.handgui = hand.HandGUI(self.player.hand)
        camera.setPos(0, -20, 0)
        self.accept("turn_time_changed", self.update_turn_time)
        self.turn_timer = TurnTimer()

        # Mouse detection:
        base.cTrav = CollisionTraverser()
        self.mouse_ray_handler = CollisionHandlerQueue()
        mouse_ray_node = CollisionNode('mouse_ray')
        mouse_ray_np = camera.attachNewNode(mouse_ray_node)
        mouse_ray_node.setFromCollideMask(GeomNode.getDefaultCollideMask())
        mouse_ray_node.setIntoCollideMask(0)
        self.mouse_ray = CollisionRay()
        mouse_ray_node.addSolid(self.mouse_ray)
        base.cTrav.addCollider(mouse_ray_np, self.mouse_ray_handler)

        self.mouse_overed_entry = None

        self.accept("mouse_enter", self.enlarge_entry)
        self.accept("mouse_leave", self.shrink_entry)

        self.accept("p-up", self.change_card_picture)

        taskMgr.doMethodLater(0.1, self.check_mouse_over, "check_mouse_over")
    def loadVirtualSuit(self):
        dna = SuitDNA.SuitDNA()
        dna.newSuit(self.getSuitName())
        self.virtualSuit = Suit.Suit()
        self.virtualSuit.reparentTo(self)
        self.virtualSuit.setDNA(dna)
        self.virtualSuit.setPos(self, 0.0, 2.5, 0.0)
        self.virtualSuit.makeSkeleton(wantNameInfo=False)
        self.virtualSuit.makeVirtual()
        self.virtualSuit.hideName()
        anims = self.generateSuitAnimDict()
        self.virtualSuit.loadAnims(anims)
        self.virtualSuit.loop('walk', 0)

        synergyBox = CollisionBox(0, 3.5, 10, 1)
        synergyBox.setTangible(0)
        synergyNode = CollisionNode(self.uniqueName('SynergyAttack'))
        synergyNode.setTag('damage', '10')
        synergyNode.addSolid(synergyBox)
        synergyNode.setIntoCollideMask(WallBitmask)
        self.synergyColl = self.virtualSuit.attachNewNode(synergyNode)
        self.synergyColl.setPos(0.0, 9.0, 0.0)
        self.synergyColl.stash()

        self.synergySfx = loader.loadSfx('phase_5/audio/sfx/SA_synergy.ogg')
        self.teeOffSfx = loader.loadSfx('phase_5/audio/sfx/SA_tee_off.ogg')
        self.writeOffSfx = loader.loadSfx('phase_5/audio/sfx/SA_writeoff_pen_only.ogg')
        self.dingSfx = loader.loadSfx('phase_5/audio/sfx/SA_writeoff_ding_only.ogg')
예제 #4
0
파일: ralph.py 프로젝트: DevanshiVyas/trex
            
    def placeCollectibles(self):
        self.placeCol = render.attachNewNode("Collectible-Placeholder")
        self.placeCol.setPos(0,0,0)
        
        # Add the health items to the placeCol node
        for i in range(self.numObjects):
            # Load in the health item model
            self.collect = loader.loadModel("models/trex")
            self.collect.setPos(0,0,0)
            self.collect.reparentTo(self.placeCol)
	    self.collect.setScale(0.1)
	    self.tex3= loader.loadTexture("models/Face.jpg")
	    self.collect.setTexture(self.tex3,1)
            
            self.placeItem(self.collect)
            
            # Add spherical collision detection
            colSphere = CollisionSphere(0,0,0,1)
            sphereNode = CollisionNode('colSphere')
            sphereNode.addSolid(colSphere)
            sphereNode.setFromCollideMask(BitMask32.allOff())
            sphereNode.setIntoCollideMask(BitMask32.bit(0))
            sphereNp = self.collect.attachNewNode(sphereNode)
            sphereColHandler = CollisionHandlerQueue()
    def __init__(self, cr):
        DistributedObject.__init__(self, cr)
        #self.model = loader.loadModel('environment')
        #self.model.setZ(0)
        #self.builder = Builder(self, "map.txt", "development")


        plane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
        cnode = CollisionNode('cnode')
        cnode.setIntoCollideMask(BitMask32.bit(1))
        cnode.setFromCollideMask(BitMask32.bit(1))
        cnode.addSolid(plane)
        self.planeNP = self.model.attachNewNode(cnode)
        self.planeNP.show()

        # Setup a traverser for the picking collisions
        self.picker = CollisionTraverser()
        # Setup mouse ray
        self.pq = CollisionHandlerQueue()
        # Create a collision Node
        pickerNode = CollisionNode('MouseRay')
        # set the nodes collision bitmask
        pickerNode.setFromCollideMask(BitMask32.bit(1))
        # create a collision ray
        self.pickerRay = CollisionRay()
        # add the ray as a solid to the picker node
        pickerNode.addSolid(self.pickerRay)
        # create a nodepath with the camera to the picker node
        self.pickerNP = base.camera.attachNewNode(pickerNode)
        # add the nodepath to the base traverser
        self.picker.addCollider(self.pickerNP, self.pq)

        print "model loaded"
        #TODO: check how to load multiple levels and set players in specific levels!
        self.accept("mouse1", self.mouseClick)
예제 #6
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
예제 #7
0
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
예제 #8
0
파일: ralph.py 프로젝트: DevanshiVyas/trex
    
    def placeHealthItems(self):
        self.placeholder = render.attachNewNode("HealthItem-Placeholder")
        self.placeholder.setPos(0,0,0)
        
        # Add the health items to the placeholder node
        for i in range(5):
            # Load in the health item model
            self.foodchick = loader.loadModel("models/chicken2")
            self.foodchick.setPos(0,0,0)
            self.foodchick.reparentTo(self.placeholder)
	    #self.tex2=self.setTexture("models/orange.jpg")
	    #self.foodchick.setTexture(self.tex2,1)
	    #self.tex2= loader.loadTexture("models/orange.jpg")
	    #self.foodchick.setTexture(self.tex1,1)
	

            
            self.placeItem(self.foodchick)
            
            # Add spherical collision detection
            healthSphere = CollisionSphere(0,0,0,1)
            sphereNode = CollisionNode('healthSphere')
            sphereNode.addSolid(healthSphere)
            sphereNode.setFromCollideMask(BitMask32.allOff())
            sphereNode.setIntoCollideMask(BitMask32.bit(0))
            sphereNp = self.foodchick.attachNewNode(sphereNode)
            sphereColHandler = CollisionHandlerQueue()
예제 #9
0
 def initCollisionRay(self, originZ, dirZ):
     ray = CollisionRay(0,0,originZ,0,0,dirZ)
     collNode = CollisionNode('playerRay')
     collNode.addSolid(ray)
     collNode.setFromCollideMask(BitMask32.bit(1))
     collNode.setIntoCollideMask(BitMask32.allOff())
     collRayNP = self.playerNode.attachNewNode(collNode)
     collRayNP.show()
     return collRayNP
예제 #10
0
def attachCollisionSphere(self, name, cx, cy, cz, r, fromCollide, intoCollide):
        from panda3d.core import CollisionSphere
        from panda3d.core import CollisionNode
        coll = CollisionSphere(cx, cy, cz, r)
        collNode = CollisionNode(name)
        collNode.addSolid(coll)
        collNode.setFromCollideMask(fromCollide)
        collNode.setIntoCollideMask(intoCollide)
        collNodePath = self.attachNewNode(collNode)
        return collNodePath
예제 #11
0
def attachCollisionSegment(self, name, ax, ay, az, bx, by, bz, fromCollide, intoCollide):
        from panda3d.core import CollisionSegment
        from panda3d.core import CollisionNode
        coll = CollisionSegment(ax, ay, az, bx, by, bz)
        collNode = CollisionNode(name)
        collNode.addSolid(coll)
        collNode.setFromCollideMask(fromCollide)
        collNode.setIntoCollideMask(intoCollide)
        collNodePath = self.attachNewNode(collNode)
        return collNodePath
예제 #12
0
def attachCollisionRay(self, name, ox, oy, oz, dx, dy, dz, fromCollide, intoCollide):
        from panda3d.core import CollisionRay
        from panda3d.core import CollisionNode
        coll = CollisionRay(ox, oy, oz, dx, dy, dz)
        collNode = CollisionNode(name)
        collNode.addSolid(coll)
        collNode.setFromCollideMask(fromCollide)
        collNode.setIntoCollideMask(intoCollide)
        collNodePath = self.attachNewNode(collNode)
        return collNodePath
예제 #13
0
 def create_sphere(self, model_name, bitmask):
     model = loader.loadModel("models/" + model_name)
     model.reparent_to(base.render)
     target = CollisionSphere(0, 0, 0, 1)
     target_node = CollisionNode('collision_target')
     target_node.setIntoCollideMask(bitmask)
     target_nodepath = model.attach_new_node(target_node)
     target_nodepath.node().addSolid(target)
     target_nodepath.show()
     return model
예제 #14
0
 def getFlyBallBubble(self):
     if self.__flyBallBubble == None:
         bubble = CollisionSphere(0, 0, 0, GolfGlobals.GOLF_BALL_RADIUS)
         node = CollisionNode('flyBallBubble')
         node.addSolid(bubble)
         node.setFromCollideMask(ToontownGlobals.PieBitmask | ToontownGlobals.CameraBitmask | ToontownGlobals.FloorBitmask)
         node.setIntoCollideMask(BitMask32.allOff())
         self.__flyBallBubble = NodePath(node)
         self.flyBallHandler = CollisionHandlerEvent()
         self.flyBallHandler.addInPattern('flyBallHit-%d' % self.index)
     return self.__flyBallBubble
예제 #15
0
 def __init__(self, model = "cube_nocol", texture = "lava", pos = (0,0,0), scale = (1,1,1), cubetype = "A"):
     super(LavaCube, self).__init__(model, texture, pos, scale)
     cn = CollisionNode('lava')
     cn.setFromCollideMask(COLLISIONMASKS['lava'])
     cn.setIntoCollideMask(BitMask32.allOff())
     np = self.node.attachNewNode(cn)
     cn.addSolid(CollisionSphere(0,0,0,1.1))
     h = CollisionHandlerEvent()
     h.addInPattern('%fn-into-%in')
     h.addOutPattern('%fn-outof-%in')
     base.cTrav.addCollider(np, h)
예제 #16
0
 def createMouseCollisions(self):
     # Fire the portals
     firingNode = CollisionNode('mouseRay')
     firingNP = self.base.camera.attachNewNode(firingNode)
     firingNode.setFromCollideMask(COLLISIONMASKS['geometry'])
     firingNode.setIntoCollideMask(BitMask32.allOff())
     firingRay = CollisionRay()
     firingRay.setOrigin(0,0,0)
     firingRay.setDirection(0,1,0)
     firingNode.addSolid(firingRay)
     self.firingHandler = CollisionHandlerQueue()
     self.base.cTrav.addCollider(firingNP, self.firingHandler)
예제 #17
0
 def setupEventSphere(self, bitmask, avatarRadius):
     self.avatarRadius = avatarRadius
     cSphere = CollisionSphere(0.0, 0.0, self.avatarRadius + 0.75, self.avatarRadius * 1.04)
     cSphere.setTangible(0)
     cSphereNode = CollisionNode('Flyer.cEventSphereNode')
     cSphereNode.addSolid(cSphere)
     cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
     cSphereNode.setFromCollideMask(bitmask)
     cSphereNode.setIntoCollideMask(BitMask32.allOff())
     self.event = CollisionHandlerEvent()
     self.event.addInPattern('enter%in')
     self.event.addOutPattern('exit%in')
     self.cEventSphereNodePath = cSphereNodePath
예제 #18
0
 def setupHeadSphere(self, avatarNodePath):
     collSphere = CollisionSphere(0, 0, 0, 1)
     collSphere.setTangible(1)
     collNode = CollisionNode('Flyer.cHeadCollSphere')
     collNode.setFromCollideMask(ToontownGlobals.CeilingBitmask)
     collNode.setIntoCollideMask(BitMask32.allOff())
     collNode.addSolid(collSphere)
     self.cHeadSphereNodePath = avatarNodePath.attachNewNode(collNode)
     self.cHeadSphereNodePath.setZ(base.localAvatar.getHeight() + 1.0)
     self.headCollisionEvent = CollisionHandlerEvent()
     self.headCollisionEvent.addInPattern('%fn-enter-%in')
     self.headCollisionEvent.addOutPattern('%fn-exit-%in')
     base.cTrav.addCollider(self.cHeadSphereNodePath, self.headCollisionEvent)
예제 #19
0
 def setupFloorEventSphere(self, avatarNodePath, bitmask, avatarRadius):
     cSphere = CollisionSphere(0.0, 0.0, 0.0, 0.75)
     cSphereNode = CollisionNode('Flyer.cFloorEventSphere')
     cSphereNode.addSolid(cSphere)
     cSphereNodePath = avatarNodePath.attachNewNode(cSphereNode)
     cSphereNode.setFromCollideMask(bitmask)
     cSphereNode.setIntoCollideMask(BitMask32.allOff())
     self.floorCollisionEvent = CollisionHandlerEvent()
     self.floorCollisionEvent.addInPattern('%fn-enter-%in')
     self.floorCollisionEvent.addAgainPattern('%fn-again-%in')
     self.floorCollisionEvent.addOutPattern('%fn-exit-%in')
     base.cTrav.addCollider(cSphereNodePath, self.floorCollisionEvent)
     self.cFloorEventSphereNodePath = cSphereNodePath
예제 #20
0
    def __init__(self, _main):
        self.main = _main
        self.name = ""
        self.points = 0
        self.health = 100.0
        self.runSpeed = 1.8
        self.keyMap = {
            "left":False,
            "right":False,
            "up":False,
            "down":False
            }
        base.camera.setPos(0,0,0)
        self.model = loader.loadModel("Player")
        self.model.find('**/+SequenceNode').node().stop()
        self.model.find('**/+SequenceNode').node().pose(0)
        base.camera.setP(-90)
        self.playerHud = Hud()
        self.playerHud.hide()
        self.model.hide()

        # Weapons: size=2, 0=main, 1=offhand
        self.mountSlot = []
        self.activeWeapon = None
        self.isAutoActive = False
        self.trigger = False
        self.lastShot = 0.0
        self.fireRate = 0.0

        self.playerTraverser = CollisionTraverser()
        self.playerEH = CollisionHandlerEvent()
        ## INTO PATTERNS
        self.playerEH.addInPattern('intoPlayer-%in')
        #self.playerEH.addInPattern('colIn-%fn')
        self.playerEH.addInPattern('intoHeal-%in')
        self.playerEH.addInPattern('intoWeapon-%in')
        ## OUT PATTERNS
        self.playerEH.addOutPattern('outOfPlayer-%in')
        playerCNode = CollisionNode('playerSphere')
        playerCNode.setFromCollideMask(BitMask32.bit(1))
        playerCNode.setIntoCollideMask(BitMask32.bit(1))
        self.playerSphere = CollisionSphere(0, 0, 0, 0.6)
        playerCNode.addSolid(self.playerSphere)
        self.playerNP = self.model.attachNewNode(playerCNode)
        self.playerTraverser.addCollider(self.playerNP, self.playerEH)
        #self.playerNP.show()

        self.playerPusher = CollisionHandlerPusher()
        self.playerPusher.addCollider(self.playerNP, self.model)
        self.playerPushTraverser = CollisionTraverser()
        self.playerPushTraverser.addCollider(self.playerNP, self.playerPusher)
예제 #21
0
 def __init__(self, model = "models/sphere", texture = "exit", pos = (0,0,0), scale = (1,1,1), cubetype = "A"):
     super(LevelExit, self).__init__(model, texture, pos, scale)
     #self.node.setTransparency(TransparencyAttrib.MAlpha)
     self.node.setTag('noportals', '1')
     self.node.setTag('isexit', '1')
     cn = CollisionNode('levelExit')
     cn.setFromCollideMask(COLLISIONMASKS['exit'])
     cn.setIntoCollideMask(BitMask32.allOff())
     np = self.node.attachNewNode(cn)
     cn.addSolid(CollisionSphere(0,0,0,1.1))
     h = CollisionHandlerEvent()
     h.addInPattern('%fn-into-%in')
     h.addOutPattern('%fn-outof-%in')
     base.cTrav.addCollider(np, h)
예제 #22
0
 def setupWallSphere(self, bitmask, avatarRadius):
     self.avatarRadius = avatarRadius
     cSphere = CollisionSphere(0.0, 0.0, self.avatarRadius + 0.75, self.avatarRadius)
     cSphereNode = CollisionNode('Flyer.cWallSphereNode')
     cSphereNode.addSolid(cSphere)
     cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
     cSphereNode.setFromCollideMask(bitmask)
     cSphereNode.setIntoCollideMask(BitMask32.allOff())
     if config.GetBool('want-fluid-pusher', 0):
         self.pusher = CollisionHandlerFluidPusher()
     else:
         self.pusher = CollisionHandlerPusher()
     self.pusher.addCollider(cSphereNodePath, self.avatarNodePath)
     self.cWallSphereNodePath = cSphereNodePath
예제 #23
0
파일: PlayerObject.py 프로젝트: qiaoma/MMOG
class PlayerObject():
	def __init__(self, render, player):
		self.username = player.getUsername()
		self.isMoving = False
		self.render = render

		self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0}

		self.actor = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"})
		self.actor.reparentTo(render)
		self.actor.setScale(0.2)
		self.actor.setPos(player.getX(), player.getY(), player.getZ())
		self.actor.setH(player.getH())

		self.cTrav = CollisionTraverser()
		self.GroundRay = CollisionRay()
		self.GroundRay.setOrigin(0,0,1000)
		self.GroundRay.setDirection(0,0,-1)
		self.GroundCol = CollisionNode('actorRay')
		self.GroundCol.addSolid(self.GroundRay)
		self.GroundCol.setFromCollideMask(BitMask32.bit(0))
		self.GroundCol.setIntoCollideMask(BitMask32.allOff())
		self.GroundColNp = self.actor.attachNewNode(self.GroundCol)
		self.GroundHandler = CollisionHandlerQueue()
		self.cTrav.addCollider(self.GroundColNp, self.GroundHandler)

# 	def getUsername(self):
# 		return self.username
	
	def getActor(self):
		return self.actor
	
	def setPos(self, x, y, z):
		self.actor.setPos(x, y, z)
		
	def setH(self, h):
		self.actor.setH(h)

	def move(self, isActorMove):
		if isActorMove == "True":
			if self.isMoving is False:
				self.actor.loop("run")
				self.isMoving = True
		else:
			if self.isMoving:
				self.actor.stop()
				self.actor.pose("walk",5)
				self.isMoving = False
예제 #24
0
 def loadLever(self):
     self.lever = self.root.attachNewNode('%sLever' % self.activityName)
     self.leverModel = self.party.defaultLeverModel.copyTo(self.lever)
     self.controlColumn = NodePath('cc')
     column = self.leverModel.find('**/column')
     column.getChildren().reparentTo(self.controlColumn)
     self.controlColumn.reparentTo(column)
     self.stickHinge = self.controlColumn.attachNewNode('stickHinge')
     self.stick = self.party.defaultStickModel.copyTo(self.stickHinge)
     self.stickHinge.setHpr(0.0, 90.0, 0.0)
     self.stick.setHpr(0, -90.0, 0)
     self.stick.flattenLight()
     self.bottom = self.leverModel.find('**/bottom')
     self.bottom.wrtReparentTo(self.controlColumn)
     self.bottomPos = self.bottom.getPos()
     cs = CollisionSphere(0.0, 1.35, 2.0, 1.0)
     cs.setTangible(False)
     cn = CollisionNode(self.leverTriggerEvent)
     cn.addSolid(cs)
     cn.setIntoCollideMask(OTPGlobals.WallBitmask)
     self.leverTrigger = self.root.attachNewNode(cn)
     self.leverTrigger.reparentTo(self.lever)
     self.leverTrigger.stash()
     cs = CollisionTube(0.0, 2.7, 0.0, 0.0, 2.7, 3.0, 1.2)
     cn = CollisionNode('levertube')
     cn.addSolid(cs)
     cn.setIntoCollideMask(OTPGlobals.WallBitmask)
     self.leverTube = self.leverModel.attachNewNode(cn)
     host = base.cr.doId2do.get(self.party.partyInfo.hostId)
     if host is None:
         self.notify.debug('%s loadLever : Host has left the game before lever could be created.' % self.activityName)
         return
     scale = host.getGeomNode().getChild(0).getSz(render)
     self.leverModel.setScale(scale)
     self.controlColumn.setPos(0, 0, 0)
     host.setPosHpr(self.lever, 0, 0, 0, 0, 0, 0)
     host.pose('leverNeutral', 0)
     host.update()
     pos = host.rightHand.getPos(self.controlColumn)
     self.controlColumn.setPos(pos[0], pos[1], pos[2] - 1)
     self.bottom.setZ(host, 0.0)
     self.bottom.setPos(self.bottomPos[0], self.bottomPos[1], self.bottom.getZ())
     lookAtPoint = Point3(0.3, 0, 0.1)
     lookAtUp = Vec3(0, -1, 0)
     self.stickHinge.lookAt(host.rightHand, lookAtPoint, lookAtUp)
     host.play('walk')
     host.update()
     return
예제 #25
0
 def setupRay(self, bitmask, floorOffset, reach):
     cRay = CollisionRay(0.0, 0.0, 3.0, 0.0, 0.0, -1.0)
     cRayNode = CollisionNode('Flyer.cRayNode')
     cRayNode.addSolid(cRay)
     self.cRayNodePath = self.avatarNodePath.attachNewNode(cRayNode)
     cRayNode.setFromCollideMask(bitmask)
     cRayNode.setIntoCollideMask(BitMask32.allOff())
     self.lifter = CollisionHandlerGravity()
     self.lifter.setLegacyMode(self._legacyLifter)
     self.lifter.setGravity(self.getGravity(0))
     self.lifter.addInPattern('%fn-enter-%in')
     self.lifter.addAgainPattern('%fn-again-%in')
     self.lifter.addOutPattern('%fn-exit-%in')
     self.lifter.setOffset(floorOffset)
     self.lifter.setReach(reach)
     self.lifter.addCollider(self.cRayNodePath, self.avatarNodePath)
예제 #26
0
 def _initCollisions(self):
     self._camCollRay = CollisionRay()
     camCollNode = CollisionNode('CameraToonRay')
     camCollNode.addSolid(self._camCollRay)
     camCollNode.setFromCollideMask(OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask)
     camCollNode.setIntoCollideMask(0)
     self._camCollNP = self._camera.attachNewNode(camCollNode)
     self._camCollNP.show()
     self._collOffset = Vec3(0, 0, 0.5)
     self._collHandler = CollisionHandlerQueue()
     self._collTrav = CollisionTraverser()
     self._collTrav.addCollider(self._camCollNP, self._collHandler)
     self._betweenCamAndToon = {}
     self._transNP = NodePath('trans')
     self._transNP.reparentTo(render)
     self._transNP.setTransparency(True)
     self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon)
     self._transNP.setBin('fixed', 10000)
class Collectible:
	
	def __init__(self, base, model, pickSound):
		self.model = model
		
		#TODO: Refactor constants and collision solid
		self.collisionNd = CollisionNode(model.getName())
		self.collisionNP = self.model.attachNewNode(self.collisionNd)
		self.collisionNd.addSolid(CollisionSphere(0, 0, 0, 0.3))
		self.collisionNd.setIntoCollideMask(CollisionMask.HAND)
		
		self.pickedSound = base.loader.loadSfx(pickSound)
		self.picked = False
		
	def __del__(self):
		self.model.removeNode()
		self.pickedSound = None
		
	def reset(self):
		self.picked = False
		self.model.show()
		
	#TODO: Make Collectible a subclass of NodePath?
	def getName(self):
		return self.model.getName()
		
	def act(self, player):
		if (not self.picked):
			self.pickedSound.play()
			self.model.hide()
			self.picked = True
			player.inventory.append(self)
		
	def wasPicked(self):
		return self.picked

	def used(self):
		self.picked = False

	def clean(self):
		#self.audio3d.unloadSfx(self.pickedSound)
		#self.audio3d.disable()
		pass
예제 #28
0
class MouseCollision:
    def __init__(self, game):

        self.game = game

        self.c_trav = CollisionTraverser()

        self.mouse_groundHandler = CollisionHandlerQueue()
        self.mouse_ground_ray = CollisionRay()
        self.mouse_ground_col = CollisionNode('mouseRay')

        self.mouse_ground_ray.setOrigin(0, 0, 0)
        self.mouse_ground_ray.setDirection(0, -1, 0)

        self.mouse_ground_col.addSolid(self.mouse_ground_ray)
        self.mouse_ground_col.setFromCollideMask(CollideMask.bit(0))
        self.mouse_ground_col.setIntoCollideMask(CollideMask.allOff())

        self.mouse_ground_col_np = self.game.camera.attachNewNode(self.mouse_ground_col)

        self.c_trav.addCollider(self.mouse_ground_col_np, self.mouse_groundHandler)

        self.game.taskMgr.add(self.update, 'updateMouse')

    def update(self, task):

        if self.game.mouseWatcherNode.hasMouse():
            if self.game.ship.model:

                mouse_pos = self.game.mouseWatcherNode.getMouse()

                self.mouse_ground_ray.setFromLens(self.game.camNode, mouse_pos.getX(), mouse_pos.getY())

                near_point = render.getRelativePoint(self.game.camera, self.mouse_ground_ray.getOrigin())
                near_vec = render.getRelativeVector(self.game.camera, self.mouse_ground_ray.getDirection())

                self.game.ship.shipPoint.setPos(self.PointAtY(self.game.ship.model.getY(), near_point, near_vec))

        return task.cont

    def PointAtY(self, y, point, vec):
        return point + vec * ((y - point.getY()) / vec.getY())
예제 #29
0
 def loadAssets(self):
     self.root = render.attachNewNode('golfSpot-%d' % self.index)
     self.root.setPos(*self.positions[self.index])
     self.ballModel = loader.loadModel('phase_6/models/golf/golf_ball')
     self.ballColor = VBase4(1, 1, 1, 1)
     if self.index < len(GolfGlobals.PlayerColors):
         self.ballColor = VBase4(*GolfGlobals.PlayerColors[self.index])
         self.ballModel.setColorScale(self.ballColor)
     self.ballModel.reparentTo(self.root)
     self.club = loader.loadModel('phase_6/models/golf/putter')
     self.clubLookatSpot = self.root.attachNewNode('clubLookat')
     self.clubLookatSpot.setY(-(GolfGlobals.GOLF_BALL_RADIUS + 0.1))
     cs = CollisionSphere(0, 0, 0, 1)
     cs.setTangible(0)
     cn = CollisionNode(self.triggerName)
     cn.addSolid(cs)
     cn.setIntoCollideMask(ToontownGlobals.WallBitmask)
     self.trigger = self.root.attachNewNode(cn)
     self.trigger.stash()
     self.hitBallSfx = loader.loadSfx('phase_6/audio/sfx/Golf_Hit_Ball.ogg')
예제 #30
0
 def createPortalCollisions(self):
     # Enter the portals
     cn = CollisionNode('bluePortal')
     cn.setFromCollideMask(COLLISIONMASKS['portals'])
     cn.setIntoCollideMask(BitMask32.allOff())
     np = self.bluePortal.attachNewNode(cn)
     cn.addSolid(CollisionSphere(0,0,0,2))
     h = CollisionHandlerEvent()
     h.addInPattern('%fn-into-%in')
     h.addOutPattern('%fn-outof-%in')
     self.base.cTrav.addCollider(np, h)
     cn = CollisionNode('orangePortal')
     cn.setFromCollideMask(COLLISIONMASKS['portals'])
     cn.setIntoCollideMask(BitMask32.allOff())
     np = self.orangePortal.attachNewNode(cn)
     cn.addSolid(CollisionSphere(0,0,0,2))
     h = CollisionHandlerEvent()
     h.addInPattern('%fn-into-%in')
     h.addOutPattern('%fn-outof-%in')
     self.base.cTrav.addCollider(np, h)
예제 #31
0
class IceTreasure(DirectObject):
    notify = DirectNotifyGlobal.directNotify.newCategory('IceTreasure')
    RADIUS = 1.0

    def __init__(self, model, pos, serialNum, gameId, penalty=False):
        self.serialNum = serialNum
        self.penalty = penalty
        center = model.getBounds().getCenter()
        center = Point3(0, 0, 0)
        self.nodePath = model.copyTo(render)
        self.nodePath.setPos(pos[0] - center[0], pos[1] - center[1],
                             pos[2] - center[2])
        self.nodePath.setZ(0)
        self.notify.debug('newPos = %s' % self.nodePath.getPos())
        if self.penalty:
            self.sphereName = 'penaltySphere-%s-%s' % (gameId, self.serialNum)
        else:
            self.sphereName = 'treasureSphere-%s-%s' % (gameId, self.serialNum)
        self.collSphere = CollisionSphere(center[0], center[1], center[2],
                                          self.RADIUS)
        self.collSphere.setTangible(0)
        self.collNode = CollisionNode(self.sphereName)
        self.collNode.setIntoCollideMask(ToontownGlobals.PieBitmask)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = render.attachNewNode(self.collNode)
        self.collNodePath.setPos(pos[0] - center[0], pos[1] - center[1],
                                 pos[2] - center[2])
        self.collNodePath.hide()
        self.track = None
        if self.penalty:
            self.tip = self.nodePath.find('**/fusetip')
            sparks = BattleParticles.createParticleEffect(file='icetnt')
            self.sparksEffect = sparks
            sparks.start(self.tip)
            self.penaltyGrabSound = loader.loadSfx(
                'phase_4/audio/sfx/MG_cannon_fire_alt.mp3')
            self.penaltyGrabSound.setVolume(0.75)
            kaboomAttachPoint = self.nodePath.attachNewNode('kaboomAttach')
            kaboomAttachPoint.setZ(3)
            self.kaboom = loader.loadModel(
                'phase_4/models/minigames/ice_game_kaboom')
            self.kaboom.reparentTo(kaboomAttachPoint)
            self.kaboom.setScale(2.0)
            self.kaboom.setBillboardPointEye()
        return

    def destroy(self):
        self.ignoreAll()
        if self.penalty:
            self.sparksEffect.cleanup()
            if self.track:
                self.track.finish()
        self.nodePath.removeNode()
        del self.nodePath
        del self.collSphere
        self.collNodePath.removeNode()
        del self.collNodePath
        del self.collNode

    def showGrab(self):
        self.nodePath.hide()
        self.collNodePath.hide()
        self.collNode.setIntoCollideMask(BitMask32(0))
        if self.penalty:
            self.track = Parallel(
                SoundInterval(self.penaltyGrabSound),
                Sequence(
                    Func(self.kaboom.showThrough),
                    LerpScaleInterval(self.kaboom,
                                      duration=0.5,
                                      scale=Point3(10, 10, 10),
                                      blendType='easeOut'),
                    Func(self.kaboom.hide)))
            self.track.start()
예제 #32
0
class MazeSuit(DirectObject):
    COLL_SPHERE_NAME = 'MazeSuitSphere'
    COLLISION_EVENT_NAME = 'MazeSuitCollision'
    MOVE_IVAL_NAME = 'moveMazeSuit'
    DIR_UP = 0
    DIR_DOWN = 1
    DIR_LEFT = 2
    DIR_RIGHT = 3
    oppositeDirections = [DIR_DOWN,
     DIR_UP,
     DIR_RIGHT,
     DIR_LEFT]
    directionHs = [0,
     180,
     90,
     270]
    DEFAULT_SPEED = 4.0
    SUIT_Z = 0.1

    def __init__(self, serialNum, maze, randomNumGen, cellWalkPeriod, difficulty, suitDnaName = 'f', startTile = None, ticFreq = MazeGameGlobals.SUIT_TIC_FREQ, walkSameDirectionProb = MazeGameGlobals.WALK_SAME_DIRECTION_PROB, walkTurnAroundProb = MazeGameGlobals.WALK_TURN_AROUND_PROB, uniqueRandomNumGen = True, walkAnimName = None):
        self.serialNum = serialNum
        self.maze = maze
        if uniqueRandomNumGen:
            self.rng = RandomNumGen(randomNumGen)
        else:
            self.rng = randomNumGen
        self.difficulty = difficulty
        self._walkSameDirectionProb = walkSameDirectionProb
        self._walkTurnAroundProb = walkTurnAroundProb
        self._walkAnimName = walkAnimName or 'walk'
        self.suit = Suit.Suit()
        d = SuitDNA.SuitDNA()
        d.newSuit(suitDnaName)
        self.suit.setDNA(d)
        if startTile is None:
            defaultStartPos = MazeGameGlobals.SUIT_START_POSITIONS[self.serialNum]
            self.startTile = (defaultStartPos[0] * self.maze.width, defaultStartPos[1] * self.maze.height)
        else:
            self.startTile = startTile
        self.ticFreq = ticFreq
        self.ticPeriod = int(cellWalkPeriod)
        self.cellWalkDuration = float(self.ticPeriod) / float(self.ticFreq)
        self.turnDuration = 0.6 * self.cellWalkDuration
        return

    def destroy(self):
        self.suit.delete()

    def uniqueName(self, str):
        return str + `(self.serialNum)`

    def gameStart(self, gameStartTime):
        self.gameStartTime = gameStartTime
        self.initCollisions()
        self.startWalkAnim()
        self.occupiedTiles = [(self.nextTX, self.nextTY)]
        n = 20
        self.nextThinkTic = self.serialNum * self.ticFreq / n
        self.fromPos = Point3(0, 0, 0)
        self.toPos = Point3(0, 0, 0)
        self.fromHpr = Point3(0, 0, 0)
        self.toHpr = Point3(0, 0, 0)
        self.moveIval = WaitInterval(1.0)

    def gameEnd(self):
        self.moveIval.pause()
        del self.moveIval
        self.shutdownCollisions()
        self.suit.loop('neutral')

    def initCollisions(self):
        self.collSphere = CollisionSphere(0, 0, 0, 2.0)
        self.collSphere.setTangible(0)
        self.collNode = CollisionNode(self.uniqueName(self.COLL_SPHERE_NAME))
        self.collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = self.suit.attachNewNode(self.collNode)
        self.collNodePath.hide()
        self.accept(self.uniqueName('enter' + self.COLL_SPHERE_NAME), self.handleEnterSphere)

    def shutdownCollisions(self):
        self.ignore(self.uniqueName('enter' + self.COLL_SPHERE_NAME))
        del self.collSphere
        self.collNodePath.removeNode()
        del self.collNodePath
        del self.collNode

    def handleEnterSphere(self, collEntry):
        messenger.send(self.COLLISION_EVENT_NAME, [self.serialNum])

    def __getWorldPos(self, sTX, sTY):
        wx, wy = self.maze.tile2world(sTX, sTY)
        return Point3(wx, wy, self.SUIT_Z)

    def onstage(self):
        sTX = int(self.startTile[0])
        sTY = int(self.startTile[1])
        c = 0
        lim = 0
        toggle = 0
        direction = 0
        while not self.maze.isWalkable(sTX, sTY):
            if 0 == direction:
                sTX -= 1
            elif 1 == direction:
                sTY -= 1
            elif 2 == direction:
                sTX += 1
            elif 3 == direction:
                sTY += 1
            c += 1
            if c > lim:
                c = 0
                direction = (direction + 1) % 4
                toggle += 1
                if not toggle & 1:
                    lim += 1

        self.TX = sTX
        self.TY = sTY
        self.direction = self.DIR_DOWN
        self.lastDirection = self.direction
        self.nextTX = self.TX
        self.nextTY = self.TY
        self.suit.setPos(self.__getWorldPos(self.TX, self.TY))
        self.suit.setHpr(self.directionHs[self.direction], 0, 0)
        self.suit.reparentTo(render)
        self.suit.pose(self._walkAnimName, 0)
        self.suit.loop('neutral')

    def offstage(self):
        self.suit.reparentTo(hidden)

    def startWalkAnim(self):
        self.suit.loop(self._walkAnimName)
        speed = float(self.maze.cellWidth) / self.cellWalkDuration
        self.suit.setPlayRate(speed / self.DEFAULT_SPEED, self._walkAnimName)

    def __applyDirection(self, dir, TX, TY):
        if self.DIR_UP == dir:
            TY += 1
        elif self.DIR_DOWN == dir:
            TY -= 1
        elif self.DIR_LEFT == dir:
            TX -= 1
        elif self.DIR_RIGHT == dir:
            TX += 1
        return (TX, TY)

    def __chooseNewWalkDirection(self, unwalkables):
        if not self.rng.randrange(self._walkSameDirectionProb):
            newTX, newTY = self.__applyDirection(self.direction, self.TX, self.TY)
            if self.maze.isWalkable(newTX, newTY, unwalkables):
                return self.direction
        if self.difficulty >= 0.5:
            if not self.rng.randrange(self._walkTurnAroundProb):
                oppositeDir = self.oppositeDirections[self.direction]
                newTX, newTY = self.__applyDirection(oppositeDir, self.TX, self.TY)
                if self.maze.isWalkable(newTX, newTY, unwalkables):
                    return oppositeDir
        candidateDirs = [self.DIR_UP,
         self.DIR_DOWN,
         self.DIR_LEFT,
         self.DIR_RIGHT]
        candidateDirs.remove(self.oppositeDirections[self.direction])
        while len(candidateDirs):
            dir = self.rng.choice(candidateDirs)
            newTX, newTY = self.__applyDirection(dir, self.TX, self.TY)
            if self.maze.isWalkable(newTX, newTY, unwalkables):
                return dir
            candidateDirs.remove(dir)

        return self.oppositeDirections[self.direction]

    def getThinkTimestampTics(self, curTic):
        if curTic < self.nextThinkTic:
            return []
        else:
            r = range(self.nextThinkTic, curTic + 1, self.ticPeriod)
            self.lastTicBeforeRender = r[-1]
            return r

    def prepareToThink(self):
        self.occupiedTiles = [(self.nextTX, self.nextTY)]

    def think(self, curTic, curT, unwalkables):
        self.TX = self.nextTX
        self.TY = self.nextTY
        self.lastDirection = self.direction
        self.direction = self.__chooseNewWalkDirection(unwalkables)
        self.nextTX, self.nextTY = self.__applyDirection(self.direction, self.TX, self.TY)
        self.occupiedTiles = [(self.TX, self.TY), (self.nextTX, self.nextTY)]
        if curTic == self.lastTicBeforeRender:
            fromCoords = self.maze.tile2world(self.TX, self.TY)
            toCoords = self.maze.tile2world(self.nextTX, self.nextTY)
            self.fromPos.set(fromCoords[0], fromCoords[1], self.SUIT_Z)
            self.toPos.set(toCoords[0], toCoords[1], self.SUIT_Z)
            self.moveIval = LerpPosInterval(self.suit, self.cellWalkDuration, self.toPos, startPos=self.fromPos, name=self.uniqueName(self.MOVE_IVAL_NAME))
            if self.direction != self.lastDirection:
                self.fromH = self.directionHs[self.lastDirection]
                toH = self.directionHs[self.direction]
                if self.fromH == 270 and toH == 0:
                    self.fromH = -90
                elif self.fromH == 0 and toH == 270:
                    self.fromH = 360
                self.fromHpr.set(self.fromH, 0, 0)
                self.toHpr.set(toH, 0, 0)
                turnIval = LerpHprInterval(self.suit, self.turnDuration, self.toHpr, startHpr=self.fromHpr, name=self.uniqueName('turnMazeSuit'))
                self.moveIval = Parallel(self.moveIval, turnIval, name=self.uniqueName(self.MOVE_IVAL_NAME))
            else:
                self.suit.setH(self.directionHs[self.direction])
            moveStartT = float(self.nextThinkTic) / float(self.ticFreq)
            self.moveIval.start(curT - (moveStartT + self.gameStartTime))
        self.nextThinkTic += self.ticPeriod

    @staticmethod
    def thinkSuits(suitList, startTime, ticFreq = MazeGameGlobals.SUIT_TIC_FREQ):
        curT = globalClock.getFrameTime() - startTime
        curTic = int(curT * float(ticFreq))
        suitUpdates = []
        for i in xrange(len(suitList)):
            updateTics = suitList[i].getThinkTimestampTics(curTic)
            suitUpdates.extend(zip(updateTics, [i] * len(updateTics)))

        suitUpdates.sort(lambda a, b: a[0] - b[0])
        if len(suitUpdates) > 0:
            curTic = 0
            for i in xrange(len(suitUpdates)):
                update = suitUpdates[i]
                tic = update[0]
                suitIndex = update[1]
                suit = suitList[suitIndex]
                if tic > curTic:
                    curTic = tic
                    j = i + 1
                    while j < len(suitUpdates):
                        if suitUpdates[j][0] > tic:
                            break
                        suitList[suitUpdates[j][1]].prepareToThink()
                        j += 1

                unwalkables = []
                for si in xrange(suitIndex):
                    unwalkables.extend(suitList[si].occupiedTiles)

                for si in xrange(suitIndex + 1, len(suitList)):
                    unwalkables.extend(suitList[si].occupiedTiles)

                suit.think(curTic, curT, unwalkables)
예제 #33
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/panda", {
            "run": "models/panda-walk",
            "walk": "models/panda-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
예제 #34
0
class bullet():
    #tuple pos, tuple target, float damage, float speed, float range, float accuracy -> bullet
    def __init__(self, sender, pos, dir, damage, speed, range, accuracy=1):
        #bullets have a speed, a model, and a damage. Both should be parameters
        #range as well
        self.start = pos
        self.sender = sender
        self.accuracy = accuracy
        self.direction = dir.normalized()
        self.damage = damage
        self.tasks = []
        self.speed = speed
        self.range = range
        self.model = base.loader.loadModel('models/bullet')
        self.model.reparentTo(base.render)
        self.model.setPos(pos)

        #self.target=target
        #create collision sphere
        #TODO account for larger bullet sizes
        cs = CollisionSphere(0, 0, 0, 1)
        self.mainCol = CollisionNode('cNode')
        #set up circular reference so collision volume knows parent
        self.mainCol.setPythonTag('owner', self)
        self.mainCol.setIntoCollideMask(
            CollideMask.bit(1)
        )  # send objects with intoCollideMask bit 1. Relates to most entities
        self.cNode = self.model.attachNewNode(self.mainCol)
        self.cNode.node().addSolid(cs)
        #create collider handler, if one doesn't already exist
        try:
            # attempt to add to global collision traverser
            base.cTrav.addCollider(self.cNode, base.bulletCollider)
        except AttributeError:
            base.bulletCollider = CollisionHandlerEvent()
            # create event called 'bulletCollision' on hit
            base.bulletCollider.addInPattern('bulletCollision')
        finally:
            # retry
            base.cTrav.addCollider(self.cNode, base.bulletCollider)

        #rotate model such that it follows the passed direction argument vector
        self.model.setHpr(helper.vectorToHPR(dir))

        #assign direction based on rotation
        #THIS TOOK WAY TOO MUCH EFFORT TO FIGURE OUT
        #normVec here is the model nodepath taking the passed argument vector (dir)
        #belonging to another node (base.render)
        #and adjusting it to its local coordinate space - what would this vector look like from
        #self.model's perspective. Then it is normalized and assigned.
        normVec = self.model.getRelativeVector(base.render, dir)
        normVec.normalize()
        self.direction = normVec

        #normVec=base.render.getRelativeVector(self.model,Vec3(0,1,0))
        #print(self.model.getHpr())
        #print(normVec)

        #start task to move forward at speed
        self.tasks.append(taskMgr.add(self.accelerate, "bulletAccelerateTask"))

    #task: accelerate
    def accelerate(self, task):
        """
        Task moves bullet forward until it hits an object or range is met
        """
        #range is decremented each tick
        #check to make sure not 0
        if self.range <= 0:
            #if range has ran out kill task and this object
            self.delete()
            return task.done

        #otherwise proceed, move object and decrement range
        dt = globalClock.getDt()

        #distVec=min((self.start-self.target),(self.target-self.start))
        #distVec=distVec.normalized()
        #print(distVec)
        #print(self.direction)
        #take normalized direction vector and apply to transform
        self.model.setFluidX(self.model, self.direction[0] * self.speed * dt)
        self.model.setFluidY(self.model, self.direction[1] * self.speed * dt)
        self.model.setFluidZ(self.model, self.direction[2] * self.speed * dt)
        self.range -= (self.speed * dt)
        return task.cont

    #class deconstructor
    def delete(self):
        self.model.hide()
        #clear tasks
        for task in self.tasks:
            taskMgr.remove(task)
        #clear collision
        self.mainCol.clearPythonTag("owner")
        #remove object
        self.model.removeNode()
예제 #35
0
class CogdoMazeDrop(NodePath, DirectObject):
    def __init__(self, game, id, x, y):
        NodePath.__init__(self, 'dropNode%s' % id)
        self.game = game
        self.id = id
        self.reparentTo(hidden)
        self.setPos(x, y, 0)
        shadow = loader.loadModel('phase_3/models/props/square_drop_shadow')
        shadow.setZ(0.2)
        shadow.setBin('ground', 10)
        shadow.setColor(1, 1, 1, 1)
        shadow.reparentTo(self)
        self.shadow = shadow
        drop = CogdoUtil.loadMazeModel('cabinetSmFalling')
        roll = random.randint(-15, 15)
        drop.setHpr(0, 0, roll)
        drop.setZ(Globals.DropHeight)
        self.collTube = CollisionTube(0, 0, 0, 0, 0, 4,
                                      Globals.DropCollisionRadius)
        self.collTube.setTangible(0)
        name = Globals.DropCollisionName
        self.collNode = CollisionNode(name)
        self.collNode.addSolid(self.collTube)
        self.collNodePath = drop.attachNewNode(self.collNode)
        self.collNodePath.hide()
        self.collNodePath.setTag('isFalling', str('True'))
        drop.reparentTo(self)
        self.drop = drop
        self._dropSfx = base.cogdoGameAudioMgr.createSfxIval('drop',
                                                             volume=0.6)

    def disableCollisionDamage(self):
        self.collTube.setTangible(1)
        self.collTube.setRadius(Globals.DroppedCollisionRadius)
        self.collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.collNodePath.setTag('isFalling', str('False'))

    def getDropIval(self):
        shadow = self.shadow
        drop = self.drop
        id = self.id
        hangTime = Globals.ShadowTime
        dropTime = Globals.DropTime
        dropHeight = Globals.DropHeight
        targetShadowScale = 0.5
        targetShadowAlpha = 0.4
        shadowScaleIval = LerpScaleInterval(shadow,
                                            dropTime,
                                            targetShadowScale,
                                            startScale=0)
        shadowAlphaIval = LerpColorScaleInterval(
            shadow,
            hangTime,
            Point4(1, 1, 1, targetShadowAlpha),
            startColorScale=Point4(1, 1, 1, 0))
        shadowIval = Parallel(shadowScaleIval, shadowAlphaIval)
        startPos = Point3(0, 0, dropHeight)
        drop.setPos(startPos)
        dropIval = LerpPosInterval(drop,
                                   dropTime,
                                   Point3(0, 0, 0),
                                   startPos=startPos,
                                   blendType='easeIn')
        dropSoundIval = self._dropSfx
        dropSoundIval.node = self
        self.drop.setTransparency(1)

        def _setRandScale(t):
            self.drop.setScale(self, 1 - random.random() / 16,
                               1 - random.random() / 16,
                               1 - random.random() / 4)

        scaleChange = 0.4 + random.random() / 4
        dropShakeSeq = Sequence(
            LerpScaleInterval(self.drop,
                              0.25,
                              Vec3(1.0 + scaleChange, 1.0 + scaleChange / 2,
                                   1.0 - scaleChange),
                              blendType='easeInOut'),
            LerpScaleInterval(self.drop,
                              0.25,
                              Vec3(1.0, 1.0, 1.0),
                              blendType='easeInOut'),
            Func(self.disableCollisionDamage),
            LerpScaleInterval(self.drop,
                              0.2,
                              Vec3(1.0 + scaleChange / 8,
                                   1.0 + scaleChange / 8,
                                   1.0 - scaleChange / 8),
                              blendType='easeInOut'),
            LerpScaleInterval(self.drop,
                              0.2,
                              Vec3(1.0, 1.0, 1.0),
                              blendType='easeInOut'),
            LerpScaleInterval(self.drop,
                              0.15,
                              Vec3(1.0 + scaleChange / 16,
                                   1.0 + scaleChange / 16,
                                   1.0 - scaleChange / 16),
                              blendType='easeInOut'),
            LerpScaleInterval(self.drop,
                              0.15,
                              Vec3(1.0, 1.0, 1.0),
                              blendType='easeInOut'),
            LerpScaleInterval(self.drop,
                              0.1,
                              Vec3(1.0 + scaleChange / 16,
                                   1.0 + scaleChange / 8,
                                   1.0 - scaleChange / 16),
                              blendType='easeInOut'),
            LerpColorScaleInterval(self.drop, Globals.DropFadeTime,
                                   Vec4(1.0, 1.0, 1.0, 0.0)))
        ival = Sequence(Func(self.reparentTo, render),
                        Parallel(Sequence(WaitInterval(hangTime), dropIval),
                                 shadowIval),
                        Parallel(Func(self.game.dropHit, self, id),
                                 dropSoundIval, dropShakeSeq),
                        Func(self.game.cleanupDrop, id),
                        name='drop%s' % id)
        self.ival = ival
        return ival

    def destroy(self):
        self.ival.pause()
        self.ival = None
        self._dropSfx.pause()
        self._dropSfx = None
        self.collTube = None
        self.collNode = None
        self.collNodePath.removeNode()
        self.collNodePath = None
        self.removeNode()
        return
예제 #36
0
class RacingGame(ShowBase):
    # method completely taken from RoamingRalph demo:
    def addInstructions(self, pos, msg):
        return OnscreenText(text=msg,
                            style=1,
                            fg=(1, 1, 1, 1),
                            scale=.05,
                            shadow=(0, 0, 0, 1),
                            parent=base.a2dTopLeft,
                            pos=(0.08, -pos - 0.04),
                            align=TextNode.ALeft)

    def addWin(self, time):
        msg = (
            "You finished the course in: \n%d seconds \n press z to race again"
            % (time))
        self.winText = OnscreenText(text=msg,
                                    style=1,
                                    fg=(1, 1, 1, 1),
                                    scale=.2,
                                    shadow=(0, 0, 0, 1),
                                    parent=base.a2dTopLeft,
                                    pos=(0.10, -0.5),
                                    align=TextNode.ALeft)

    def destroyWin(self):
        if (self.winText != None):
            self.winText.destroy()

    def setUpFlyingInstructions(self):
        self.inst[0] = self.addInstructions(.06, "Arrow Keys to move around")
        self.inst[1] = self.addInstructions(.12, "w and s to control pitch")
        self.inst[2] = self.addInstructions(.18, "a and d to control yaw")
        self.inst[3] = self.addInstructions(.24, "h to switch to driving mode")
        self.inst[4] = self.addInstructions(.3, "mouse click to add object")
        self.inst[5] = self.addInstructions(.36, "m to go to main")

    def startMovement(self):
        taskMgr.add(self.move, "moveTask")

    def destroyInstructions(self):
        # got way to destroy text from:
        # https://www.panda3d.org/manual/index.php/OnscreenText
        for element in self.inst:
            element.destroy()

    def startCreating(self):
        self.switchToCreateMode()
        self.destroyStartScreenButtons()
        self.startMovement()

    def startDriving(self):
        self.switchToDrivingMode()
        self.destroyStartScreenButtons()
        self.startMovement()

    def startTutorial(self):
        self.mode = self.modeTutorial
        self.setUpTutorial()
        self.destroyStartScreenButtons()
        self.startMovement()

    def setUpStartScreenButtons(self):
        self.creatingButton = DirectButton(text="Start Creating",
                                           scale=.1,
                                           command=self.startCreating,
                                           pos=(0, 0, .2))
        self.drivingButton = DirectButton(text="Start Driving",
                                          scale=.1,
                                          command=self.startDriving,
                                          pos=(0, 0, 0))
        self.tutorialButton = DirectButton(text="Start Tutorial",
                                           scale=.1,
                                           command=self.startTutorial,
                                           pos=(0, 0, -.2))

    def destroyStartScreenButtons(self):
        self.creatingButton.destroy()
        self.drivingButton.destroy()
        self.tutorialButton.destroy()

    def setAddObjectTree(self):
        self.createdObject = self.createTree

    def setAddObjectRock(self):
        self.createdObject = self.createRock

    def setAddObjectPole(self):
        self.createdObject = self.createPole

    def setUpCreateButtons(self):
        # todo: add toggle for instructions so that they do not always interfere with button
        self.treeButton = DirectButton(text="Add Block",
                                       scale=.1,
                                       command=self.setAddObjectTree,
                                       pos=(0, 0, .85))
        #self.rockButton = DirectButton(text="Add Rock", scale=.1, command=self.setAddObjectRock, pos=(-.5,.9,.85))
        self.poleButton = DirectButton(text="Add Pole",
                                       scale=.1,
                                       command=self.setAddObjectPole,
                                       pos=(.5, 0, .85))

    def setUpCreateObjects(self):
        self.createdObject = 0
        self.createTree = 0
        self.createRock = 1
        self.createPole = 2

    def destroyCreateButtons(self):
        self.treeButton.destroy()
        #self.rockButton.destroy()
        self.poleButton.destroy()

    def setUpDrivingInstructions(self):
        self.inst[0] = self.addInstructions(
            .06, "Right arrow and left arrow to turn")
        self.inst[1] = self.addInstructions(
            .12, "Forward and Backward arrow to go forward and backward")
        self.inst[2] = self.addInstructions(.18,
                                            "h to switch to add object mode")
        self.inst[3] = self.addInstructions(.24,
                                            "z to switch to start the race")
        self.inst[4] = self.addInstructions(.30, "m to go to main")

    def setUpWindow(self):
        # set up the egg files needed
        # since this method is made for python 2.7 but these objects are made for python 3.5, seems to be incompatible
        #m = Mountain("TestMountain", 60)
        #m.editFile()
        #p = Pole("TestPole", 0, 0, 0)
        #p.editFile()
        #c = Car("TestCar", 0,0,0)
        #c.editFile()
        #b = BeaconLight("BeaconLight",0,0,0)
        #b.editFile()
        # Set up the window, camera, etc
        ShowBase.__init__(self)

        # Set the background color to black
        self.win.setClearColor((0, 1, 1, 1))
        # this is the model I created using mountainMaker.py
        self.environ = loader.loadModel("TestMountain1")
        self.environ.reparentTo(render)

        self.car = loader.loadModel("TestCar")
        # found how to solve the problem of only being able to see objects from
        # certain angles with this:
        # http://www.panda3d.org/manual/index.php/Backface_Culling_and_Frontface_Culling
        self.car.setTwoSided(True)
        self.car.reparentTo(render)

        # Create some lighting
        # this is a part that is completely unchanged from demo
        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))
        # to get light from other direction to light up things on both sides
        directionalLight2 = DirectionalLight("directionalLight")
        directionalLight2.setDirection((5, 5, 5))
        directionalLight2.setColor((1, 1, 1, 1))
        directionalLight2.setSpecularColor((1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambientLight))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(directionalLight2))

    def setUpCar(self):
        # for adjusting so that the position is the center of the car
        self.adjustedXForCenter = 10 / 2
        self.adjustedYForCenter = 20 / 2

        # for some reason can't change this or the collisions do not work
        self.carPositionX = 20
        self.carPositionY = 20
        self.carPositionZ = 100
        # note for rotating camera: from this website:
        # https://www.panda3d.org/manual/index.php/Common_State_Changes
        # setHpr(Yaw, Pitch, Roll)

        # setting up initial conditions for which way camera is rotated
        self.carYaw = 0
        self.carPitch = 0
        (actualXPos, actualYPos) = RacingGame.findActualCenter(
            self, self.carPositionX, self.carPositionY,
            self.adjustedXForCenter, self.adjustedYForCenter, self.carYaw)
        self.car.setX(actualXPos)
        self.car.setY(actualYPos)
        self.car.setZ(self.carPositionZ)
        self.car.setHpr(self.carYaw, self.carPitch, 0)

    def setUpCamera(self):
        # for flying mode
        self.cameraPositionX = 500
        self.cameraPositionY = 500
        self.cameraPositionZ = 40
        # note for rotating camera: from this website:
        # https://www.panda3d.org/manual/index.php/Common_State_Changes
        # setHpr(Yaw, Pitch, Roll)

        # setting up initial conditions for which way camera is rotated
        self.cameraYaw = 0
        self.cameraPitch = 0

        # Set up the camera
        self.disableMouse()

        # should probably clean up these magic numbers
        self.camera.setPos(self.cameraPositionX, self.cameraPositionY,
                           self.cameraPositionZ)

    def setUpKeyMap(self):
        # This is used to store which keys are currently pressed.
        self.keyMap = {
            "left": 0,
            "right": 0,
            "forward": 0,
            "cam-left": 0,
            "cam-right": 0,
            "backward": 0,
            "cam-up": 0,
            "cam-down": 0,
            "add-car": 0,
            "switch-mode": 0,
            "mouse-click": 0,
            "race-start": 0,
            "to-main": 0
        }
        # Accept the control keys for movement and rotation

        #setting up keys for movement
        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, ["backward", 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, ["backward", False])

        self.accept("m", self.setKey, ["to-main", True])
        self.accept("m-up", self.setKey, ["to-main", False])

        # starting race
        self.accept("z", self.setKey, ["race-start", True])
        self.accept("z-up", self.setKey, ["race-start", False])

        # adding car
        self.accept("mouse1", self.setKey, ["mouse-click", True])
        self.accept("mouse1-up", self.setKey, ["mouse-click", False])

        # setting up orientation of the camera
        self.accept("a", self.setKey, ["cam-left", True])
        self.accept("s", self.setKey, ["cam-down", True])
        self.accept("a-up", self.setKey, ["cam-left", False])
        self.accept("s-up", self.setKey, ["cam-down", False])
        self.accept("d", self.setKey, ["cam-right", True])
        self.accept("d-up", self.setKey, ["cam-right", False])
        self.accept("w", self.setKey, ["cam-up", True])
        self.accept("w-up", self.setKey, ["cam-up", False])

        # to switch between tasks
        self.accept("h", self.setKey, ["switch-mode", True])
        self.accept("h-up", self.setKey, ["switch-mode", False])

    def __init__(self):
        self.setUpWindow()
        self.setUpKeyMap()
        #instructions
        self.inst = [""] * 6
        self.setUpFlyingInstructions()

        self.mouseClicked = False

        self.winText = None

        # important for setting the size relative to everything else
        # found it here : https://www.panda3d.org/manual/index.php/Common_State_Changes
        # set the mode that the player is currently in
        self.mode = 0
        self.modeFly = 2
        self.modeRace = 1
        self.modeStart = 0
        self.modeTutorial = 3
        # to ensure that when pressing h it only switches once each press
        self.hasSwitched = False
        self.raceBegan = False
        self.raceTime = 0
        self.poleOn = 0

        self.setUpCamera()
        self.setUpCar()
        self.setUpCarCollider()
        self.setUpMouseCollider()
        self.setUpStartScreenButtons()
        # make the rocks and other stuff that will show up
        self.setUpCreateObjects()
        self.objects = []
        self.poles = []
        self.beaconLight = None
        self.beaconLightZ = 50
        self.target = None

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

    def findCollisionTube(self):
        # using bassically same formula as Y position
        # decided not to use this because possible problems with ground getting
        # hit instead of things in front
        degToRad = math.pi / 180
        xAddition = (
            self.adjustedXForCenter * math.cos(self.carYaw * degToRad) +
            self.adjustedYForCenter * math.sin(self.carYaw * degToRad)) / 2
        yAddition = (
            self.adjustedXForCenter * math.cos(self.carYaw * degToRad) +
            self.adjustedYForCenter * math.sin(self.carYaw * degToRad))

    def findCarFrontDir(self):
        degToRad = math.pi / 180
        xDir = -1 * math.sin(degToRad * self.carYaw) * math.cos(
            degToRad * self.carPitch)
        yDir = 1 * math.cos(degToRad * self.carYaw) * math.cos(
            degToRad * self.carPitch)
        zDir = 1 * math.sin(degToRad * self.carPitch)
        return (xDir, yDir, zDir)

    def setUpCarCollider(self):
        self.carCollideTrav = CollisionTraverser()
        base.cTrav = self.carCollideTrav
        self.handler = CollisionHandlerQueue()
        self.carRay = CollisionRay(self.carPositionX, self.carPositionY,
                                   self.carPositionZ, 0, 0, -1)
        self.carForwardHandler = CollisionHandlerQueue()
        # so that it doesn't collide with things forward and backward.
        degToRad = math.pi / 180
        (xDir, yDir, zDir) = self.findCarFrontDir()
        self.carRayForward = CollisionRay(self.carPositionX, self.carPositionY,
                                          self.carPositionZ, xDir, yDir, zDir)
        self.carForwardCollision = CollisionNode("forwardCollision")
        self.carForwardCollision.addSolid(self.carRayForward)
        self.carForwardCollision.setIntoCollideMask(CollideMask.allOff())
        self.carForwardCollisionNode = self.car.attachNewNode(
            self.carForwardCollision)
        (centerX,
         centerY) = self.findActualCenter(0, 0, self.adjustedXForCenter,
                                          self.adjustedYForCenter, self.carYaw)
        self.carRayForward.setOrigin(5, 10, 5)
        self.carCollision = CollisionNode("groundCollision")
        self.carCollision.addSolid(self.carRay)
        self.carCollision.setIntoCollideMask(CollideMask.allOff())
        self.carCollisionNode = self.car.attachNewNode(self.carCollision)
        self.carCollideTrav.addCollider(self.carCollisionNode, self.handler)
        self.carCollideTrav.addCollider(self.carForwardCollisionNode,
                                        self.carForwardHandler)
        self.carForwardCollisionNode.show()

    def setUpMouseCollider(self):
        # clicking on objects stuff came from here:
        # https://www.panda3d.org/manual/index.php/Collision_Traversers
        # https://www.panda3d.org/manual/index.php/Collision_Handlers
        # will not use the traverser set up by car because slow
        # instead we will render each time clicked
        self.mouseCollideTrav = CollisionTraverser("mouseTraverse")
        self.mousehandler = CollisionHandlerQueue()
        # edit this so that from Object is the camera
        # self.mouseCollideTrav.addCollider(fromObject, queue)
        # self.mouseCollideTrav.traverse(render)
        # this next part came from:
        # https://www.panda3d.org/manual/index.php/Clicking_on_3D_Objects
        pickerNode = CollisionNode("mouseRay")
        pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
        pickerNode.setIntoCollideMask(CollideMask.allOff())
        self.pickerRay = CollisionRay()
        pickerNode.addSolid(self.pickerRay)
        pickerNp = camera.attachNewNode(pickerNode)
        self.mouseCollideTrav.addCollider(pickerNp, self.mousehandler)

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

    def switchToCreateMode(self):
        self.mode = self.modeFly
        self.destroyInstructions()
        self.setUpFlyingInstructions()
        self.hasSwitched = True
        self.setUpCreateButtons()

    def switchToDrivingMode(self):
        self.mode = self.modeRace
        self.destroyInstructions()
        self.setUpDrivingInstructions()
        self.hasSwitched = True

    def switchToMainMode(self):
        self.mode = 0
        self.setUpStartScreenButtons()

    def setTutorialText(self, str):
        # reusing inst so that it is easy to erase
        self.inst[0] = self.addInstructions(.06, str)

    def move(self, task):
        if (self.keyMap["to-main"]):
            self.switchToMainMode()
        elif (self.mode == self.modeFly):
            if self.keyMap["switch-mode"] and not self.hasSwitched:
                self.switchToDrivingMode()
                self.destroyCreateButtons()
            elif not self.keyMap["switch-mode"]:
                # to ensure switch mode only happens once per button pressed
                self.hasSwitched = False
            self.findNewCameraPosition()
            self.checkAndAddNewObject()
        elif (self.mode == self.modeRace):
            if self.keyMap["switch-mode"] and not self.hasSwitched:
                self.destroyWin()
                self.switchToCreateMode()
            elif not self.keyMap["switch-mode"]:
                # this ensures that when key is pressed only switch states once
                self.hasSwitched = False
            self.findCarNewXandY()
            # when implementing the use of the mouse look here:
            # https://www.panda3d.org/manual/index.php/Clicking_on_3D_Objects
            self.setCarZ()
            self.setCameraPositionBehindCar()
            if (self.keyMap["race-start"] and not self.raceBegan
                    and len(self.poles) >= 2):
                self.destroyWin()
                # try so that if there are not enough poles then the game
                # doesn't crash
                try:
                    self.raceBegan = True
                    self.raceTime = time.time()
                    # puts in the car where the first two poles are
                    # first col of poles is model, second x coord, thrid y coord, fourth z coord
                    self.carPositionX = (self.poles[0][1] +
                                         self.poles[1][1]) / 2
                    self.carPositionY = (self.poles[0][2] +
                                         self.poles[1][2]) / 2
                    # meant to show where car should go
                    # got info on how to do point lights from here:
                    # https://www.panda3d.org/manual/index.php/Lighting
                    self.beaconLight = PointLight("beaconLight")
                    self.beaconLight.setColor((1, 1, 1, 1))
                    self.beaconLight.setAttenuation((0, 0, 1))
                    self.beaconLightHolder = render.attachNewNode(
                        self.beaconLight)
                    (beaconLightX, beaconLightY) = self.getNextGateCenter()
                    # target for driver
                    if (self.target == None):
                        self.target = loader.loadModel("BeaconLight.egg")
                    self.target.setTwoSided(True)
                    self.target.reparentTo(render)
                    if (beaconLightX != None):
                        self.beaconLightHolder.setPos(beaconLightX,
                                                      beaconLightY,
                                                      self.beaconLightZ)
                        render.setLight(self.beaconLightHolder)
                        self.target.setPos(beaconLightX, beaconLightY,
                                           self.beaconLightZ)
                except:
                    # not enough poles
                    pass
            if (self.raceBegan):
                # minus 1 just in case non even
                if (self.poleOn + 1 >= len(self.poles)):
                    self.raceBegan = False
                    self.addWin(time.time() - self.raceTime)
                    # since race ended
                    try:
                        self.target.destroy()
                    except:
                        pass
                    self.beaconLight = None  # use object + lights
                    self.beaconLightHolder = None
                    self.poleOn = 0
                else:
                    acceptableError = 100
                    # formula I created: (p2y-p1y)/(p2x-p1x)*(p2x-pAx)+p2y =
                    # expected pAy
                    # so if the actual car positionY is within acceptableError of
                    # pAy then the car is between the two poles
                    # if in between poles
                    middleX = (self.poles[self.poleOn][1] +
                               self.poles[self.poleOn + 1][1]) / 2
                    middleY = (self.poles[self.poleOn][2] +
                               self.poles[self.poleOn + 1][2]) / 2
                    expectedCarY = (
                        (self.poles[self.poleOn][2] -
                         self.poles[self.poleOn + 1][2]) /
                        (self.poles[self.poleOn][1] -
                         self.poles[self.poleOn + 1][1]) *
                        (self.poles[self.poleOn][1] - self.carPositionX) +
                        self.poles[self.poleOn][2])
                    # do not really care about car being inbetween pole in z axis
                    # because 2 demensional
                    if (expectedCarY + acceptableError > self.carPositionY
                            and expectedCarY - acceptableError <
                            self.carPositionY):
                        self.poleOn += 2
                        # only when last pole found is it necesary to add light
                        # to guide to next place elsewhere
                        (beaconLightX, beaconLightY) = self.getNextGateCenter()
                        if (beaconLightX != None):
                            self.beaconLightHolder.setPos(
                                beaconLightX, beaconLightY, self.beaconLightZ)
                            self.target.setPos(beaconLightX, beaconLightY,
                                               self.beaconLightZ)
        elif (self.mode == self.modeTutorial):
            self.destroyWin()
            # do the tutorial part for the creating
            timeBeforeNext = 2
            if (self.tutorialPause == True):
                if (time.time() - self.tutorialActionTime > timeBeforeNext):
                    self.tutorialPause = False
            else:
                if (self.tutorialStep == -1):
                    self.destroyInstructions()
                    self.setTutorialText(
                        "use w and s to move camera up and down")
                    self.tutorialStep += 1
                # do this until the user has completed all of the task
                self.checkTutorialStep(
                    0, (self.keyMap["cam-up"] or self.keyMap["cam-down"]),
                    "use a and d to rotate camera right and left")
                self.checkTutorialStep(
                    1, (self.keyMap["cam-left"] or self.keyMap["cam-right"]),
                    "use up-arrow and down-arrow to turn camera forward and backward"
                )
                self.checkTutorialStep(
                    2, (self.keyMap["forward"] or self.keyMap["backward"]),
                    "use left-arrow and right-arrow to slide camera left and right"
                )
                self.checkTutorialStep(
                    3, (self.keyMap["left"] or self.keyMap["right"]),
                    "use mouse click to place objects on terrain")
                self.checkTutorialStep(
                    4, (self.keyMap["mouse-click"]),
                    "use up-arrow and down-arrow to move car forward and backward",
                    (self.switchToDrivingMode, self.destroyInstructions))
                # need to ensure that the mode stays as tutorial
                self.mode = self.modeTutorial
                # then tutorial part for the driving
                self.checkTutorialStep(
                    5, (self.keyMap["forward"] or self.keyMap["backward"]),
                    "use right-arrow and left-arrow to rotate car left and right"
                )
                self.checkTutorialStep(
                    6, (self.keyMap["left"] or self.keyMap["right"]),
                    "Use poles to make the race course\n use z to start race")
                self.checkTutorialStep(
                    7, True,
                    "Follow yellow block through the gates till you win")
                self.checkTutorialStep(
                    8, True,
                    "Watch for high Terrain and blocks because you can not get through those"
                )
                self.checkTutorialStep(9, True, "")
                if (self.tutorialStep > 9):
                    # switch to main
                    self.switchToMainMode()
            # for movement
            if (self.tutorialStep <= 4):
                self.findNewCameraPosition()
                self.checkAndAddNewObject()
            if (self.tutorialStep > 4 and self.tutorialStep <= 9):
                self.findCarNewXandY()
                self.setCarZ()
                self.setCameraPositionBehindCar()
        return task.cont

    def getNextGateCenter(self):
        if (len(self.poles) > self.poleOn + 1):
            positionX = (self.poles[self.poleOn][1] +
                         self.poles[self.poleOn + 1][1]) / 2
            positionY = (self.poles[self.poleOn][2] +
                         self.poles[self.poleOn + 1][2]) / 2
            return (positionX, positionY)
        else:
            return (None, None)

    def checkTutorialStep(self, step, keysNeeded, nextText, functions=None):
        if (self.tutorialStep == step and self.tutorialNextStep == True):
            if (functions != None):
                for func in functions:
                    func()
            self.destroyInstructions()
            self.setTutorialText(nextText)
            self.tutorialStep += 1
            self.tutorialNextStep = False
        elif (self.tutorialStep == step and keysNeeded):
            self.tutorialNextStep = True
            self.tutorialActionTime = time.time()
            self.tutorialPause = True

    def setUpTutorial(self):
        self.tutorialStep = -1
        self.tutorialPause = False
        # this records when last tutorial action taken
        self.tutorialActionTime = 0
        self.tutorialNextStep = False

    def checkAndAddNewObject(self):
        # clicking on 3D objects comes from here:
        # https://www.panda3d.org/manual/index.php/Clicking_on_3D_Objects
        # checks if it needs to add any objects:
        if (self.keyMap["mouse-click"] and self.mouseClicked == False):
            self.mouseClicked = True
            # found way to speed this up by only doing collision check
            # when mouse clicked by not using cTrav like in this method
            # the way I did it I found here:
            # https://www.panda3d.org/manual/index.php/Clicking_on_3D_Objects
            # self.mouseCollideTrav.traverse(render)
            if (base.mouseWatcherNode.hasMouse()):
                mousePos = base.mouseWatcherNode.getMouse()
                self.pickerRay.setFromLens(base.camNode, mousePos.getX(),
                                           mousePos.getY())
                # do not put this before previous line, will get the coordinates
                # of last mouse click and where pickerRay was
                # ahhhhhhh!!!!!!!!!!!
                self.mouseCollideTrav.traverse(render)
                if (self.mousehandler.getNumEntries() > 0):
                    entries = list(self.mousehandler.getEntries())
                    # pathagorean formula for sorting
                    entries.sort(
                        key=lambda x: ((x.getSurfacePoint(render).getX(
                        ) - self.cameraPositionX)**2 + (x.getSurfacePoint(
                            render).getY() - self.cameraPositionY)**2)**.5)
                    newX = entries[0].getSurfacePoint(render).getX()
                    newY = entries[0].getSurfacePoint(render).getY()
                    newZ = entries[0].getSurfacePoint(render).getZ()
                    adjustedX = 10 / 2
                    adjustedY = 20 / 2
                    yaw = 0
                    # have to adjust this once there are different sized
                    # objects added
                    (actualXPos, actualYPos) = RacingGame.findActualCenter(
                        self, newX, newY, adjustedX, adjustedY, yaw)
                    if (self.createdObject == self.createPole):
                        self.poles.append([
                            loader.loadModel("TestPole.egg"), actualXPos,
                            actualYPos, newZ
                        ])
                        self.poles[len(self.poles) - 1][0].reparentTo(render)
                        self.poles[len(self.poles) - 1][0].setTwoSided(True)
                        self.poles[len(self.poles) - 1][0].setPos(
                            actualXPos, actualYPos, newZ)
                    else:
                        newCar = loader.loadModel("TestCar.egg")
                        newCar.reparentTo(render)
                        newCar.setPos(actualXPos, actualYPos, newZ)
                        # should take out because slow, but objects can not be
                        # seen without this because only seen from one direction
                        # even though normal vectors set up.
                        newCar.setTwoSided(True)
                        self.objects.append(newCar)
        elif (not self.keyMap["mouse-click"]):
            # elif because for some reason mouseClicked was becoming false
            # while click still pressed
            self.mouseClicked = False

    def findNewCameraPosition(self):
        # 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()
        # the angle is in degrees with 360 equal to full rotation
        angleAdjustment = 100
        if self.keyMap["cam-left"]:
            self.cameraYaw += angleAdjustment * dt
        if self.keyMap["cam-right"]:
            self.cameraYaw -= angleAdjustment * dt
        if self.keyMap["cam-up"]:
            self.cameraPitch += angleAdjustment * dt
        if self.keyMap["cam-down"]:
            self.cameraPitch -= angleAdjustment * dt

        positionAdjustment = 500
        # should switch rad and Deg in variable name
        radToDeg = math.pi / 180
        # the x and y component of left and right moves, do not need to
        # compensate in z axis because not doing any roll, so there should be
        # no zComponent
        xComponent = math.cos(self.cameraYaw * radToDeg)
        yComponent = math.sin(self.cameraYaw * radToDeg)

        if self.keyMap["left"]:
            self.cameraPositionX -= positionAdjustment * dt * xComponent
            self.cameraPositionY -= positionAdjustment * dt * yComponent
        if self.keyMap["right"]:
            self.cameraPositionX += positionAdjustment * dt * xComponent
            self.cameraPositionY += positionAdjustment * dt * yComponent

        # for going forward, the orientation is rotated 90 degrees so need to
        # change components
        xComponent = math.cos(self.cameraYaw * radToDeg + math.pi /
                              2) * math.cos(self.cameraPitch * radToDeg)
        yComponent = math.sin(self.cameraYaw * radToDeg + math.pi /
                              2) * math.cos(self.cameraPitch * radToDeg)
        zComponent = math.sin(self.cameraPitch * radToDeg)

        if self.keyMap["forward"]:
            self.cameraPositionX += positionAdjustment * dt * xComponent
            self.cameraPositionY += positionAdjustment * dt * yComponent
            self.cameraPositionZ += positionAdjustment * dt * zComponent
        if self.keyMap["backward"]:
            self.cameraPositionX -= positionAdjustment * dt * xComponent
            self.cameraPositionY -= positionAdjustment * dt * yComponent
            self.cameraPositionZ -= positionAdjustment * dt * zComponent

        self.camera.setX(self.cameraPositionX)
        self.camera.setY(self.cameraPositionY)
        self.camera.setZ(self.cameraPositionZ)
        self.camera.setHpr(self.cameraYaw, self.cameraPitch, 0)

    def carForwardImpact(self):
        # update position so that it is pointing right directions
        #(dirX, dirY, dirZ) = self.findCarFrontDir()
        #self.carRayForward.setDirection(dirX, dirY, dirZ)
        degToRad = math.pi / 180
        # + math.pi since it is taking corner and going to center rather
        # than opposite that function actually does
        #(centerX,centerY) = self.findActualCenter(0,0,self.adjustedXForCenter,
        #                                   self.adjustedYForCenter, self.carYaw
        #                                   +math.pi)
        posAboveGround = 5
        # need to update with new coordinates
        self.carCollideTrav.traverse(render)
        collisions = list(self.carForwardHandler.getEntries())
        # closest collision using pythagorean formula
        collisions.sort(
            key=lambda x:
            (x.getSurfacePoint(render).getX() - self.carPositionX)**2 +
            (x.getSurfacePoint(render).getY() - self.carPositionY)**2)
        if (len(collisions) > 0):
            (actualX, actualY) = RacingGame.findActualCenter(
                self, self.carPositionX, self.carPositionY,
                self.adjustedXForCenter, self.adjustedYForCenter, self.carYaw)
            distance = (
                (collisions[0].getSurfacePoint(render).getX() - actualX)**2 +
                (collisions[0].getSurfacePoint(render).getY() - actualY)**
                2)**.5
            error = .9  # so that the collisionray does not detect car itself
            return distance / 2 <= self.adjustedYForCenter * .9
        else:
            return False

    def findCarNewXandY(self):
        # 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.
        deltaTime = globalClock.getDt()
        degreeAdjustment = 60
        positionAdjustment = 100
        # should switch rad and Deg in variable name
        radToDeg = math.pi / 180
        # the x and y component of left and right moves, do not need to
        # compensate in z axis because not doing any roll, so there should be
        # no zComponent
        xComponent = math.sin(self.carYaw * radToDeg)
        yComponent = math.cos(self.carYaw * radToDeg)
        if self.keyMap["left"]:
            self.carYaw += degreeAdjustment * deltaTime
        if self.keyMap["right"]:
            self.carYaw -= degreeAdjustment * deltaTime
        if (self.keyMap["forward"] and not self.carForwardImpact()):
            self.carPositionX -= positionAdjustment * deltaTime * xComponent
            self.carPositionY += positionAdjustment * deltaTime * yComponent
        if self.keyMap["backward"]:
            self.carPositionX += positionAdjustment * deltaTime * xComponent
            self.carPositionY -= positionAdjustment * deltaTime * yComponent
        # need to consider both the x and y component of offset for both
        # because x slowly changes to y as it turns
        (actualXPos, actualYPos) = RacingGame.findActualCenter(
            self, self.carPositionX, self.carPositionY,
            self.adjustedXForCenter, self.adjustedYForCenter, self.carYaw)
        self.car.setX(actualXPos)
        self.car.setY(actualYPos)
        self.car.setZ(self.carPositionZ)
        self.car.setHpr(self.carYaw, self.carPitch, 0)

    def setCarZ(self):
        # almost directly taken from ralph example
        entries = list(self.handler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())
        # worry about which thing it collides with later
        if (len(entries) > 0):
            # and entries[0].getIntoNode().getName() == "mountainCollide":
            self.carPositionZ = (entries[0].getSurfacePoint(render).getZ())
        else:
            # because at 25 everything should be below car and do not want
            # to continually go up or else it may go up forever.
            self.carPositionZ = 25
        self.setCameraPositionBehindCar()

    def setCameraPositionBehindCar(self):
        # Modify view of camera so that it is behind car
        # should be named degToRad
        radToDeg = math.pi / 180
        distanceBehind = 200
        distanceAbove = 60
        self.camera.setHpr(self.carYaw, -.5, 0)
        (actualXPos, actualYPos) = self.findActualCenter(
            self.carPositionX, self.carPositionY, self.adjustedXForCenter,
            self.adjustedXForCenter, self.carYaw)
        camX = actualXPos + distanceBehind * math.sin(radToDeg * self.carYaw)
        camY = actualYPos - distanceBehind * math.cos(radToDeg * self.carYaw)
        camZ = self.carPositionZ + distanceAbove
        self.camera.setPos(camX, camY, camZ)

    def findActualCenter(self, positionX, positionY, adjustedX, adjustedY,
                         yaw):
        # will need to fix this later, it seems to be adjusting wrong
        # so that it is puting box away from click instead of on it
        # update, I think this is fixed?!?
        degToRad = math.pi / 180
        actualXPos = (positionX - adjustedX * math.cos(degToRad * yaw) +
                      adjustedY * math.sin(degToRad * yaw))
        actualYPos = (positionY - adjustedY * math.cos(degToRad * yaw) -
                      adjustedX * math.sin(degToRad * yaw))
        return (actualXPos, actualYPos)
예제 #37
0
    def makeWriteOffTrack(self):
        pad = BattleProps.globalPropPool.getProp('pad')
        pad.setScale(1.89)
        pencil = BattleProps.globalPropPool.getProp('pencil')
        BattleParticles.loadParticles()
        checkmark = copyProp(BattleParticles.getParticle('checkmark'))
        checkmark.setBillboardPointEye()

        # Make prop virtual:
        pad.setColorScale(1.0, 0.0, 0.0, 0.8)
        pad.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
        pencil.setColorScale(1.0, 0.0, 0.0, 0.8)
        pencil.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
        checkmark.setColorScale(1.0, 0.0, 0.0, 0.8)
        checkmark.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))

        # Prop collisions:
        colNode = CollisionNode(self.uniqueName('SuitAttack'))
        colNode.setTag('damage', str(self.attackInfo[1]))

        bounds = checkmark.getBounds()
        center = bounds.getCenter()
        radius = bounds.getRadius()
        sphere = CollisionSphere(center.getX(), center.getY(), center.getZ(),
                                 radius)
        sphere.setTangible(0)
        colNode.addSolid(sphere)
        colNode.setIntoCollideMask(WallBitmask)
        checkmark.attachNewNode(colNode)

        toonId = self.toon

        toon = base.cr.doId2do.get(toonId)
        if not toon:
            return

        self.virtualSuit.lookAt(toon)

        if self.virtualSuit.style.body in ['a', 'b']:
            throwDelay = 3
        elif self.virtualSuit.style.body == 'c':
            throwDelay = 2.3
        else:
            throwDelay = 2

        def throwProp():
            if not self.virtualSuit:
                return

            toon = self.cr.doId2do.get(toonId)
            if not toon:
                self.cleanupProp(checkmark, False)
                self.finishPropAttack()
                return

            self.virtualSuit.lookAt(toon)

            checkmark.wrtReparentTo(render)

            hitPos = toon.getPos() + Vec3(0, 0, 2.5)
            distance = (checkmark.getPos() - hitPos).length()
            speed = 50.0

            if self.attackProp == 'teeth':
                throwSequence = Sequence(
                    Parallel(
                        checkmark.posInterval(distance / speed, hitPos),
                        ActorInterval(checkmark,
                                      'teeth',
                                      duration=distance / speed),
                    ),
                    Func(self.cleanupProp, checkmark, False),
                )
            else:
                throwSequence = Sequence(
                    checkmark.posInterval(distance / speed, hitPos),
                    Func(self.cleanupProp, checkmark, False))

            throwSequence.start()

        pencilTrack = Sequence(
            Wait(0.5),
            Func(pencil.setPosHpr, -0.47, 1.08, 0.28, 21.045, 12.702,
                 -176.374),
            Func(pencil.reparentTo, self.virtualSuit.getRightHand()),
            LerpScaleInterval(pencil,
                              0.5,
                              Point3(1.5, 1.5, 1.5),
                              startScale=Point3(0.01)),
            Wait(throwDelay),
            Func(checkmark.reparentTo, render),
            Func(checkmark.setScale, 1.6),
            Func(checkmark.setPosHpr, pencil, 0, 0, 0, 0, 0, 0),
            Func(checkmark.setP, 0),
            Func(checkmark.setR, 0),
            Func(throwProp),
            Wait(0.3),
            LerpScaleInterval(pencil, 0.5, Point3(0.01, 0.01, 0.01)),
            Func(pencil.removeNode),
        )

        suitTrack = Sequence(
            ActorInterval(self.virtualSuit, 'hold-pencil'),
            Func(self.virtualSuit.loop, 'neutral', 0),
        )

        soundTrack = Sequence(
            Wait(2.3),
            SoundInterval(self.writeOffSfx,
                          duration=0.9,
                          node=self.virtualSuit),
            SoundInterval(self.dingSfx, node=self.virtualSuit))

        padTrack = Track(
            (0.0,
             Func(pad.setPosHpr, -0.25, 1.38, -0.08, -19.078, -6.603,
                  -171.594)),
            (0.4, Func(pad.reparentTo, self.virtualSuit.getLeftHand())),
            (3.0, Func(pad.removeNode)),
        )

        track = Sequence(
            Parallel(suitTrack, soundTrack, padTrack, pencilTrack,
                     Func(self.sayFaceoffTaunt)),
            Func(self.virtualSuit.loop, 'walk', 0))
        return track
예제 #38
0
class World(ShowBase):
    def __init__(self):

        # Setup window size, title and so on
        load_prc_file_data(
            "", """
            win-size 1600 900
            window-title Render Pipeline - Roaming Ralph Demo
        """)

        # ------ Begin of render pipeline code ------

        # Insert the pipeline path to the system path, this is required to be
        # able to import the pipeline classes
        pipeline_path = "../../"

        # Just a special case for my development setup, so I don't accidentally
        # commit a wrong path. You can remove this in your own programs.
        if not os.path.isfile(os.path.join(pipeline_path, "setup.py")):
            pipeline_path = "../../RenderPipeline/"

        sys.path.insert(0, pipeline_path)

        from rpcore import RenderPipeline, SpotLight
        self.render_pipeline = RenderPipeline()
        self.render_pipeline.create(self)

        # ------ End of render pipeline code, thats it! ------

        # Set time of day
        self.render_pipeline.daytime_mgr.time = "7:40"

        # Use a special effect for rendering the scene, this is because the
        # roaming ralph model has no normals or valid materials
        self.render_pipeline.set_effect(render,
                                        "scene-effect.yaml", {},
                                        sort=250)

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

        # Post the instructions

        self.inst1 = addInstructions(0.95, "[ESC]  Quit")
        self.inst4 = addInstructions(0.90, "[W]  Run Ralph Forward")
        self.inst4 = addInstructions(0.85, "[S]  Run Ralph Backward")
        self.inst2 = addInstructions(0.80, "[A]  Rotate Ralph Left")
        self.inst3 = addInstructions(0.75, "[D]  Rotate Ralph Right")
        self.inst6 = addInstructions(0.70, "[Left Arrow]  Rotate Camera Left")
        self.inst7 = addInstructions(0.65,
                                     "[Right Arrow]  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("resources/world")
        self.environ.reparentTo(render)
        self.environ.setPos(0, 0, 0)

        # Remove wall nodes
        self.environ.find("**/wall").remove_node()

        # Create the main character, Ralph
        self.ralph = Actor("resources/ralph", {
            "run": "resources/ralph-run",
            "walk": "resources/ralph-walk"
        })
        self.ralph.reparentTo(render)
        self.ralph.setScale(.2)
        self.ralph.setPos(Vec3(-110.9, 29.4, 1.8))

        # 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("a", self.setKey, ["left", 1])
        self.accept("d", self.setKey, ["right", 1])
        self.accept("w", self.setKey, ["forward", 1])
        self.accept("s", self.setKey, ["backward", 1])
        self.accept("arrow_left", self.setKey, ["cam-left", 1])
        self.accept("arrow_right", self.setKey, ["cam-right", 1])
        self.accept("a-up", self.setKey, ["left", 0])
        self.accept("d-up", self.setKey, ["right", 0])
        self.accept("w-up", self.setKey, ["forward", 0])
        self.accept("s-up", self.setKey, ["backward", 0])
        self.accept("arrow_left-up", self.setKey, ["cam-left", 0])
        self.accept("arrow_right-up", self.setKey, ["cam-right", 0])
        self.accept("=", self.adjustSpeed, [0.25])
        self.accept("+", self.adjustSpeed, [0.25])
        self.accept("-", self.adjustSpeed, [-0.25])

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

        # Game state variables
        self.isMoving = False

        # Set up the camera

        base.disableMouse()
        base.camera.setPos(self.ralph.getX() + 10, self.ralph.getY() + 10, 2)
        base.camLens.setFov(80)

        # 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

    # Adjust movement speed
    def adjustSpeed(self, delta):
        newSpeed = self.speed + delta
        if 0 <= newSpeed <= 3:
            self.speed = newSpeed

    # 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())
        elif (self.keyMap["right"] != 0):
            self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt())
        if (self.keyMap["forward"] != 0):
            self.ralph.setY(self.ralph, -25 * self.speed * globalClock.getDt())
        elif (self.keyMap["backward"] != 0):
            self.ralph.setY(self.ralph, 25 * self.speed * 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["backward"]!=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)
        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)
        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
예제 #39
0
class GameContainer(ShowBase):
    def __init__(self):

        ShowBase.__init__(self)

        ########## Window configuration #########

        wp = WindowProperties()
        wp.setSize(1024, 860)

        self.win.requestProperties(wp)

        ########## Gameplay settings #########

        self.GAME_MODE = NORMAL
        self.NAVIGATION_MODE = SPACE

        self.mode_initialized = False

        #Trigger game chain

        self.loadWorld(LEVEL)

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

        self.disableMouse()

        self.mainCamera = Camera(self.camera)

        self.mainCamera.camObject.setHpr(0, 0, 0)

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

        self.taskMgr.add(self.gameLoop, "gameLoop", priority=35)

        self.keys = {"w": 0, "s": 0, "a": 0, "d": 0, "space": 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("space", self.setKey, ["space", 1])
        self.accept("space-up", self.setKey, ["space", 0])
        self.accept("wheel_up", self.zoomCamera, [-1])
        self.accept("wheel_down", self.zoomCamera, [1])
        self.accept("escape", self.switchGameMode, [IN_GAME_MENU])

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

        self.accept("playerGroundRayJumping-in",
                    self.avatar.handleCollisionEvent, ["in"])
        self.accept("playerGroundRayJumping-out",
                    self.avatar.handleCollisionEvent, ["out"])

        ######### GUI #########

        self.gui_elements = []

    def loadWorld(self, level):

        self.avatarActor = Actor("models/panda", {"walk": "models/panda-walk"})
        self.avatarActor.setScale(.5, .5, .5)
        self.avatarActor.setHpr(180, 0, 0)
        self.avatarActor.setPythonTag("moving", False)
        self.avatarActor.setCollideMask(BitMask32.allOff())

        if int(level) == level:

            pass

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

        self.environ = loader.loadModel("models/environment")
        self.environ.setName("terrain")
        self.environ.reparentTo(render)
        self.environ.setPos(0, 0, 0)
        self.environ.setCollideMask(BitMask32.bit(0))

        ######### Models #########

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

        base.enableParticles()

        gravityForce = LinearVectorForce(0, 0, -9.81)
        gravityForce.setMassDependent(False)
        gravityFN = ForceNode("world-forces")
        gravityFN.addForce(gravityForce)
        render.attachNewNode(gravityFN)
        base.physicsMgr.addLinearForce(gravityForce)

        self.avatarPhysicsActorNP = render.attachNewNode(ActorNode("player"))
        self.avatarPhysicsActorNP.node().getPhysicsObject().setMass(50.)
        self.avatarActor.reparentTo(self.avatarPhysicsActorNP)
        base.physicsMgr.attachPhysicalNode(self.avatarPhysicsActorNP.node())

        self.avatarPhysicsActorNP.setPos(15, 10, 5)

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

        self.avatar = Avatar(self.avatarPhysicsActorNP)

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

        self.cTrav = CollisionTraverser()

        #Make player rigid body

        self.pandaBodySphere = CollisionSphere(0, 0, 4, 3)

        self.pandaBodySphereNode = CollisionNode("playerBodyRay")
        self.pandaBodySphereNode.addSolid(self.pandaBodySphere)
        self.pandaBodySphereNode.setFromCollideMask(BitMask32.bit(0))
        self.pandaBodySphereNode.setIntoCollideMask(BitMask32.allOff())

        self.pandaBodySphereNodepath = self.avatar.objectNP.attachNewNode(
            self.pandaBodySphereNode)
        self.pandaBodySphereNodepath.show()

        self.pandaBodyCollisionHandler = PhysicsCollisionHandler()
        self.pandaBodyCollisionHandler.addCollider(
            self.pandaBodySphereNodepath, self.avatar.objectNP)

        #Keep player on ground

        self.pandaGroundSphere = CollisionSphere(0, 0, 1, 1)

        self.pandaGroundSphereNode = CollisionNode("playerGroundRay")
        self.pandaGroundSphereNode.addSolid(self.pandaGroundSphere)
        self.pandaGroundSphereNode.setFromCollideMask(BitMask32.bit(0))
        self.pandaGroundSphereNode.setIntoCollideMask(BitMask32.allOff())

        self.pandaGroundSphereNodepath = self.avatar.objectNP.attachNewNode(
            self.pandaGroundSphereNode)
        self.pandaGroundSphereNodepath.show()

        self.pandaGroundCollisionHandler = PhysicsCollisionHandler()
        self.pandaGroundCollisionHandler.addCollider(
            self.pandaGroundSphereNodepath, self.avatar.objectNP)

        #Notify when player lands

        self.pandaGroundRayJumping = CollisionSphere(0, 0, 1, 1)

        self.pandaGroundRayNodeJumping = CollisionNode(
            "playerGroundRayJumping")
        self.pandaGroundRayNodeJumping.addSolid(self.pandaGroundRayJumping)
        self.pandaGroundRayNodeJumping.setFromCollideMask(BitMask32.bit(0))
        self.pandaGroundRayNodeJumping.setIntoCollideMask(BitMask32.allOff())

        self.pandaGroundRayNodepathJumping = self.avatar.objectNP.attachNewNode(
            self.pandaGroundRayNodeJumping)
        self.pandaGroundRayNodepathJumping.show()

        self.collisionNotifier = CollisionHandlerEvent()
        self.collisionNotifier.addInPattern("%fn-in")
        self.collisionNotifier.addOutPattern("%fn-out")

        self.cTrav.addCollider(self.pandaGroundSphereNodepath,
                               self.pandaGroundCollisionHandler)
        self.cTrav.addCollider(self.pandaGroundRayNodepathJumping,
                               self.collisionNotifier)
        self.cTrav.addCollider(self.pandaBodySphereNodepath,
                               self.pandaBodyCollisionHandler)

    def setKey(self, key, value):

        self.keys[key] = value

    def zoomCamera(self, direction):

        Camera.AVATAR_DIST += direction

    def b(self, hey):

        self.avatarLanded = True

    def handleWindowEvent(self, window=None):

        wp = window.getProperties()

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

    def switchGameMode(self, newGameMode=None):

        self.cleanupGUI()

        if self.GAME_MODE == IN_GAME_MENU:

            if newGameMode == NORMAL:

                render.clearFog()

            elif newGameMode == MAIN_MENU:

                print "bubbles!"

        elif True:

            pass

        self.GAME_MODE = newGameMode

        self.mode_initialized = False

    def cleanupGUI(self):

        for gui_element in self.gui_elements:

            gui_element.destroy()

    def evenButtonPositions(self, button_spacing, button_height, num_buttons):

        center_offset = (button_spacing / (2.0) if
                         (num_buttons % 2 == 0) else 0)

        button_positions = []

        current_pos = center_offset + ((num_buttons - 1) / 2) * button_spacing

        for i in range(0, num_buttons):

            button_positions.append(current_pos + (button_height / 2.0))

            current_pos -= button_spacing

        return button_positions

    def buildInGameMenu(self):

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

        resume_button = DirectButton(
            text="Resume",
            scale=.1,
            command=(lambda: self.switchGameMode(NORMAL)),
            rolloverSound=None)

        main_menu_button = DirectButton(text="Main Menu",
                                        scale=.1,
                                        command=self.b,
                                        rolloverSound=None)

        options_button = DirectButton(text="Options",
                                      scale=.1,
                                      command=self.b,
                                      rolloverSound=None)

        exit_button = DirectButton(text="Exit",
                                   scale=.1,
                                   command=exit,
                                   rolloverSound=None)

        BUTTON_SPACING = .2
        BUTTON_HEIGHT = resume_button.getSy()

        button_positions = self.evenButtonPositions(BUTTON_SPACING,
                                                    BUTTON_HEIGHT, 4)

        resume_button.setPos(Vec3(0, 0, button_positions[0]))
        main_menu_button.setPos(Vec3(0, 0, button_positions[1]))
        options_button.setPos(Vec3(0, 0, button_positions[2]))
        exit_button.setPos(Vec3(0, 0, button_positions[3]))

        self.gui_elements.append(resume_button)
        self.gui_elements.append(main_menu_button)
        self.gui_elements.append(options_button)
        self.gui_elements.append(exit_button)

    def buildMainMenu(self):

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

        start_game_button = DirectButton(text="Start",
                                         scale=.1,
                                         command=self.b)

        select_level_button = DirectButton(text="Select Level",
                                           scale=.1,
                                           command=self.b)

        game_options_button = DirectButton(text="Options",
                                           scale=.1,
                                           command=self.b)

        exit_button = DirectButton(text="Exit", scale=.1, command=exit)

        BUTTON_SPACING = .2
        BUTTON_HEIGHT = start_game_button.getSy()

        button_positions = self.evenButtonPositions(BUTTON_SPACING,
                                                    BUTTON_HEIGHT)

        start_game_button.setPos(Vec3(0, 0, button_positions[0]))
        select_level_button.setPos(Vec3(0, 0, button_positions[1]))
        game_options_button.setPos(Vec3(0, 0, button_positions[2]))
        exit_button.setPos(Vec3(0, 0, button_positions[3]))

        self.gui_elements.append(start_game_button)
        self.gui_elements.append(select_level_button)
        self.gui_elements.append(game_options_button)
        self.gui_elements.append(exit_button)

    def gameLoop(self, task):

        #Compensate for inconsistent update intervals

        dt = globalClock.getDt()

        if self.GAME_MODE == MAIN_MENU:

            if not self.mode_initialized:

                self.buildMainMenu()

                self.mode_initialized = True

        if self.GAME_MODE == IN_GAME_MENU:

            #Fog out background

            if not self.mode_initialized:

                inGameMenuFogColor = (50, 150, 50)

                inGameMenuFog = Fog("inGameMenuFog")

                inGameMenuFog.setMode(Fog.MExponential)
                inGameMenuFog.setColor(*inGameMenuFogColor)
                inGameMenuFog.setExpDensity(.01)

                render.setFog(inGameMenuFog)

                self.buildInGameMenu()

                self.mode_initialized = True

        if self.GAME_MODE == NORMAL:

            if not self.mode_initialized:

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

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

                self.mode_initialized = True

            if self.NAVIGATION_MODE == TERRAIN:

                pass

            elif self.NAVIGATION_MODE == SPACE:

                pass

            print "asssss"
            print self.NAVIGATION_MODE

            #Handle keyboard input

            self.avatar.handleKeys(self.keys)
            self.avatar.move(dt)

            ########## Mouse-based viewpoint rotation ##########

            mouse_pos = self.win.getPointer(0)

            #Side to side

            if self.NAVIGATION_MODE == TERRAIN:

                current_mouse_x = mouse_pos.getX()
                mouse_shift_x = current_mouse_x - self.last_mouse_x
                self.last_mouse_x = current_mouse_x

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

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

                yaw_shift = -((mouse_shift_x) * Camera.ROT_RATE[0])

                self.avatar.yawRot += yaw_shift

            #Up and down

            current_mouse_y = mouse_pos.getY()
            mouse_shift_y = current_mouse_y - self.last_mouse_y
            self.last_mouse_y = current_mouse_y

            if current_mouse_y < 5 or current_mouse_y >= (self.win_center_y *
                                                          1.5):

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

            pitch_shift = -((mouse_shift_y) * Camera.ROT_RATE[1])

            self.mainCamera.pitchRot += pitch_shift

            if self.mainCamera.pitchRot > Camera.FLEX_ROT_MAG[0]:

                self.mainCamera.pitchRot = Camera.FLEX_ROT_MAG[0]

            elif self.mainCamera.pitchRot < -Camera.FLEX_ROT_MAG[0]:

                self.mainCamera.pitchRot = -Camera.FLEX_ROT_MAG[0]

            xy_plane_cam_dist = Camera.AVATAR_DIST

            cam_x_adjust = xy_plane_cam_dist * sin(radians(self.avatar.yawRot))
            cam_y_adjust = xy_plane_cam_dist * cos(radians(self.avatar.yawRot))
            cam_z_adjust = Camera.ELEVATION

            self.avatar.objectNP.setH(self.avatar.yawRot)

            self.mainCamera.camObject.setH(self.avatar.yawRot)
            self.mainCamera.camObject.setP(self.mainCamera.pitchRot)

            self.mainCamera.camObject.setPos(
                self.avatar.objectNP.getX() + cam_x_adjust,
                self.avatar.objectNP.getY() - cam_y_adjust,
                self.avatar.objectNP.getZ() + cam_z_adjust)

            #Find collisions

            self.cTrav.traverse(render)

        return Task.cont
예제 #40
0
class World(DirectObject):

    def __init__(self):
        self.last_mousex = 0
        self.last_mousey = 0

        self.zone = None
        self.zone_reload_name = None
        
        self.winprops = WindowProperties( )

        # simple console output
        self.consoleNode = NodePath(PandaNode("console_root"))
        self.consoleNode.reparentTo(aspect2d)

        self.console_num_lines = 24
        self.console_cur_line = -1
        self.console_lines = []
        for i in range(0, self.console_num_lines):
            self.console_lines.append(OnscreenText(text='', style=1, fg=(1,1,1,1),
                        pos=(-1.3, .4-i*.05), align=TextNode.ALeft, scale = .035, parent = self.consoleNode))

        # Configuration
        self.consoleOut('zonewalk v.%s loading configuration' % VERSION)
        self.configurator = Configurator(self)
        cfg = self.configurator.config
        resaveRes = False
        if 'xres' in cfg:
            self.xres = int(cfg['xres'])
        else:
            self.xres = 1024
            resaveRes = True

        if 'yres' in cfg:
            self.yres = int(cfg['yres'])
        else:
            self.yres = 768
            resaveRes = True

        if resaveRes:
            self.saveDefaultRes()

        self.xres_half = self.xres / 2
        self.yres_half = self.yres / 2
        self.mouse_accum = MouseAccume( lambda: (self.xres_half,self.yres_half))

        self.eyeHeight = 7.0
        self.rSpeed = 80
        self.flyMode = 1

        # application window setup
        base.win.setClearColor(Vec4(0,0,0,1))
        self.winprops.setTitle( 'zonewalk')
        self.winprops.setSize(self.xres, self.yres) 
        
        base.win.requestProperties( self.winprops ) 
        base.disableMouse()

        # network test stuff
        self.login_client = None
        if 'testnet' in cfg:
            if cfg['testnet'] == '1':
                self.doLogin()
        
        # Post the instructions
        self.title = addTitle('zonewalk v.' + VERSION)
        self.inst0 = addInstructions(0.95, "[FLYMODE][1]")
        self.inst1 = addInstructions(-0.95, "Camera control with WSAD/mouselook. Press K for hotkey list, ESC to exit.")
        self.inst2 = addInstructions(0.9,  "Loc:")
        self.inst3 = addInstructions(0.85, "Hdg:")
        self.error_inst = addInstructions(0, '')
        self.kh = []
        
        self.campos = Point3(155.6, 41.2, 4.93)
        base.camera.setPos(self.campos)
        
        # Accept the application control keys: currently just esc to exit navgen       
        self.accept("escape", self.exitGame)
        self.accept("window-event", self.resizeGame)
        
        # Create some lighting
        ambient_level = .6
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(ambient_level, ambient_level, ambient_level, 1.0))
        render.setLight(render.attachNewNode(ambientLight))

        direct_level = 0.8
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0.0, 0.0, -1.0))
        directionalLight.setColor(Vec4(direct_level, direct_level, direct_level, 1))
        directionalLight.setSpecularColor(Vec4(direct_level, direct_level, direct_level, 1))
        render.setLight(render.attachNewNode(directionalLight))
        
        # create a point light that will follow our view point (the camera for now)
        # attenuation is set so that this point light has a torch like effect
        self.plight = PointLight('plight')
        self.plight.setColor(VBase4(0.8, 0.8, 0.8, 1.0))
        self.plight.setAttenuation(Point3(0.0, 0.0, 0.0002))
        
        self.plnp = base.camera.attachNewNode(self.plight)
        self.plnp.setPos(0, 0, 0)
        render.setLight(self.plnp)
        self.cam_light = 1
        
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0, "cam-left":0, \
            "cam-right":0, "mouse3":0, "flymode":1 }

        # setup FOG
        self.fog_colour = (0.8,0.8,0.8,1.0)
        self.linfog = Fog("A linear-mode Fog node")
        self.linfog.setColor(self.fog_colour)
        self.linfog.setLinearRange(700, 980)         # onset, opaque distances as params
        # linfog.setLinearFallback(45,160,320)
        base.camera.attachNewNode(self.linfog)
        render.setFog(self.linfog)
        self.fog = 1
        
        # camera control
        self.campos = Point3(0, 0, 0)
        self.camHeading = 0.0
        self.camPitch = 0.0
        base.camLens.setFov(65.0)
        base.camLens.setFar(1200) 
        
        self.cam_speed = 0  # index into self.camp_speeds
        self.cam_speeds = [40.0, 80.0, 160.0, 320.0, 640.0]
        
        
        # Collision Detection for "WALKMODE"
        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  The ray 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.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0.0, 0.0, 0.0)
        self.camGroundRay.setDirection(0,0,-1)      # straight down
        self.camGroundCol = CollisionNode('camRay')
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.camGroundCol.setIntoCollideMask(BitMask32.allOff())
        
        # attach the col node to the camCollider dummy node
        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.camGroundColNp.show()
       
        # Uncomment this line to show a visual representation of the 
        # collisions occuring
        # self.cTrav.showCollisions(render)
        
        # Add the spinCameraTask procedure to the task manager.
        # taskMgr.add(self.spinCameraTask, "SpinCameraTask")
        taskMgr.add(self.camTask, "camTask")

        self.toggleControls(1)

        # need to step the task manager once to make our fake console work
        taskMgr.step()

    # CONSOLE ---------------------------------------------------------------------
    def consoleScroll(self):
        for i in range(0, self.console_num_lines-1):
            self.console_lines[i].setText(self.console_lines[i+1].getText())
            
    def consoleOut(self, text):
        print text  # output to stdout/log too

        if self.console_cur_line == self.console_num_lines-1:
            self.consoleScroll()
        elif self.console_cur_line < self.console_num_lines-1:
            self.console_cur_line += 1

        self.console_lines[self.console_cur_line].setText(text)

        taskMgr.step()
    
    def consoleOn(self):
        self.consoleNode.show()
        
    def consoleOff(self):
        self.consoleNode.hide()
        
    # User controls -----------------------------------------------------------
    def toggleControls(self, on):

        cfg = self.configurator.config

        if on == 1:
            self.accept("escape", self.exitGame)

            self.accept("1", self.setSpeed, ["speed", 0])
            self.accept("2", self.setSpeed, ["speed", 1])
            self.accept("3", self.setSpeed, ["speed", 2])
            self.accept("4", self.setSpeed, ["speed", 3])
            self.accept("5", self.setSpeed, ["speed", 4])

            self.accept("alt-f", self.fogToggle)

            self.accept(cfg['control_lighting'], self.camLightToggle)
            self.accept(cfg['control_help'], self.displayKeyHelp)
            self.accept(cfg['control_flymode'], self.toggleFlymode)
            self.accept(cfg['control_reload-zone'], self.reloadZone)
            # Deactivate this for now
            #self.accept("z", self.saveDefaultZone)
            self.accept(cfg['control_cam-left'], self.setKey, ["cam-left",1])
            self.accept(cfg['control_cam-right'], self.setKey, ["cam-right",1])
            self.accept(cfg['control_forward'], self.setKey, ["forward",1])
            # Mouse1 should be for clicking on objects
            #self.accept("mouse1", self.setKey, ["forward",1])
            self.accept("mouse3", self.setKey, ["mouse3",1])
            self.accept(cfg['control_backward'], self.setKey, ["backward",1])
        
            self.accept("k-up", self.hideKeyHelp)
            self.accept(cfg['control_cam-left']+"-up", self.setKey, ["cam-left",0])
            self.accept(cfg['control_cam-right']+"-up", self.setKey, ["cam-right",0])
            self.accept(cfg['control_forward']+"-up", self.setKey, ["forward",0])
            # Mouse1 should be for clicking on objects
            #self.accept("mouse1-up", self.setKey, ["forward",0])
            self.accept("mouse3-up", self.setKey, ["mouse3",0])
            self.accept(cfg['control_backward']+"-up", self.setKey, ["backward",0])
        else:
            messenger.clear()
            
    def setSpeed(self, key, value):
        self.cam_speed = value
        self.setFlymodeText()
        
    def fogToggle(self):
        if self.fog == 1:
            render.clearFog()
            base.camLens.setFar(100000) 
            self.fog = 0
        else:
            render.setFog(self.linfog)
            base.camLens.setFar(1200) 
            self.fog = 1
            
    def camLightToggle(self):
        if self.cam_light == 0:
            render.setLight(self.plnp)
            self.cam_light = 1
        else:
            render.clearLight(self.plnp)
            self.cam_light = 0
        
    def displayKeyHelp(self):
        self.kh = []
        msg = 'HOTKEYS:'
        pos = 0.75
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = '------------------'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'W: camera fwd, S: camera bck, A: rotate view left, D: rotate view right'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = '1-5: set camera movement speed'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'F: toggle Flymode/Walkmode'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'L: load a zone'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'ALT-F: toggle FOG and FAR plane on/off'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'T: toggle additional camera "torch" light on/off'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'Z: set currently loaded zone as new startup default'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'ESC: exit zonewalk'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
     
    def hideKeyHelp(self):
        for n in self.kh:
            n.removeNode()
                        
    def setFlymodeText(self):
        zname = ''
        if self.zone:
            zname = self.zone.name
            
        if self.flyMode == 0:
            self.inst0.setText("[WALKMODE][%i] %s" % (self.cam_speed+1, zname))
        else:
            self.inst0.setText("[FLYMODE][%i] %s " % (self.cam_speed+1, zname))
        
    def toggleFlymode(self):
        zname = ''
        if self.zone:
            zname = self.zone.name

        if self.flyMode == 0:
            self.flyMode = 1
        else:
            self.flyMode = 0
            
        self.setFlymodeText()

    # Define a procedure to move the camera.
    def spinCameraTask(self, task):
        angleDegrees = task.time * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        base.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
        base.camera.setHpr(angleDegrees, 0, 0)
        return task.cont


    def camTask(self, task):
        # query the mouse
        mouse_dx = 0
        mouse_dy = 0


        # if we have a mouse and the right button is depressed
        if base.mouseWatcherNode.hasMouse():
            if self.keyMap["mouse3"] != 0:
                self.mouse_accum.update()
            else:
                self.mouse_accum.reset()

        mouse_dx = self.mouse_accum.dx
        mouse_dy = self.mouse_accum.dy

        self.rXSpeed = fabs(self.mouse_accum.dx) * (self.cam_speed+1) * max(5 * 1000/self.xres,3)
        self.rYSpeed = fabs(self.mouse_accum.dy) * (self.cam_speed+1) * max(3 * 1000/self.yres,1)
            
        if (self.keyMap["cam-left"]!=0 or mouse_dx < 0):
            if self.rSpeed < 160:
                self.rSpeed += 80 * globalClock.getDt()

            if mouse_dx != 0:
                self.camHeading += self.rXSpeed * globalClock.getDt()
            else:
                self.camHeading += self.rSpeed * globalClock.getDt()

            if self.camHeading > 360.0:
                self.camHeading = self.camHeading - 360.0
        elif (self.keyMap["cam-right"]!=0 or mouse_dx > 0):
            if self.rSpeed < 160:
                self.rSpeed += 80 * globalClock.getDt()

            if mouse_dx != 0:
                self.camHeading -= self.rXSpeed * globalClock.getDt()
            else:
                self.camHeading -= self.rSpeed * globalClock.getDt()

            if self.camHeading < 0.0:
                self.camHeading = self.camHeading + 360.0
        else:
            self.rSpeed = 80

        if mouse_dy > 0:
            self.camPitch += self.rYSpeed * globalClock.getDt()
        elif mouse_dy < 0:
            self.camPitch -= self.rYSpeed * globalClock.getDt()
            
        # set camera heading and pitch
        base.camera.setHpr(self.camHeading, self.camPitch, 0)

        # viewer position (camera) movement control
        v = render.getRelativeVector(base.camera, Vec3.forward())
        if not self.flyMode:
            v.setZ(0.0)
        
        move_speed = self.cam_speeds[self.cam_speed]
        if self.keyMap["forward"] == 1:
            self.campos += v * move_speed * globalClock.getDt()
        if self.keyMap["backward"] == 1:
            self.campos -= v * move_speed * globalClock.getDt()            

        # actually move the camera
        lastPos = base.camera.getPos()
        base.camera.setPos(self.campos)
        # self.plnp.setPos(self.campos)      # move the point light with the viewer position

        # WALKMODE: simple collision detection
        # we simply check a ray from slightly below the "eye point" straight down
        # for geometry collisions and if there are any we detect the point of collision
        # and adjust the camera's Z accordingly
        if self.flyMode == 0:   
            # move the camera to where it would be if it made the move 
            # the colliderNode moves with it
            # base.camera.setPos(self.campos)
            # check for collissons
            self.cTrav.traverse(render)
            entries = []
            for i in range(self.camGroundHandler.getNumEntries()):
                entry = self.camGroundHandler.getEntry(i)
                entries.append(entry)
                # print 'collision'
            entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                         x.getSurfacePoint(render).getZ()))
                                     
            if (len(entries) > 0): # and (entries[0].getIntoNode().getName() == "terrain"):
                # print len(entries)
                self.campos.setZ(entries[0].getSurfacePoint(render).getZ()+self.eyeHeight)
            else:
                self.campos = lastPos
                base.camera.setPos(self.campos)
        
            #if (base.camera.getZ() < self.player.getZ() + 2.0):
            #    base.camera.setZ(self.player.getZ() + 2.0)


        # update loc and hpr display
        pos = base.camera.getPos()
        hpr = base.camera.getHpr()
        self.inst2.setText('Loc: %.2f, %.2f, %.2f' % (pos.getX(), pos.getY(), pos.getZ()))
        self.inst3.setText('Hdg: %.2f, %.2f, %.2f' % (hpr.getX(), hpr.getY(), hpr.getZ()))
        return task.cont

        
    def exitGame(self):           
        sys.exit(0)

    def resizeGame(self,win):
        props = base.win.getProperties() 
        self.xres = props.getXSize()
        self.yres = props.getYSize()
        self.xres_half = self.xres / 2
        self.yres_half = self.yres / 2
        self.saveDefaultRes()
                
    #Records the state of the arrow keys
    # this is used for camera control
    def setKey(self, key, value):
        self.keyMap[key] = value

    # -------------------------------------------------------------------------
    # this is the mythical MAIN LOOP :)
    def update(self):

        if self.zone_reload_name != None:
            self.doReload(self.zone_reload_name)
            self.zone_reload_name = None

        if self.zone != None:
            self.zone.update()

        taskMgr.step()
   
        if self.login_client != None:
            self.login_client.update()  
        
        
    # ZONE loading ------------------------------------------------------------
    
    # general zone loader driver
    # removes existing zone (if any) and load the new one 
    def loadZone(self, name, path):
        if path[len(path)-1] != '/':
            path += '/'

        if self.zone:
            self.zone.rootNode.removeNode()
            
        self.zone = Zone(self, name, path)
        error = self.zone.load()
        if error == 0:
            self.consoleOff()
            self.setFlymodeText()
            base.setBackgroundColor(self.fog_colour)
        
    def saveDefaultRes(self):
        cfg = self.configurator.config
        cfg['xres'] = str(self.xres)
        cfg['yres'] = str(self.yres)
        #self.configurator.saveConfig()

    # initial world load after bootup
    def load(self):       
        cfg = self.configurator.config
        
        if self.login_client != None:
            return
            
        zone_name = cfg['default_zone']
        basepath = cfg['basepath']
        self.loadZone(zone_name, basepath)
    

    # config save user interfacce
    def saveDefaultZone(self):
        if self.zone:
            cfg = self.configurator.config
            cfg['default_zone'] = self.zone.name
            #self.configurator.saveConfig()

    # zone reload user interface
    
    # this gets called from our update loop when it detects that zone_reload_name has been set
    # we do this in this convoluted fashion in order to keep the main loop taskMgr updates ticking
    # because otherwise our status console output at various stages during the zone load would not
    # be displayed. Yes, this is hacky.
    def doReload(self, name):
        cfg = self.configurator.config
        basepath = cfg['basepath']
        self.loadZone(name, basepath)

    # form dialog callback
    # this gets called from the form when the user has entered a something
    # (hopefully a correct zone short name)
    def reloadZoneDialogCB(self, name):
        self.frmDialog.end()
        self.zone_reload_name = name
        self.toggleControls(1)

    # this is called when the user presses "l"
    # it disables normal controls and fires up our query form dialog
    def reloadZone(self):
        base.setBackgroundColor((0,0,0))
        self.toggleControls(0)
        self.consoleOn()
        self.frmDialog = FileDialog(
            "Please enter the shortname of the zone you wish to load:", 
            "Examples: qrg, blackburrow, freportn, crushbone etc.",
            self.reloadZoneDialogCB) 
        
        self.frmDialog.activate()   # relies on the main update loop to run

    ###############################
    # EXPERIMENTAL         
    def doLogin(self):
        
        self.login_client = UDPClientStream('127.0.0.1', 5998)

    #####################################
    # Custom methods
    #####################################


    # What happens when a user clicks on a model
    def onModelClick():
        # Code adapted freely from http://www.panda3d.org/forums/viewtopic.php?t=12717
        global picker, selected_model
        namedNode, thePoint, rawNode = picker.pick()
        if namedNode:
            if "_mesh" not in namedNode.getName():  # rough test to avoid printing infos on global zone mesh (ie: "freporte_mesh")
                name = namedNode.getName()
                p = namedNode.getParent()
                pos = p.getPos()
                selected_model = namedNode
                print namedNode.getName()
                print "Collision Point: ", thePoint

                namedNode.ls()
            else:
                print "Clicked location point (y, x, z):", thePoint
                #selected_model.setPos(thePoint.getX(), thePoint.getY(), thePoint.getZ())

                m.setPos(thePoint.getX(), thePoint.getY(), thePoint.getZ())
                print "Moved !"

    # Handles populating the zone with spawn data from the EQEmu DB
    # also makes each spawner model pickable
    def PopulateSpawns(self, cursor, numrows):
        spawn_coords = list()
        globals.model_list = list()
        for x in range(0, numrows):
            row = cursor.fetchone()
            point = Point3(long(row["Spawn2Y"]), long(row["Spawn2X"]), long(row["Spawn2Z"]))
            if point not in spawn_coords:
                s = loader.loadModel("models/cube.egg")
                s.reparentTo(render)
                s.setPos(row["Spawn2Y"], row["Spawn2X"], row["Spawn2Z"])
                min,macks= s.getTightBounds()
                radius = max([macks.getY() - min.getY(), macks.getX() - min.getX()])/2
                cs = CollisionSphere(row["Spawn2X"], row["Spawn2Y"], row["Spawn2Z"], radius)
                csNode = s.attachNewNode(CollisionNode("modelCollide"))
                csNode.node().addSolid(cs)
                s.setTag("name", row["name"])
                picker.makePickable(s)
                globals.model_list.append(s)
                spawn_coords.append(point)

    # Establishes a connection to the EQEmu database
    def ConnectToDatabase(self):
        configurator = Configurator(world)
        cfg = configurator.config
        conn = MySQLdb.Connection(
            host=cfg['host'],
            user=cfg['user'],
            passwd=cfg['password'],
            db=cfg['db'])

        return conn

    # Queries the Database in order to get spawn data
    # (this should be refactored at some point)
    def GetDbSpawnData(self, connection):
        cursor = connection.cursor(MySQLdb.cursors.DictCursor)

        query = """SELECT nt.name, s2.zone, s2.x as Spawn2X, s2.y as Spawn2Y, s2.z as Spawn2Z, sg.name as spawngroup_name,sg.id as Spawngroup_id, sg.min_x as Spawngroup_minX, sg.max_x as Spawngroup_maxX, sg.min_y as Spawngroup_minY, sg.max_y as Spawngroup_maxY, sg.dist as Spawngroup_dist, sg.mindelay as Spawngroup_mindelay,
                sg.delay as Spawngroup_delay FROM spawn2 s2
                JOIN spawngroup sg ON sg.id = s2.spawngroupid
                JOIN spawnentry se
                ON se.spawngroupid = sg.id
                JOIN npc_types nt
                ON nt.id = se.npcid
                WHERE s2.zone = 'freporte'"""
        cursor.execute(query)
        return cursor

    # Initializes the camera position upon startup
    def InitCameraPosition(self):
        world.campos = Point3(-155.6, 41.2, 4.9 + world.eyeHeight)
        world.camHeading = 270.0

        base.camera.setPos(world.campos)

    def GetCamera(self):
        return base.camera
예제 #41
0
class DynObject():
    def __init__(self, render, objid, start_pos, gameclient):
        self.client = gameclient
        self.id = objid
        self.motion_controller = None
        self.is_player = False

        # state  management
        self.isAnimating = False
        self.state = state.IDLE

        self.render = render  # scene graph root

        #  create the panda3d actor: just load a default model for now
        self.actor = Actor("models/ralph", {
            "run": "models/ralph-run",
            "walk": "models/ralph-walk"
        })

        self.actor.reparentTo(render)
        self.actor.setScale(.2)
        self.actor.setPos(start_pos)

        # prepare collision handling
        self.cTrav = CollisionTraverser()
        self.GroundRay = CollisionRay()
        self.GroundRay.setOrigin(0, 0, 1000)
        self.GroundRay.setDirection(0, 0, -1)
        self.GroundCol = CollisionNode('actorRay')
        self.GroundCol.addSolid(self.GroundRay)
        self.GroundCol.setFromCollideMask(BitMask32.bit(0))
        self.GroundCol.setIntoCollideMask(BitMask32.allOff())
        self.GroundColNp = self.actor.attachNewNode(self.GroundCol)
        self.GroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.GroundColNp, self.GroundHandler)

    def destroy(self):
        if self.actor != None:
            self.actor.cleanup()
            self.actor.removeNode()
            self.actor = None

    # called reqularly from a Panda3 task
    # move the object according to its current state
    def move(self):
        actor = self.actor

        # save our initial position so that we can restore it,
        # in case we fall off the map or run into something.
        startpos = actor.getPos()

        # let the motion_controller determine our new state
        self.motion_controller.processMove()

        # evaluate state and  move/rotate the actor accordingly
        if (self.state & state.LEFT):
            actor.setH(actor.getH() + 300 * globalClock.getDt())
        if (self.state & state.RIGHT):
            actor.setH(actor.getH() - 300 * globalClock.getDt())
        if (self.state & state.FORWARD):
            actor.setY(actor, -25 * globalClock.getDt())

        # Simplistic animation control:
        # If we are moving, loop the run animation.
        # If we are standing still, stop the animation.
        if (self.state != state.IDLE):
            if self.isAnimating is False:
                actor.loop("run")
                self.isAnimating = True
        else:
            if self.isAnimating:
                actor.stop()
                actor.pose("walk", 5)
                self.isAnimating = False

        # Now check for collisions.
        self.cTrav.traverse(render)

        # Adjust Z coordinate.  If the ray hit terrain,
        # update Z. If it hit anything else, or didn't hit anything, put
        # us back where we were last frame.
        entries = []
        for i in range(self.GroundHandler.getNumEntries()):
            entry = self.GroundHandler.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.actor.setZ(entries[0].getSurfacePoint(render).getZ())
        else:
            self.actor.setPos(startpos)

        # if this is the player avatar: make the camera follow us
        if self.is_player is True:
            self.client.world.moveCamera()

    # convenience getter/setters
    def setPos(self, pos):
        self.actor.setPos(pos)

    def getPos(self):
        return self.actor.getPos()

    def getH(self):
        return self.actor.getH()

    def getX(self):
        return self.actor.getX()

    def getY(self):
        return self.actor.getY()

    def getZ(self):
        return self.actor.getZ()
class DistributedElevator(DistributedObject):
    notify = directNotify.newCategory('DistributedElevator')

    def __init__(self, cr):
        DistributedObject.__init__(self, cr)
        self.openSfx = base.loadSfx('phase_5/audio/sfx/elevator_door_open.ogg')
        self.closeSfx = base.loadSfx(
            'phase_5/audio/sfx/elevator_door_close.ogg')
        self.elevatorPoints = ElevatorPoints
        self.type = ELEVATOR_NORMAL
        self.countdownTime = ElevatorData[self.type]['countdown']
        self.localAvOnElevator = False
        self.thebldg = None
        self.bldgDoId = None
        self.toZoneId = None
        self.elevatorModel = None
        self.countdownTextNP = None
        self.toonsInElevator = []
        self.hopOffButton = None
        self.fsm = ClassicFSM.ClassicFSM('DistributedElevator', [
            State.State('off', self.enterOff, self.exitOff),
            State.State('opening', self.enterOpening, self.exitOpening),
            State.State('waitEmpty', self.enterWaitEmpty, self.exitWaitEmpty),
            State.State('waitCountdown', self.enterWaitCountdown,
                        self.exitWaitCountdown),
            State.State('closing', self.enterClosing, self.exitClosing),
            State.State('closed', self.enterClosed, self.exitClosed)
        ], 'off', 'off')
        self.fsm.enterInitialState()

    def setElevatorType(self, etype):
        self.type = etype

    def getElevatorType(self):
        return self.type

    def setBldgDoId(self, doId):
        self.bldgDoId = doId

    def getBldgDoId(self):
        return self.bldgDoId

    def setToZoneId(self, zoneId):
        self.toZoneId = zoneId

    def getToZoneId(self):
        return self.toZoneId

    def enterOpening(self, ts=0):
        self.openDoors.start(ts)

    def exitOpening(self):
        self.openDoors.finish()

    def enterClosing(self, ts=0):
        if self.localAvOnElevator:
            self.hideHopOffButton()
        self.closeDoors.start(ts)

    def exitClosing(self):
        self.closeDoors.finish()

    def enterClosed(self, ts=0):
        closeDoors(self.getLeftDoor(), self.getRightDoor())

    def exitClosed(self):
        pass

    def __handleElevatorTrigger(self, entry):
        if not self.localAvOnElevator:
            self.cr.playGame.getPlace().fsm.request('stop')
            self.sendUpdate('requestEnter')

    def enterWaitEmpty(self, ts=0):
        if not self.localAvOnElevator:
            self.acceptOnce('enter' + self.uniqueName('elevatorSphere'),
                            self.__handleElevatorTrigger)
        openDoors(self.getLeftDoor(), self.getRightDoor())

    def exitWaitEmpty(self):
        self.ignore('enter' + self.uniqueName('elevatorSphere'))

    def enterWaitCountdown(self, ts=0):
        if not self.localAvOnElevator:
            self.acceptOnce('enter' + self.uniqueName('elevatorSphere'),
                            self.__handleElevatorTrigger)
        openDoors(self.getLeftDoor(), self.getRightDoor())
        if self.countdownTextNP:
            self.countdownTextNP.show()
            self.countdownTrack = Sequence()
            time = int(ElevatorData[self.type]['countdown'])
            for i in range(time):
                self.countdownTrack.append(
                    Func(self.countdownTextNP.node().setText, str(time - i)))
                self.countdownTrack.append(Wait(1.0))
            self.countdownTrack.start(ts)

    def exitWaitCountdown(self):
        if self.countdownTextNP:
            self.countdownTextNP.hide()
        self.countdownTrack.finish()
        del self.countdownTrack

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def getLeftDoor(self):
        # Can be overridden by inheritors.
        return self.thebldg.leftDoor

    def getRightDoor(self):
        return self.thebldg.rightDoor

    def startPoll(self):
        # Start polling for the building
        taskMgr.add(self.__pollBuilding, self.uniqueName('pollBuilding'))

    def __pollBuilding(self, task):
        self.getTheBldg()
        if self.thebldg:
            self.postAnnounceGenerate()
            return task.done
        return task.cont

    def stopPoll(self):
        taskMgr.remove(self.uniqueName('pollBuilding'))

    def announceGenerate(self):
        DistributedObject.announceGenerate(self)
        self.getTheBldg()
        if not self.thebldg:
            self.startPoll()
            return
        self.postAnnounceGenerate()

    def postAnnounceGenerate(self):
        self.leftDoor = self.getLeftDoor()
        self.rightDoor = self.getRightDoor()
        self.setupElevator()
        self.setupCountdownText()
        self.sendUpdate('requestStateAndTimestamp')

    def setState(self, state, timestamp):
        if not self.thebldg:
            return
        self.fsm.request(state, [globalClockDelta.localElapsedTime(timestamp)])

    def stateAndTimestamp(self, state, timestamp):
        self.fsm.request(state, [globalClockDelta.localElapsedTime(timestamp)])

    def setupCountdownText(self):
        tn = TextNode('countdownText')
        tn.setFont(CIGlobals.getMickeyFont())
        tn.setTextColor(VBase4(0.5, 0.5, 0.5, 1.0))
        tn.setAlign(TextNode.ACenter)
        self.countdownTextNP = self.getElevatorModel().attachNewNode(tn)
        self.countdownTextNP.setScale(2)
        self.countdownTextNP.setPos(0, 1, 7)
        #self.countdownTextNP.setH(180)

    def setupElevator(self):
        collisionRadius = ElevatorData[self.type]['collRadius']
        self.elevatorSphere = CollisionSphere(0, 5, 0, collisionRadius)
        self.elevatorSphere.setTangible(0)
        self.elevatorSphereNode = CollisionNode(
            self.uniqueName('elevatorSphere'))
        self.elevatorSphereNode.setIntoCollideMask(CIGlobals.WallBitmask)
        self.elevatorSphereNode.addSolid(self.elevatorSphere)
        self.elevatorSphereNodePath = self.getElevatorModel().attachNewNode(
            self.elevatorSphereNode)
        self.elevatorSphereNodePath.reparentTo(self.getElevatorModel())
        self.openDoors = getOpenInterval(self, self.getLeftDoor(),
                                         self.getRightDoor(), self.openSfx,
                                         None, self.type)
        self.closeDoors = getCloseInterval(self, self.getLeftDoor(),
                                           self.getRightDoor(), self.closeSfx,
                                           None, self.type)
        self.closeDoors = Sequence(self.closeDoors,
                                   Func(self.onDoorCloseFinish))

    def disable(self):
        self.stopPoll()
        if hasattr(self, 'openDoors'):
            self.openDoors.pause()
        if hasattr(self, 'closeDoors'):
            self.closeDoors.pause()
        self.ignore('enter' + self.uniqueName('elevatorSphere'))
        self.elevatorSphereNodePath.removeNode()
        del self.elevatorSphereNodePath
        del self.elevatorSphereNode
        del self.elevatorSphere
        self.fsm.request('off')
        self.openSfx = None
        self.closeSfx = None
        self.elevatorPoints = None
        self.type = None
        self.countdownTime = None
        self.localAvOnElevator = None
        self.thebldg = None
        self.bldgDoId = None
        self.toZoneId = None
        self.elevatorModel = None
        self.toonsInElevator = None
        self.hopOffButton = None
        self.leftDoor = None
        self.rightDoor = None
        self.openDoors = None
        self.closeDoors = None
        if self.countdownTextNP:
            self.countdownTextNP.removeNode()
            self.countdownTextNP = None
        DistributedObject.disable(self)

    def onDoorCloseFinish(self):
        if self.localAvOnElevator:
            base.transitions.fadeScreen(1.0)
            base.localAvatar.wrtReparentTo(render)

            loader = 'suitInterior'
            where = 'suitInterior'
            how = 'IDK'
            world = base.cr.playGame.getCurrentWorldName()

            if self.thebldg.fsm.getCurrentState().getName() == 'bldgComplete':
                loader = 'townLoader'
                where = 'street'
                how = 'elevatorIn'
                world = CIGlobals.CogTropolis

            requestStatus = {
                'zoneId': self.getToZoneId(),
                'hoodId': self.cr.playGame.hood.hoodId,
                'where': where,
                'avId': base.localAvatar.doId,
                'loader': loader,
                'shardId': None,
                'wantLaffMeter': 1,
                'world': world,
                'how': how
            }

            self.cr.playGame.getPlace().doneStatus = requestStatus
            messenger.send(self.cr.playGame.getPlace().doneEvent)

    def doMusic(self):
        self.elevMusic = base.loadMusic('phase_7/audio/bgm/tt_elevator.ogg')
        base.playMusic(self.elevMusic, looping=1, volume=0.8)

    def fillSlot(self, index, avId):
        toon = self.cr.doId2do.get(avId)
        if toon:
            point = ElevatorPoints[index]
            toon.stopSmooth()
            toon.wrtReparentTo(self.getElevatorModel())
            toon.headsUp(point)
            track = Sequence()
            track.append(Func(toon.animFSM.request, 'run'))
            track.append(
                LerpPosInterval(toon,
                                duration=0.5,
                                pos=point,
                                startPos=toon.getPos(self.getElevatorModel())))
            track.append(
                LerpHprInterval(toon,
                                duration=0.1,
                                hpr=(180, 0, 0),
                                startHpr=toon.getHpr(self.getElevatorModel())))
            track.append(Func(toon.animFSM.request, 'neutral'))
            if avId == base.localAvatar.doId:
                self.localAvOnElevator = True
                track.append(Func(self.showHopOffButton))
                base.localAvatar.stopSmartCamera()
                base.localAvatar.walkControls.setCollisionsActive(0)
                base.camera.wrtReparentTo(self.getElevatorModel())
                cameraBoardTrack = LerpPosHprInterval(camera, 1.5,
                                                      Point3(0, -16, 5.5),
                                                      Point3(0, 0, 0))
                cameraBoardTrack.start()
            track.start()

    def emptySlot(self, index, avId):
        toon = self.cr.doId2do.get(avId)
        if toon:
            OutPoint = ElevatorOutPoints[index]
            InPoint = ElevatorPoints[index]
            toon.stopSmooth()
            toon.headsUp(OutPoint)
            track = Sequence(
                Func(toon.animFSM.request, 'run'),
                LerpPosInterval(toon,
                                duration=0.5,
                                pos=OutPoint,
                                startPos=InPoint),
                Func(toon.animFSM.request, 'neutral'), Func(toon.startSmooth))
            if avId == base.localAvatar.doId:
                self.localAvOnElevator = False
                track.append(Func(self.freedom))
            track.start()

    def freedom(self):
        if self.fsm.getCurrentState().getName() in [
                'waitEmpty', 'waitCountdown'
        ]:
            self.acceptOnce('enter' + self.uniqueName('elevatorSphere'),
                            self.__handleElevatorTrigger)
        base.localAvatar.walkControls.setCollisionsActive(1)
        self.cr.playGame.getPlace().fsm.request('walk')

    def setToonsInElevator(self, toonsInElevator):
        for i in xrange(len(toonsInElevator)):
            avId = toonsInElevator[i]
            toon = self.cr.doId2do.get(avId)
            if toon:
                toon.reparentTo(self.getElevatorModel())
                toon.stopSmooth()
                point = ElevatorPoints[i]
                toon.setPos(point)
                toon.setHpr(180, 0, 0)
                toon.animFSM.request('neutral')

    def getTheBldg(self):
        self.thebldg = self.cr.doId2do.get(self.bldgDoId)

    def getElevatorModel(self):
        return self.thebldg.getElevatorModel()

    def enterRejected(self):
        self.cr.playGame.getPlace().fsm.request('walk')

    def showHopOffButton(self):
        gui = loader.loadModel('phase_3.5/models/gui/inventory_gui.bam')
        upButton = gui.find('**/InventoryButtonUp')
        downButton = gui.find('**/InventoryButtonDown')
        rlvrButton = gui.find('**/InventoryButtonRollover')
        self.hopOffBtn = DirectButton(relief=None,
                                      text="Hop off",
                                      text_fg=(0.9, 0.9, 0.9, 1),
                                      text_pos=(0, -0.23),
                                      text_scale=0.75,
                                      image=(upButton, downButton, rlvrButton),
                                      image_color=(0.5, 0.5, 0.5, 1),
                                      image_scale=(20, 1, 11),
                                      pos=(0, 0, 0.8),
                                      scale=0.15,
                                      command=self.handleHopOffButton)

    def hideHopOffButton(self):
        if hasattr(self, 'hopOffBtn'):
            self.hopOffBtn.destroy()
            del self.hopOffBtn

    def handleHopOffButton(self):
        self.hideHopOffButton()
        self.sendUpdate('requestExit')
예제 #43
0
    def __init__(self):
        GameObject.__init__(
            self, Vec3(0, 0, 0), "Models/PandaChan/act_p3d_chan", {
                "stand": "Models/PandaChan/a_p3d_chan_idle",
                "walk": "Models/PandaChan/a_p3d_chan_run"
            }, 5, 10, "player")
        self.actor.getChild(0).setH(180)

        mask = BitMask32()
        mask.setBit(1)

        self.collider.node().setIntoCollideMask(mask)

        mask = BitMask32()
        mask.setBit(1)

        self.collider.node().setFromCollideMask(mask)

        base.pusher.addCollider(self.collider, self.actor)
        base.cTrav.addCollider(self.collider, base.pusher)

        self.lastMousePos = Vec2(0, 0)

        self.groundPlane = Plane(Vec3(0, 0, 1), Vec3(0, 0, 0))

        self.ray = CollisionRay(0, 0, 0, 0, 1, 0)

        rayNode = CollisionNode("playerRay")
        rayNode.addSolid(self.ray)

        mask = BitMask32()

        mask.setBit(2)
        rayNode.setFromCollideMask(mask)

        mask = BitMask32()
        rayNode.setIntoCollideMask(mask)

        self.rayNodePath = render.attachNewNode(rayNode)
        self.rayQueue = CollisionHandlerQueue()

        base.cTrav.addCollider(self.rayNodePath, self.rayQueue)

        self.beamModel = loader.loadModel("Models/Misc/bambooLaser")
        self.beamModel.reparentTo(self.actor)
        self.beamModel.setZ(1.5)
        self.beamModel.setLightOff()
        self.beamModel.hide()

        self.beamHitModel = loader.loadModel("Models/Misc/bambooLaserHit")
        self.beamHitModel.reparentTo(render)
        self.beamHitModel.setZ(1.5)
        self.beamHitModel.setLightOff()
        self.beamHitModel.hide()

        self.beamHitPulseRate = 0.15
        self.beamHitTimer = 0

        self.damagePerSecond = -5.0

        self.score = 0

        self.scoreUI = OnscreenText(text="0",
                                    pos=(-1.3, 0.825),
                                    mayChange=True,
                                    align=TextNode.ALeft)

        self.healthIcons = []
        for i in range(self.maxHealth):
            icon = OnscreenImage(image="UI/health.png",
                                 pos=(-1.275 + i * 0.075, 0, 0.95),
                                 scale=0.04)
            icon.setTransparency(True)
            self.healthIcons.append(icon)

        self.damageTakenModel = loader.loadModel("Models/Misc/playerHit")
        self.damageTakenModel.setLightOff()
        self.damageTakenModel.setZ(1.0)
        self.damageTakenModel.reparentTo(self.actor)
        self.damageTakenModel.hide()

        self.damageTakenModelTimer = 0
        self.damageTakenModelDuration = 0.15

        self.beamHitLight = PointLight("beamHitLight")
        self.beamHitLight.setColor(Vec4(0.1, 1.0, 0.2, 1))
        self.beamHitLight.setAttenuation((1.0, 0.1, 0.5))
        self.beamHitLightNodePath = render.attachNewNode(self.beamHitLight)

        self.yVector = Vec2(0, 1)

        self.actor.loop("stand")
예제 #44
0
    def makePropAttackTrack(self):
        prop = BattleProps.globalPropPool.getProp(self.attackProp)
        propIsActor = True
        animName = 'throw-paper'
        x, y, z, h, p, r = (0.1, 0.2, -0.35, 0, 336, 0)
        if self.attackProp == 'redtape':
            animName = 'throw-object'
            x, y, z, h, p, r = (0.24, 0.09, -0.38, -1.152, 86.581, -76.784)
            propIsActor = False
        elif self.attackProp == 'newspaper':
            animName = 'throw-object'
            propIsActor = False
            x, y, z, h, p, r = (-0.07, 0.17, -0.13, 161.867, -33.149, -48.086)
            prop.setScale(4)
        elif self.attackProp == 'pink-slip':
            animName = 'throw-paper'
            propIsActor = False
            x, y, z, h, p, r = (0.07, -0.06, -0.18, -172.075, -26.715, -89.131)
            prop.setScale(5)
        elif self.attackProp == 'power-tie':
            animName = 'throw-paper'
            propIsActor = False
            x, y, z, h, p, r = (1.16, 0.24, 0.63, 171.561, 1.745, -163.443)
            prop.setScale(4)
        elif self.attackProp == 'baseball':
            animName = 'throw-object'
            propIsActor = False
            x, y, z, h, p, r = (0.04, 0.03, -0.31, 0, 336, 0)
            prop.setScale(4)
        elif self.attackProp == 'teeth':
            animName = 'throw-object'
            propIsActor = True
            x, y, z, h, p, r = -0.05, 0.41, -0.54, 4.465, -3.563, 51.479
            prop.setScale(3)
        elif self.attackProp == 'golf-ball':
            propIsActor = False
            x, y, z = self.getGolfStartPoint()
            h, p, r = 0, 0, 0
            prop.setScale(1.5)

        # Make prop virtual:
        prop.setColorScale(1.0, 0.0, 0.0, 0.8)
        prop.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))

        # Prop collisions:
        colNode = CollisionNode(self.uniqueName('SuitAttack'))
        colNode.setTag('damage', str(self.attackInfo[1]))

        bounds = prop.getBounds()
        center = bounds.getCenter()
        radius = bounds.getRadius()
        sphere = CollisionSphere(center.getX(), center.getY(), center.getZ(),
                                 radius)
        sphere.setTangible(0)
        colNode.addSolid(sphere)
        colNode.setIntoCollideMask(WallBitmask)
        prop.attachNewNode(colNode)

        toonId = self.toon

        toon = base.cr.doId2do.get(toonId)
        if not toon:
            return

        self.virtualSuit.lookAt(toon)

        if self.virtualSuit.style.body in ['a', 'b']:
            throwDelay = 3
        elif self.virtualSuit.style.body == 'c':
            throwDelay = 2.3
        else:
            throwDelay = 2

        def throwProp():
            if not self.virtualSuit:
                return

            toon = self.cr.doId2do.get(toonId)
            if not toon:
                self.cleanupProp(prop, propIsActor)
                self.finishPropAttack()
                return

            self.virtualSuit.lookAt(toon)

            prop.wrtReparentTo(render)

            hitPos = toon.getPos() + Vec3(0, 0, 2.5)
            distance = (prop.getPos() - hitPos).length()
            speed = 50.0
            if self.attackProp == 'golf-ball':
                speed *= 2

            if self.attackProp == 'teeth':
                throwSequence = Sequence(
                    Parallel(
                        prop.posInterval(distance / speed, hitPos),
                        ActorInterval(prop, 'teeth',
                                      duration=distance / speed),
                    ),
                    Func(self.cleanupProp, prop, propIsActor),
                )
            else:
                throwSequence = Sequence(
                    prop.posInterval(distance / speed, hitPos),
                    Func(self.cleanupProp, prop, propIsActor))

            throwSequence.start()

        if self.attackProp == 'golf-ball':
            club = BattleProps.globalPropPool.getProp('golf-club')
            club.setScale(1.1)
            track = Sequence(
                Parallel(
                    Track(
                        (0.4,
                         Func(club.reparentTo,
                              self.virtualSuit.getRightHand())),
                        (0.0,
                         Func(club.setPosHpr, 0.0, 0.0, 0.0, 63.097, 43.988,
                              -18.435)),
                        (0.0, Func(prop.reparentTo, self.virtualSuit)),
                        (0.0, Func(prop.setPosHpr, x, y, z, h, p, r)),
                        (0.0, Func(self.sayFaceoffTaunt)),
                        (0.1,
                         Sequence(
                             ActorInterval(self.virtualSuit,
                                           'golf-club-swing'),
                             Func(self.virtualSuit.loop, 'neutral', 0))),
                        (4.1,
                         SoundInterval(self.teeOffSfx, node=self.virtualSuit)),
                        (throwDelay + 1.5, Func(throwProp)),
                        (throwDelay + 2, Func(club.removeNode)),
                        (throwDelay + 3, Func(self.finishPropAttack))), ),
                Func(self.virtualSuit.setHpr, 0, 0, 0),
                Func(self.virtualSuit.loop, 'walk', 0),
            )
        else:
            track = Sequence(
                Parallel(
                    Sequence(ActorInterval(self.virtualSuit, animName),
                             Func(self.virtualSuit.loop, 'neutral', 0)),
                    Track((0.4,
                           Func(prop.reparentTo,
                                self.virtualSuit.getRightHand())),
                          (0.0, Func(prop.setPosHpr, x, y, z, h, p, r)),
                          (0.0, Func(self.sayFaceoffTaunt)),
                          (throwDelay, Func(throwProp)),
                          (throwDelay + 2, Func(self.finishPropAttack))),
                ),
                Func(self.virtualSuit.setHpr, 0, 0, 0),
                Func(self.virtualSuit.loop, 'walk', 0),
            )
        track.prop = prop
        track.propIsActor = propIsActor

        return track
예제 #45
0
class DistributedCogKart(DistributedElevatorExt.DistributedElevatorExt):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedCogKart')
    JumpOutOffsets = ((6.5, -2, -0.025), (-6.5, -2, -0.025), (3.75, 5, -0.025),
                      (-3.75, 5, -0.025))

    def __init__(self, cr):
        DistributedElevatorExt.DistributedElevatorExt.__init__(self, cr)
        self.type = ElevatorConstants.ELEVATOR_COUNTRY_CLUB
        self.kartModelPath = 'phase_12/models/bossbotHQ/Coggolf_cart3.bam'
        self.leftDoor = None
        self.rightDoor = None
        self.fillSlotTrack = None
        return

    def generate(self):
        DistributedElevatorExt.DistributedElevatorExt.generate(self)
        self.loader = self.cr.playGame.hood.loader
        if self.loader:
            self.notify.debug('Loader has been loaded')
            self.notify.debug(str(self.loader))
        else:
            self.notify.debug('Loader has not been loaded')
        self.golfKart = render.attachNewNode('golfKartNode')
        self.kart = loader.loadModel(self.kartModelPath)
        self.kart.setPos(0, 0, 0)
        self.kart.setScale(1)
        self.kart.reparentTo(self.golfKart)
        self.golfKart.reparentTo(self.loader.geom)
        self.wheels = self.kart.findAllMatches('**/wheelNode*')
        self.numWheels = self.wheels.getNumPaths()

    def announceGenerate(self):
        DistributedElevatorExt.DistributedElevatorExt.announceGenerate(self)
        angle = self.startingHpr[0]
        angle -= 90
        radAngle = deg2Rad(angle)
        unitVec = Vec3(math.cos(radAngle), math.sin(radAngle), 0)
        unitVec *= 45.0
        self.endPos = self.startingPos + unitVec
        self.endPos.setZ(0.5)
        dist = Vec3(self.endPos - self.enteringPos).length()
        wheelAngle = dist / (4.8 * 1.4 * math.pi) * 360
        self.kartEnterAnimateInterval = Parallel(
            LerpHprInterval(
                self.wheels[0], 5.0,
                Vec3(self.wheels[0].getH(), wheelAngle,
                     self.wheels[0].getR())),
            LerpHprInterval(
                self.wheels[1], 5.0,
                Vec3(self.wheels[1].getH(), wheelAngle,
                     self.wheels[1].getR())),
            LerpHprInterval(
                self.wheels[2], 5.0,
                Vec3(self.wheels[2].getH(), wheelAngle,
                     self.wheels[2].getR())),
            LerpHprInterval(
                self.wheels[3], 5.0,
                Vec3(self.wheels[3].getH(), wheelAngle,
                     self.wheels[3].getR())),
            name='CogKartAnimate')
        trolleyExitTrack1 = Parallel(LerpPosInterval(self.golfKart, 5.0,
                                                     self.endPos),
                                     self.kartEnterAnimateInterval,
                                     name='CogKartExitTrack')
        self.trolleyExitTrack = Sequence(trolleyExitTrack1)
        self.trolleyEnterTrack = Sequence(
            LerpPosInterval(self.golfKart,
                            5.0,
                            self.startingPos,
                            startPos=self.enteringPos))
        self.closeDoors = Sequence(self.trolleyExitTrack,
                                   Func(self.onDoorCloseFinish))
        self.openDoors = Sequence(self.trolleyEnterTrack)

    def delete(self):
        DistributedElevatorExt.DistributedElevatorExt.delete(self)
        if hasattr(self, 'elevatorFSM'):
            del self.elevatorFSM

    def setBldgDoId(self, bldgDoId):
        self.bldg = None
        self.setupElevatorKart()
        return

    def setupElevatorKart(self):
        collisionRadius = ElevatorConstants.ElevatorData[
            self.type]['collRadius']
        self.elevatorSphere = CollisionSphere(0, 0, 0, collisionRadius)
        self.elevatorSphere.setTangible(1)
        self.elevatorSphereNode = CollisionNode(
            self.uniqueName('elevatorSphere'))
        self.elevatorSphereNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.elevatorSphereNode.addSolid(self.elevatorSphere)
        self.elevatorSphereNodePath = self.getElevatorModel().attachNewNode(
            self.elevatorSphereNode)
        self.elevatorSphereNodePath.hide()
        self.elevatorSphereNodePath.reparentTo(self.getElevatorModel())
        self.elevatorSphereNodePath.stash()
        self.boardedAvIds = {}
        self.finishSetup()

    def setColor(self, r, g, b):
        pass

    def getElevatorModel(self):
        return self.golfKart

    def enterWaitEmpty(self, ts):
        DistributedElevatorExt.DistributedElevatorExt.enterWaitEmpty(self, ts)

    def exitWaitEmpty(self):
        DistributedElevatorExt.DistributedElevatorExt.exitWaitEmpty(self)

    def forceDoorsOpen(self):
        pass

    def forceDoorsClosed(self):
        pass

    def setPosHpr(self, x, y, z, h, p, r):
        self.startingPos = Vec3(x, y, z)
        self.enteringPos = Vec3(x, y, z - 10)
        self.startingHpr = Vec3(h, 0, 0)
        self.golfKart.setPosHpr(x, y, z, h, 0, 0)

    def enterClosing(self, ts):
        if self.localToonOnBoard:
            elevator = self.getPlaceElevator()
            if elevator:
                elevator.fsm.request('elevatorClosing')
        self.closeDoors.start(ts)

    def enterClosed(self, ts):
        self.forceDoorsClosed()
        self.kartDoorsClosed(self.getZoneId())

    def kartDoorsClosed(self, zoneId):
        if self.localToonOnBoard:
            hoodId = ZoneUtil.getHoodId(zoneId)
            doneStatus = {
                'loader': 'suitInterior',
                'where': 'suitInterior',
                'hoodId': hoodId,
                'zoneId': zoneId,
                'shardId': None
            }
            elevator = self.elevatorFSM
            del self.elevatorFSM
            elevator.signalDone(doneStatus)
        return

    def setCountryClubInteriorZone(self, zoneId):
        if self.localToonOnBoard:
            hoodId = self.cr.playGame.hood.hoodId
            countryClubId = self.countryClubId
            if bboard.has('countryClubIdOverride'):
                countryClubId = bboard.get('countryClubIdOverride')
            doneStatus = {
                'loader': 'cogHQLoader',
                'where': 'countryClubInterior',
                'how': 'teleportIn',
                'zoneId': zoneId,
                'countryClubId': self.countryClubId,
                'hoodId': hoodId
            }
            self.cr.playGame.getPlace().elevator.signalDone(doneStatus)

    def setCountryClubInteriorZoneForce(self, zoneId):
        place = self.cr.playGame.getPlace()
        if place:
            place.fsm.request('elevator', [self, 1])
            hoodId = self.cr.playGame.hood.hoodId
            countryClubId = self.countryClubId
            if bboard.has('countryClubIdOverride'):
                countryClubId = bboard.get('countryClubIdOverride')
            doneStatus = {
                'loader': 'cogHQLoader',
                'where': 'countryClubInterior',
                'how': 'teleportIn',
                'zoneId': zoneId,
                'countryClubId': self.countryClubId,
                'hoodId': hoodId
            }
            if hasattr(place, 'elevator') and place.elevator:
                place.elevator.signalDone(doneStatus)
            else:
                self.notify.warning(
                    "setMintInteriorZoneForce: Couldn't find playGame.getPlace().elevator, zoneId: %s"
                    % zoneId)
        else:
            self.notify.warning(
                "setCountryClubInteriorZoneForce: Couldn't find playGame.getPlace(), zoneId: %s"
                % zoneId)

    def setCountryClubId(self, countryClubId):
        self.countryClubId = countryClubId

    def getZoneId(self):
        return 0

    def fillSlot(self, index, avId, wantBoardingShow=0):
        self.notify.debug('%s.fillSlot(%s, %s, ... %s)' %
                          (self.doId, index, avId, globalClock.getRealTime()))
        request = self.toonRequests.get(index)
        if request:
            self.cr.relatedObjectMgr.abortRequest(request)
            del self.toonRequests[index]
        if avId == 0:
            pass
        elif avId not in self.cr.doId2do:
            func = PythonUtil.Functor(self.gotToon, index, avId)
            self.toonRequests[index] = self.cr.relatedObjectMgr.requestObjects(
                [avId], allCallback=func)
        elif not self.isSetup:
            self.deferredSlots.append((index, avId, wantBoardingShow))
        else:
            if avId == base.localAvatar.getDoId():
                place = base.cr.playGame.getPlace()
                if not place:
                    return
                elevator = self.getPlaceElevator()
                if elevator == None:
                    place.fsm.request('elevator')
                    elevator = self.getPlaceElevator()
                if not elevator:
                    return
                self.localToonOnBoard = 1
                if hasattr(localAvatar,
                           'boardingParty') and localAvatar.boardingParty:
                    localAvatar.boardingParty.forceCleanupInviteePanel()
                    localAvatar.boardingParty.forceCleanupInviterPanels()
                if hasattr(base.localAvatar, 'elevatorNotifier'):
                    base.localAvatar.elevatorNotifier.cleanup()
                cameraTrack = Sequence()
                cameraTrack.append(
                    Func(elevator.fsm.request, 'boarding',
                         [self.getElevatorModel()]))
                cameraTrack.append(Func(elevator.fsm.request, 'boarded'))
            toon = self.cr.doId2do[avId]
            toon.stopSmooth()
            toon.wrtReparentTo(self.golfKart)
            sitStartDuration = toon.getDuration('sit-start')
            jumpTrack = self.generateToonJumpTrack(toon, index)
            track = Sequence(jumpTrack,
                             Func(toon.setAnimState, 'Sit', 1.0),
                             Func(self.clearToonTrack, avId),
                             name=toon.uniqueName('fillElevator'),
                             autoPause=1)
            if wantBoardingShow:
                boardingTrack, boardingTrackType = self.getBoardingTrack(
                    toon, index, True)
                track = Sequence(boardingTrack, track)
                if avId == base.localAvatar.getDoId():
                    cameraWaitTime = 2.5
                    if boardingTrackType == BoardingGroupShow.TRACK_TYPE_RUN:
                        cameraWaitTime = 0.5
                    cameraTrack = Sequence(Wait(cameraWaitTime), cameraTrack)
            if self.canHideBoardingQuitBtn(avId):
                track = Sequence(
                    Func(localAvatar.boardingParty.groupPanel.disableQuitButton
                         ), track)
            if avId == base.localAvatar.getDoId():
                track = Parallel(cameraTrack, track)
            track.delayDelete = DelayDelete.DelayDelete(
                toon, 'CogKart.fillSlot')
            self.storeToonTrack(avId, track)
            track.start()
            self.fillSlotTrack = track
            self.boardedAvIds[avId] = None
        return

    def generateToonJumpTrack(self, av, seatIndex):
        av.pose('sit', 47)
        hipOffset = av.getHipsParts()[2].getPos(av)

        def getToonJumpTrack(av, seatIndex):
            def getJumpDest(av=av, node=self.golfKart):
                dest = Point3(0, 0, 0)
                if hasattr(self, 'golfKart') and self.golfKart:
                    dest = Vec3(self.golfKart.getPos(av.getParent()))
                    seatNode = self.golfKart.find('**/seat' +
                                                  str(seatIndex + 1))
                    dest += seatNode.getPos(self.golfKart)
                    dna = av.getStyle()
                    dest -= hipOffset
                    if seatIndex < 2:
                        dest.setY(dest.getY() + 2 * hipOffset.getY())
                    dest.setZ(dest.getZ() + 0.1)
                else:
                    self.notify.warning(
                        'getJumpDestinvalid golfKart, returning (0,0,0)')
                return dest

            def getJumpHpr(av=av, node=self.golfKart):
                hpr = Point3(0, 0, 0)
                if hasattr(self, 'golfKart') and self.golfKart:
                    hpr = self.golfKart.getHpr(av.getParent())
                    if seatIndex < 2:
                        hpr.setX(hpr.getX() + 180)
                    else:
                        hpr.setX(hpr.getX())
                    angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX())
                    hpr.setX(angle)
                else:
                    self.notify.warning(
                        'getJumpHpr invalid golfKart, returning (0,0,0)')
                return hpr

            toonJumpTrack = Parallel(
                ActorInterval(av, 'jump'),
                Sequence(
                    Wait(0.43),
                    Parallel(
                        LerpHprInterval(av, hpr=getJumpHpr, duration=0.9),
                        ProjectileInterval(av,
                                           endPos=getJumpDest,
                                           duration=0.9))))
            return toonJumpTrack

        def getToonSitTrack(av):
            toonSitTrack = Sequence(ActorInterval(av, 'sit-start'),
                                    Func(av.loop, 'sit'))
            return toonSitTrack

        toonJumpTrack = getToonJumpTrack(av, seatIndex)
        toonSitTrack = getToonSitTrack(av)
        jumpTrack = Sequence(
            Parallel(toonJumpTrack, Sequence(Wait(1), toonSitTrack)))
        return jumpTrack

    def emptySlot(self, index, avId, bailFlag, timestamp, timeSent=0):
        if self.fillSlotTrack:
            self.fillSlotTrack.finish()
            self.fillSlotTrack = None
        if avId == 0:
            pass
        elif not self.isSetup:
            newSlots = []
            for slot in self.deferredSlots:
                if slot[0] != index:
                    newSlots.append(slot)

            self.deferredSlots = newSlots
        elif avId in self.cr.doId2do:
            if bailFlag == 1 and hasattr(self, 'clockNode'):
                if timestamp < self.countdownTime and timestamp >= 0:
                    self.countdown(self.countdownTime - timestamp)
                else:
                    self.countdown(self.countdownTime)
            toon = self.cr.doId2do[avId]
            toon.stopSmooth()
            sitStartDuration = toon.getDuration('sit-start')
            jumpOutTrack = self.generateToonReverseJumpTrack(toon, index)
            track = Sequence(jumpOutTrack,
                             Func(self.notifyToonOffElevator, toon),
                             Func(self.clearToonTrack, avId),
                             name=toon.uniqueName('emptyElevator'),
                             autoPause=1)
            if self.canHideBoardingQuitBtn(avId):
                track.append(
                    Func(
                        localAvatar.boardingParty.groupPanel.enableQuitButton))
                track.append(Func(localAvatar.boardingParty.enableGoButton))
            track.delayDelete = DelayDelete.DelayDelete(
                toon, 'CogKart.emptySlot')
            self.storeToonTrack(toon.doId, track)
            track.start()
            if avId == base.localAvatar.getDoId():
                messenger.send('exitElevator')
            if avId in self.boardedAvIds:
                del self.boardedAvIds[avId]
        else:
            self.notify.warning('toon: ' + str(avId) + " doesn't exist, and" +
                                ' cannot exit the elevator!')
        return

    def generateToonReverseJumpTrack(self, av, seatIndex):
        self.notify.debug('av.getH() = %s' % av.getH())

        def getToonJumpTrack(av, destNode):
            def getJumpDest(av=av, node=destNode):
                dest = node.getPos(av.getParent())
                dest += Vec3(*self.JumpOutOffsets[seatIndex])
                return dest

            def getJumpHpr(av=av, node=destNode):
                hpr = node.getHpr(av.getParent())
                hpr.setX(hpr.getX() + 180)
                angle = PythonUtil.fitDestAngle2Src(av.getH(), hpr.getX())
                hpr.setX(angle)
                return hpr

            toonJumpTrack = Parallel(
                ActorInterval(av, 'jump'),
                Sequence(
                    Wait(0.1),
                    Parallel(
                        ProjectileInterval(av,
                                           endPos=getJumpDest,
                                           duration=0.9))))
            return toonJumpTrack

        toonJumpTrack = getToonJumpTrack(av, self.golfKart)
        jumpTrack = Sequence(toonJumpTrack, Func(av.loop, 'neutral'),
                             Func(av.wrtReparentTo, render))
        return jumpTrack

    def startCountdownClock(self, countdownTime, ts):
        DistributedElevatorExt.DistributedElevatorExt.startCountdownClock(
            self, countdownTime, ts)
        self.clock.setH(self.clock.getH() + 180)

    def rejectBoard(self, avId, reason=0):
        print('rejectBoard %s' % reason)
        if hasattr(base.localAvatar, 'elevatorNotifier'):
            if reason == ElevatorConstants.REJECT_SHUFFLE:
                base.localAvatar.elevatorNotifier.showMe(
                    TTLocalizer.ElevatorHoppedOff)
            elif reason == ElevatorConstants.REJECT_MINLAFF:
                base.localAvatar.elevatorNotifier.showMe(
                    TTLocalizer.KartMinLaff % self.minLaff)
            elif reason == ElevatorConstants.REJECT_PROMOTION:
                base.localAvatar.elevatorNotifier.showMe(
                    TTLocalizer.BossElevatorRejectMessage)
            elif reason == ElevatorConstants.REJECT_NOT_YET_AVAILABLE:
                base.localAvatar.elevatorNotifier.showMe(
                    TTLocalizer.NotYetAvailable)
        doneStatus = {'where': 'reject'}
        elevator = self.getPlaceElevator()
        if elevator:
            elevator.signalDone(doneStatus)

    def getDestName(self):
        if self.countryClubId == ToontownGlobals.BossbotCountryClubIntA:
            return TTLocalizer.ElevatorBossBotCourse0
        elif self.countryClubId == ToontownGlobals.BossbotCountryClubIntB:
            return TTLocalizer.ElevatorBossBotCourse1
        elif self.countryClubId == ToontownGlobals.BossbotCountryClubIntC:
            return TTLocalizer.ElevatorBossBotCourse2
예제 #46
0
class entity(Actor):
    '''
    Base class for any characters
    Contains methods for movement, collision, model loading
    '''

    #procedure class constructor
    # NodePath model, ShowBase caller, tuple Pos -> class construction
    def __init__(self, model: str, base: ShowBase, pos: tuple, physics=True):
        '''
        constructor for entity. attaches model to calling instance renderer
        also stores size definitions and creates basic collision object
        '''
        Actor.__init__(self)
        DEFAULT_HEALTH = 50

        #reference base for later
        self.base = base

        # set health
        self.health = DEFAULT_HEALTH
        self.damagedSound = base.loader.loadSfx("sounds/oof.ogg")

        # speed
        self.speed = 10
        self.turnSpeed = 5
        # gravity -- is touching ground?
        self.isGrounded = False
        # creates actor object using constructor and parents to passed renderer
        self.loadModel(model)
        self.renderer = base.render
        self.reparentTo(self.renderer)
        # put at specified location
        self.setPos(pos)
        # store dimensions for later
        # https://discourse.panda3d.org/t/getting-the-height-width-and-length-of-models-solved/6504
        # Post describes the output of the Nodepath class's getTightBounds() method. Using this
        # I am able to get an approximation of the dimensions of an object in the global coordinate space
        minimum, maximum = self.getTightBounds()
        # make sure all numbers are positive for best (any) results
        self.bounds = [abs(num) for num in (minimum - maximum)]
        self.width, self.length, self.height = self.bounds[0], self.bounds[
            1], self.bounds[2]

        # COLLISION PROPERTIES
        # create collision ray that is height of model pointing down (will detect ground collisions)

        if physics:
            self.groundRay = CollisionRay()
            self.groundRay.setOrigin(0, 0, 1000)
            self.groundRay.setDirection(0, 0, -1)
            self.groundCol = CollisionNode('groundRay')
            self.groundCol.addSolid(self.groundRay)
            self.groundCol.setFromCollideMask(BitMask32.bit(0))
            self.groundCol.setIntoCollideMask(BitMask32.allOff())
            self.groundColNode = self.attachNewNode(self.groundCol)
            base.cTrav.addCollider(self.groundColNode, base.groundHandler)

            #and another one for everything else
            self.mainCol = CollisionNode('actorCollision' + str(id(self)))
            # create collision sphere as solid for this collision node
            self.mainCol.addSolid(
                CollisionSphere(0, 0, self.height / 2, self.height / 2))
            # specify valid collisions for collision node
            self.mainCol.setFromCollideMask(CollideMask.bit(0))
            self.mainCol.setIntoCollideMask(CollideMask.bit(
                1))  # accepts incoming objects with collideMask bit(1)
            # attach collision node to actor
            self.cNode = self.attachNewNode(self.mainCol)
            # show
            #self.cNode.show()
            # make instance collision traverser aware of this collision node, tell it how to handle (with pusher)
            base.cTrav.addCollider(self.cNode, base.pusher)
            # add collision to pusher collision handler; tell pusher which node to associate with which actor IOT push
            base.pusher.addCollider(self.cNode, self, base.drive.node())

        # add to base.entities (since all allies/enemies created through this constructor, makes sense
        base.entities.append(self)
        # add as client of entity collision handler
        # base.cTrav.addCollider(self.cNode,base.entityCollisionHandler)

        #add to cleanup for deletion later
        base.cleanup.append(self)

        #store reference to self
        #https://discourse.panda3d.org/t/inheriting-from-nodepath/10886/4
        #post describes how to set up a reference from nodepath to itself to retrieve custom properties
        #I use python tags to distinguish collision volume owners
        self.mainCol.setPythonTag("owner", self)

        # TODO if no initial collision, enforce gravity until collision
        #taskMgr.add(self.doGravity, "entityGravity")

    #procedure update
    #do all actions that must be done for this object every frame - called from game loop
    def updateState(self):
        #by default do gravity for all entities
        self.doGravity()
        return

    #procedure entityGravity
    # drops entity by gravity if isGrounded is not true (set True by collision with ground)
    def doGravity(self):
        dt = globalClock.getDt()
        #gravity - if not grounded, make it so
        if not self.isGrounded:
            self.setZ(self.getZ() - 50 * dt)
            return
        else:
            entries = []
            for entry in base.groundHandler.getEntries():
                if entry.getFromNodePath().getParent() == self \
                        or entry.getIntoNodePath().getParent() == self:
                    entries.append(entry)
            if (len(entries) > 0) and (entries[0].getIntoNode().getName()
                                       == "terrain"):
                self.setZ(entries[0].getSurfacePoint(base.render).getZ() + 2)

    #procedure add Damage
    #float dmg -> decrement self.health
    def addDamage(self, sender, dmg):
        '''
        Adds a specified amount to this entity
        Can be negative or positive
        If self.health < 0 call delete self
        '''
        #get shooter for scoring purposes
        shooter = sender.owner
        # TODO make pretty death
        self.health -= dmg
        if self.damagedSound is not None:
            self.damagedSound.play()
        if self.health <= 0:
            #if shooter was player, add to score
            if shooter is base.player:
                if shooter.team is self.team:
                    base.player.score -= 15
                else:
                    base.player.score += 15
            #if player, end game
            if self is base.player:
                messenger.send('Leave-Game')
            self.kill()

    #procedure kill
    # destroys object, but fancy-like
    def kill(self):
        self.pose('death', 0)
        taskMgr.add(self.deleteTask, 'deleteTask')

    #procedure deleteTask
    #destroys object after five seconds of being in death state
    def deleteTask(self, task):
        if task.time < 5.0:
            return task.cont
        else:
            self.delete()
            return task.done

    #procedure class deconstructor
    def delete(self):
        '''
        Class destructor
        Destroy an object cleanly from instance
        '''
        #also remove from base.entities
        if self in base.entities:
            base.entities.remove(self)

        # remove pythontag from collision
        self.mainCol.clearPythonTag("owner")
        # remove collision node from global collider
        base.cTrav.removeCollider(self.cNode)
        #destroy actor
        if not self.is_empty():
            self.hide()
            self.cleanup()
            #self.detachNode()
            del self

    #class deconstructor
    def __del__(self):
        self.removeNode()
예제 #47
0
class World(DirectObject):
    def freezeGame():
        # Pause all of the AI, stop model animations, cease taking inputs, except for reset
        return 0
        
    def resetGame(self):
        # Set everything back to its starting position and remove the game over message
        self.caught.destroy()
        self.pieDisplay.destroy()
        self.pieCount = 0
        self.pieDisplay = grabPie(self.pieCount)
        self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0, "run":0, "reset":0}
        eveStartPos = self.environ.find("**/start_point").getPos()
        self.gameOver = 0
        self.eve.setPos(eveStartPos)
        self.eateve.setPos(eveStartPos)
        self.pie.setPos(Vec3(-50, -30, 10))
        self.rand.setPos(Vec3(-70, -5, eveStartPos.getZ() + 5))
        self.rand2.setPos(Vec3(-70, -5, eveStartPos.getZ() + 10))
        
        # Blue Dragon
        self.character3.loop('win')
        self.character3.setPos(-114,11,1.9)
        self.blueDragonSound.play()
        
        # Red Dragon
        self.character2.loop('win')
        self.character2.setPos(-108,11,.3)
        self.redDragonStartPos = self.character2.getPos()
        self.redDragonCollideCount = 0
        self.redDragonSound.play()
        
        # Green Dragon
        self.character.loop('win')
        self.character.setPos(-118,21,0)
        self.greenDragonSound.play()
        self.dragonStartPos = self.character.getPos()
        self.dragonCollideCount = 0
        self.AIbehaviors.pursue(self.eateve, 1)
        
        self.AIbehaviorsRand.wander(10,0,47,.5)
        
        self.AIbehaviorsRand2.wander(10,0,47,.5)

        self.AIbehaviors3.pursue(self.rand, 1)
        
        self.redDragonChasingEve = 0
        self.AIbehaviors2.pursue(self.rand2, 1)
        
        self.isMoving = False
        self.isRunning = False
        self.isWalking = False
        
        base.camera.setPos(self.eve.getX(),self.eve.getY()+10,2)
        self.fixPieZ()
        return 0
    
    
    def __init__(self):
        # Sound
        
        self.collectSoundEffect = loader.loadMusic("sounds/item_collect.mp3")
        
        self.footstepSound = loader.loadMusic("sounds/footsteps.mp3")
        self.footstepSound.setLoop(1);
        
        audio3d = Audio3DManager.Audio3DManager(base.sfxManagerList[0], base.camera)
        
        self.musicend = loader.loadMusic("sounds/Enchanted-Woods.mp3")
    
        # Sky Box
        starTexture = loader.loadTexture("models/stars.jpg")
        self.sky = loader.loadModel("models/box.egg")
        self.sky.setScale(300)
        self.sky.setPos(-200,-150,0)
        self.sky.setBin('background', 0)
        self.sky.setDepthWrite(0)
        self.sky.setTwoSided(True)
        self.sky.setTexture(starTexture, 1)
        
        self.sky.reparentTo(render)
        self.sky.set_compass()
    
        # allow transparency
        render.setTransparency(TransparencyAttrib.MAlpha)

        self.pieCount = 0
        self.pieDisplay = grabPie(self.pieCount)
        self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0, "run":0, "reset":0}
        base.win.setClearColor(Vec4(0,0,0,1))
        self.environ = loader.loadModel("models/world")      
        self.environ.reparentTo(render)
        self.environ.setPos(0,0,0)
        
        # Create the main character
        eveStartPos = self.environ.find("**/start_point").getPos()
        self.eve = Actor("models/eve",
                                 {"run":"models/eve_run",
                                  "walk":"models/eve_walk"})
        print(eveStartPos)
        self.gameOver = 0
        self.eve.reparentTo(render)
        self.eve.setScale(.2)
        #self.eve.setShear(.5, .5, .5)
        self.eve.setPos(eveStartPos)

        self.eateve = Actor("models/eve")
        self.eateve.reparentTo(render)
        self.eateve.setScale(.2)
        self.eateve.setPos(eveStartPos)
        self.eateve.hide()
        
        self.pie = loader.loadModel("models/fruit-pie-slice")
        self.pie.reparentTo(render)
        self.pie.setScale(.5)
        self.pie.setPos(Vec3(-50, -30, 10))
        #self.pie.setP(20)
        
        self.rand = Actor("models/eve")
        self.rand.reparentTo(render)
        self.rand.setScale(.2)
        self.rand.setPos(Vec3(-70, -5, eveStartPos.getZ() + 5))
        self.rand.hide()       
         
        self.rand2 = Actor("models/eve")
        self.rand2.reparentTo(render)
        self.rand2.setScale(.2)
        self.rand2.setPos(Vec3(-70, -5, eveStartPos.getZ() + 10))
        self.rand2.hide()
        # print(eveStartPos)
        
        # Blue Dragon
        self.character3=Actor('models/nik-dragon')
        #self.character3.loadModel('models/nik-dragon')
        self.character3.reparentTo(render)
        self.character3.loadAnims({'win': 'models/nik-dragon'})
        self.character3.loop('win')
        self.character3.setPlayRate(.5,'win')
        self.character3.setScale(.23)
        self.character3.setTransparency(1)
        #self.character3.setColorScale(0.4,0.2,.4,.7)
        self.character3.setColorScale(9,9,9,.3)
        self.character3.setPos(-114,11,1.9)
        
        self.blueDragonSound = audio3d.loadSfx("sounds/Snoring Giant.mp3")
        audio3d.attachSoundToObject(self.blueDragonSound, self.character3)
        self.blueDragonSound.setLoop(True)
        self.blueDragonSound.play()
        
        # Red Dragon
        self.character2=Actor()
        self.character2.loadModel('models/nik-dragon')
        self.character2.reparentTo(render)
        self.character2.loadAnims({'win': 'models/nik-dragon'})
        self.character2.loop('win')
        self.character2.setPlayRate(1.5,'win')
        self.character2.setScale(.06)
        self.character2.setColorScale(6,0.2,0.2,50)
        self.character2.setPos(-108,11,.3)

        self.redDragonStartPos = self.character2.getPos()
        self.redDragonCollideCount = 0
        
        self.redDragonSound = audio3d.loadSfx("sounds/Velociraptor Call.mp3")
        audio3d.attachSoundToObject(self.redDragonSound, self.character3)
        self.redDragonSound.setLoop(True)
        self.redDragonSound.play()
        
        # Green Dragon
        self.character=Actor()
        self.character.loadModel('models/nik-dragon')
        self.character.reparentTo(render)
        self.character.loadAnims({'win': 'models/nik-dragon'})
        self.character.loop('win')
        self.character.setScale(.1)
        self.character.setPos(-118,21,0)
        
        self.greenDragonSound = audio3d.loadSfx("sounds/Raptor Call.mp3")
        audio3d.attachSoundToObject(self.greenDragonSound, self.character3)
        self.greenDragonSound.setLoop(True)
        self.greenDragonSound.play()
        
        self.dragonStartPos = self.character.getPos()
        self.dragonCollideCount = 0
        self.AIworld = AIWorld(render)
        #self.AIworld.addObstacle(self.environ)
        
        self.dragonAI = AICharacter("character", self.character, 100, 0.05, 5)
        self.AIworld.addAiChar(self.dragonAI)
        self.AIbehaviors = self.dragonAI.getAiBehaviors()
        #self.AIbehaviors.seek(self.character2)
        #self.AIbehaviors.wander(2, 0, 5, .5)
        self.AIbehaviors.pursue(self.eateve, 1)
        #self.AIbehaviors.wander(5,0,10,.5)
        #self.AIbehaviors.evade(self.character3, 10, 20, 300)
        #self.AIbehaviors.seek(self.eve, .5)
        #self.AIbehaviors.obstacleAvoidance(1)
        
        self.randomChase = AICharacter("rand", self.rand, 50, 20, 20)
        self.AIworld.addAiChar(self.randomChase)
        self.AIbehaviorsRand = self.randomChase.getAiBehaviors()
        self.AIbehaviorsRand.wander(10,0,47,.5)
        
        self.randomChase2 = AICharacter("rand2", self.rand2, 50, 20, 20)
        self.AIworld.addAiChar(self.randomChase2)
        self.AIbehaviorsRand2 = self.randomChase2.getAiBehaviors()
        self.AIbehaviorsRand2.wander(10,0,47,.5)

        self.ghostDragonAI = AICharacter("character3", self.character3, 250, .05, 5)
        self.AIworld.addAiChar(self.ghostDragonAI)
        self.AIbehaviors3 = self.ghostDragonAI.getAiBehaviors()
        self.AIbehaviors3.pursue(self.rand, 1)
        #self.AIbehaviors3.wander(5,0,10,.5)
        
        self.redDragonChasingEve = 0
        self.redDragonAI = AICharacter("character2", self.character2, 100, .05, 7)
        self.AIworld.addAiChar(self.redDragonAI)
        self.AIbehaviors2 = self.redDragonAI.getAiBehaviors()
        self.AIbehaviors2.pursue(self.rand2, 1)
        
        taskMgr.add(self.AIUpdate, "AIUpdate")

    
        # Create a floater object to use for camera management
        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(render)
        
        # Enable Particles
        base.enableParticles()

        # 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("space", self.setKey, ["run",1])
        self.accept("a", self.setKey, ["cam-left",1])
        self.accept("s", self.setKey, ["cam-right",1])
        self.accept("r", self.setKey, ["reset",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("space-up", self.setKey, ["run",0])
        self.accept("a-up", self.setKey, ["cam-left",0])
        self.accept("s-up", self.setKey, ["cam-right",0])
        self.accept("r-up", self.setKey, ["reset",0])

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

        # Game state variables
        self.isMoving = False
        self.isRunning = False
        self.isWalking = False

        # Set up the camera
        base.disableMouse()
        base.camera.setPos(self.eve.getX(),self.eve.getY()+10,2)
        
        # Collision detection for eve against the ground and against objects
        # 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 eve'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.eveGroundRay = CollisionRay()
        self.eveGroundRay.setOrigin(0,0,4.5)
        self.eveGroundRay.setDirection(0,0,-1)
        self.eveGroundCol = CollisionNode('eveRay')
        self.eveGroundCol.addSolid(self.eveGroundRay)
        self.eveGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.eveGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.eveGroundColNp = self.eve.attachNewNode(self.eveGroundCol)
        self.eveGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.eveGroundColNp, self.eveGroundHandler)

        self.dragonGroundRay = CollisionRay()
        self.dragonGroundRay.setOrigin(0,0,10)
        self.dragonGroundRay.setDirection(0,0,-1)
        self.dragonGroundCol = CollisionNode('dragonRay')
        self.dragonGroundCol.addSolid(self.dragonGroundRay)
        self.dragonGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.dragonGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.dragonGroundColNp = self.character.attachNewNode(self.dragonGroundCol)
        self.dragonGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.dragonGroundColNp, self.dragonGroundHandler)

        self.ghostDragonGroundRay = CollisionRay()
        self.ghostDragonGroundRay.setOrigin(0,0,25)
        self.ghostDragonGroundRay.setDirection(0,0,-1)
        self.ghostDragonGroundCol = CollisionNode('ghostDragonRay')
        self.ghostDragonGroundCol.addSolid(self.ghostDragonGroundRay)
        self.ghostDragonGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.ghostDragonGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.ghostDragonGroundColNp = self.character3.attachNewNode(self.ghostDragonGroundCol)
        self.ghostDragonGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.ghostDragonGroundColNp, self.ghostDragonGroundHandler)

        self.redDragonGroundRay = CollisionRay()
        self.redDragonGroundRay.setOrigin(0,0,5)
        self.redDragonGroundRay.setDirection(0,0,-1)
        self.redDragonGroundCol = CollisionNode('redDragonRay')
        self.redDragonGroundCol.addSolid(self.redDragonGroundRay)
        self.redDragonGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.redDragonGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.redDragonGroundColNp = self.character2.attachNewNode(self.ghostDragonGroundCol)
        self.redDragonGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.redDragonGroundColNp, self.redDragonGroundHandler)
        
        self.pieRay = CollisionRay()
        self.pieRay.setOrigin(0,0,10)
        self.pieRay.setDirection(0,0,-1)
        self.pieCol = CollisionNode('pieRay')
        self.pieCol.addSolid(self.pieRay)
        self.pieCol.setFromCollideMask(BitMask32.bit(0))
        self.pieCol.setIntoCollideMask(BitMask32.allOff())
        self.pieColNp = self.pie.attachNewNode(self.pieCol)
        self.pieHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.pieColNp, self.pieHandler)
        
        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)

        # Shows collision rays
        #self.eveGroundColNp.show()
        #self.camGroundColNp.show()
       
        # Shows collisions
        #self.cTrav.showCollisions(render)
        
        self.fixPieZ()
        
        # 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))
        #directionalLight.setShadowCaster(True, 512, 512)
        render.setLight(render.attachNewNode(ambientLight))
        render.setLight(render.attachNewNode(directionalLight))
        #render.setShaderAuto()
    
    # Records the state of the arrow keys
    def setKey(self, key, value):
        self.keyMap[key] = value
    
    def AIUpdate(self, task):
        self.AIworld.update()
        return task.cont
    
    def fixPieZ(self):
        self.cTrav.traverse(render)
        entries = []
        for i in range(self.pieHandler.getNumEntries()):
            entry = self.pieHandler.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.pie.setZ(entries[0].getSurfacePoint(render).getZ() + .5)
            return False
        else:
            return True
    
    # 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 (self.gameOver != 1):
            if math.sqrt((self.eve.getX() - self.pie.getX())**2 + (self.eve.getY() - self.pie.getY())**2) < .6:
                # particle effect
                self.p = ParticleEffect()
                self.p.loadConfig("models/sparkleparticlerenderer.ptf")
                
                self.copyPie = self.pie.copyTo(render)
                self.copyPie.setColor(0.0, 0.0, 0.0, 0.0)
                
                self.p.start(parent = self.copyPie, renderParent = render)
                taskMgr.add(self.timedParticle, "timedParticle")
                
                # play collect sounds
                self.collectSoundEffect.play()
                
                # collect pie
                try:
                    self.pie.setPos(Vec3(random.randrange(-120,-19), random.randrange(-60,51), 10))
                    while self.fixPieZ():
                        self.pie.setPos(Vec3(random.randrange(-120,-19), random.randrange(-60,51), 10))
                except Exception as ex:
                    print ex
                    raw_input()
                self.pieDisplay.clearText()
                self.pieCount = self.pieCount + 1
                self.pieDisplay = grabPie(self.pieCount)
                
                
            if math.sqrt((self.eve.getX() - self.character.getX())**2 + (self.eve.getY() - self.character.getY())**2) < 1 and self.gameOver == 0:
                self.caught = displayGameOver()
                self.gameOver = 1
    
            if math.sqrt((self.eve.getX() - self.character2.getX())**2 + (self.eve.getY() - self.character2.getY())**2) < 1 and self.gameOver == 0:
                self.caught = displayGameOver()
                self.gameOver = 1
                
            if math.sqrt((self.eve.getX() - self.character3.getX())**2 + (self.eve.getY() - self.character3.getY())**2) < 1.3 and self.gameOver == 0:
                self.caught = displayGameOver()
                self.gameOver = 1
    
            if math.sqrt((self.eve.getX() - self.character2.getX())**2 + (self.eve.getY() - self.character2.getY())**2) < 12.5 and self.redDragonCollideCount == 0 and self.redDragonChasingEve == 0:
                self.redDragonChasingEve = 1
                self.AIbehaviors2.removeAi("pursue")
                self.AIbehaviors2.pauseAi("seek")
                self.AIbehaviors2.pursue(self.eve, 1)
                
            # If the camera-left key is pressed, move camera left.
            # If the camera-right key is pressed, move camera right.
            base.camera.lookAt(self.eve)
            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())
    
            self.pie.setH(self.pie.getH() + 100 * globalClock.getDt())
    
            # save eve's initial position so that we can restore it,
            # in case she falls off the map or runs into something.
            startpos = self.eve.getPos()
            # If a move-key is pressed, move eve in the specified direction.
            if (self.keyMap["left"]!=0):
                self.eve.setH(self.eve.getH() + 300 * globalClock.getDt())
            if (self.keyMap["right"]!=0):
                self.eve.setH(self.eve.getH() - 300 * globalClock.getDt())
            if (self.keyMap["forward"]!=0):
                if (self.keyMap["run"] != 0):
                    self.eve.setY(self.eve, -30 * globalClock.getDt())
                else:
                    self.eve.setY(self.eve, -10 * globalClock.getDt())
                
            # If eve is moving, loop the run animation.
            # If she 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:
                    if (self.keyMap["run"] != 0):
                        self.eve.loop("run")
                        self.isMoving = True
                        self.isRunning = True
                        self.isWalking = False
                        self.footstepSound.setPlayRate(1.3)
                        self.footstepSound.play()
    
                    else:
                        self.eve.loop("walk")
                        self.eve.setPlayRate(2.0, "walk")
                        self.isMoving = True
                        self.isWalking = True
                        self.isRunning = False
                        self.footstepSound.setPlayRate(1.0)
                        self.footstepSound.play()
                else:
                    if (self.keyMap["run"] != 0 and self.isWalking):
                        self.eve.loop("run" )
                        self.isRunning = True
                        self.isWalking = False
                        self.footstepSound.setPlayRate(1.3)
    
                    elif (self.keyMap["run"] == 0 and self.isRunning):
                        self.eve.loop("walk")
                        self.eve.setPlayRate(2.0, "walk")
                        self.isWalking = True
                        self.isRunning = False
                        self.footstepSound.setPlayRate(1.0)
                        
            else:
                if self.isMoving:
                    self.eve.stop()
                    self.eve.pose("walk",10)
                    self.isMoving = False
                    self.footstepSound.stop()
    
            # If the camera is too far from eve, move it closer.
            # If the camera is too close to eve, move it farther.
            camvec = self.eve.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 eve's Z coordinate. If eve's ray hit terrain,s
            # update her Z. If it hit anything else, or didn't hit anything, put
            # her back where she was last frame.
            entries = []
            for i in range(self.eveGroundHandler.getNumEntries()):
                entry = self.eveGroundHandler.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.eve.setZ(entries[0].getSurfacePoint(render).getZ())
            else:
                self.eve.setPos(startpos)
                
                
    
            
            # Adjust the dragon's Z coordinate like with eve. Additionally, if
            # the dragon has hit an object, have it seek a location behind it
            # temporarily.
            if self.dragonCollideCount == 0:
                self.AIbehaviors.resumeAi("pursue")
                self.AIbehaviors.pauseAi("seek")
            else:
                self.dragonCollideCount = self.dragonCollideCount - 1
            
            entries = []
            for i in range(self.dragonGroundHandler.getNumEntries()):
                entry = self.dragonGroundHandler.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.character.setZ(entries[0].getSurfacePoint(render).getZ() + 1)
            elif (self.dragonCollideCount == 0):
                try:
                    self.AIbehaviors.pauseAi("pursue")
                except Exception as ex:
                    print ex
                    raw_input()
                self.AIbehaviors.seek(Vec3(self.character.getX() + 2000*(-self.character.getX() + self.dragonStartPos.getX()), self.character.getY() + 2000*(-self.character.getY() + self.dragonStartPos.getY()), self.character.getZ() + 2000*(-self.character.getZ() + self.dragonStartPos.getZ())), 20000)
                #self.AIbehaviors.seek(self.character3)
                self.dragonCollideCount = 100
                #self.AIbehaviors.flee(self.character.getPos(), 1, 10, 10000)
                #self.character.setPos(dragonStartPos)
            else:
                #do nothing
                self.dragonCollideCount = self.dragonCollideCount
            
            if self.redDragonCollideCount == 0 and self.redDragonChasingEve == 0:
                self.AIbehaviors2.pursue(self.rand2, 1)
                self.AIbehaviors2.pauseAi("seek")
            elif self.redDragonChasingEve == 0:
                self.redDragonCollideCount = self.redDragonCollideCount - 1
            
            # Red dragon z correcting and collision detecting
            entries = []
            for i in range(self.redDragonGroundHandler.getNumEntries()):
                entry = self.redDragonGroundHandler.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.character2.setZ(entries[0].getSurfacePoint(render).getZ() + .6)
            elif (self.redDragonCollideCount == 0):
                try:
                    self.AIbehaviors2.removeAi("pursue")
                except Exception as ex:
                    print ex
                    raw_input()
                self.redDragonChasingEve = 0
                self.AIbehaviors2.seek(Vec3(self.character2.getX() + 2000*(-self.character2.getX() + self.redDragonStartPos.getX()), self.character2.getY() + 2000*(-self.character2.getY() + self.redDragonStartPos.getY()), self.character2.getZ() + 2000*(-self.character2.getZ() + self.redDragonStartPos.getZ())), 20000)
                #self.AIbehaviors.seek(self.character3)
                self.redDragonCollideCount = 100
                #self.AIbehaviors.flee(self.character.getPos(), 1, 10, 10000)
                #self.character.setPos(dragonStartPos)
            else:
                #do nothing
                self.redDragonCollideCount = self.redDragonCollideCount
            
            # Adjust the ghost dragon's Z coordinate like with eve.
            # Additionally, if the ghost dragon has hit an object, have it
            # seek a location behind it temporarily.
            #if self.ghostDragonCollideCount == 0:
            #    self.AIbehaviors.resumeAi("wander")
            #    self.AIbehaviors3.pauseAi("seek")
            #else:
            #    self.ghostDragonCollideCount = self.dragonCollideCount - 1
            
            entries = []
            for i in range(self.ghostDragonGroundHandler.getNumEntries()):
                entry = self.ghostDragonGroundHandler.getEntry(i)
                entries.append(entry)
            entries.sort(lambda x,y: ghostDragonCmp(x,y))
            
            if (len(entries)>0):
                self.character3.setZ(entries[0].getSurfacePoint(render).getZ() + 2.5)
            #elif (self.ghostDragonCollideCount == 0):
            #    self.AIbehaviors3.pauseAi("wander")
            #    self.AIbehaviors3.seek(Vec3(self.character.getX() + 2000*(-self.character.getX() + self.dragonStartPos.getX()), self.character.getY() + 2000*(-self.character.getY() + self.dragonStartPos.getY()), self.character.getZ() + 2000*(-self.character.getZ() + self.dragonStartPos.getZ())), 20000)
                #self.AIbehaviors.seek(self.character3)
            #    self.ghostDragonCollideCount = 100
                #self.AIbehaviors.flee(self.character.getPos(), 1, 10, 10000)
                #self.character.setPos(dragonStartPos)
            #else:
                #do nothing
            #   self.ghostDragonCollideCount = self.ghostDragonCollideCount
                
            # Keep the camera at one foot above the terrain,
            # or two feet above eve, 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.eve.getZ() + 2.0):
                base.camera.setZ(self.eve.getZ() + 2.0)
                
            # The camera should look in eve's direction,
            # but it should also try to stay horizontal, so look at
            # a floater which hovers above eve's head.
            self.floater.setPos(self.eve.getPos())
            self.floater.setZ(self.eve.getZ() + 2.0)
            base.camera.lookAt(self.floater)
    
    
            self.eateve.setPos(self.eve.getX(), self.eve.getY(), self.eve.getZ() + 1)
            self.dragonStartPos = self.character.getPos()
            self.redDragonStartPos = self.character2.getPos()
            return task.cont
        else:
            self.eve.stop()
            self.isMoving = False
            self.footstepSound.stop()
            self.character.stop()
            self.AIbehaviors.pauseAi("wander")
            self.AIbehaviors.pauseAi("seek")
            self.AIbehaviors.pauseAi("pursue")
            self.character2.stop()
            self.AIbehaviors2.pauseAi("wander")
            self.AIbehaviors2.pauseAi("seek")
            self.AIbehaviors2.pauseAi("pursue")
            self.character3.stop()
            self.AIbehaviors3.pauseAi("wander")
            self.AIbehaviors3.pauseAi("seek")
            self.AIbehaviors3.pauseAi("pursue")
            self.greenDragonSound.stop()
            self.redDragonSound.stop()
            self.blueDragonSound.stop()
            if self.musicend.status() != self.musicend.PLAYING:
                self.musicend.setLoop(1)
                self.musicend.play()
            if (self.keyMap["reset"] == 1):
                self.gameOver = 0
                self.musicend.stop()
                self.resetGame()
                # Fill in all of the things
            return task.cont
            
    def timedParticle(self, task):
        if task.time < 1.0:
            return task.cont
        
        self.p.disable()
        self.copyPie.removeNode()
        return task.done
예제 #48
0
파일: main.py 프로젝트: MarcMDE/LASO
class BallInMazeDemo(ShowBase):
    def __init__(self):
        global action
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        action = "start"
        ShowBase.__init__(self)
        winProps = WindowProperties()
        winProps.setTitle("LASO Simulation - (RLP 2019-2020)")
        base.win.requestProperties(winProps)

        if not base.win.getGsg().getSupportsBasicShaders():
            print(
                "Error: Video driver reports that depth textures are not supported."
            )
            return
        if not base.win.getGsg().getSupportsDepthTexture():
            print(
                "Error: Video driver reports that depth textures are not supported."
            )
            return

        self.accept("escape", finalitzar)  # Escape quits

        # Disable default mouse-based camera control.  This is a method on the
        # ShowBase class from which we inherit.
        #self.disableMouse()

        # Place the camera
        camera.setPosHpr(0, 0, 80, 0, -90, 0)

        base.trackball.node().set_pos(0, 200, 0)
        base.trackball.node().set_hpr(0, 60, 0)

        #camera.setPosHpr(0, 0, 25, 0, -90, 0)
        #base.camLens.setNearFar(200, 600)

        #self.enableMouse()

        # Load the maze and place it in the scene
        #self.maze = loader.loadModel("models/maze")

        self.skybox = loader.loadModel("models/skybox")
        self.skybox.reparentTo(render)
        self.skybox.setPosHpr(0, 0, 45 + MAZE_OFFSETS[CURR_MAZE], 0, -180, 0)
        #self.skybox.setScale(2.54)

        self.taula = loader.loadModel("models/taula")
        self.taula.reparentTo(render)
        self.taula.setPosHpr(0, 0, -53.6 + MAZE_OFFSETS[CURR_MAZE], 0, 0, 0)
        self.taula.setScale(1.8)

        self.laso_box = loader.loadModel("models/laso_box")
        self.laso_box.reparentTo(render)
        self.laso_box.setPosHpr(0, 0, MAZE_OFFSETS[CURR_MAZE], 0, 0, 0)

        self.laso_ax = loader.loadModel("models/laso_ax")
        self.laso_ax.reparentTo(self.laso_box)
        self.laso_ax.setPosHpr(0, 0, MAZE_HEIGHT, 0, 0, 0)

        self.maze_i = CURR_MAZE

        self.maze = loader.loadModel("models/" + MAZES_NAME[self.maze_i])
        self.maze.reparentTo(render)
        self.maze.setPosHpr(0, 0, MAZE_HEIGHT, 0, 0, 0)
        #self.maze.setScale(2.54)

        # Load custom maze

        #self.maze2 = loader.loadModel("models/lab4")
        #self.maze2.reparentTo(render)

        # Most times, you want collisions to be tested against invisible geometry
        # rather than every polygon. This is because testing against every polygon
        # in the scene is usually too slow. You can have simplified or approximate
        # geometry for the solids and still get good results.
        #
        # Sometimes you'll want to create and position your own collision solids in
        # code, but it's often easier to have them built automatically. This can be
        # done by adding special tags into an egg file. Check maze.egg and ball.egg
        # and look for lines starting with <Collide>. The part is brackets tells
        # Panda exactly what to do. Polyset means to use the polygons in that group
        # as solids, while Sphere tells panda to make a collision sphere around them
        # Keep means to keep the polygons in the group as visable geometry (good
        # for the ball, not for the triggers), and descend means to make sure that
        # the settings are applied to any subgroups.
        #
        # Once we have the collision tags in the models, we can get to them using
        # NodePath's find command

        # Find the collision node named wall_collide
        #self.walls = self.maze.find("**/wall_collide")
        self.walls = self.maze.find("**/wall_col")

        # Collision objects are sorted using BitMasks. BitMasks are ordinary numbers
        # with extra methods for working with them as binary bits. Every collision
        # solid has both a from mask and an into mask. Before Panda tests two
        # objects, it checks to make sure that the from and into collision masks
        # have at least one bit in common. That way things that shouldn't interact
        # won't. Normal model nodes have collision masks as well. By default they
        # are set to bit 20. If you want to collide against actual visable polygons,
        # set a from collide mask to include bit 20
        #
        # For this example, we will make everything we want the ball to collide with
        # include bit 0
        self.walls.node().setIntoCollideMask(BitMask32.bit(0))
        # CollisionNodes are usually invisible but can be shown. Uncomment the next
        # line to see the collision walls
        #self.walls.show() # Show wall colliders

        # We will now find the triggers for the holes and set their masks to 0 as
        # well. We also set their names to make them easier to identify during
        # collisions

        self.loseTriggers = []
        #for i in range(6):
        for i in range(3):
            #trigger = self.maze.find("**/hole_collide" + str(i))
            trigger = self.maze.find("**/hole" + str(i + 1) + "_col")
            trigger.node().setIntoCollideMask(BitMask32.bit(0))
            trigger.node().setName("loseTrigger")
            self.loseTriggers.append(trigger)
            # Uncomment this line to see the triggers
            #trigger.show() # Show lose triggers colliders

        # Ground_collide is a single polygon on the same plane as the ground in the
        # maze. We will use a ray to collide with it so that we will know exactly
        # what height to put the ball at every frame. Since this is not something
        # that we want the ball itself to collide with, it has a different
        # bitmask.
        #self.mazeGround = self.maze.find("**/ground_collide")
        self.mazeGround = self.maze.find("**/ground_col")
        self.mazeGround.node().setIntoCollideMask(BitMask32.bit(1))

        # Load the ball and attach it to the scene
        # It is on a root dummy node so that we can rotate the ball itself without
        # rotating the ray that will be attached to it
        self.ballRoot = render.attachNewNode("ballRoot")
        self.ball = loader.loadModel("models/bball")
        self.ball.reparentTo(self.ballRoot)

        # Find the collison sphere for the ball which was created in the egg file
        # Notice that it has a from collision mask of bit 0, and an into collison
        # mask of no bits. This means that the ball can only cause collisions, not
        # be collided into
        self.ballSphere = self.ball.find("**/ball")
        self.ballSphere.node().setFromCollideMask(BitMask32.bit(0))
        self.ballSphere.node().setIntoCollideMask(BitMask32.allOff())

        # No we create a ray to start above the ball and cast down. This is to
        # Determine the height the ball should be at and the angle the floor is
        # tilting. We could have used the sphere around the ball itself, but it
        # would not be as reliable
        self.ballGroundRay = CollisionRay()  # Create the ray
        self.ballGroundRay.setOrigin(0, 0, 10)  # Set its origin
        self.ballGroundRay.setDirection(0, 0, -1)  # And its direction
        # Collision solids go in CollisionNode
        # Create and name the node
        self.ballGroundCol = CollisionNode('groundRay')
        self.ballGroundCol.addSolid(self.ballGroundRay)  # Add the ray
        self.ballGroundCol.setFromCollideMask(
            BitMask32.bit(1))  # Set its bitmasks
        self.ballGroundCol.setIntoCollideMask(BitMask32.allOff())
        # Attach the node to the ballRoot so that the ray is relative to the ball
        # (it will always be 10 feet over the ball and point down)
        self.ballGroundColNp = self.ballRoot.attachNewNode(self.ballGroundCol)
        # Uncomment this line to see the ray
        #self.ballGroundColNp.show()  # Show ball collision ray

        # Finally, we create a CollisionTraverser. CollisionTraversers are what
        # do the job of walking the scene graph and calculating collisions.
        # For a traverser to actually do collisions, you need to call
        # traverser.traverse() on a part of the scene. Fortunately, ShowBase
        # has a task that does this for the entire scene once a frame.  By
        # assigning it to self.cTrav, we designate that this is the one that
        # it should call traverse() on each frame.
        self.cTrav = CollisionTraverser()

        # Collision traversers tell collision handlers about collisions, and then
        # the handler decides what to do with the information. We are using a
        # CollisionHandlerQueue, which simply creates a list of all of the
        # collisions in a given pass. There are more sophisticated handlers like
        # one that sends events and another that tries to keep collided objects
        # apart, but the results are often better with a simple queue
        self.cHandler = CollisionHandlerQueue()
        # Now we add the collision nodes that can create a collision to the
        # traverser. The traverser will compare these to all others nodes in the
        # scene. There is a limit of 32 CollisionNodes per traverser
        # We add the collider, and the handler to use as a pair
        self.cTrav.addCollider(self.ballSphere, self.cHandler)
        self.cTrav.addCollider(self.ballGroundColNp, self.cHandler)

        # Collision traversers have a built in tool to help visualize collisions.
        # Uncomment the next line to see it.
        #self.cTrav.showCollisions(render)  # Show traveser collisions

        # This section deals with lighting for the ball. Only the ball was lit
        # because the maze has static lighting pregenerated by the modeler
        self.alightColor = 0.1
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(
            (self.alightColor, self.alightColor, self.alightColor, 1))
        #ambientLight.setColor((1, 0, 0, 1))
        self.ambientL = render.attachNewNode(ambientLight)
        render.setLight(self.ambientL)
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 1, 0))
        #directionalLight.setColor((0.375, 0.375, 0.375, 1))
        directionalLight.setColor((1, 1, 1, 1))
        directionalLight.setSpecularColor((1, 1, 1, 1))
        #self.directL = render.attachNewNode(directionalLight)
        #render.setLight(self.directL)
        """
        self.teapot = loader.loadModel('teapot')
        self.teapot.reparentTo(render)
        self.teapot.setPos(0, 0, 0)
        self.teapotMovement = self.teapot.hprInterval(50, LPoint3(0, 360, 360))
        self.teapotMovement.loop()
        """

        self.lightColor = 1000
        self.light = render.attachNewNode(Spotlight("Spot"))
        self.light.node().setScene(render)
        self.light.node().setShadowCaster(True, 1024, 1024)
        self.light.node().setAttenuation((1, 0, 1))
        #self.light.node().showFrustum()
        self.light.node().getLens().setFov(48)
        self.light.node().getLens().setNearFar(5, 500)
        #self.light.node().setColor((100000, 100000, 100000, 1))
        self.light.node().setColor(
            (self.lightColor, self.lightColor, self.lightColor, 1))
        self.light.setPos(0, 0, 100)
        self.light.setHpr(LVector3(0, -90, 0))
        render.setLight(self.light)

        plight = PointLight('plight')
        plight.setColor((0.8, 0.8, 0.8, 1))
        plnp = render.attachNewNode(plight)
        plnp.setPos(0, 0, 80)
        render.setLight(plnp)

        render.setShaderAuto()

        #self.maze2.setPos(0, 0, 10)

        #self.ballRoot.setLight(render.attachNewNode(ambientLight))
        #self.ballRoot.setLight(render.attachNewNode(directionalLight))

        # Maze 2 light
        #self.maze2.setLight(self.light)
        #self.maze2.setLight(self.ambientL)
        #self.maze2.hide()
        #self.maze.hide()

        # This section deals with adding a specular highlight to the ball to make
        # it look shiny.  Normally, this is specified in the .egg file.
        m = Material()
        m.setSpecular((1, 1, 1, 1))
        m.setShininess(96)
        self.ball.setMaterial(m, 1)

        #self.maze2.setMaterial(m,1)

        # Set maze rotation speed
        self.mazeSpeed = 10
        self.mazeVoiceSpeed = 8

        # Set maze max rotation
        self.mazeMaxRotation = 10
        self.mazeVoiceMaxRotation = 10

        # Distància minima per passar al següent punt
        self.minDist = 25
        # Pas per saltar punts del path
        self.pas = 25

        base.setBackgroundColor(0.2, 0.2, 0.2)

        self.camera2_buffer = base.win.makeTextureBuffer("c2buffer",
                                                         PI_CAMERA_RES,
                                                         PI_CAMERA_RES,
                                                         to_ram=True)
        #mytexture.write("text1.png")
        # print(mytexture)
        # cv2.imshow("Texure1", mytexture)
        #self.camera2_buffer.setSort(-100)
        self.camera2 = base.makeCamera(self.camera2_buffer)
        self.camera2.reparentTo(render)

        self.camera2.setPosHpr(0, 0, PI_CAMERA_H, 0, -90, 0)
        self.camera2.node().getLens().setFov(PI_CAMERA_FOV)
        self.camera2.node().getLens().setFilmSize(1, 1)

        self.digitizer = Digitizer()
        self.aStar = aStar()
        self.path = None

        self.ready_to_solve = False

        # Finally, we call start for more initialization
        self.start()

    def start(self):
        # The maze model also has a locator in it for where to start the ball
        # To access it we use the find command
        #startPos = self.maze.find("**/start").getPos()
        startPos = (MAZES_START_POS[self.maze_i][0],
                    MAZES_START_POS[self.maze_i][1], MAZE_HEIGHT + BALL_OFFSET)
        self.ballRoot.setPos(startPos)

        if not self.ready_to_solve:
            self.ballRoot.hide()

        self.pid = pid(startPos[0], startPos[1])
        # INICIALITZAR A* AMB LABERINT HARDCODEJAT, S'HA DE CANVIAR

        # ----------- self.path_matrix, self.path = self.aStar.a_star(laberint, 26, 10, 465, 448, 89, 461) -----------------

        self.indexPuntActual = 0

        self.ballV = LVector3(0, 0, 0)  # Initial velocity is 0
        self.accelV = LVector3(0, 0, 0)  # Initial acceleration is 0

        # Create the movement task, but first make sure it is not already
        # running
        taskMgr.remove("rollTask")
        self.mainLoop = taskMgr.add(self.rollTask, "rollTask")

    # This function handles the collision between the ray and the ground
    # Information about the interaction is passed in colEntry
    def groundCollideHandler(self, colEntry):
        # Set the ball to the appropriate Z value for it to be exactly on the
        # ground
        newZ = colEntry.getSurfacePoint(render).getZ()
        #self.ballRoot.setZ(newZ + .4)
        self.ballRoot.setZ(newZ + 1.4)
        # Find the acceleration direction. First the surface normal is crossed with
        # the up vector to get a vector perpendicular to the slope
        norm = colEntry.getSurfaceNormal(render)
        accelSide = norm.cross(LVector3.up())
        # Then that vector is crossed with the surface normal to get a vector that
        # points down the slope. By getting the acceleration in 3D like this rather
        # than in 2D, we reduce the amount of error per-frame, reducing jitter
        self.accelV = norm.cross(accelSide)

    # This function handles the collision between the ball and a wall
    def wallCollideHandler(self, colEntry):
        # First we calculate some numbers we need to do a reflection
        norm = colEntry.getSurfaceNormal(render) * -1  # The normal of the wall
        curSpeed = self.ballV.length()  # The current speed
        inVec = self.ballV / curSpeed  # The direction of travel
        velAngle = norm.dot(inVec)  # Angle of incidance
        hitDir = colEntry.getSurfacePoint(render) - self.ballRoot.getPos()
        hitDir.normalize()
        # The angle between the ball and the normal
        hitAngle = norm.dot(hitDir)

        # Ignore the collision if the ball is either moving away from the wall
        # already (so that we don't accidentally send it back into the wall)
        # and ignore it if the collision isn't dead-on (to avoid getting caught on
        # corners)
        if velAngle > 0 and hitAngle > .995:
            # Standard reflection equation
            reflectVec = (norm * norm.dot(inVec * -1) * 2) + inVec

            # This makes the velocity half of what it was if the hit was dead-on
            # and nearly exactly what it was if this is a glancing blow
            self.ballV = reflectVec * (curSpeed * (((1 - velAngle) * .5) + .5))
            # Since we have a collision, the ball is already a little bit buried in
            # the wall. This calculates a vector needed to move it so that it is
            # exactly touching the wall
            disp = (colEntry.getSurfacePoint(render) -
                    colEntry.getInteriorPoint(render))
            newPos = self.ballRoot.getPos() + disp
            self.ballRoot.setPos(newPos)

    def rotateMaze(self, p, r):
        maxRot = self.mazeMaxRotation
        maxVel = self.mazeSpeed
        if voice_solving:
            maxRot = self.mazeVoiceMaxRotation
            maxVel = self.mazeVoiceSpeed

        if self.ready_to_solve:
            dt = globalClock.getDt()
            if r != 0 or p != 0:
                self.maze.setR(self.maze, r * maxVel * dt)

                self.maze.setP(self.maze, p * maxVel * dt)

                # Check bounds
                if self.maze.getR() > maxRot:
                    self.maze.setR(maxRot)
                elif self.maze.getR() < -maxRot:
                    self.maze.setR(-maxRot)

                if self.maze.getP() > maxRot:
                    self.maze.setP(maxRot)
                elif self.maze.getP() < -maxRot:
                    self.maze.setP(-maxRot)

                self.laso_ax.setP(self.maze.getP())

                self.maze.setH(0)
                self.laso_ax.setH(0)
                self.laso_ax.setR(0)

    def solve(self):

        # PI CAMERA PHOTO
        screenshot = self.camera2_buffer.getScreenshot()
        if screenshot:
            img = np.asarray(screenshot.getRamImage(), dtype=np.uint8).copy()
            img = img.reshape(
                (screenshot.getYSize(), screenshot.getXSize(), 4))
            img = img[::-1]
            img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)

            self.digitizer.set_src_img(img)
            self.digitizer.digitize_source()
            print("solve!!")

            trobat = False

            radi = 30
            m_seg = 20

            while trobat == False:
                trobat, self.pm, self.path = self.aStar.a_star(
                    self.digitizer.source_mask.copy(), radi, int(m_seg),
                    self.digitizer.startPos[1], self.digitizer.startPos[0],
                    self.digitizer.endPos[1], self.digitizer.endPos[0])
                radi = max(radi - 1, 0)
                m_seg = max(m_seg - 0.5, 0)
                print(radi, m_seg)

            #print(self.pm)

            self.pathFollowed = np.zeros(self.pm.shape)

            check_result = cv2.addWeighted(
                self.digitizer.source_img_g.astype('uint8'), 0.5,
                np.clip(self.pm * 255, 0, 255).astype('uint8'), 0.5, 1)
            cv2.imshow("laberint resolt sobre original", check_result)

            self.ready_to_solve = True
            self.ballRoot.show()
            # cv2.imshow('img', img)
            # cv2.waitKey(0)

    def get_ball_position(self):
        # PI CAMERA PHOTO
        #startTime = time.time()
        screenshot = self.camera2_buffer.getScreenshot()
        if screenshot:
            #v = memoryview(screenshot.getRamImage()).tolist()
            img = np.asarray(screenshot.getRamImage(), dtype=np.uint8).copy()
            img = img.reshape(
                (screenshot.getYSize(), screenshot.getXSize(), 4))
            img = img[::-1]
            img = img[:, :, :3]
        #self.camera2_buffer.saveScreenshot("ts.jpg")
        #img = cv2.imread("ts.jpg", 1)

        #img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)

        pos = self.digitizer.get_ball_pos(img)

        if pos is not False:
            pos = pos.astype(np.int32)

            self.pathFollowed[pos[0] - 1:pos[0] + 2, pos[1] - 1:pos[1] + 2] = 1

            img[self.pm == 1] = 0
            img[self.pm == 1, 2] = 255

            img[self.pathFollowed == 1] = 0
            img[self.pathFollowed == 1, 1] = 255

            #print(pos)

            img[pos[0] - 2:pos[0] + 3, pos[1] - 2:pos[1] + 3] = 0

            posActual = self.path[self.indexPuntActual]

            img[posActual[0] - 2:posActual[0] + 3,
                posActual[1] - 2:posActual[1] + 3] = 255

            cv2.imshow('img', img)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                pass

            #if pos is not None:
            #print("BALL POSITION: ", pos)
            #check_res = cv2.circle(self.digitizer.source_img, (int(pos[0]), int(pos[1])), 24, (0, 0, 255))
            #cv2.imshow("BALL POS RES", check_res)
        return pos

    # This is the task that deals with making everything interactive
    def rollTask(self, task):
        # Standard technique for finding the amount of time since the last
        # frame
        #print("\r",self.maze.getR(), self.maze.getP(), self.ballRoot.getPos(), end="")

        dt = globalClock.getDt()
        print("\r{:.3} fps      ".format(1 / dt), end="")

        # If dt is large, then there has been a # hiccup that could cause the ball
        # to leave the field if this functions runs, so ignore the frame
        if dt > .2:
            return Task.cont

        #print(action)
        if action == "start":
            a = 1

        elif action == "stop":
            while action == "stop":
                a = 0

    # elif action == "restart": in Line 531

        elif action == "coord":
            a = 1
            #ALGUNA CRIDA A METODE DE NARCIS/MARC

        key_down = base.mouseWatcherNode.is_button_down

        if self.ready_to_solve:

            if key_down(KeyboardButton.ascii_key('d')):
                screenshot = self.camera2_buffer.getScreenshot()
                if screenshot:
                    v = memoryview(screenshot.getRamImage()).tolist()
                    img = np.array(v, dtype=np.uint8)
                    img = img.reshape(
                        (screenshot.getYSize(), screenshot.getXSize(), 4))
                    img = img[::-1]
                    #self.digitizer.set_src_img(img)
                    #self.digitizer.digitalize_source()
                    cv2.imshow('img', img)
                    #cv2.waitKey(0)

            if key_down(KeyboardButton.ascii_key('s')):
                print("Screenshot!")
                self.camera2_buffer.saveScreenshot("screenshot.jpg")

            # The collision handler collects the collisions. We dispatch which function
            # to handle the collision based on the name of what was collided into
            for i in range(self.cHandler.getNumEntries()):
                entry = self.cHandler.getEntry(i)
                name = entry.getIntoNode().getName()
                if action == "restart":
                    self.loseGame(entry)
                if name == "wall_col":
                    self.wallCollideHandler(entry)
                elif name == "ground_col":
                    self.groundCollideHandler(entry)
                elif name == "loseTrigger":
                    vr.restart = 1
                    global th
                    th = threading.Thread(target=listenVoice)
                    th.start()
                    self.loseGame(entry)

            # Read the mouse position and tilt the maze accordingly
            # Rotation axes use (roll, pitch, heave)
            """
            if base.mouseWatcherNode.hasMouse():
                mpos = base.mouseWatcherNode.getMouse()  # get the mouse position
                self.maze.setP(mpos.getY() * -10)
                self.maze.setR(mpos.getX() * 10)
            """

            ballPos = self.get_ball_position()
            #print("BALL POS: ", ballPos)

            posFPixel = self.path[self.indexPuntActual]

            xFinal = posFPixel[1]  #posFPixel[1]/np.shape(laberint)[0]*13 - 6.5
            yFinal = posFPixel[
                0]  #-(posFPixel[0]/np.shape(laberint)[1]*13.5 - 6.8)

            dist = math.sqrt((xFinal - ballPos[1])**2 +
                             (yFinal - ballPos[0])**2)

            if (dist < self.minDist):
                if (self.indexPuntActual == len(self.path) - 1):
                    print("SOLVED!!", end="")

                while (self.aStar.distance(
                    (ballPos[0], ballPos[1]), self.path[self.indexPuntActual])
                       < self.pas):
                    if (self.indexPuntActual < len(self.path) - 1):
                        self.indexPuntActual += 1
                    else:
                        break

            # ball pos (y,x)

            #print("END POS: ", self.digitizer.endPos)

            if voice_solving:
                p_rotation = dir_veu[0]
                r_rotation = dir_veu[1]
                if p_rotation == 0 and r_rotation == 0 and ballPos is not None:
                    p_rotation, r_rotation = self.pid.getPR(
                        ballPos[1], ballPos[0], ballPos[1], ballPos[0],
                        self.maze.getP(), self.maze.getR(), dt)

            else:
                p_rotation = 0
                r_rotation = 0
                #print(ballPos, dist)

                #print(ballPos)

                if ballPos is not None:

                    p_rotation, r_rotation = self.pid.getPR(
                        ballPos[1], ballPos[0], xFinal, yFinal,
                        self.maze.getP(), self.maze.getR(), dt)
                    #print(p_rotation, r_rotation)

            if key_down(KeyboardButton.up()):
                p_rotation = -1
            elif key_down(KeyboardButton.down()):
                p_rotation = 1

            if key_down(KeyboardButton.left()):
                r_rotation = -1
            elif key_down(KeyboardButton.right()):
                r_rotation = 1

            self.rotateMaze(p_rotation, r_rotation)

            # Finally, we move the ball
            # Update the velocity based on acceleration
            self.ballV += self.accelV * dt * ACCEL
            # Clamp the velocity to the maximum speed
            if self.ballV.lengthSquared() > MAX_SPEED_SQ:
                self.ballV.normalize()
                self.ballV *= MAX_SPEED
            # Update the position based on the velocity
            self.ballRoot.setPos(self.ballRoot.getPos() + (self.ballV * dt))
            #print(self.ballRoot.getPos())

            # This block of code rotates the ball. It uses something called a quaternion
            # to rotate the ball around an arbitrary axis. That axis perpendicular to
            # the balls rotation, and the amount has to do with the size of the ball
            # This is multiplied on the previous rotation to incrimentally turn it.
            prevRot = LRotationf(self.ball.getQuat())
            axis = LVector3.up().cross(self.ballV)
            newRot = LRotationf(axis, 45.5 * dt * self.ballV.length())
            self.ball.setQuat(prevRot * newRot)

        elif key_down(KeyboardButton.ascii_key('1')):
            self.solve()

        if key_down(KeyboardButton.ascii_key('i')):
            self.light.setY(self.light.getY() + 10 * dt)
        elif key_down(KeyboardButton.ascii_key('k')):
            self.light.setY(self.light.getY() - 10 * dt)

        if key_down(KeyboardButton.ascii_key('j')):
            self.light.setX(self.light.getX() - 10 * dt)
        elif key_down(KeyboardButton.ascii_key('l')):
            self.light.setX(self.light.getX() + 10 * dt)

        if key_down(KeyboardButton.ascii_key('u')):
            self.lightColor += 10000 * dt
            self.light.node().setColor(
                (self.lightColor, self.lightColor, self.lightColor, 1))
        elif key_down(KeyboardButton.ascii_key('o')):
            self.lightColor -= 10000 * dt
            self.light.node().setColor(
                (self.lightColor, self.lightColor, self.lightColor, 1))

        if key_down(KeyboardButton.ascii_key('8')):
            self.alightColor += 1 * dt
            self.ambientL.node().setColor(
                (self.alightColor, self.alightColor, self.alightColor, 1))
        elif key_down(KeyboardButton.ascii_key('9')):
            self.alightColor -= 1 * dt
            self.ambientL.node().setColor(
                (self.alightColor, self.alightColor, self.alightColor, 1))

        if key_down(KeyboardButton.ascii_key('r')):
            base.trackball.node().set_pos(0, 200, 0)
            base.trackball.node().set_hpr(0, 60, 0)

        return Task.cont  # Continue the task indefinitely

    # If the ball hits a hole trigger, then it should fall in the hole.
    # This is faked rather than dealing with the actual physics of it.

    def loseGame(self, entry):
        # The triggers are set up so that the center of the ball should move to the
        # collision point to be in the hole
        global action
        action = "start"
        toPos = entry.getInteriorPoint(render)
        taskMgr.remove('rollTask')  # Stop the maze task
        self.pathFollowed = np.zeros(self.pm.shape)
        self.maze.setP(0)
        self.maze.setR(0)

        # Move the ball into the hole over a short sequence of time. Then wait a
        # second and call start to reset the game
        Sequence(
            Parallel(
                LerpFunc(self.ballRoot.setX,
                         fromData=self.ballRoot.getX(),
                         toData=toPos.getX(),
                         duration=.1),
                LerpFunc(self.ballRoot.setY,
                         fromData=self.ballRoot.getY(),
                         toData=toPos.getY(),
                         duration=.1),
                LerpFunc(self.ballRoot.setZ,
                         fromData=self.ballRoot.getZ(),
                         toData=self.ballRoot.getZ() - .9,
                         duration=.2)), Wait(1), Func(self.start)).start()

    def toggleInterval(self, ival):
        if ival.isPlaying():
            ival.pause()
        else:
            ival.resume()

    def shaderSupported(self):
        return base.win.getGsg().getSupportsBasicShaders() and \
               base.win.getGsg().getSupportsDepthTexture() and \
               base.win.getGsg().getSupportsShadowFilter()
예제 #49
0
    def makeCrunchTrack(self):
        toonId = self.toon

        toon = base.cr.doId2do.get(toonId)
        if not toon:
            return

        self.virtualSuit.lookAt(toon)

        if self.virtualSuit.style.body in ['a', 'b']:
            throwDelay = 3
        elif self.virtualSuit.style.body == 'c':
            throwDelay = 2.3
        else:
            throwDelay = 2

        numberNames = ['one', 'two', 'three', 'four', 'five', 'six']
        BattleParticles.loadParticles()
        numberSpill1 = BattleParticles.createParticleEffect(file='numberSpill')
        numberSpill2 = BattleParticles.createParticleEffect(file='numberSpill')
        spillTexture1 = random.choice(numberNames)
        spillTexture2 = random.choice(numberNames)
        BattleParticles.setEffectTexture(numberSpill1,
                                         'audit-' + spillTexture1)
        BattleParticles.setEffectTexture(numberSpill2,
                                         'audit-' + spillTexture2)
        numberSpillTrack1 = getPartTrack(numberSpill1, 1.1, 2.2,
                                         [numberSpill1, self.virtualSuit, 0])
        numberSpillTrack2 = getPartTrack(numberSpill2, 1.5, 1.0,
                                         [numberSpill2, self.virtualSuit, 0])
        numberSprayTracks = Parallel()
        numOfNumbers = random.randint(5, 9)
        for i in xrange(0, numOfNumbers - 1):
            nextSpray = BattleParticles.createParticleEffect(
                file='numberSpray')
            nextTexture = random.choice(numberNames)
            BattleParticles.setEffectTexture(nextSpray, 'audit-' + nextTexture)
            nextStartTime = random.random() * 0.6 + 3.03
            nextDuration = random.random() * 0.4 + 1.4
            nextSprayTrack = getPartTrack(nextSpray, nextStartTime,
                                          nextDuration,
                                          [nextSpray, self.virtualSuit, 0])
            numberSprayTracks.append(nextSprayTrack)

        def throwProp(prop):
            if not self.virtualSuit:
                return

            toon = self.cr.doId2do.get(toonId)
            if not toon:
                self.cleanupProp(prop, False)
                self.finishPropAttack()
                return

            self.virtualSuit.lookAt(toon)

            prop.wrtReparentTo(render)

            hitPos = toon.getPos() + Vec3(0, 0, 2.5)
            distance = (prop.getPos() - hitPos).length()
            speed = 50.0

            throwSequence = Sequence(
                prop.posInterval(distance / speed, hitPos),
                Func(self.cleanupProp, prop, False))

            throwSequence.start()

        numberTracks = Parallel()
        for i in xrange(0, numOfNumbers):
            texture = random.choice(numberNames)
            next = copyProp(BattleParticles.getParticle('audit-' + texture))
            next.reparentTo(self.virtualSuit.getRightHand())
            next.setScale(0.01, 0.01, 0.01)
            next.setColor(Vec4(0.0, 0.0, 0.0, 1.0))
            next.setPos(random.random() * 0.6 - 0.3,
                        random.random() * 0.6 - 0.3,
                        random.random() * 0.6 - 0.3)
            next.setHpr(VBase3(-1.15, 86.58, -76.78))

            # Make prop virtual:
            next.setColorScale(1.0, 0.0, 0.0, 0.8)
            next.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))

            # Prop collisions:
            colNode = CollisionNode(self.uniqueName('SuitAttack'))
            colNode.setTag('damage', str(self.attackInfo[1]))

            bounds = next.getBounds()
            center = bounds.getCenter()
            radius = bounds.getRadius()
            sphere = CollisionSphere(center.getX(), center.getY(),
                                     center.getZ(), radius)
            sphere.setTangible(0)
            colNode.addSolid(sphere)
            colNode.setIntoCollideMask(WallBitmask)
            next.attachNewNode(colNode)

            numberTrack = Sequence(
                Wait(throwDelay),
                Parallel(
                    LerpScaleInterval(next, 0.6, Point3(1.0, 1.0, 1.0)),
                    Func(throwProp, next),
                ),
            )
            numberTracks.append(numberTrack)

            suitTrack = Parallel(
                Func(self.sayFaceoffTaunt),
                Sequence(ActorInterval(self.virtualSuit, 'throw-object'),
                         ActorInterval(self.virtualSuit, 'neutral')),
            )

            return Sequence(
                Parallel(suitTrack, numberSpillTrack1, numberSpillTrack2,
                         numberTracks, numberSprayTracks),
                Func(self.virtualSuit.loop, 'walk', 0),
                Func(self.virtualSuit.setHpr, 0, 0, 0),
            )
예제 #50
0
파일: polls.py 프로젝트: yglkings/PlaneNet
class BallInMazeDemo(ShowBase):
    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)
        base.setBackgroundColor(0, 0, 0)

        self.accept("escape", sys.exit)  # Escape quits
        self.disableMouse()
        camera.setPosHpr(0, 0, 0, 0, 0, 0)

        lens = PerspectiveLens()
        lens.setFov(90, 60)
        lens.setNear(0.01)
        lens.setFar(100000)
        self.cam.node().setLens(lens)

        self.ballSize = 0.025
        self.cueLength = 0.2
        # self.ballRoot = render.attachNewNode("ballRoot")
        # #self.ball = loader.loadModel("models/ball")
        # self.ball = loader.loadModel("models/ball_0_center.egg")
        # #self.ball = loader.loadModel("models/ball.dae")
        # self.ball.setScale(ballSize, ballSize, ballSize)
        # self.ball.reparentTo(self.ballRoot)
        # #print(self.ball.getBounds())
        # #exit(1)
        # #self.ballSphere = self.ball.find("**/ball")
        # #print(self.ball.getScale()[0])
        # cs = CollisionSphere(0, 0, 0, 1)
        # self.ballSphere = self.ball.attachNewNode(CollisionNode('ball'))
        # self.ballSphere.node().addSolid(cs)

        # self.ballSphere.node().setFromCollideMask(BitMask32.bit(0))
        # self.ballSphere.node().setIntoCollideMask(BitMask32.bit(1))

        self.sceneIndex = 2
        self.planeInfo = PlaneScene(self.sceneIndex)

        self.planeScene = self.planeInfo.generateEggModel()
        self.planeScene.setTwoSided(True)
        self.planeScene.reparentTo(render)
        self.planeScene.hide()

        planeTriangles, horizontalPlaneTriangles, self.gravityDirection = self.planeInfo.getPlaneTriangles(
        )

        self.ballRoots = []
        self.balls = []
        self.ballSpheres = []
        self.ballGroundRays = []
        for ballIndex in xrange(3):
            ballRoot = render.attachNewNode("ballRoot_" + str(ballIndex))
            ball = loader.loadModel("models/ball_" + str(ballIndex) +
                                    "_center.egg")
            ball.setScale(self.ballSize, self.ballSize, self.ballSize)

            cs = CollisionSphere(0, 0, 0, 1)
            ballSphere = ball.attachNewNode(
                CollisionNode('ball_' + str(ballIndex)))
            ballSphere.node().addSolid(cs)
            ballSphere.node().setFromCollideMask(
                BitMask32.bit(0) | BitMask32.bit(1) | BitMask32.bit(3)
                | BitMask32.bit(4))
            ballSphere.node().setIntoCollideMask(BitMask32.bit(1))

            ball.reparentTo(ballRoot)
            self.ballRoots.append(ballRoot)
            self.balls.append(ball)
            self.ballSpheres.append(ballSphere)

            ballGroundRay = CollisionRay()  # Create the ray
            ballGroundRay.setOrigin(0, 0, 0)  # Set its origin
            ballGroundRay.setDirection(
                self.gravityDirection[0], self.gravityDirection[1],
                self.gravityDirection[2])  # And its direction
            # Collision solids go in CollisionNode
            # Create and name the node
            ballGroundCol = CollisionNode('ball_ray_' + str(ballIndex))
            ballGroundCol.addSolid(ballGroundRay)  # Add the ray
            ballGroundCol.setFromCollideMask(
                BitMask32.bit(2))  # Set its bitmasks
            ballGroundCol.setIntoCollideMask(BitMask32.allOff())
            # Attach the node to the ballRoot so that the ray is relative to the ball
            # (it will always be 10 feet over the ball and point down)
            ballGroundColNp = ballRoot.attachNewNode(ballGroundCol)
            self.ballGroundRays.append(ballGroundColNp)

            ballRoot.hide()
            continue

        # Finally, we create a CollisionTraverser. CollisionTraversers are what
        # do the job of walking the scene graph and calculating collisions.
        # For a traverser to actually do collisions, you need to call
        # traverser.traverse() on a part of the scene. Fortunately, ShowBase
        # has a task that does this for the entire scene once a frame.  By
        # assigning it to self.cTrav, we designate that this is the one that
        # it should call traverse() on each frame.
        self.cTrav = CollisionTraverser()

        # Collision traversers tell collision handlers about collisions, and then
        # the handler decides what to do with the information. We are using a
        # CollisionHandlerQueue, which simply creates a list of all of the
        # collisions in a given pass. There are more sophisticated handlers like
        # one that sends events and another that tries to keep collided objects
        # apart, but the results are often better with a simple queue
        self.cHandler = CollisionHandlerQueue()
        # Now we add the collision nodes that can create a collision to the
        # traverser. The traverser will compare these to all others nodes in the
        # scene. There is a limit of 32 CollisionNodes per traverser
        # We add the collider, and the handler to use as a pair

        #self.cTrav.addCollider(self.ballSphere, self.cHandler)
        for ballSphere in self.ballSpheres:
            self.cTrav.addCollider(ballSphere, self.cHandler)
            continue
        for ballGroundRay in self.ballGroundRays:
            self.cTrav.addCollider(ballGroundRay, self.cHandler)
            continue
        #self.cTrav.addCollider(self.ballGroundColNp, self.cHandler)

        # Collision traversers have a built in tool to help visualize collisions.
        # Uncomment the next line to see it.
        #self.cTrav.showCollisions(render)

        # This section deals with lighting for the ball. Only the ball was lit
        # because the maze has static lighting pregenerated by the modeler
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.55, .55, .55, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 0, -1))
        directionalLight.setColor((0.375, 0.375, 0.375, 1))
        directionalLight.setSpecularColor((1, 1, 1, 1))

        for ballRoot in self.ballRoots:
            ballRoot.setLight(render.attachNewNode(ambientLight))
            ballRoot.setLight(render.attachNewNode(directionalLight))
            continue

        # This section deals with adding a specular highlight to the ball to make
        # it look shiny.  Normally, this is specified in the .egg file.
        m = Material()
        m.setSpecular((1, 1, 1, 1))
        m.setShininess(96)
        for ball in self.balls:
            ball.setMaterial(m, 1)
            continue

        self.original = False
        if self.original:
            camera.setPosHpr(0, 0, 25, 0, -90, 0)
            self.maze = loader.loadModel("models/maze")
            self.maze.reparentTo(render)
            self.walls = self.maze.find("**/wall_collide")
            self.walls.node().setIntoCollideMask(BitMask32.bit(0))
            self.walls.show()
            pass

        #planeTriangles, planeNormals = self.planeInfo.getPlaneGeometries()

        self.triNPs = []
        for triangleIndex, triangle in enumerate(planeTriangles):
            #print(triangleIndex)
            #for triangle in triangles:
            #print(triangle)
            tri = CollisionPolygon(
                Point3(triangle[0][0], triangle[0][1], triangle[0][2]),
                Point3(triangle[1][0], triangle[1][1], triangle[1][2]),
                Point3(triangle[2][0], triangle[2][1], triangle[2][2]))
            triNP = render.attachNewNode(
                CollisionNode('tri_' + str(triangleIndex)))
            triNP.node().setIntoCollideMask(BitMask32.bit(0))
            triNP.node().addSolid(tri)
            self.triNPs.append(triNP)
            #triNP.show()
            continue

        #print(horizontalPlaneTriangles)

        for triangleIndex, triangle in enumerate(horizontalPlaneTriangles):
            #print(triangleIndex)
            #for triangle in triangles:
            #print(triangle)
            tri = CollisionPolygon(
                Point3(triangle[0][0], triangle[0][1], triangle[0][2]),
                Point3(triangle[1][0], triangle[1][1], triangle[1][2]),
                Point3(triangle[2][0], triangle[2][1], triangle[2][2]))
            triNP = render.attachNewNode(
                CollisionNode('ground_' + str(triangleIndex)))
            triNP.node().setIntoCollideMask(BitMask32.bit(2))
            triNP.node().addSolid(tri)
            self.triNPs.append(triNP)
            #triNP.show()
            continue

        # tri = CollisionPolygon(Point3(-1, 4, -1), Point3(2, 4, -1), Point3(2, 4, 2))
        # triNP = render.attachNewNode(CollisionNode('tri'))
        # triNP.node().setIntoCollideMask(BitMask32.bit(0))
        # triNP.node().addSolid(tri)
        # triNP.show()

        #self.planeScene.node().setIntoCollideMask(BitMask32.bit(0))
        # roomRootNP = self.planeScene
        # roomRootNP.flattenLight()
        # mesh = BulletTriangleMesh()
        # polygons = roomRootNP.findAllMatches("**/+GeomNode")

        # # p0 = Point3(-10, 4, -10)
        # # p1 = Point3(-10, 4, 10)
        # # p2 = Point3(10, 4, 10)
        # # p3 = Point3(10, 4, -10)
        # # mesh.addTriangle(p0, p1, p2)
        # # mesh.addTriangle(p1, p2, p3)

        # print(polygons)
        # for polygon in polygons:
        #     geom_node = polygon.node()
        #     #geom_node.reparentTo(self.render)
        #     #print(geom_node.getNumGeoms())
        #     ts = geom_node.getTransform()
        #     #print(ts)
        #     for geom in geom_node.getGeoms():
        #         mesh.addGeom(geom, ts)
        #         continue
        #     continue
        # #self.scene = roomRootNP
        # shape = BulletTriangleMeshShape(mesh, dynamic=False)
        # #shape = BulletPlaneShape(Vec3(0, 0, 1), 1)
        # room = BulletRigidBodyNode('scene')
        # room.addShape(shape)
        # #room.setLinearDamping(0.0)
        # #room.setFriction(0.0)
        # print(shape)
        # room.setDeactivationEnabled(False)
        # roomNP = render.attachNewNode(room)
        # roomNP.setPos(0, 0, 0)
        # roomNP.node().setIntoCollideMask(BitMask32.bit(0))
        # self.world = BulletWorld()
        # self.world.setGravity(Vec3(0, 0, 0))
        # self.world.attachRigidBody(roomNP.node())
        #room.setRestitution(1)

        #self.roomNP = self.scene

        self.cueRoot = render.attachNewNode("cueRoot")
        self.cue = loader.loadModel("models/cue_center.egg")
        self.cue.setScale(self.cueLength * 3, self.cueLength * 3,
                          self.cueLength)
        self.cue.reparentTo(self.cueRoot)

        self.cuePos = (10, 0, 0)

        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 separate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(2))
        self.pickerNode.setIntoCollideMask(BitMask32.allOff())
        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.cTrav.addCollider(self.pickerNP, self.cHandler)

        self.accept("mouse1", self.hit)  # left-click grabs a piece

        self.holeLength = 0.06
        holePos, holeHpr = self.planeInfo.getHolePos()
        self.holeRoot = render.attachNewNode("holeRoot")
        #self.hole = loader.loadModel("models/hole_horizontal_center.egg")
        self.hole = loader.loadModel("models/hole_color.egg")
        #self.hole = loader.loadModel("models/billiards_hole_center.egg")
        self.hole.setScale(self.holeLength, self.holeLength, self.holeLength)
        self.hole.reparentTo(self.holeRoot)
        self.hole.setTwoSided(True)
        self.holeRoot.setPos(holePos[0], holePos[1], holePos[2])
        self.holeRoot.setHpr(holeHpr[0], holeHpr[1], holeHpr[2])
        #tex = loader.loadTexture('models/Black_Hole.jpg')
        #self.hole.setTexture(tex, 1)
        self.holeRoot.hide()

        ct = CollisionTube(0, 0, 0, 0, 0.001, 0, 0.5)
        self.holeTube = self.hole.attachNewNode(CollisionNode('hole'))
        self.holeTube.node().addSolid(ct)
        self.holeTube.node().setFromCollideMask(BitMask32.allOff())
        self.holeTube.node().setIntoCollideMask(BitMask32.bit(4))
        #self.holeTube.show()

        inPortalPos, inPortalHpr, outPortalPos, outPortalHpr, self.portalNormal = self.planeInfo.getPortalPos(
        )
        self.portalLength = 0.06
        self.inPortalRoot = render.attachNewNode("inPortalRoot")
        self.inPortal = loader.loadModel("models/portal_2_center.egg")
        self.inPortal.setScale(self.portalLength, self.portalLength,
                               self.portalLength)
        self.inPortal.reparentTo(self.inPortalRoot)
        self.inPortalRoot.setPos(inPortalPos[0], inPortalPos[1],
                                 inPortalPos[2])
        self.inPortalRoot.setHpr(inPortalHpr[0], inPortalHpr[1],
                                 inPortalHpr[2])
        self.inPortalRoot.hide()

        ct = CollisionTube(0, 0, 0, 0, 0.001, 0, 1)
        self.inPortalTube = self.inPortal.attachNewNode(
            CollisionNode('portal_in'))
        self.inPortalTube.node().addSolid(ct)
        self.inPortalTube.node().setFromCollideMask(BitMask32.allOff())
        self.inPortalTube.node().setIntoCollideMask(BitMask32.bit(3))
        #self.inPortalTube.hide()

        self.outPortalRoot = render.attachNewNode("outPortalRoot")
        self.outPortal = loader.loadModel("models/portal_2_center.egg")
        self.outPortal.setScale(self.portalLength, self.portalLength,
                                self.portalLength)
        self.outPortal.reparentTo(self.outPortalRoot)
        self.outPortalRoot.setPos(outPortalPos[0], outPortalPos[1],
                                  outPortalPos[2])
        self.outPortalRoot.setHpr(outPortalHpr[0], outPortalHpr[1],
                                  outPortalHpr[2])
        self.outPortalRoot.hide()

        ct = CollisionTube(0, 0, 0, 0, 0.001, 0, 1)
        self.outPortalTube = self.outPortal.attachNewNode(
            CollisionNode('portal_out'))
        self.outPortalTube.node().addSolid(ct)
        self.outPortalTube.node().setFromCollideMask(BitMask32.allOff())
        self.outPortalTube.node().setIntoCollideMask(BitMask32.bit(3))
        #self.outPortalTube.hide()
        #self.inPortalTube.show()
        #self.outPortalTube.show()
        #self.holeTube.show()

        #self.cTrav.addCollider(self.holeTube, self.cHandler)

        background_image = loader.loadTexture('dump/' + str(self.sceneIndex) +
                                              '_image.png')
        cm = CardMaker('background')
        cm.setHas3dUvs(True)
        info = np.load('dump/' + str(self.sceneIndex) + '_info.npy')
        #self.camera = getCameraFromInfo(self.info)
        depth = 10.0
        sizeU = info[2] / info[0] * depth
        sizeV = info[6] / info[5] * depth
        cm.setFrame(Point3(-sizeU, depth, -sizeV),
                    Point3(sizeU, depth, -sizeV), Point3(sizeU, depth, sizeV),
                    Point3(-sizeU, depth, sizeV))
        self.card = self.render.attachNewNode(cm.generate())
        self.card.setTransparency(True)
        self.card.setTexture(background_image)
        self.card.hide()

        self.ballGroundMap = {}
        self.ballBouncing = np.full(len(self.balls), 3)

        self.started = False
        self.start()

        self.hitIndex = 0

        self.showing = 'none'
        self.showingProgress = 0

        partsScene = PartsScene(self.sceneIndex)
        self.planeNPs, self.planeCenters = partsScene.generateEggModel()
        return

    def start(self):
        #startPos = self.maze.find("**/start").getPos()
        #self.ballRoot.setPos(0.5, 0, 0)
        #self.ballV = LVector3(0, 0.5, 0)         # Initial velocity is 0
        #self.accelV = LVector3(0, 0, 0)        # Initial acceleration is 0

        self.ballVs = []
        self.accelVs = []
        for ballIndex in xrange(len(self.balls)):
            self.ballVs.append(LVector3(0, 0, 0))
            self.accelVs.append(LVector3(0, 0, 0))
            continue
        self.ballRoots[0].setPos(0.2, 1.05, -0.1)
        #self.ballVs[0] = LVector3(0, 0.0, 0)
        self.ballRoots[1].setPos(0.32, 1.2, -0.1)
        #self.ballRoots[2].setHpr(0, 0, 90)
        self.ballRoots[2].setPos(-0.4, 1.1, 0.4)
        axis = LVector3.up()
        prevRot = LRotationf(self.balls[2].getQuat())
        newRot = LRotationf(axis, 90)
        self.balls[2].setQuat(prevRot * newRot)

        # Create the movement task, but first make sure it is not already
        # running
        taskMgr.remove("rollTask")
        #taskMgr.remove("mouseTask")
        self.mainLoop = taskMgr.add(self.rollTask, "rollTask")
        #self.mainLoop = taskMgr.add(self.mouseTask, "mouseTask")

        return

    def hit(self):
        if self.cuePos[0] < 5:
            cueDirection = self.ballRoots[0].getPos() - LVector3(
                self.cuePos[0], self.cuePos[1], self.cuePos[2])
            #power = cueDirection.length()
            cueDirection = cueDirection / cueDirection.length()
            if self.hitIndex < 0:
                self.ballVs[0] = cueDirection * self.cuePower * 8
            elif self.hitIndex == 0:
                self.ballVs[0] = LVector3(0.5, 0.47, 0)
                self.hitIndex += 1
            elif self.hitIndex == 1:
                self.ballVs[0] = LVector3(0.072, 0.62, 0)
                self.hitIndex += 1
            elif self.hitIndex == 2:
                self.ballVs[0] = LVector3(0.7, 0.0, 0)
                self.hitIndex += 1
                pass
            self.started = True
            print('hit', cueDirection)
            self.ballBouncing = np.full(len(self.balls), 3)
            pass

    # This function handles the collision between the ball and a wall
    def planeCollideHandler(self, colEntry):
        #return
        ballName = colEntry.getFromNode().getName()
        ballIndex = int(ballName[5:])

        # First we calculate some numbers we need to do a reflection
        # print(colEntry)
        # name = colEntry.getIntoNode().getName()
        # triangleIndex = int(name[4:])
        # print(triangleIndex)
        # print(self.planeNormals[triangleIndex])
        # print(colEntry.getSurfaceNormal(render))
        # exit(1)
        norm = colEntry.getSurfaceNormal(render) * -1  # The normal of the wall
        norm.normalize()
        curSpeed = self.ballVs[ballIndex].length()  # The current speed
        inVec = self.ballVs[ballIndex] / curSpeed  # The direction of travel
        velAngle = norm.dot(inVec)  # Angle of incidance
        hitDir = colEntry.getSurfacePoint(
            render) - self.ballRoots[ballIndex].getPos()
        hitDir.normalize()
        # The angle between the ball and the normal
        hitAngle = norm.dot(hitDir)

        # Ignore the collision if the ball is either moving away from the wall
        # already (so that we don't accidentally send it back into the wall)
        # and ignore it if the collision isn't dead-on (to avoid getting caught on
        # corners)
        #print(velAngle, hitAngle)

        if velAngle > 0 and hitAngle > .995:
            print('plane', ballName, velAngle)
            # Standard reflection equation
            reflectVec = (norm * norm.dot(inVec * -1) * 2) + inVec

            # This makes the velocity half of what it was if the hit was dead-on
            # and nearly exactly what it was if this is a glancing blow
            #self.ballVs[ballIndex] = reflectVec * (curSpeed * (((1 - velAngle) * .5) + .5))
            self.ballVs[ballIndex] = reflectVec * curSpeed
            # Since we have a collision, the ball is already a little bit buried in
            # the wall. This calculates a vector needed to move it so that it is
            # exactly touching the wall
            disp = (colEntry.getSurfacePoint(render) -
                    colEntry.getInteriorPoint(render))
            newPos = self.ballRoots[ballIndex].getPos() + disp
            self.ballRoots[ballIndex].setPos(newPos)
            pass
        return

    # This function handles the collision between the ball and a wall
    def portal(self, colEntry):
        ballName = colEntry.getFromNode().getName()
        print('portal', ballName)
        ballIndex = int(ballName[5:])

        #norm = colEntry.getSurfaceNormal(render) * -1  # The normal of the wall
        norm = LVector3(self.portalNormal[0], self.portalNormal[1],
                        self.portalNormal[2])
        norm.normalize()
        curSpeed = self.ballVs[ballIndex].length()  # The current speed
        inVec = self.ballVs[ballIndex] / curSpeed  # The direction of travel
        velAngle = norm.dot(inVec)  # Angle of incidance
        hitDir = colEntry.getSurfacePoint(
            render) - self.ballRoots[ballIndex].getPos()
        hitDir.normalize()
        # The angle between the ball and the normal
        #print(colEntry.getSurfacePoint(render), self.ballRoots[ballIndex].getPos())
        #print(norm, hitDir)
        hitAngle = norm.dot(hitDir)

        # Ignore the collision if the ball is either moving away from the wall
        # already (so that we don't accidentally send it back into the wall)
        # and ignore it if the collision isn't dead-on (to avoid getting caught on
        # corners)
        #print(velAngle, hitAngle)
        #print(velAngle, hitAngle)
        if velAngle > 0:
            print(colEntry.getIntoNode().getName())
            if '_in' in colEntry.getIntoNode().getName():
                self.ballRoots[ballIndex].setPos(self.outPortalRoot.getPos())
            else:
                self.ballRoots[ballIndex].setPos(self.inPortalRoot.getPos())
                pass
            print(self.ballVs[ballIndex],
                  ((norm * norm.dot(inVec * -1) * 2) + inVec) * curSpeed, norm)
            #exit(1)
            self.ballVs[ballIndex] = (
                (norm * norm.dot(inVec * -1) * 2) + inVec) * curSpeed
            #self.ballVs[ballIndex] *= -1
            pass
        return

    # This function handles the collision between the ball and a wall
    def ballCollideHandler(self, colEntry):
        # First we calculate some numbers we need to do a reflection
        fromBallName = colEntry.getFromNode().getName()
        fromBallIndex = int(fromBallName[5:])
        #if fromBallIndex != 0:
        #return
        intoBallName = colEntry.getIntoNode().getName()
        intoBallIndex = int(intoBallName[5:])

        print('ball', fromBallName, intoBallName)

        norm = colEntry.getSurfaceNormal(render) * -1  # The normal of the wall
        norm = norm / norm.length()
        curSpeed = self.ballVs[fromBallIndex].length()  # The current speed
        inVec = self.ballVs[fromBallIndex] / curSpeed  # The direction of travel
        velAngle = norm.dot(inVec)  # Angle of incidance
        hitDir = colEntry.getSurfacePoint(
            render) - self.ballRoots[fromBallIndex].getPos()
        hitDir.normalize()
        # The angle between the ball and the normal
        hitAngle = norm.dot(hitDir)

        # print(norm)
        # print(self.ballVs[fromBallIndex])
        # print(velAngle, hitAngle)
        # print(self.ballRoots[fromBallIndex].getPos())
        # print(self.ballRoots[intoBallIndex].getPos())
        # exit(1)
        #print(fromBallIndex, intoBallIndex)
        #exit(1)

        # Ignore the collision if the ball is either moving away from the wall
        # already (so that we don't accidentally send it back into the wall)
        # and ignore it if the collision isn't dead-on (to avoid getting caught on
        # corners)
        #print(velAngle, hitAngle)
        if velAngle > 0 and hitAngle > .995:
            # Standard reflection equation
            self.ballVs[fromBallIndex] = (
                (norm * norm.dot(inVec * -1)) + inVec) * curSpeed

            disp = (colEntry.getSurfacePoint(render) -
                    colEntry.getInteriorPoint(render))
            newPos = self.ballRoots[fromBallIndex].getPos() + disp
            self.ballRoots[fromBallIndex].setPos(newPos)

            self.ballVs[intoBallIndex] = norm * norm.dot(inVec) * curSpeed
            pass
        return

    def groundCollideHandler(self, colEntry):
        # Set the ball to the appropriate Z value for it to be exactly on the
        # ground
        ballName = colEntry.getFromNode().getName()

        if 'mouseRay' in ballName:
            for v in self.ballVs:
                if v.length() > 1e-4:
                    self.cuePos = (10, 0, 0)
                    return
                continue
            #print(self.mouseWatcherNode.hasMouse())
            norm = colEntry.getSurfaceNormal(render)
            norm.normalize()
            touchPoint = colEntry.getSurfacePoint(render)
            cuePoint = touchPoint + norm * self.ballSize
            cueDirection = self.ballRoots[0].getPos() - cuePoint
            self.cuePower = cueDirection.length()
            cueDirection = cueDirection / cueDirection.length()
            cuePoint = self.ballRoots[0].getPos(
            ) - cueDirection * self.cueLength
            self.cuePos = cuePoint
            #self.cueRoot.setH(np.rad2deg(np.arctan2(cueDirection[1], cueDirection[0])) + 90)
            self.cueRoot.setH(
                np.rad2deg(np.arctan2(cueDirection[1], cueDirection[0])) + 90)
            self.cueRoot.setP(-np.rad2deg(np.arcsin(cueDirection[2])) + 90)
            #self.cueRoot.setP(90)
            #print(np.rad2deg(np.arctan2(cueDirection[1], cueDirection[0])), np.rad2deg(np.arcsin(cueDirection[2])))

            # prevRot = LRotationf(self.cue.getQuat())
            # axis = LVector3.up().cross(self.ballVs[ballIndex])
            # newRot = LRotationf(axis, 45.5 * dt * self.ballVs[ballIndex].length())
            # self.balls[ballIndex].setQuat(prevRot * newRot)
            return

        #print('ground', ballName)
        #print(ballName, colEntry.getIntoNode().getName())
        #print(colEntry.getFromNode().getBitMask(), colEntry.getIntoNode().getBitMask())
        ballIndex = int(ballName[9:])

        groundName = colEntry.getIntoNode().getName()
        groundIndex = int(groundName[7:])
        #print(groundIndex)
        #print(self.ballGroundMap)
        if ballIndex == 0 and False:
            print(groundIndex, self.ballGroundMap)
            pass

        if ballIndex not in self.ballGroundMap or self.ballGroundMap[
                ballIndex][0] != groundIndex:
            return

        norm = -colEntry.getSurfaceNormal(render)
        norm = norm / norm.length()

        curSpeed = self.ballVs[ballIndex].length()  # The current speed
        inVec = self.ballVs[ballIndex] / max(curSpeed,
                                             1e-4)  # The direction of travel
        velAngle = norm.dot(inVec)  # Angle of incidance
        hitDir = colEntry.getSurfacePoint(
            render) - self.ballRoots[ballIndex].getPos()
        hitDir.normalize()
        # The angle between the ball and the normal
        hitAngle = norm.dot(hitDir)

        surfacePos = colEntry.getSurfacePoint(render)
        ballPos = self.ballRoots[ballIndex].getPos()
        surfacePos = ballPos + norm * norm.dot(surfacePos - ballPos)

        distance = norm.dot(surfacePos - ballPos)
        if distance < 0:
            return

        if distance < self.ballSize + 1e-3:
            self.ballRoots[ballIndex].setPos(surfacePos - norm * self.ballSize)
            if self.ballVs[ballIndex].length() > 1e-2:
                self.ballVs[ballIndex] = (-norm * velAngle + inVec) * curSpeed
                #self.ballVs[ballIndex] = -norm.cross(norm.cross(self.ballVs[ballIndex]))
                self.accelVs[ballIndex] = -self.ballVs[
                    ballIndex] / self.ballVs[ballIndex].length() * 0.0025
            else:
                self.ballVs[ballIndex] = LVector3(0, 0, 0)
                self.accelVs[ballIndex] = LVector3(0, 0, 0)
                pass
        else:
            self.accelVs[
                ballIndex] = self.accelVs[ballIndex] - norm * norm.dot(
                    self.accelVs[ballIndex]) + norm * 0.05
            pass
        return

        # if self.started:
        #     if abs(distance - self.ballSize) > 0.001 and abs(distance - self.ballSize) < self.ballSize:
        #         self.ballRoots[ballIndex].setPos(surfacePos - norm * self.ballSize)
        #         pass
        #     self.ballVs[ballIndex] = -norm.cross(norm.cross(self.ballVs[ballIndex]))
        #     if self.ballVs[ballIndex].length() > 1e-3:
        #         self.accelVs[ballIndex] = -self.ballVs[ballIndex] / self.ballVs[ballIndex].length() * 0.015
        #     else:
        #         self.ballVs[ballIndex] = LVector3(0, 0, 0)
        #         self.accelVs[ballIndex] = LVector3(0, 0, 0)
        #         pass
        #     #print(self.ballVs[ballIndex], self.accelVs[ballIndex])
        #     #print(surfacePos - norm * self.ballSize)

        #     return

        if ballIndex == 0:
            print('distance_1', self.started, distance, velAngle,
                  self.ballVs[ballIndex], self.accelVs[ballIndex])

        if distance < self.ballSize:
            self.ballRoots[ballIndex].setPos(surfacePos - norm * self.ballSize)
            if velAngle > 0 and hitAngle > .995:
                if abs(velAngle * curSpeed) < 0.2:
                    if ((-norm * velAngle + inVec) * curSpeed).length() < 0.02:
                        self.ballVs[ballIndex] = LVector3(0, 0, 0)
                        self.accelVs[ballIndex] = LVector3(0, 0, 0)
                        pass
                    pass
                else:
                    if self.ballBouncing[ballIndex] > 0:
                        if ballIndex == 0:
                            print('bouncing')
                            pass
                        self.ballVs[ballIndex] = (
                            -norm * velAngle + inVec
                        ) * curSpeed * 0.5 - norm * velAngle * curSpeed * 0.25
                        self.accelVs[ballIndex] = LVector3(0, 0, 0)
                        self.ballBouncing[ballIndex] -= 1
                    else:
                        self.ballVs[ballIndex] = (-norm * velAngle +
                                                  inVec) * curSpeed
                        self.accelVs[ballIndex] = LVector3(0, 0, 0)
                        pass
                    pass
                pass

            pass

        if (distance - self.ballSize) > 0.001:
            self.accelVs[
                ballIndex] = self.accelVs[ballIndex] - norm * norm.dot(
                    self.accelVs[ballIndex]) + norm * 0.1
            # print(self.accelVs[ballIndex] - norm * norm.dot(self.accelVs[ballIndex]))
            # print(norm)
            # print(inVec)
            # print(velAngle)
            # print(-norm * velAngle + inVec)
            # print(norm * 0.01)
            # exit(1)
        elif distance - self.ballSize > -0.001:
            if self.ballVs[ballIndex].length() < 0.001:
                #print('stop', self.ballVs[ballIndex], self.accelVs[ballIndex])

                self.ballVs[ballIndex] = LVector3(0, 0, 0)
                self.accelVs[ballIndex] = LVector3(0, 0, 0)
                self.started = False
            else:
                if abs(velAngle) < 1e-3:
                    self.ballVs[ballIndex] = (-norm * velAngle +
                                              inVec) * curSpeed
                    #self.ballVs[ballIndex] = -norm.cross(norm.cross(self.ballVs[ballIndex]))
                    self.accelVs[ballIndex] = -self.ballVs[
                        ballIndex] / self.ballVs[ballIndex].length() * 0.01
                    #print('speed', self.ballVs[ballIndex], self.accelVs[ballIndex])
                    pass
                pass
            pass

        # #print(distance - self.ballSize)
        # if (distance - self.ballSize) > 0.01:
        #     self.accelVs[ballIndex] = self.accelVs[ballIndex] - norm * norm.dot(self.accelVs[ballIndex]) + norm * 0.01
        #     #if ballIndex == 0:
        #     #print(velAngle, self.ballVs[ballIndex], self.accelVs[ballIndex], norm)
        #     #pass

        #     print('fall', self.accelVs[ballIndex], distance)
        #     # print(self.accelVs[ballIndex] - norm * norm.dot(self.accelVs[ballIndex]))
        #     # print(norm)
        #     # print(inVec)
        #     # print(velAngle)
        #     # print(-norm * velAngle + inVec)
        #     # print(norm * 0.01)
        #     # exit(1)
        # else:
        #     #hitAngle > .995
        #     #print(velAngle)
        #     #print(norm)

        #     #self.ballRoots[ballIndex].setPos(surfacePos - norm * self.ballSize)
        #     if curSpeed > 1e-1:
        #         print('angle', velAngle, norm)
        #         self.norm = norm
        #         pass
        #     if velAngle > 1e-3:
        #         if curSpeed < 1e-3:
        #             self.ballVs[ballIndex] = LVector3(0, 0, 0)
        #             self.accelVs[ballIndex] = LVector3(0, 0, 0)
        #             self.ballRoots[ballIndex].setPos(surfacePos - norm * self.ballSize)
        #         else:
        #             self.ballVs[ballIndex] = (-norm * velAngle + inVec) * curSpeed * 0.9 - norm * velAngle * curSpeed * 0.25
        #             self.accelVs[ballIndex] = LVector3(0, 0, 0)
        #             pass
        #         #print((-norm * velAngle + inVec) * curSpeed * 0.9, norm * velAngle * curSpeed * 0.25)
        #         #print(curSpeed, norm.dot(self.ballVs[ballIndex]) / self.ballVs[ballIndex].length(), self.ballVs[ballIndex], self.accelVs[ballIndex])
        #         #print(norm.dot(self.ballVs[ballIndex]) / self.ballVs[ballIndex].length(), norm.dot(self.accelVs[ballIndex]) / self.accelVs[ballIndex].length(), self.ballVs[ballIndex], self.accelVs[ballIndex])
        #     elif velAngle > -1e-3:
        #         if self.ballVs[ballIndex].length() < 0.001:
        #             #self.ballVs[ballIndex] = LVector3(0, 0, 0)
        #             #self.accelVs[ballIndex] = LVector3(0, 0, 0)
        #             #print('stop', self.ballVs[ballIndex], self.accelVs[ballIndex])
        #             pass
        #         else:
        #             #self.ballVs[ballIndex] = (-norm * velAngle + inVec) * curSpeed * 0.9
        #             #print(self.ballVs[ballIndex], self.accelVs[ballIndex])
        #             self.accelVs[ballIndex] = -(-norm * velAngle + inVec) * 0.1
        #             print('accel', self.accelVs[ballIndex])
        #             pass
        #         pass
        #     else:
        #         #print('stop', self.ballVs[ballIndex], self.accelVs[ballIndex])
        #         #self.ballVs[ballIndex] = LVector3(0, 0, 0)
        #         #self.accelVs[ballIndex] = LVector3(0, 0, 0)
        #         pass
        #     pass
        return

    # This is the task that deals with making everything interactive
    def rollTask(self, task):
        # Standard technique for finding the amount of time since the last
        # frame
        dt = globalClock.getDt()

        # If dt is large, then there has been a # hiccup that could cause the ball
        # to leave the field if this functions runs, so ignore the frame
        if dt > .2:
            return Task.cont

        # if base.mouseWatcherNode.is_button_down('a'):
        #     self.holeRoot.setH(self.holeRoot.getH() + 1)
        #     print(self.holeRoot.getHpr())
        #     pass
        # if base.mouseWatcherNode.is_button_down('s'):
        #     self.holeRoot.setP(self.holeRoot.getP() + 1)
        #     print(self.holeRoot.getHpr())
        #     pass
        # if base.mouseWatcherNode.is_button_down('d'):
        #     self.holeRoot.setR(self.holeRoot.getR() + 1)
        #     print(self.holeRoot.getHpr())
        #     pass

        if base.mouseWatcherNode.is_button_down(
                'space') and self.showing == 'none':
            self.showing = 'parts'
            #self.showingProgress = 0
            pass
        #print(self.showing)
        #print(self.showing)
        if self.showing == 'none':
            return Task.cont
        if self.showing == 'parts':
            self.showingProgress += 0.01
            #self.showingProgress += 1
            print(self.showingProgress)
            scale = 2 - self.showingProgress
            scaleY = 1 + (scale - 1) * 0.5
            for planeIndex, planeNP in enumerate(self.planeNPs):
                center = self.planeCenters[planeIndex]
                planeNP.setPos(center[0] * scale, center[1] * scaleY,
                               center[2] * scale)
                planeNP.reparentTo(self.render)
                planeNP.setTwoSided(True)
                continue
            if self.showingProgress > 1:
                self.showing = 'moving'
                for planeIndex, planeNP in enumerate(self.planeNPs):
                    planeNP.removeNode()
                    continue
                self.planeScene.show()
                self.showingProgress = 0
            return Task.cont
        if self.showing == 'moving':
            self.showingProgress += 0.005
            #self.showingProgress += 1
            #print(self.showingProgress, np.sign(self.showingProgress - 0.5) * min(self.showingProgress % 0.5, 0.5 - self.showingProgress % 0.5) * 4)
            self.camera.setPos(
                np.sign(self.showingProgress - 0.5) *
                min(self.showingProgress % 0.5,
                    0.5 - self.showingProgress % 0.5) * 3, 0, 0)
            #self.camera.setHpr(angleDegrees, 0, 0)
            #self.camera.lookAt(0, 0, 0)
            self.camera.lookAt(0, 3, 0)
            if self.showingProgress > 1:
                self.showing = 'geometry'
                self.camera.setPos(0, 0, 0)
                #self.planeScene.removeNode()
                # for triNP in self.triNPs:
                #     triNP.show()
                #     continue
                self.showingProgress = 1
            return Task.cont
        if self.showing == 'geometry':
            self.showingProgress += 0.02
            if self.showingProgress > 1:
                #self.showing = 'image'
                self.showing = 'placement'
                self.showingProgress = 0
                self.holeRoot.show()
                self.inPortalRoot.show()
                self.outPortalRoot.show()
                self.inPortalTube.show()
                self.outPortalTube.show()
                for ballRoot in self.ballRoots:
                    ballRoot.show()
                    continue
                self.showingProgress = 0
                pass
            return Task.cont
        # if self.showing == 'placement':
        #     self.showingProgress += 0.005
        #         continue

        if self.mouseWatcherNode.hasMouse():
            mpos = self.mouseWatcherNode.getMouse()
            self.mpos = mpos
            self.pickerRay.setFromLens(self.camNode, mpos.getX(), mpos.getY())
            pass

        if base.mouseWatcherNode.is_button_down(
                'space') and self.showing == 'placement':
            self.card.show()
            self.planeScene.removeNode()
            self.showing = 'image'
            pass
        # if base.mouseWatcherNode.is_button_down('space') and self.showing == 'image':
        #     for triNP in self.triNPs:
        #         triNP.hide()
        #         continue
        #     self.showing = 'start'
        #     pass

        # The collision handler collects the collisions. We dispatch which function
        # to handle the collision based on the name of what was collided into

        self.ballGroundMap = {}
        for i in range(self.cHandler.getNumEntries()):
            entry = self.cHandler.getEntry(i)
            ballName = entry.getFromNode().getName()
            groundName = entry.getIntoNode().getName()
            if 'ball_ray_' not in ballName:
                continue
            if 'ground_' not in groundName:
                continue
            ballIndex = int(ballName[9:])
            groundIndex = int(groundName[7:])
            norm = -entry.getSurfaceNormal(render)
            if norm.length() == 0:
                continue
            norm = norm / norm.length()
            distance = norm.dot(
                entry.getSurfacePoint(render) -
                self.ballRoots[ballIndex].getPos())
            #print(distance)
            if distance < 0:
                continue
            if ballIndex not in self.ballGroundMap or distance < self.ballGroundMap[
                    ballIndex][1]:
                self.ballGroundMap[ballIndex] = (groundIndex, distance)
                pass
            continue

        for i in range(self.cHandler.getNumEntries()):
            entry = self.cHandler.getEntry(i)
            fromName = entry.getFromNode().getName()
            #if 'mouseRay' in fromName:
            #continue
            name = entry.getIntoNode().getName()
            #if name == "plane_collide":
            if 'tri_' in name:
                self.planeCollideHandler(entry)
            #elif name == "wall_collide":
            #self.wallCollideHandler(entry)
            #elif name == "ground_collide":
            #self.groundCollideHandler(entry)
            elif 'ball_' in name:
                self.ballCollideHandler(entry)
            elif 'ground_' in name:
                self.groundCollideHandler(entry)
            elif 'hole' in name:
                self.score(entry)
            elif 'portal_' in name:
                self.portal(entry)
                pass
            continue

        # Read the mouse position and tilt the maze accordingly
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()  # get the mouse position
            #self.maze.setP(mpos.getY() * -10)
            #self.maze.setR(mpos.getX() * 10)
            pass

        # if base.mouseWatcherNode.is_button_down('mouse1'):
        #     print(base.mouseWatcherNode.getMouseX())
        #     print(base.mouseWatcherNode.getMouseY())
        #     exit(1)

        # Finally, we move the ball
        # Update the velocity based on acceleration
        for ballIndex in xrange(len(self.balls)):
            if self.ballVs[ballIndex].length(
            ) < 1e-4 and self.ballVs[ballIndex].dot(
                    self.accelVs[ballIndex]) < -1e-4:
                self.ballVs[ballIndex] = LVector3(0, 0, 0)
                self.accelVs[ballIndex] = LVector3(0, 0, 0)
            else:
                self.ballVs[ballIndex] += self.accelVs[ballIndex] * dt * ACCEL
                pass
            #print('current speed', self.ballVs[ballIndex], self.accelVs[ballIndex])
            # Clamp the velocity to the maximum speed
            if self.ballVs[ballIndex].lengthSquared() > MAX_SPEED_SQ:
                self.ballVs[ballIndex].normalize()
                self.ballVs[ballIndex] *= MAX_SPEED
                pass
            #print(self.ballVs[ballIndex], self.accelVs[ballIndex], self.ballRoots[ballIndex].getPos())

            # Update the position based on the velocity
            self.ballRoots[ballIndex].setPos(
                self.ballRoots[ballIndex].getPos() +
                (self.ballVs[ballIndex] * dt))

            # This block of code rotates the ball. It uses something called a quaternion
            # to rotate the ball around an arbitrary axis. That axis perpendicular to
            # the balls rotation, and the amount has to do with the size of the ball
            # This is multiplied on the previous rotation to incrimentally turn it.
            prevRot = LRotationf(self.balls[ballIndex].getQuat())
            axis = LVector3.up().cross(self.ballVs[ballIndex])
            newRot = LRotationf(
                axis,
                np.rad2deg(dt * self.ballVs[ballIndex].length() /
                           self.ballSize))
            self.balls[ballIndex].setQuat(prevRot * newRot)
            continue

        self.cueRoot.setPos(self.cuePos[0], self.cuePos[1], self.cuePos[2])
        return Task.cont  # Continue the task indefinitely

    def score(self, colEntry):
        ballName = colEntry.getFromNode().getName()
        if 'ball_' not in ballName:
            return
        print('score', ballName)
        ballIndex = int(ballName[5:])
        self.ballRoots[ballIndex].removeNode()

        del self.ballRoots[ballIndex]
        del self.balls[ballIndex]
        del self.ballSpheres[ballIndex]
        del self.ballGroundRays[ballIndex]
        del self.ballVs[ballIndex]
        del self.accelVs[ballIndex]
        for otherIndex in xrange(ballIndex, len(self.balls)):
            self.ballSpheres[otherIndex].setName('ball_' + str(otherIndex))
            self.ballGroundRays[otherIndex].setName('ball_ray_' +
                                                    str(otherIndex))
            continue
        return

    # If the ball hits a hole trigger, then it should fall in the hole.
    # This is faked rather than dealing with the actual physics of it.
    def loseGame(self, entry):
        # The triggers are set up so that the center of the ball should move to the
        # collision point to be in the hole
        toPos = entry.getInteriorPoint(render)
        taskMgr.remove('rollTask')  # Stop the maze task

        # Move the ball into the hole over a short sequence of time. Then wait a
        # second and call start to reset the game
        Sequence(
            Parallel(
                LerpFunc(self.ballRoot.setX,
                         fromData=self.ballRoot.getX(),
                         toData=toPos.getX(),
                         duration=.1),
                LerpFunc(self.ballRoot.setY,
                         fromData=self.ballRoot.getY(),
                         toData=toPos.getY(),
                         duration=.1),
                LerpFunc(self.ballRoot.setZ,
                         fromData=self.ballRoot.getZ(),
                         toData=self.ballRoot.getZ() - .9,
                         duration=.2)), Wait(1), Func(self.start)).start()
예제 #51
0
class GameContainer(ShowBase):
    def __init__(self):

        ShowBase.__init__(self)

        ########## Window configuration #########

        wp = WindowProperties()

        wp.setSize(1024, 860)
        wp.setTitle("")
        wp.setOrigin(-2, -2)

        self.win.requestProperties(wp)

        self.win.movePointer(0, wp.getXSize() / 2, wp.getYSize() / 2)
        print wp.getXSize() / 2, wp.getYSize() / 2

        ########## Gameplay settings #########

        self.gameMode = {"display": PLAY, "play": TERRAIN}

        self.level = 1.5

        self.mode_initialized = False

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

        self.disableMouse()

        self.mainCamera = Camera(self.camera)

        self.mainCamera.camObject.setHpr(0, 0, 0)

        self.loadLevel()

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

        self.taskMgr.add(self.gameLoop, "gameLoop", priority=35)

        self.keys = {"w": 0, "s": 0, "a": 0, "d": 0, "space": 0, "escape": 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("space", self.setKey, ["space", 1])
        self.accept("space-up", self.setKey, ["space", 0])
        self.accept("escape", self.setKey, ["escape", 1])
        self.accept("escape-up", self.setKey, ["escape", 0])
        self.accept("wheel_up", self.zoomCamera, [-1])
        self.accept("wheel_down", self.zoomCamera, [1])

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

        ######### GUI #########

        #self.fonts = {"failure" : loader.loadFont('myfont.ttf')}

        self.guiElements = []

        self._GCLK = None
        self._FT = None

        #Trigger game chain

        #self.enableParticles()

        #self.buildMainMenu()

    def setKey(self, key, value):

        self.keys[key] = value

    def zoomCamera(self, direction):

        if self.gameMode["play"] == TERRAIN:

            Camera.AVATAR_DIST += direction

    def toggleCursor(self, state):

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

    def handleWindowEvent(self, window=None):

        wp = window.getProperties()

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

    def processKeys(self):

        if self.keys["escape"]:

            if self.gameMode["display"] == PLAY:

                self.switchDisplayMode(IN_GAME_MENU)

            elif self.gameMode["display"] == IN_GAME_MENU:

                self.switchDisplayMode(PLAY)

            self.setKey("escape", 0)

    ######### Level specific features #########

    def maintainTurrets(self):

        pass

    def switchDisplayMode(self, newGameMode):

        self.cleanupGUI()

        if self.gameMode["display"] == MAIN_MENU:

            pass

        elif self.gameMode["display"] == IN_GAME_MENU:

            if newGameMode == PLAY:

                render.clearFog()

                self.togglePhysicsPause()

            elif newGameMode == MAIN_MENU:

                pass

        elif self.gameMode["display"] == PLAY:

            if newGameMode == IN_GAME_MENU:

                self.togglePhysicsPause()

        self.gameMode["display"] = newGameMode

        self.mode_initialized = False

    def advanceLevel(self):

        self.level += .5

        self.loadLevel()

    def evenButtonPositions(self, button_spacing, button_height, num_buttons):

        centerOffset = (button_spacing / (2.0) if
                        (num_buttons % 2 == 0) else 0)

        buttonPositions = []

        current_pos = centerOffset + ((num_buttons - 1) / 2) * button_spacing

        for i in range(0, num_buttons):

            buttonPositions.append(current_pos + (button_height / 2.0))

            current_pos -= button_spacing

        return buttonPositions

    def buildInGameMenu(self):

        self.toggleCursor(False)

        resume_button = DirectButton(
            text="Resume",
            scale=.1,
            command=(lambda: self.switchDisplayMode(PLAY)),
            rolloverSound=None)
        main_menu_button = DirectButton(text="Main Menu",
                                        scale=.1,
                                        command=None,
                                        rolloverSound=None)
        options_button = DirectButton(text="Settings",
                                      scale=.1,
                                      command=None,
                                      rolloverSound=None)
        exit_button = DirectButton(text="Exit",
                                   scale=.1,
                                   command=exit,
                                   rolloverSound=None)

        BUTTON_SPACING = .2
        BUTTON_HEIGHT = resume_button.getSy()

        button_positions = self.evenButtonPositions(BUTTON_SPACING,
                                                    BUTTON_HEIGHT, 4)

        resume_button.setPos(Vec3(0, 0, button_positions[0]))
        main_menu_button.setPos(Vec3(0, 0, button_positions[1]))
        options_button.setPos(Vec3(0, 0, button_positions[2]))
        exit_button.setPos(Vec3(0, 0, button_positions[3]))

        self.guiElements.append(resume_button)
        self.guiElements.append(main_menu_button)
        self.guiElements.append(options_button)
        self.guiElements.append(exit_button)

    def buildMainMenu(self):

        self.toggleCursor(False)

        start_game_button = DirectButton(text="Start", scale=.1, command=None)
        select_level_button = DirectButton(text="Select Level",
                                           scale=.1,
                                           command=None)
        game_options_button = DirectButton(text="Settings",
                                           scale=.1,
                                           command=None)
        exit_button = DirectButton(text="Exit", scale=.1, command=exit)

        BUTTON_SPACING = .2
        BUTTON_HEIGHT = start_game_button.getSy()

        button_positions = self.evenButtonPositions(BUTTON_SPACING,
                                                    BUTTON_HEIGHT, 4)

        start_game_button.setPos(Vec3(0, 0, button_positions[0]))
        select_level_button.setPos(Vec3(0, 0, button_positions[1]))
        game_options_button.setPos(Vec3(0, 0, button_positions[2]))
        exit_button.setPos(Vec3(0, 0, button_positions[3]))

        self.guiElements.append(start_game_button)
        self.guiElements.append(select_level_button)
        self.guiElements.append(game_options_button)
        self.guiElements.append(exit_button)

        particles = Particles()
        particles.setPoolSize(1000)
        particles.setBirthRate(.1)
        particles.setLitterSize(10)
        particles.setLitterSpread(3)
        particles.setFactory("PointParticleFactory")
        particles.setRenderer("PointParticleRenderer")
        particles.setEmitter("SphereVolumeEmitter")
        particles.enable()

        self.effect = ParticleEffect("peffect", particles)
        self.effect.reparentTo(render)
        #self.effect.setPos(self.avatar.objectNP.getX(), self.avatar.objectNP.getY(), self.avatar.objectNP.getZ() + 5)
        self.effect.setPos(-1, 0, 0)
        self.effect.enable()

    def buildDeathScreen(self):

        self.toggleCursor(False)

        backFrame = DirectFrame(frameColor=(1, 0, 0, .7),
                                frameSize=(-.5, .5, -.3, .3),
                                pos=(0, 0, 0))

        deadMessage = DirectLabel(text="MISSION FAILURE",
                                  scale=.1,
                                  pos=(0, 0, .16),
                                  relief=None,
                                  text_font=None)

        restartButton = DirectButton(text="Restart",
                                     scale=.1,
                                     pos=(0, 0, -.1),
                                     command=self.resetLevel)

        deadMessage.reparentTo(backFrame)
        restartButton.reparentTo(backFrame)

        self.guiElements.append(backFrame)
        self.guiElements.append(deadMessage)
        self.guiElements.append(restartButton)

    def cleanupGUI(self):

        for guiElement in self.guiElements:

            guiElement.destroy()

    def loadSpaceTexture(self, level):

        if level < 10: return 'textures/space#.jpg'
        elif level < 15: pass

    def resetLevel(self):

        self.switchDisplayMode(PLAY)

        self.loadLevel(True)

    def loadLevel(self, reset=False):

        #Resets

        self.avatarActor = Actor("models/panda", {"walk": "models/panda-walk"})
        self.avatarActor.setScale(.5, .5, .5)
        self.avatarActor.setHpr(180, 0, 0)
        self.avatarActor.setCollideMask(BitMask32.allOff())

        self.asteroidManager = AsteroidManager()

        self.cTrav = CollisionTraverser()

        #Alternate modes

        if int(self.level) == self.level: self.gameMode["play"] = TERRAIN

        else: self.gameMode["play"] = SPACE

        #Specifics

        if self.gameMode["play"] == SPACE:

            if reset:

                self.avatar.reset()

            else:

                self.avatar = Avatar(self.avatarActor, self.level)

                self.avatar.objectNP.reparentTo(render)

            ########## Sky #########

            cubeMap = loader.loadCubeMap(self.loadSpaceTexture(self.level))
            self.spaceSkyBox = loader.loadModel('models/box')
            self.spaceSkyBox.setScale(100)
            self.spaceSkyBox.setBin('background', 0)
            self.spaceSkyBox.setDepthWrite(0)
            self.spaceSkyBox.setTwoSided(True)
            self.spaceSkyBox.setTexGen(TextureStage.getDefault(),
                                       TexGenAttrib.MWorldCubeMap)
            self.spaceSkyBox.setTexture(cubeMap, 1)
            parentNP = render.attachNewNode('parent')
            self.spaceSkyBox.reparentTo(parentNP)
            self.spaceSkyBox.setPos(-self.spaceSkyBox.getSx() / 2,
                                    -self.spaceSkyBox.getSy() / 2,
                                    -self.spaceSkyBox.getSz() / 2)

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

            bound = self.avatarActor.getBounds()

            self.pandaBodySphere = CollisionSphere(
                bound.getCenter()[0] / self.avatar.objectNP.getSx() -
                self.avatar.objectNP.getX(),
                bound.getCenter()[1] / self.avatar.objectNP.getSx() -
                self.avatar.objectNP.getY(),
                bound.getCenter()[2] / self.avatar.objectNP.getSx() -
                self.avatar.objectNP.getZ(), 5)

            self.pandaBodySphere.setRadius(bound.getRadius() + 1)

            self.pandaBodySphereNode = CollisionNode("playerBodyRay")
            self.pandaBodySphereNode.addSolid(self.pandaBodySphere)
            self.pandaBodySphereNode.setFromCollideMask(BitMask32.bit(0))
            self.pandaBodySphereNode.setIntoCollideMask(BitMask32.allOff())

            self.pandaBodySphereNodepath = self.avatar.objectNP.attachNewNode(
                self.pandaBodySphereNode)
            self.pandaBodySphereNodepath.show()

            self.collisionNotifier = CollisionHandlerEvent()
            self.collisionNotifier.addInPattern("%fn-in")
            self.collisionNotifier.addOutPattern("%fn-out")

            self.cTrav.addCollider(self.pandaBodySphereNodepath,
                                   self.collisionNotifier)

            self.accept("playerGroundRayJumping-in",
                        self.avatar.handleCollisionEvent, ["in"])
            self.accept("playerGroundRayJumping-out",
                        self.avatar.handleCollisionEvent, ["out"])
            self.accept("playerBodyRay-in", self.avatar.handleCollisionEvent,
                        ["in"])

            self.asteroidManager.initialize(self.level)

        elif self.gameMode["play"] == TERRAIN:

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

            #self.environ = loader.loadModel("../mystuff/test.egg")
            self.environ = loader.loadModel("models/environment")
            self.environ.setName("terrain")
            self.environ.reparentTo(render)
            self.environ.setPos(0, 0, 0)
            self.environ.setCollideMask(BitMask32.bit(0))

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

            self.enableParticles()

            gravityForce = LinearVectorForce(0, 0, -9.81)
            gravityForce.setMassDependent(False)
            gravityFN = ForceNode("world-forces")
            gravityFN.addForce(gravityForce)
            render.attachNewNode(gravityFN)
            base.physicsMgr.addLinearForce(gravityForce)

            self.avatarPhysicsActorNP = render.attachNewNode(
                ActorNode("player"))
            self.avatarPhysicsActorNP.node().getPhysicsObject().setMass(50.)
            self.avatarActor.reparentTo(self.avatarPhysicsActorNP)
            base.physicsMgr.attachPhysicalNode(
                self.avatarPhysicsActorNP.node())

            self.avatarPhysicsActorNP.setPos(15, 10, 5)

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

            self.avatar = Avatar(self.avatarPhysicsActorNP, self.level)

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

            self.pandaBodySphere = CollisionSphere(0, 0, 4, 3)

            self.pandaBodySphereNode = CollisionNode("playerBodySphere")
            self.pandaBodySphereNode.addSolid(self.pandaBodySphere)
            self.pandaBodySphereNode.setFromCollideMask(BitMask32.bit(0))
            self.pandaBodySphereNode.setIntoCollideMask(BitMask32.allOff())

            self.pandaBodySphereNodepath = self.avatar.objectNP.attachNewNode(
                self.pandaBodySphereNode)
            self.pandaBodySphereNodepath.show()

            self.pandaBodyCollisionHandler = PhysicsCollisionHandler()
            self.pandaBodyCollisionHandler.addCollider(
                self.pandaBodySphereNodepath, self.avatar.objectNP)

            #Keep player on ground

            self.pandaGroundSphere = CollisionSphere(0, 0, 1, 1)

            self.pandaGroundSphereNode = CollisionNode("playerGroundRay")
            self.pandaGroundSphereNode.addSolid(self.pandaGroundSphere)
            self.pandaGroundSphereNode.setFromCollideMask(BitMask32.bit(0))
            self.pandaGroundSphereNode.setIntoCollideMask(BitMask32.allOff())

            self.pandaGroundSphereNodepath = self.avatar.objectNP.attachNewNode(
                self.pandaGroundSphereNode)
            self.pandaGroundSphereNodepath.show()

            self.pandaGroundCollisionHandler = PhysicsCollisionHandler()
            self.pandaGroundCollisionHandler.addCollider(
                self.pandaGroundSphereNodepath, self.avatar.objectNP)

            #Notify when player lands

            self.pandaGroundRayJumping = CollisionSphere(0, 0, 1, 1)

            self.pandaGroundRayNodeJumping = CollisionNode(
                "playerGroundRayJumping")
            self.pandaGroundRayNodeJumping.addSolid(self.pandaGroundRayJumping)
            self.pandaGroundRayNodeJumping.setFromCollideMask(BitMask32.bit(0))
            self.pandaGroundRayNodeJumping.setIntoCollideMask(
                BitMask32.allOff())

            self.pandaGroundRayNodepathJumping = self.avatar.objectNP.attachNewNode(
                self.pandaGroundRayNodeJumping)
            self.pandaGroundRayNodepathJumping.show()

            self.collisionNotifier = CollisionHandlerEvent()
            self.collisionNotifier.addInPattern("%fn-in")
            self.collisionNotifier.addOutPattern("%fn-out")

            self.cTrav.addCollider(self.pandaGroundSphereNodepath,
                                   self.pandaGroundCollisionHandler)
            self.cTrav.addCollider(self.pandaGroundRayNodepathJumping,
                                   self.collisionNotifier)
            self.cTrav.addCollider(self.pandaBodySphereNodepath,
                                   self.pandaBodyCollisionHandler)

            self.accept("playerGroundRayJumping-in",
                        self.avatar.handleCollisionEvent, ["in"])
            self.accept("playerGroundRayJumping-out",
                        self.avatar.handleCollisionEvent, ["out"])
            self.accept("playerBodyRay-in", self.avatar.handleCollisionEvent,
                        ["in"])

    def togglePhysicsPause(self):

        if (self._GCLK == None):

            self.disableParticles()

            self._GCLK = ClockObject.getGlobalClock()
            self._FT = self._GCLK.getFrameTime()
            self._GCLK.setMode(ClockObject.MSlave)

        else:

            self._GCLK.setRealTime(self._FT)
            self._GCLK.setMode(ClockObject.MNormal)

            self.enableParticles()

            self._GCLK = None

    def gameLoop(self, task):

        dt = globalClock.getDt()

        self.processKeys()

        if self.gameMode["display"] == MAIN_MENU:

            if not self.mode_initialized:

                self.buildMainMenu()

                self.mode_initialized = True

        if self.gameMode["display"] == IN_GAME_MENU:

            if not self.mode_initialized:

                #Fog out background

                inGameMenuFogColor = (50, 150, 50)

                inGameMenuFog = Fog("inGameMenuFog")

                inGameMenuFog.setMode(Fog.MExponential)
                inGameMenuFog.setColor(*inGameMenuFogColor)
                inGameMenuFog.setExpDensity(.01)

                render.setFog(inGameMenuFog)

                self.buildInGameMenu()

                self.mode_initialized = True

        if self.gameMode["display"] == DEAD:

            if not self.mode_initialized:

                self.buildDeathScreen()

                self.mode_initialized = True

        if self.gameMode["display"] == PLAY:

            alive = self.avatar.states["alive"]

            if not self.mode_initialized:

                self.toggleCursor(True)

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

                self.mode_initialized = True

            if self.gameMode["play"] == TERRAIN:

                if alive:

                    self.maintainTurrets()
                    self.avatar.move(dt)

                else:
                    self.switchDisplayMode(DEAD)

            elif self.gameMode["play"] == SPACE:

                if alive:

                    self.asteroidManager.maintainAsteroidField(
                        self.avatar.objectNP.getPos(), self.avatar.speed,
                        Camera.AVATAR_DIST, dt)

                else:
                    self.switchDisplayMode(DEAD)

            if alive:

                #Handle keyboard input

                self.avatar.handleKeys(self.keys, self.gameMode["play"])

                ########## Mouse-based viewpoint rotation ##########

                mouse_pos = self.win.getPointer(0)

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

                #Side to side

                if self.gameMode["play"] == TERRAIN:

                    mouse_shift_x = current_mouse_x - self.last_mouse_x
                    self.last_mouse_x = current_mouse_x

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

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

                    yaw_shift = -((mouse_shift_x) * Camera.ROT_RATE[0])

                    self.avatar.yawRot += yaw_shift

                    self.avatar.objectNP.setH(self.avatar.yawRot)

                #Up and down

                mouse_shift_y = current_mouse_y - self.last_mouse_y
                self.last_mouse_y = current_mouse_y

                if current_mouse_y < 5 or current_mouse_y >= (
                        self.win_center_y * 1.5):

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

                pitch_shift = -((mouse_shift_y) * Camera.ROT_RATE[1])

                self.mainCamera.pitchRot += pitch_shift

                if self.mainCamera.pitchRot > Camera.FLEX_ROT_BOUND[0]:

                    self.mainCamera.pitchRot = Camera.FLEX_ROT_BOUND[0]

                elif self.mainCamera.pitchRot < -Camera.FLEX_ROT_BOUND[0]:

                    self.mainCamera.pitchRot = -Camera.FLEX_ROT_BOUND[0]

                xy_plane_cam_dist = Camera.AVATAR_DIST

                cam_x_adjust = xy_plane_cam_dist * sin(
                    radians(self.avatar.yawRot))
                cam_y_adjust = xy_plane_cam_dist * cos(
                    radians(self.avatar.yawRot))
                cam_z_adjust = Camera.ELEVATION

                self.mainCamera.camObject.setH(self.avatar.yawRot)
                self.mainCamera.camObject.setP(self.mainCamera.pitchRot)

                self.mainCamera.camObject.setPos(
                    self.avatar.objectNP.getX() + cam_x_adjust,
                    self.avatar.objectNP.getY() - cam_y_adjust,
                    self.avatar.objectNP.getZ() + cam_z_adjust)

                #Find collisions

                self.cTrav.traverse(render)

        return Task.cont
class DistributedPartyTrampolineActivity(DistributedPartyActivity):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'DistributedPartyTrampolineActivity')

    def __init__(self, cr, doJellyBeans=True, doTricks=False, texture=None):
        DistributedPartyTrampolineActivity.notify.debug('__init__')
        DistributedPartyActivity.__init__(
            self,
            cr,
            PartyGlobals.ActivityIds.PartyTrampoline,
            PartyGlobals.ActivityTypes.GuestInitiated,
            wantLever=False,
            wantRewardGui=True)
        self.doJellyBeans = doJellyBeans
        self.doTricks = doTricks
        self.texture = texture
        self.toon = None
        self.trampHeight = 3.6
        self.trampK = 400.0
        self.normalTrampB = 2.5
        self.leavingTrampB = 8.0
        self.trampB = self.normalTrampB
        self.g = -32.0
        self.jumpBoost = 330.0
        self.beginningBoost = 500.0
        self.beginningBoostThreshold = self.trampHeight + 1.5
        self.earlyJumpThreshold = 75.0
        self.boingThreshold = 300.0
        self.turnFactor = 120.0
        self.stepDT = 0.001
        self.targetCameraPos = Point3(0.0, 40.0, 10.0)
        self.cameraSpeed = 2.0
        self.hopOffPos = Point3(16.0, 0.0, 0.0)
        self.indicatorFactor = 0.0095
        self.dropShadowCutoff = 15.0
        self.minHeightForText = 15.0
        self.heightTextOffset = -0.065
        self.beanOffset = 0.5
        self.guiBeanOffset = -0.02
        self.jumpTextShown = False
        self.toonJumped = False
        self.turnLeft = False
        self.turnRight = False
        self.leavingTrampoline = False
        self.toonVelocity = 0.0
        self.topHeight = 0.0
        self.lastPeak = 0.0
        self.beginRoundInterval = None
        self.hopOnAnim = None
        self.hopOffAnim = None
        self.flashTextInterval = None
        self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans
        self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus
        self.jellyBeanStartHeight = 20.0
        self.jellyBeanStopHeight = 90.0
        self.jellyBeanColors = [
            VBase4(1.0, 0.5, 0.5, 1.0),
            VBase4(0.5, 1.0, 0.5, 1.0),
            VBase4(0.5, 1.0, 1.0, 1.0),
            VBase4(1.0, 1.0, 0.4, 1.0),
            VBase4(0.4, 0.4, 1.0, 1.0),
            VBase4(1.0, 0.5, 1.0, 1.0)
        ]
        delta = (self.jellyBeanStopHeight -
                 self.jellyBeanStartHeight) / (self.numJellyBeans - 1)
        self.jellyBeanPositions = [
            self.jellyBeanStartHeight + n * delta
            for n in xrange(self.numJellyBeans)
        ]
        self.doSimulateStep = False

    def load(self):
        DistributedPartyTrampolineActivity.notify.debug('load')
        DistributedPartyActivity.load(self)
        self.loadModels()
        self.loadCollision()
        self.loadGUI()
        self.loadSounds()
        self.loadIntervals()
        self.activityFSM = TrampolineActivityFSM(self)
        self.activityFSM.request('Idle')
        self.animFSM = TrampolineAnimFSM(self)
        self.setBestHeightInfo('', 0)

    def loadModels(self):
        self.tramp = self.root.attachNewNode(self.uniqueName('tramp'))
        self.trampActor = Actor(
            'phase_13/models/parties/trampoline_model',
            {'emptyAnim': 'phase_13/models/parties/trampoline_anim'})
        self.trampActor.reparentTo(self.tramp)
        if self.texture:
            reskinNode = self.tramp.find(
                '**/trampoline/__Actor_modelRoot/-GeomNode')
            reskinNode.setTexture(loader.loadTexture(self.texture), 100)
        self.surface = NodePath(self.uniqueName('trampSurface'))
        self.surface.reparentTo(self.tramp)
        self.surface.setZ(self.trampHeight)
        self.trampActor.controlJoint(self.surface, 'modelRoot',
                                     'trampoline_joint1')
        self.sign.setPos(PartyGlobals.TrampolineSignOffset)
        self.beans = [
            loader.loadModelCopy('phase_4/models/props/jellybean4')
            for i in xrange(self.numJellyBeans)
        ]
        for bean in self.beans:
            bean.find('**/jellybean').setP(-35.0)
            bean.setScale(3.0)
            bean.setTransparency(True)
            bean.reparentTo(self.tramp)
            bean.stash()

        self.beans[-1].setScale(8.0)

    def loadCollision(self):
        collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4)
        collTube.setTangible(True)
        self.trampolineCollision = CollisionNode(
            self.uniqueName('TrampolineCollision'))
        self.trampolineCollision.addSolid(collTube)
        self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask
                                                | OTPGlobals.WallBitmask)
        self.trampolineCollisionNP = self.tramp.attachNewNode(
            self.trampolineCollision)
        collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0)
        collSphere.setTangible(False)
        self.trampolineTrigger = CollisionNode(
            self.uniqueName('TrampolineTrigger'))
        self.trampolineTrigger.addSolid(collSphere)
        self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.trampolineTriggerNP = self.tramp.attachNewNode(
            self.trampolineTrigger)
        self.accept('enter%s' % self.uniqueName('TrampolineTrigger'),
                    self.onTrampolineTrigger)

    def loadGUI(self):
        self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI')
        self.gui.reparentTo(base.a2dTopLeft)
        self.gui.setPos(0.115, 0, -1)
        self.gui.hide()
        self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar')
        jumpLineLocator = self.gui.find('**/jumpLine_locator')
        guiBean = self.gui.find('**/trampolineGUI_GreenJellyBean')
        self.gui.find('**/trampolineGUI_GreenJellyBean').stash()
        self.guiBeans = [
            guiBean.instanceUnderNode(jumpLineLocator,
                                      self.uniqueName('guiBean%d' % i))
            for i in xrange(self.numJellyBeans)
        ]
        self.guiBeans[-1].setScale(1.5)
        heightTextNode = TextNode(
            self.uniqueName('TrampolineActivity.heightTextNode'))
        heightTextNode.setFont(ToontownGlobals.getSignFont())
        heightTextNode.setAlign(TextNode.ALeft)
        heightTextNode.setText('0.0')
        heightTextNode.setShadow(0.05, 0.05)
        heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0)
        heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0)
        self.heightText = jumpLineLocator.attachNewNode(heightTextNode)
        self.heightText.setX(0.15)
        self.heightText.setScale(0.1)
        self.heightText.setAlphaScale(0.0)
        self.quitEarlyButtonModels = loader.loadModel(
            'phase_3.5/models/gui/inventory_gui')
        quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp')
        quitEarlyDown = self.quitEarlyButtonModels.find(
            '**/InventoryButtonDown')
        quitEarlyRollover = self.quitEarlyButtonModels.find(
            '**/InventoryButtonRollover')
        self.quitEarlyButton = DirectButton(
            parent=base.a2dTopRight,
            relief=None,
            text=TTLocalizer.PartyTrampolineQuitEarlyButton,
            text_fg=(1, 1, 0.65, 1),
            text_pos=(0, -0.23),
            text_scale=0.7,
            image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover),
            image_color=(1, 0, 0, 1),
            image_scale=(20, 1, 11),
            pos=(-0.183, 0, -0.4),
            scale=0.09,
            command=self.leaveTrampoline)
        self.quitEarlyButton.stash()
        self.flashText = OnscreenText(text='',
                                      pos=(0.0, -0.45),
                                      scale=0.2,
                                      fg=(1.0, 1.0, 0.65, 1.0),
                                      align=TextNode.ACenter,
                                      font=ToontownGlobals.getSignFont(),
                                      mayChange=True)
        self.timer = PartyUtils.getNewToontownTimer()
        self.timer.posInTopRightCorner()

    def loadSounds(self):
        self.jellyBeanSound = base.loader.loadSfx(
            'phase_4/audio/sfx/sparkly.ogg')
        self.boingSound = base.loader.loadSfx(
            'phase_4/audio/sfx/target_trampoline_2.ogg')
        self.whistleSound = base.loader.loadSfx(
            'phase_4/audio/sfx/AA_sound_whistle.ogg')

    def loadIntervals(self):
        def prepareHeightText():
            self.heightText.node().setText(
                TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ()))
            self.heightText.setZ(self.indicatorFactor * self.toon.getZ() +
                                 self.heightTextOffset)

        self.heightTextInterval = Sequence(
            Func(prepareHeightText),
            LerpFunc(self.heightText.setAlphaScale,
                     fromData=1.0,
                     toData=0.0,
                     duration=1.0))

    def unload(self):
        DistributedPartyTrampolineActivity.notify.debug('unload')
        if self.hopOnAnim and self.hopOnAnim.isPlaying():
            self.hopOnAnim.finish()
        if self.hopOffAnim and self.hopOffAnim.isPlaying():
            self.hopOffAnim.finish()
        if self.beginRoundInterval and self.beginRoundInterval.isPlaying():
            self.beginRoundInterval.finish()
        if self.flashTextInterval and self.flashTextInterval.isPlaying():
            self.flashTextInterval.finish()
        if self.heightTextInterval and self.heightTextInterval.isPlaying():
            self.heightTextInterval.finish()
        self.timer.stop()
        DistributedPartyActivity.unload(self)
        taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask'))
        taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask'))
        self.ignoreAll()
        del self.heightTextInterval
        del self.beginRoundInterval
        del self.hopOnAnim
        del self.hopOffAnim
        del self.flashTextInterval
        if hasattr(self, 'beanAnims'):
            self.cleanupJellyBeans()
        self.quitEarlyButton.destroy()
        del self.quitEarlyButton
        del self.gui
        del self.activityFSM
        del self.animFSM

    def setBestHeightInfo(self, toonName, height):
        self.bestHeightInfo = (toonName, height)
        DistributedPartyTrampolineActivity.notify.debug(
            '%s has the best height of %d' % (toonName, height))
        if height > 0:
            self.setSignNote(TTLocalizer.PartyTrampolineBestHeight %
                             self.bestHeightInfo)
        else:
            self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet)

    def leaveTrampoline(self):
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp)
            self.leavingTrampoline = True
            self.timer.reset()
            self.trampB = self.leavingTrampB
            self.ignore(base.JUMP)
            self.quitEarlyButton.stash()
            self.gui.hide()

    def requestAnim(self, request):
        self.animFSM.request(request)

    def b_requestAnim(self, request):
        self.requestAnim(request)
        self.sendUpdate('requestAnim', [request])

    def requestAnimEcho(self, request):
        if self.toon != None and self.toon.doId != base.localAvatar.doId:
            self.requestAnim(request)

    def removeBeans(self, beansToRemove):
        for i in beansToRemove:
            height, bean, guiBean, beanAnim = self.beanDetails[i]
            guiBean.stash()
            if i in self.beansToCollect:
                self.beansToCollect.remove(i)
            else:
                self.notify.warning(
                    'removeBeans avoided a crash, %d not in self.beansToCollect'
                    % i)
            self.poofBean(bean, beanAnim)

    def b_removeBeans(self, beansToRemove):
        self.removeBeans(beansToRemove)
        self.sendUpdate('removeBeans', [beansToRemove])

    def removeBeansEcho(self, beansToRemove):
        if self.toon != None and self.toon.doId != base.localAvatar.doId:
            self.removeBeans(beansToRemove)
        return

    def joinRequestDenied(self, reason):
        DistributedPartyActivity.joinRequestDenied(self, reason)
        self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny)
        base.cr.playGame.getPlace().fsm.request('walk')

    def exitRequestDenied(self, reason):
        DistributedPartyActivity.exitRequestDenied(self, reason)
        self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny)

    def setState(self, newState, timestamp):
        DistributedPartyTrampolineActivity.notify.debug(
            'setState( newState=%s, ... )' % newState)
        DistributedPartyActivity.setState(self, newState, timestamp)
        self.activityFSM.request(newState)

    def startIdle(self):
        DistributedPartyTrampolineActivity.notify.debug('startIdle')

    def finishIdle(self):
        DistributedPartyTrampolineActivity.notify.debug('finishIdle')

    def startRules(self):
        DistributedPartyTrampolineActivity.notify.debug('startRules')
        if self.doJellyBeans:
            self.setupJellyBeans()
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            self.acquireToon()

    def startActive(self):
        DistributedPartyTrampolineActivity.notify.debug('startActive')
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            base.setCellsActive(base.bottomCells, True)
            self.accept(base.MOVE_LEFT, self.onLeft)
            self.accept(base.MOVE_LEFT + '-up', self.onLeftUp)
            self.accept(base.MOVE_RIGHT, self.onRight)
            self.accept(base.MOVE_RIGHT + '-up', self.onRightUp)
            self.beginRoundInterval = Sequence(
                Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady),
                Wait(1.2),
                Func(self.flashMessage, TTLocalizer.PartyTrampolineGo),
                Func(self.beginRound))
            self.beginRoundInterval.start()

    def finishActive(self):
        DistributedPartyTrampolineActivity.notify.debug('finishActive')
        if self.doJellyBeans:
            self.cleanupJellyBeans()

    def setupJellyBeans(self):
        self.beanAnims = []
        self.beansToCollect = []
        self.beanDetails = []
        self.numBeansCollected = 0
        for i in xrange(self.numJellyBeans):
            bean = self.beans[i]
            guiBean = self.guiBeans[i]
            height = self.jellyBeanPositions[i]
            color = random.choice(self.jellyBeanColors)
            bean.find('**/jellybean').setColor(color)
            if self.toon.doId == base.localAvatar.doId:
                bean.setAlphaScale(1.0)
            else:
                bean.setAlphaScale(0.5)
            guiBean.setColor(color)
            bean.setZ(height + self.toon.getHeight() + self.beanOffset)
            guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset)
            bean.setH(0.0)
            bean.unstash()
            guiBean.unstash()
            beanAnim = bean.hprInterval(
                1.5, VBase3((i % 2 * 2 - 1) * 360.0, 0.0, 0.0))
            beanAnim.loop()
            self.beanAnims.append(beanAnim)
            self.beanDetails.append((height, bean, guiBean, beanAnim))

        self.beansToCollect = range(self.numJellyBeans)

    def cleanupJellyBeans(self):
        for bean in self.beans:
            bean.stash()

        for guiBean in self.guiBeans:
            guiBean.stash()

        if hasattr(self, 'beanAnims'):
            for beanAnim in self.beanAnims:
                beanAnim.finish()

            del self.beanAnims
            del self.beansToCollect

    def beginRound(self):
        base.playSfx(self.whistleSound)
        self.timer.setTime(PartyGlobals.TrampolineDuration)
        self.timer.countdown(PartyGlobals.TrampolineDuration)
        self.timer.show()
        self.gui.show()
        self.quitEarlyButton.unstash()
        self.notify.debug('Accepting contorl')
        self.accept(base.JUMP, self.onJump)
        self.notify.debug('setting simulate step to true')
        self.doSimulateStep = True

    def acquireToon(self):
        self.toon.disableSmartCameraViews()
        self.toon.stopUpdateSmartCamera()
        camera.wrtReparentTo(render)
        self.toon.dropShadow.reparentTo(hidden)
        self.toon.startPosHprBroadcast(period=0.2)
        self.toonAcceleration = 0.0
        self.toonVelocity = 0.0
        self.topHeight = 0.0
        self.trampB = self.normalTrampB
        self.leavingTrampoline = False
        self.hopOnAnim = Sequence(
            Func(self.toon.b_setAnimState, 'jump', 1.0), Wait(0.4),
            PartyUtils.arcPosInterval(0.75, self.toon,
                                      Point3(0.0, 0.0, self.trampHeight), 5.0,
                                      self.tramp), Func(self.postHopOn))
        self.hopOnAnim.start()

    def postHopOn(self):
        self.toon.setH(self.toon.getH() + 90.0)
        self.toon.dropShadow.reparentTo(self.surface)
        self.timeLeftToSimulate = 0.0
        self.doSimulateStep = False
        taskMgr.add(self.updateTask,
                    self.uniqueName('TrampolineActivity.updateTask'))
        base.setCellsActive(base.leftCells, False)
        base.setCellsActive(base.bottomCells, False)
        DistributedPartyActivity.startRules(self)

    def releaseToon(self):
        self._hideFlashMessage()
        self.ignore(base.MOVE_LEFT)
        self.ignore(base.MOVE_LEFT + '-up')
        self.ignore(base.MOVE_RIGHT)
        self.ignore(base.MOVE_RIGHT + '-up')
        taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask'))
        self.hopOffAnim = Sequence(
            self.toon.hprInterval(0.5,
                                  VBase3(-90.0, 0.0, 0.0),
                                  other=self.tramp),
            Func(self.toon.b_setAnimState, 'jump', 1.0),
            Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4),
            PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0,
                                      self.tramp), Func(self.postHopOff))
        self.hopOffAnim.start()

    def postHopOff(self):
        base.setCellsActive(base.leftCells, True)
        self.timer.stop()
        self.timer.hide()
        self.toon.dropShadow.reparentTo(self.toon.getShadowJoint())
        self.toon.dropShadow.setAlphaScale(1.0)
        self.toon.dropShadow.setScale(1.0)
        self.b_requestAnim('Off')
        camera.reparentTo(base.localAvatar)
        base.localAvatar.startUpdateSmartCamera()
        base.localAvatar.enableSmartCameraViews()
        base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex)
        place = base.cr.playGame.getPlace()
        if self.doJellyBeans:
            self.sendUpdate('awardBeans',
                            [self.numBeansCollected,
                             int(self.topHeight)])
            if int(self.topHeight) > self.bestHeightInfo[1]:
                self.sendUpdate('reportHeightInformation',
                                [int(self.topHeight)])
        self.d_toonExitDemand()

    def onTrampolineTrigger(self, collEntry):
        if self.activityFSM.state == 'Idle' and self.toon == None and base.cr.playGame.getPlace(
        ).fsm.getCurrentState().getName() == 'walk':
            base.cr.playGame.getPlace().fsm.request('activity')
            self.d_toonJoinRequest()
        else:
            self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied,
                              duration=2.0)

    def onJump(self):
        self.notify.debug('got onJump')
        if self.toon != None and self.toon.getZ() < self.trampHeight:
            self.toonJumped = True
            self.b_requestAnim('Jump')
        else:
            self.notify.debug('z is less than tramp height')

    def onLeft(self):
        self.turnLeft = True

    def onLeftUp(self):
        self.turnLeft = False

    def onRight(self):
        self.turnRight = True

    def onRightUp(self):
        self.turnRight = False

    def handleToonJoined(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug('handleToonJoined')
        self.toon = self.getAvatar(toonId)
        if self.toon != None and not self.toon.isEmpty():
            self.oldJumpSquatPlayRate = self.toon.getPlayRate('jump-squat')
            self.oldJumpLandPlayRate = self.toon.getPlayRate('jump-land')
            self.toon.setPlayRate(2.5, 'jump-squat')
            self.toon.setPlayRate(2.0, 'jump-land')
            self.turnLeft = False
            self.turnRight = False
            self.activityFSM.request('Rules')
            if self.toon.doId != base.localAvatar.doId:
                taskMgr.add(
                    self.remoteUpdateTask,
                    self.uniqueName('TrampolineActivity.remoteUpdateTask'))
        else:
            self.notify.warning('handleToonJoined could not get toon %d' %
                                toonId)

    def handleToonExited(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug('handleToonExited')
        if self.toon != None:
            if self.toon.doId != base.localAvatar.doId:
                taskMgr.remove(
                    self.uniqueName('TrampolineActivity.remoteUpdateTask'))
            self.surface.setZ(self.trampHeight)
            self.toon.setPlayRate(self.oldJumpSquatPlayRate, 'jump-squat')
            self.toon.setPlayRate(self.oldJumpLandPlayRate, 'jump-land')
            self.toon = None

    def handleToonDisabled(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug('handleToonDisabled')
        DistributedPartyTrampolineActivity.notify.debug('avatar ' +
                                                        str(toonId) +
                                                        ' disabled')
        if base.localAvatar.doId == toonId:
            self.releaseToon()

    def handleRulesDone(self):
        self.sendUpdate('toonReady')
        self.finishRules()

    def getTitle(self):
        if self.doJellyBeans:
            return TTLocalizer.PartyTrampolineJellyBeanTitle
        elif self.doTricks:
            return TTLocalizer.PartyTrampolineTricksTitle
        else:
            return DistributedPartyActivity.getTitle(self)

    def getInstructions(self):
        return TTLocalizer.PartyTrampolineActivityInstructions

    def updateTask(self, task):
        z = self.toon.getZ()
        dt = globalClock.getDt()
        if self.doSimulateStep:
            self.timeLeftToSimulate += dt
            while self.timeLeftToSimulate >= self.stepDT:
                z, a = self.simulateStep(z)
                self.timeLeftToSimulate -= self.stepDT

        self.toon.setZ(z)
        if z <= self.trampHeight:
            self.surface.setZ(z)
        else:
            self.surface.setZ(self.trampHeight)
        self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor)
        if self.turnLeft:
            self.toon.setH(self.toon.getH() + self.turnFactor * dt)
        if self.turnRight:
            self.toon.setH(self.toon.getH() - self.turnFactor * dt)
        currentPos = base.camera.getPos(self.toon)
        vec = self.targetCameraPos - currentPos
        newPos = currentPos + vec * (dt * self.cameraSpeed)
        base.camera.setPos(self.toon, newPos)
        base.camera.lookAt(self.toon)
        #if z > self.trampHeight:
        #    heightFactor = 1.0 - min(1.0, (z - self.trampHeight) / self.dropShadowCutoff)
        #    self.toon.dropShadow.setAlphaScale(heightFactor)
        #    self.toon.dropShadow.setScale(max(0.1, heightFactor))
        #else:
        #    self.toon.dropShadow.setAlphaScale(1.0)
        #    self.toon.dropShadow.setScale(1.0)
        if self.leavingTrampoline and z < self.trampHeight and abs(a) < 0.1:
            self.releaseToon()
        return Task.cont

    def simulateStep(self, z):
        if z >= self.trampHeight:
            a = self.g
            self.toonJumped = False
        else:
            a = self.g + self.trampK * (self.trampHeight -
                                        z) - self.trampB * self.toonVelocity
            if self.toonJumped:
                if self.lastPeak > self.earlyJumpThreshold or self.toonVelocity >= -300000.0:
                    a += self.jumpBoost
                    if self.lastPeak < self.beginningBoostThreshold:
                        a += self.beginningBoost
        lastVelocity = self.toonVelocity
        self.toonVelocity += a * self.stepDT
        if lastVelocity > 0.0 and self.toonVelocity <= 0.0:
            topOfJump = True
            bottomOfJump = False
        elif lastVelocity < 0.0 and self.toonVelocity >= 0.0:
            topOfJump = False
            bottomOfJump = True
        else:
            topOfJump = False
            bottomOfJump = False
        newZ = z + self.toonVelocity * self.stepDT
        if newZ > self.topHeight:
            self.topHeight = newZ
            if self.doJellyBeans:
                self.collectJellyBeans(newZ)
        if topOfJump:
            self.lastPeak = newZ
            if newZ >= self.minHeightForText:
                self.heightTextInterval.start()
        if topOfJump:
            if newZ > self.trampHeight + 20.0:
                self.b_requestAnim('Falling')
            elif self.animFSM.state == 'Jump':
                self.b_requestAnim('Falling')
        if newZ <= self.trampHeight and z > self.trampHeight:
            if self.animFSM.state == 'Falling':
                self.b_requestAnim('Land')
            elif self.animFSM.state != 'Neutral':
                self.b_requestAnim('Neutral')
        if bottomOfJump and a > self.boingThreshold:
            base.playSfx(self.boingSound)
        return (newZ, a)

    def collectJellyBeans(self, z):
        beansToRemove = []
        for i in self.beansToCollect:
            height = self.beanDetails[i][0]
            if height <= z:
                beansToRemove.append(i)

        if len(beansToRemove) > 0:
            base.playSfx(self.jellyBeanSound)
            self.numBeansCollected += len(beansToRemove)
            self.b_removeBeans(beansToRemove)

    def remoteUpdateTask(self, task):
        if self.toon != None and not self.toon.isEmpty():
            z = self.toon.getZ()
            if z <= self.trampHeight:
                self.surface.setZ(z)
            else:
                self.surface.setZ(self.trampHeight)
        return Task.cont

    def poofBean(self, bean, beanAnim):
        if bean == None:
            self.notify.warning(
                'poofBean, returning immediately as bean is None')
            return
        if bean.isEmpty():
            self.notify.warning(
                'poofBean, returning immediately as bean is empty')
            return
        currentAlpha = bean.getColorScale()[3]
        currentScale = bean.getScale()
        poofAnim = Sequence(
            Parallel(
                LerpFunc(bean.setAlphaScale,
                         fromData=currentAlpha,
                         toData=0.0,
                         duration=0.25),
                LerpFunc(bean.setScale,
                         fromData=currentScale,
                         toData=currentScale * 5.0,
                         duration=0.25)), Func(bean.stash),
            Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha),
            Func(bean.setScale, currentScale))
        poofAnim.start()

    def _showFlashMessage(self, message):
        if self.isDisabled():
            return
        if self.flashTextInterval is not None and self.flashTextInterval.isPlaying(
        ):
            self.flashTextInterval.finish()
        self.flashText.setText(message)
        self.flashText.setAlphaScale(1.0)
        self.flashText.unstash()

    def _hideFlashMessage(self, duration=0.0):
        if self.isDisabled():
            pass
        self.flashTextInterval = Sequence(
            Wait(duration),
            LerpFunc(self.flashText.setAlphaScale,
                     fromData=1.0,
                     toData=0.0,
                     duration=1.0), Func(self.flashText.stash))
        self.flashTextInterval.start()

    def flashMessage(self, message, duration=0.5):
        self._showFlashMessage(message)
        self._hideFlashMessage(duration)
예제 #53
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()
예제 #54
0
class CogThief(DirectObject):
    notify = directNotify.newCategory('CogThief')
    DefaultSpeedWalkAnim = 4.0
    CollisionRadius = 1.25
    MaxFriendsVisible = 4
    Infinity = 100000.0
    SeparationDistance = 6.0
    MinUrgency = 0.5
    MaxUrgency = 0.75

    def __init__(self, cogIndex, suitType, game, cogSpeed):
        self.cogIndex = cogIndex
        self.suitType = suitType
        self.game = game
        self.cogSpeed = cogSpeed
        suit = Suit.Suit()
        d = SuitDNA.SuitDNA()
        d.newSuit(suitType)
        suit.setDNA(d)
        suit.pose('walk', 0)
        self.suit = suit
        self.goal = CTGG.NoGoal
        self.goalId = CTGG.InvalidGoalId
        self.lastLocalTimeStampFromAI = 0
        self.lastPosFromAI = Point3(0, 0, 0)
        self.lastThinkTime = 0
        self.doneAdjust = False
        self.barrel = CTGG.NoBarrelCarried
        self.signalledAtReturnPos = False
        self.defaultPlayRate = 1.0
        self.netTimeSentToStartByHit = 0
        self.velocity = Vec3(0, 0, 0)
        self.oldVelocity = Vec3(0, 0, 0)
        self.acceleration = Vec3(0, 0, 0)
        self.bodyLength = self.CollisionRadius * 2
        self.cruiseDistance = 2 * self.bodyLength
        self.maxVelocity = self.cogSpeed
        self.maxAcceleration = 5.0
        self.perceptionRange = 6
        self.notify.debug('cogSpeed=%s' % self.cogSpeed)
        self.kaboomSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_cannon_fire_alt.mp3')
        self.kaboom = loader.loadModel(
            'phase_4/models/minigames/ice_game_kaboom')
        self.kaboom.setScale(2.0)
        self.kaboom.setBillboardPointEye()
        self.kaboom.hide()
        self.kaboomTrack = None
        splatName = 'splat-creampie'
        self.splat = globalPropPool.getProp(splatName)
        self.splat.setBillboardPointEye()
        self.splatType = globalPropPool.getPropType(splatName)
        self.pieHitSound = globalBattleSoundCache.getSound(
            'AA_wholepie_only.mp3')
        return

    def destroy(self):
        self.ignoreAll()
        self.suit.delete()
        self.game = None
        return

    def uniqueName(self, baseStr):
        return baseStr + '-' + str(self.game.doId)

    def handleEnterSphere(self, collEntry):
        intoNp = collEntry.getIntoNodePath()
        self.notify.debug('handleEnterSphere suit %d hit %s' %
                          (self.cogIndex, intoNp))
        if self.game:
            self.game.handleEnterSphere(collEntry)

    def gameStart(self, gameStartTime):
        self.gameStartTime = gameStartTime
        self.initCollisions()
        self.startWalkAnim()

    def gameEnd(self):
        self.moveIval.pause()
        del self.moveIval
        self.shutdownCollisions()
        self.suit.loop('neutral')

    def initCollisions(self):
        self.collSphere = CollisionSphere(0, 0, 0, 1.25)
        self.collSphere.setTangible(1)
        name = 'CogThiefSphere-%d' % self.cogIndex
        self.collSphereName = self.uniqueName(name)
        self.collNode = CollisionNode(self.collSphereName)
        self.collNode.setIntoCollideMask(CTGG.BarrelBitmask
                                         | ToontownGlobals.WallBitmask)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = self.suit.attachNewNode(self.collNode)
        self.accept('enter' + self.collSphereName, self.handleEnterSphere)
        self.pieCollSphere = CollisionTube(0, 0, 0, 0, 0, 4,
                                           self.CollisionRadius)
        self.pieCollSphere.setTangible(1)
        name = 'CogThiefPieSphere-%d' % self.cogIndex
        self.pieCollSphereName = self.uniqueName(name)
        self.pieCollNode = CollisionNode(self.pieCollSphereName)
        self.pieCollNode.setIntoCollideMask(ToontownGlobals.PieBitmask)
        self.pieCollNode.addSolid(self.pieCollSphere)
        self.pieCollNodePath = self.suit.attachNewNode(self.pieCollNode)

    def shutdownCollisions(self):
        self.ignore(self.uniqueName('enter' + self.collSphereName))
        del self.collSphere
        self.collNodePath.removeNode()
        del self.collNodePath
        del self.collNode

    def updateGoal(self, timestamp, inResponseClientStamp, goalType, goalId,
                   pos):
        self.notify.debug('self.netTimeSentToStartByHit =%s' %
                          self.netTimeSentToStartByHit)
        if not self.game:
            self.notify.debug('updateGoal self.game is None, just returning')
            return
        if not self.suit:
            self.notify.debug('updateGoal self.suit is None, just returning')
            return
        if self.goal == CTGG.NoGoal:
            self.startWalkAnim()
        if goalType == CTGG.NoGoal:
            self.notify.debug('updateGoal setting position to %s' % pos)
            self.suit.setPos(pos)
        self.lastThinkTime = 0
        self.velocity = Vec3(0, 0, 0)
        self.oldVelocity = Vec3(0, 0, 0)
        self.acceleration = Vec3(0, 0, 0)
        if goalType == CTGG.RunAwayGoal:
            pass
        if inResponseClientStamp < self.netTimeSentToStartByHit and self.goal == CTGG.NoGoal and goalType == CTGG.RunAwayGoal:
            self.notify.warning(
                'ignoring newGoal %s as cog %d was recently hit responsetime=%s hitTime=%s'
                % (CTGG.GoalStr[goalType], self.cogIndex,
                   inResponseClientStamp, self.netTimeSentToStartByHit))
        else:
            self.lastLocalTimeStampFromAI = globalClockDelta.networkToLocalTime(
                timestamp, bits=32)
            self.goal = goalType
            self.goalId = goalId
            self.lastPosFromAI = pos
            self.doneAdjust = False
        self.signalledAtReturnPos = False

    def startWalkAnim(self):
        if self.suit:
            self.suit.loop('walk')
            speed = self.cogSpeed
            self.defaultPlayRate = float(self.cogSpeed /
                                         self.DefaultSpeedWalkAnim)
            self.suit.setPlayRate(self.defaultPlayRate, 'walk')

    def think(self):
        if self.goal == CTGG.ToonGoal:
            self.thinkAboutCatchingToon()
        elif self.goal == CTGG.BarrelGoal:
            self.thinkAboutGettingBarrel()
        elif self.goal == CTGG.RunAwayGoal:
            self.thinkAboutRunAway()

    def thinkAboutCatchingToon(self):
        if not self.game:
            return
        av = self.game.getAvatar(self.goalId)
        if av:
            if not self.lastThinkTime:
                self.lastThinkTime = globalClock.getFrameTime()
            diffTime = globalClock.getFrameTime() - self.lastThinkTime
            avPos = av.getPos()
            myPos = self.suit.getPos()
            if not self.doneAdjust:
                myPos = self.lastPosFromAI
                self.notify.debug(
                    'thinkAboutCatchingToon not doneAdjust setting pos %s' %
                    myPos)
                self.doneAdjust = True
            self.suit.setPos(myPos)
            if self.game.isToonPlayingHitTrack(self.goalId):
                self.suit.headsUp(av)
                self.velocity = Vec3(0, 0, 0)
                self.oldVelocity = Vec3(0, 0, 0)
                self.acceleration = Vec3(0, 0, 0)
            else:
                self.commonMove()
            newPos = self.suit.getPos()
            self.adjustPlayRate(newPos, myPos, diffTime)
        self.lastThinkTime = globalClock.getFrameTime()

    def convertNetworkStampToGameTime(self, timestamp):
        localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32)
        gameTime = self.game.local2GameTime(localStamp)
        return gameTime

    def respondToToonHit(self, timestamp):
        localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32)
        if self.netTimeSentToStartByHit < timestamp:
            self.clearGoal()
            self.showKaboom()
            startPos = CTGG.CogStartingPositions[self.cogIndex]
            oldPos = self.suit.getPos()
            self.suit.setPos(startPos)
            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            self.notify.debug(
                'localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToToonHit'
                % (localStamp, self.lastLocalTimeStampFromAI))
        self.notify.debug(
            'respondToToonHit self.netTimeSentToStartByHit = %s' %
            self.netTimeSentToStartByHit)

    def clearGoal(self):
        self.goal = CTGG.NoGoal
        self.goalId = CTGG.InvalidGoalId

    def thinkAboutGettingBarrel(self):
        if not self.game:
            return
        if not hasattr(self.game, 'barrels'):
            return
        if self.goalId not in range(len(self.game.barrels)):
            return
        if not self.lastThinkTime:
            self.lastThinkTime = globalClock.getFrameTime()
        diffTime = globalClock.getFrameTime() - self.lastThinkTime
        barrel = self.game.barrels[self.goalId]
        barrelPos = barrel.getPos()
        myPos = self.suit.getPos()
        if not self.doneAdjust:
            myPos = self.lastPosFromAI
            self.notify.debug(
                'thinkAboutGettingBarrel not doneAdjust setting position to %s'
                % myPos)
            self.suit.setPos(myPos)
            self.doneAdjust = True
        displacement = barrelPos - myPos
        distanceToToon = displacement.length()
        self.suit.headsUp(barrel)
        lengthTravelled = diffTime * self.cogSpeed
        if lengthTravelled > distanceToToon:
            lengthTravelled = distanceToToon
        displacement.normalize()
        dirVector = displacement
        dirVector *= lengthTravelled
        newPos = myPos + dirVector
        newPos.setZ(0)
        self.suit.setPos(newPos)
        self.adjustPlayRate(newPos, myPos, diffTime)
        self.lastThinkTime = globalClock.getFrameTime()

    def stopWalking(self, timestamp):
        localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32)
        if localStamp > self.lastLocalTimeStampFromAI:
            self.suit.loop('neutral')
            self.clearGoal()

    def thinkAboutRunAway(self):
        if not self.game:
            return
        if not self.lastThinkTime:
            self.lastThinkTime = globalClock.getFrameTime()
        diffTime = globalClock.getFrameTime() - self.lastThinkTime
        returnPos = CTGG.CogReturnPositions[self.goalId]
        myPos = self.suit.getPos()
        if not self.doneAdjust:
            myPos = self.lastPosFromAI
            self.suit.setPos(myPos)
            self.doneAdjust = True
        displacement = returnPos - myPos
        distanceToToon = displacement.length()
        tempNp = render.attachNewNode('tempRet')
        tempNp.setPos(returnPos)
        self.suit.headsUp(tempNp)
        tempNp.removeNode()
        lengthTravelled = diffTime * self.cogSpeed
        if lengthTravelled > distanceToToon:
            lengthTravelled = distanceToToon
        displacement.normalize()
        dirVector = displacement
        dirVector *= lengthTravelled
        newPos = myPos + dirVector
        newPos.setZ(0)
        self.suit.setPos(newPos)
        self.adjustPlayRate(newPos, myPos, diffTime)
        if (self.suit.getPos() - returnPos).length() < 0.0001:
            if not self.signalledAtReturnPos and self.barrel >= 0:
                self.game.sendCogAtReturnPos(self.cogIndex, self.barrel)
                self.signalledAtReturnPos = True
        self.lastThinkTime = globalClock.getFrameTime()

    def makeCogCarryBarrel(self, timestamp, inResponseClientStamp, barrelModel,
                           barrelIndex, cogPos):
        if not self.game:
            return
        localTimeStamp = globalClockDelta.networkToLocalTime(timestamp,
                                                             bits=32)
        self.lastLocalTimeStampFromAI = localTimeStamp
        inResponseGameTime = self.convertNetworkStampToGameTime(
            inResponseClientStamp)
        self.notify.debug('inResponseGameTime =%s timeSentToStart=%s' %
                          (inResponseGameTime, self.netTimeSentToStartByHit))
        if inResponseClientStamp < self.netTimeSentToStartByHit and self.goal == CTGG.NoGoal:
            self.notify.warning('ignoring makeCogCarrybarrel')
        else:
            barrelModel.setPos(0, -1.0, 1.5)
            barrelModel.reparentTo(self.suit)
            self.suit.setPos(cogPos)
            self.barrel = barrelIndex

    def makeCogDropBarrel(self, timestamp, inResponseClientStamp, barrelModel,
                          barrelIndex, barrelPos):
        localTimeStamp = globalClockDelta.networkToLocalTime(timestamp,
                                                             bits=32)
        self.lastLocalTimeStampFromAI = localTimeStamp
        barrelModel.reparentTo(render)
        barrelModel.setPos(barrelPos)
        self.barrel = CTGG.NoBarrelCarried

    def respondToPieHit(self, timestamp):
        localStamp = globalClockDelta.networkToLocalTime(timestamp, bits=32)
        if self.netTimeSentToStartByHit < timestamp:
            self.clearGoal()
            self.showSplat()
            startPos = CTGG.CogStartingPositions[self.cogIndex]
            oldPos = self.suit.getPos()
            self.suit.setPos(startPos)
            if self.netTimeSentToStartByHit < timestamp:
                self.netTimeSentToStartByHit = timestamp
        else:
            self.notify.debug(
                'localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToPieHit'
                % (localStamp, self.lastLocalTimeStampFromAI))
            self.notify.debug(
                'respondToPieHit self.netTimeSentToStartByHit = %s' %
                self.netTimeSentToStartByHit)

    def cleanup(self):
        self.clearGoal()
        self.ignoreAll()
        self.suit.delete()
        if self.kaboomTrack and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.suit = None
        self.game = None
        return

    def adjustPlayRate(self, newPos, oldPos, diffTime):
        lengthTravelled = (newPos - oldPos).length()
        if diffTime:
            speed = lengthTravelled / diffTime
        else:
            speed = self.cogSpeed
        rateMult = speed / self.cogSpeed
        newRate = rateMult * self.defaultPlayRate
        self.suit.setPlayRate(newRate, 'walk')

    def commonMove(self):
        if not self.lastThinkTime:
            self.lastThinkTime = globalClock.getFrameTime()
        dt = globalClock.getFrameTime() - self.lastThinkTime
        self.oldpos = self.suit.getPos()
        pos = self.suit.getPos()
        pos += self.velocity * dt
        self.suit.setPos(pos)
        self.seeFriends()
        acc = Vec3(0, 0, 0)
        self.accumulate(acc, self.getTargetVector())
        if self.numFlockmatesSeen > 0:
            keepDistanceVector = self.keepDistance()
            oldAcc = Vec3(acc)
            self.accumulate(acc, keepDistanceVector)
            if self.cogIndex == 0:
                pass
        if acc.length() > self.maxAcceleration:
            acc.normalize()
            acc *= self.maxAcceleration
        self.oldVelocity = self.velocity
        self.velocity += acc
        if self.velocity.length() > self.maxVelocity:
            self.velocity.normalize()
            self.velocity *= self.maxVelocity
        forwardVec = Vec3(1, 0, 0)
        heading = rad2Deg(math.atan2(self.velocity[1], self.velocity[0]))
        heading -= 90
        self.suit.setH(heading)

    def getTargetVector(self):
        targetPos = Point3(0, 0, 0)
        if self.goal == CTGG.ToonGoal:
            av = self.game.getAvatar(self.goalId)
            if av:
                targetPos = av.getPos()
        elif self.goal == CTGG.BarrelGoal:
            barrel = self.game.barrels[self.goalId]
            targetPos = barrel.getPos()
        elif self.goal == CTGG.RunAwayGoal:
            targetPos = CTGG.CogReturnPositions[self.goalId]
        targetPos.setZ(0)
        myPos = self.suit.getPos()
        diff = targetPos - myPos
        if diff.length() > 1.0:
            diff.normalize()
            diff *= 1.0
        return diff

    def accumulate(self, accumulator, valueToAdd):
        accumulator += valueToAdd
        return accumulator.length()

    def seeFriends(self):
        self.clearVisibleList()
        for cogIndex in self.game.cogInfo.keys():
            if cogIndex == self.cogIndex:
                continue
            if self.sameGoal(cogIndex):
                dist = self.canISee(cogIndex)
                if dist != self.Infinity:
                    self.addToVisibleList(cogIndex)
                    if dist < self.distToNearestFlockmate:
                        self.nearestFlockmate = cogIndex
                        self.distToNearestFlockmate = dist

        return self.numFlockmatesSeen

    def clearVisibleList(self):
        self.visibleFriendsList = []
        self.numFlockmatesSeen = 0
        self.nearestFlockmate = None
        self.distToNearestFlockmate = self.Infinity
        return

    def addToVisibleList(self, cogIndex):
        if self.numFlockmatesSeen < self.MaxFriendsVisible:
            self.visibleFriendsList.append(cogIndex)
            self.numFlockmatesSeen += 1
            if self.cogIndex == 0:
                pass

    def canISee(self, cogIndex):
        if self.cogIndex == cogIndex:
            return self.Infinity
        cogThief = self.game.getCogThief(cogIndex)
        distance = self.suit.getDistance(cogThief.suit)
        if distance < self.perceptionRange:
            return distance
        return self.Infinity

    def sameGoal(self, cogIndex):
        cogThief = self.game.getCogThief(cogIndex)
        result = cogThief.goalId == self.goalId and cogThief.goal == self.goal
        return result

    def keepDistance(self):
        ratio = self.distToNearestFlockmate / self.SeparationDistance
        nearestThief = self.game.getCogThief(self.nearestFlockmate)
        change = nearestThief.suit.getPos() - self.suit.getPos()
        if ratio < self.MinUrgency:
            ratio = self.MinUrgency
        if ratio > self.MaxUrgency:
            ratio = self.MaxUrgency
        if self.distToNearestFlockmate < self.SeparationDistance:
            change.normalize()
            change *= -(1 - ratio)
        elif self.distToNearestFlockmate > self.SeparationDistance:
            change.normalize()
            change *= ratio
        else:
            change = Vec3(0, 0, 0)
        return change

    def showKaboom(self):
        if self.kaboomTrack and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.kaboom.reparentTo(render)
        self.kaboom.setPos(self.suit.getPos())
        self.kaboom.setZ(3)
        self.kaboomTrack = Parallel(
            SoundInterval(self.kaboomSound, volume=0.5),
            Sequence(
                Func(self.kaboom.showThrough),
                LerpScaleInterval(self.kaboom,
                                  duration=0.5,
                                  scale=Point3(10, 10, 10),
                                  startScale=Point3(1, 1, 1),
                                  blendType='easeOut'),
                Func(self.kaboom.hide)))
        self.kaboomTrack.start()

    def showSplat(self):
        if self.kaboomTrack and self.kaboomTrack.isPlaying():
            self.kaboomTrack.finish()
        self.splat.reparentTo(render)
        self.splat.setPos(self.suit.getPos())
        self.splat.setZ(3)
        self.kaboomTrack = Parallel(
            SoundInterval(self.pieHitSound, volume=1.0),
            Sequence(
                Func(self.splat.showThrough),
                LerpScaleInterval(self.splat,
                                  duration=0.5,
                                  scale=1.75,
                                  startScale=Point3(0.1, 0.1, 0.1),
                                  blendType='easeOut'), Func(self.splat.hide)))
        self.kaboomTrack.start()
예제 #55
0
class World(DirectObject):
    cfg = None
    def __init__(self):
        self.last_mousex = 0
        self.last_mousey = 0

        self.zone = None
        self.zone_reload_name = None
        
        self.winprops = WindowProperties( )

        # simple console output
        self.consoleNode = NodePath(PandaNode("console_root"))
        self.consoleNode.reparentTo(aspect2d)

        self.console_num_lines = 24
        self.console_cur_line = -1
        self.console_lines = []
        for i in range(0, self.console_num_lines):
            self.console_lines.append(OnscreenText(text='', style=1, fg=(1,1,1,1),
                        pos=(-1.3, .4-i*.05), align=TextNode.ALeft, scale = .035, parent = self.consoleNode))

        # Configuration
        self.consoleOut('World Forge v.%s loading configuration' % VERSION)
        self.configurator = Configurator(self)
        cfg = self.configurator.config
        resaveRes = False
        if 'xres' in cfg:
            self.xres = int(cfg['xres'])
        else:
            self.xres = 1024
            resaveRes = True

        if 'yres' in cfg:
            self.yres = int(cfg['yres'])
        else:
            self.yres = 768
            resaveRes = True

        if resaveRes:
            self.saveDefaultRes()

        self.xres_half = self.xres / 2
        self.yres_half = self.yres / 2
        self.mouse_accum = MouseAccume( lambda: (self.xres_half,self.yres_half))

        self.eyeHeight = 7.0
        self.rSpeed = 80
        self.flyMode = 1

        # application window setup
        base.win.setClearColor(Vec4(0,0,0,1))
        self.winprops.setTitle( 'World Forge')
        self.winprops.setSize(self.xres, self.yres) 
        
        base.win.requestProperties( self.winprops ) 
        base.disableMouse()
        
        # Post the instructions
        self.title = addTitle('World Forge v.' + VERSION)
        self.inst0 = addInstructions(0.95, "[FLYMODE][1]")
        self.inst1 = addInstructions(-0.95, "Camera control with WSAD/mouselook. Press K for hotkey list, ESC to exit.")
        self.inst2 = addInstructions(0.9,  "Loc:")
        self.inst3 = addInstructions(0.85, "Hdg:")
        self.error_inst = addInstructions(0, '')
        self.kh = []
        
        self.campos = Point3(155.6, 41.2, 4.93)
        base.camera.setPos(self.campos)
        
        # Accept the application control keys: currently just esc to exit navgen       
        self.accept("escape", self.exitGame)
        self.accept("window-event", self.resizeGame)
        
        # Create some lighting
        ambient_level = .6
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(ambient_level, ambient_level, ambient_level, 1.0))
        render.setLight(render.attachNewNode(ambientLight))

        direct_level = 0.8
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0.0, 0.0, -1.0))
        directionalLight.setColor(Vec4(direct_level, direct_level, direct_level, 1))
        directionalLight.setSpecularColor(Vec4(direct_level, direct_level, direct_level, 1))
        render.setLight(render.attachNewNode(directionalLight))
        
        # create a point light that will follow our view point (the camera for now)
        # attenuation is set so that this point light has a torch like effect
        self.plight = PointLight('plight')
        self.plight.setColor(VBase4(0.8, 0.8, 0.8, 1.0))
        self.plight.setAttenuation(Point3(0.0, 0.0, 0.0002))
        
        self.plnp = base.camera.attachNewNode(self.plight)
        self.plnp.setPos(0, 0, 0)
        render.setLight(self.plnp)
        self.cam_light = 1
        
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0, "cam-left":0, \
            "cam-right":0, "mouse3":0, "flymode":1 }

        # setup FOG
        self.fog_colour = (0.8,0.8,0.8,1.0)
        self.linfog = Fog("A linear-mode Fog node")
        self.linfog.setColor(self.fog_colour)
        self.linfog.setLinearRange(700, 980)         # onset, opaque distances as params
        # linfog.setLinearFallback(45,160,320)
        base.camera.attachNewNode(self.linfog)
        render.setFog(self.linfog)
        self.fog = 1
        
        # camera control
        self.campos = Point3(0, 0, 0)
        self.camHeading = 0.0
        self.camPitch = 0.0
        base.camLens.setFov(65.0)
        base.camLens.setFar(1200) 
        
        self.cam_speed = 0  # index into self.camp_speeds
        self.cam_speeds = [40.0, 80.0, 160.0, 320.0, 640.0]
        
        
        # Collision Detection for "WALKMODE"
        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  The ray 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.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0.0, 0.0, 0.0)
        self.camGroundRay.setDirection(0,0,-1)      # straight down
        self.camGroundCol = CollisionNode('camRay')
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.camGroundCol.setIntoCollideMask(BitMask32.allOff())
        
        # attach the col node to the camCollider dummy node
        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.camGroundColNp.show()
       
        # Uncomment this line to show a visual representation of the 
        # collisions occuring
        # self.cTrav.showCollisions(render)
        
        # Add the spinCameraTask procedure to the task manager.
        # taskMgr.add(self.spinCameraTask, "SpinCameraTask")
        globals.hasClickedSpawn = False;
        globals.hasClickedGrid = False;
        taskMgr.add(self.camTask, "camTask")

        self.toggleControls(1)

        # need to step the task manager once to make our fake console work
        taskMgr.step()

    # CONSOLE ---------------------------------------------------------------------
    def consoleScroll(self):
        for i in range(0, self.console_num_lines-1):
            self.console_lines[i].setText(self.console_lines[i+1].getText())
            
    def consoleOut(self, text):
        print text  # output to stdout/log too

        if self.console_cur_line == self.console_num_lines-1:
            self.consoleScroll()
        elif self.console_cur_line < self.console_num_lines-1:
            self.console_cur_line += 1

        self.console_lines[self.console_cur_line].setText(text)

        taskMgr.step()
    
    def consoleOn(self):
        self.consoleNode.show()
        
    def consoleOff(self):
        self.consoleNode.hide()
        
    # User controls -----------------------------------------------------------
    def toggleControls(self, on):

        cfg = self.configurator.config

        if on == 1:
            self.accept("escape", self.exitGame)

            self.accept("1", self.setSpeed, ["speed", 0])
            self.accept("2", self.setSpeed, ["speed", 1])
            self.accept("3", self.setSpeed, ["speed", 2])
            self.accept("4", self.setSpeed, ["speed", 3])
            self.accept("5", self.setSpeed, ["speed", 4])

            self.accept("alt-f", self.fogToggle)

            self.accept(cfg['control_lighting'], self.camLightToggle)
            self.accept(cfg['control_help'], self.displayKeyHelp)
            self.accept(cfg['control_flymode'], self.toggleFlymode)
            self.accept(cfg['control_reload-zone'], self.reloadZone)
            self.accept(cfg['control_cam-left'], self.setKey, ["cam-left",1])
            self.accept(cfg['control_cam-right'], self.setKey, ["cam-right",1])
            self.accept(cfg['control_forward'], self.setKey, ["forward",1])
            self.accept("mouse3", self.setKey, ["mouse3",1])
            self.accept(cfg['control_backward'], self.setKey, ["backward",1])
        
            self.accept("k-up", self.hideKeyHelp)
            self.accept(cfg['control_cam-left']+"-up", self.setKey, ["cam-left",0])
            self.accept(cfg['control_cam-right']+"-up", self.setKey, ["cam-right",0])
            self.accept(cfg['control_forward']+"-up", self.setKey, ["forward",0])
            self.accept("mouse3-up", self.setKey, ["mouse3",0])
            self.accept(cfg['control_backward']+"-up", self.setKey, ["backward",0])
            self.accept(cfg['toggle_edit-mode'], self.toggleEditMode)
            self.accept(cfg['toggle_insert-mode'], self.toggleInsertMode)
            self.accept(cfg['toggle_explore-mode'], self.toggleExploreMode)
            self.accept(cfg['toggle_grid-mode'], self.toggleGridMode)
            # Accept both single-presses and long presses for rotating models
            self.accept(cfg['rotate-right'] + "-repeat", self.rotateModelRight)
            self.accept(cfg['rotate-left'] + "-repeat", self.rotateModelLeft)
            self.accept(cfg['rotate-right'], self.rotateModelRight)
            self.accept(cfg['rotate-left'], self.rotateModelLeft)
            self.accept(cfg['clear-selection'], self.clearSelection)
        else:
            messenger.clear()

    def rotateModelRight(self):
        if globals.editMode == True:
            if globals.selectedSpawn:
                cfg = self.configurator.config
                globals.selectedSpawn.model.setH(globals.selectedSpawn.model.getH() + int(cfg['rotation-amount']))
                # Really not sure about that...
                if globals.selectedSpawn.model.getH() > 360:
                    globals.selectedSpawn.model.setH(0)
                print globals.selectedSpawn.model.getH()
                globals.selectedSpawn.setheadingfromworld(globals.selectedSpawn.model.getH())
                globals.spawndialog.m_spawnEntryHeadingTextCtrl.SetValue(str(globals.selectedSpawn.spawnentry_heading))
                if globals.config['autosave_edit-mode'] == 'True':
                    globals.database.UpdateSpawn(globals.selectedSpawn)
                print globals.selectedSpawn.spawnentry_heading

    def rotateModelLeft(self):
        if globals.editMode == True:
            if globals.selectedSpawn:
                cfg = self.configurator.config
                globals.selectedSpawn.model.setH(globals.selectedSpawn.model.getH() - int(cfg['rotation-amount']))
                # Really not sure about that either...
                if globals.selectedSpawn.model.getH() < -360:
                    globals.selectedSpawn.model.setH(0)
                print globals.selectedSpawn.model.getH()
                globals.selectedSpawn.setheadingfromworld(globals.selectedSpawn.model.getH())
                globals.spawndialog.m_spawnEntryHeadingTextCtrl.SetValue(str(globals.selectedSpawn.spawnentry_heading))
                if globals.config['autosave_edit-mode'] == 'True':
                    globals.database.UpdateSpawn(globals.selectedSpawn)
                print globals.selectedSpawn.spawnentry_heading

    def clearSelection(self, eraseNpcId = True):
        globals.selectedspawn = None
        globals.selectedgrid = None
        globals.picker.lastSelectedObject = None
        if self.inst6:
            self.inst6.destroy()
        self.inst6 = addInstructions(0.7, "Current selection: None")
        npcid = globals.spawndialog.m_spawnEntryNpcIdTextCtrl.Value
        globals.spawndialog.Reset()
        # f*****g hacky shit man
        if eraseNpcId == False:
            globals.spawndialog.m_spawnEntryNpcIdTextCtrl.SetValue(npcid)
        gridmanager = GridpointManager()
        gridmanager.ResetGridList()
        print "Cleared all selections !"

    def toggleDefaultMode(self):
        globals.editMode = False
        globals.insertMode = False
        globals.exploreMode = True
        globals.gridMode = False
        print "STARTUP Explore mode ACTIVATED"
        print "STARTUP Grid mode DEACTIVATED"
        self.inst4 = addInstructions(0.8, "Explore mode ON")
        self.inst5 = addInstructions(0.75, "Grid mode OFF")
        self.inst6 = addInstructions(0.7, "Current selection: None")

    def toggleEditMode(self):
        globals.editMode = True
        globals.insertMode = False
        globals.exploreMode = False
        print "Edit mode ACTIVATED"
        if self.inst4:
            self.inst4.destroy()
        self.inst4 = addInstructions(0.8, "Edit mode ON")

    def toggleInsertMode(self):
        globals.editMode = False
        globals.insertMode = True
        globals.exploreMode = False
        print "Insert mode ACTIVATED"
        if self.inst4:
            self.inst4.destroy()
        self.inst4 = addInstructions(0.8, "Insert mode ON")

    def toggleExploreMode(self):
        globals.editMode = False
        globals.insertMode = False
        globals.exploreMode = True
        print "Explore mode ACTIVATED"
        if self.inst4:
            self.inst4.destroy()
        self.inst4 = addInstructions(0.8, "Explore mode ON")

    def toggleGridMode(self):
        if globals.gridMode == False:
            globals.gridMode = True
            print "Grid mode ACTIVATED"
            if self.inst5:
                self.inst5.destroy()
            self.inst5 = addInstructions(0.75, "Grid mode ON")
        else:
            globals.gridMode = False
            print "Grid mode DEACTIVATED"
            if self.inst5:
                self.inst5.destroy()
            self.inst5 = addInstructions(0.75, "Grid mode OFF")

    def setSpeed(self, key, value):
        self.cam_speed = value
        self.setFlymodeText()
        
    def fogToggle(self):
        if self.fog == 1:
            render.clearFog()
            base.camLens.setFar(100000) 
            self.fog = 0
        else:
            render.setFog(self.linfog)
            base.camLens.setFar(1200) 
            self.fog = 1
            
    def camLightToggle(self):
        if self.cam_light == 0:
            render.setLight(self.plnp)
            self.cam_light = 1
        else:
            render.clearLight(self.plnp)
            self.cam_light = 0
        
    def displayKeyHelp(self):
        self.kh = []
        msg = 'HOTKEYS:'
        pos = 0.75
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = '------------------'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'W: camera fwd, S: camera bck, A: rotate view left, D: rotate view right'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = '1-5: set camera movement speed'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'F: toggle Flymode/Walkmode'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'L: load a zone'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'ALT-F: toggle FOG and FAR plane on/off'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'T: toggle additional camera "torch" light on/off'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'Z: set currently loaded zone as new startup default'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
        msg = 'ESC: exit World Forge'
        pos -= 0.05
        self.kh.append(OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-0.5, pos), align=TextNode.ALeft, scale = .04))
     
    def hideKeyHelp(self):
        for n in self.kh:
            n.removeNode()
                        
    def setFlymodeText(self):
        zname = ''
        if self.zone:
            zname = self.zone.name
            
        if self.flyMode == 0:
            self.inst0.setText("[WALKMODE][%i] %s" % (self.cam_speed+1, zname))
        else:
            self.inst0.setText("[FLYMODE][%i] %s " % (self.cam_speed+1, zname))
        
    def toggleFlymode(self):
        zname = ''
        if self.zone:
            zname = self.zone.name

        if self.flyMode == 0:
            self.flyMode = 1
        else:
            self.flyMode = 0
            
        self.setFlymodeText()

    # Define a procedure to move the camera.
    def spinCameraTask(self, task):
        angleDegrees = task.time * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        base.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
        base.camera.setHpr(angleDegrees, 0, 0)
        return task.cont


    def camTask(self, task):
        if globals.hasClickedSpawn:
           base.camera.setPos(globals.selectedSpawnPoint3D)
           self.campos = globals.selectedSpawnPoint3D
           globals.hasClickedSpawn = False
        elif globals.hasClickedGrid:
            base.camera.setPos(globals.selectedGridPoint3D)
            self.campos = globals.selectedGridPoint3D
            globals.hasClickedGrid = False
        else:
            # query the mouse
            mouse_dx = 0
            mouse_dy = 0


            # if we have a mouse and the right button is depressed
            if base.mouseWatcherNode.hasMouse():
                if self.keyMap["mouse3"] != 0:
                    self.mouse_accum.update()
                else:
                    self.mouse_accum.reset()

            mouse_dx = self.mouse_accum.dx
            mouse_dy = self.mouse_accum.dy

            self.rXSpeed = fabs(self.mouse_accum.dx) * (self.cam_speed+1) * max(5 * 1000/self.xres,3)
            self.rYSpeed = fabs(self.mouse_accum.dy) * (self.cam_speed+1) * max(3 * 1000/self.yres,1)
            
            if (self.keyMap["cam-left"]!=0 or mouse_dx < 0):
                if self.rSpeed < 160:
                    self.rSpeed += 80 * globalClock.getDt()

                if mouse_dx != 0:
                    self.camHeading += self.rXSpeed * globalClock.getDt()
                else:
                    self.camHeading += self.rSpeed * globalClock.getDt()

                if self.camHeading > 360.0:
                    self.camHeading = self.camHeading - 360.0
            elif (self.keyMap["cam-right"]!=0 or mouse_dx > 0):
                if self.rSpeed < 160:
                    self.rSpeed += 80 * globalClock.getDt()

                if mouse_dx != 0:
                    self.camHeading -= self.rXSpeed * globalClock.getDt()
                else:
                    self.camHeading -= self.rSpeed * globalClock.getDt()

                if self.camHeading < 0.0:
                    self.camHeading = self.camHeading + 360.0
            else:
                self.rSpeed = 80

            if mouse_dy > 0:
                self.camPitch += self.rYSpeed * globalClock.getDt()
            elif mouse_dy < 0:
                self.camPitch -= self.rYSpeed * globalClock.getDt()
            
            # set camera heading and pitch
            base.camera.setHpr(self.camHeading, self.camPitch, 0)

            # viewer position (camera) movement control
            v = render.getRelativeVector(base.camera, Vec3.forward())
            if not self.flyMode:
                v.setZ(0.0)
        
            move_speed = self.cam_speeds[self.cam_speed]
            if self.keyMap["forward"] == 1:
                self.campos += v * move_speed * globalClock.getDt()
            if self.keyMap["backward"] == 1:
                self.campos -= v * move_speed * globalClock.getDt()            

            # actually move the camera
            lastPos = base.camera.getPos()
            base.camera.setPos(self.campos)
            # self.plnp.setPos(self.campos)      # move the point light with the viewer position

            # WALKMODE: simple collision detection
            # we simply check a ray from slightly below the "eye point" straight down
            # for geometry collisions and if there are any we detect the point of collision
            # and adjust the camera's Z accordingly
            if self.flyMode == 0:   
                # move the camera to where it would be if it made the move 
                # the colliderNode moves with it
                # base.camera.setPos(self.campos)
                # check for collissons
                self.cTrav.traverse(render)
                entries = []
                for i in range(self.camGroundHandler.getNumEntries()):
                    entry = self.camGroundHandler.getEntry(i)
                    entries.append(entry)
                    # print 'collision'
                entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                             x.getSurfacePoint(render).getZ()))
                                     
                if (len(entries) > 0): # and (entries[0].getIntoNode().getName() == "terrain"):
                    # print len(entries)
                    self.campos.setZ(entries[0].getSurfacePoint(render).getZ()+self.eyeHeight)
                else:
                    self.campos = lastPos
                    base.camera.setPos(self.campos)
        
                #if (base.camera.getZ() < self.player.getZ() + 2.0):
                #    base.camera.setZ(self.player.getZ() + 2.0)


            # update loc and hpr display
            pos = base.camera.getPos()
            hpr = base.camera.getHpr()
            self.inst2.setText('Loc: %.2f, %.2f, %.2f' % (pos.getX(), pos.getY(), pos.getZ()))
            self.inst3.setText('Hdg: %.2f, %.2f, %.2f' % (hpr.getX(), hpr.getY(), hpr.getZ()))
        return task.cont

    def exitGame(self):
        globals.database.conn.close()
        print "DB connection closed !"
        sys.exit(0)

    def resizeGame(self,win):
        props = base.win.getProperties() 
        self.xres = props.getXSize()
        self.yres = props.getYSize()
        self.xres_half = self.xres / 2
        self.yres_half = self.yres / 2
        self.saveDefaultRes()
                
    #Records the state of the arrow keys
    # this is used for camera control
    def setKey(self, key, value):
        self.keyMap[key] = value

    # -------------------------------------------------------------------------
    # this is the mythical MAIN LOOP :)
    def update(self):

        if self.zone_reload_name != None:
            self.doReload(self.zone_reload_name)
            self.zone_reload_name = None

        if self.zone != None:
            self.zone.update()

        taskMgr.step()
        
        
    # ZONE loading ------------------------------------------------------------
    
    # general zone loader driver
    # removes existing zone (if any) and load the new one 
    def loadZone(self, name, path):
        if path[len(path)-1] != '/':
            path += '/'

        if self.zone:
            self.zone.rootNode.removeNode()
            
        self.zone = Zone(self, name, path)
        error = self.zone.load()
        if error == 0:
            self.consoleOff()
            self.setFlymodeText()
            base.setBackgroundColor(self.fog_colour)
        
    def saveDefaultRes(self):
        cfg = self.configurator.config
        cfg['xres'] = str(self.xres)
        cfg['yres'] = str(self.yres)

    # initial world load after bootup
    def load(self):       
        cfg = self.configurator.config
            
        zone_name = cfg['default_zone']
        globals.currentZone = zone_name
        basepath = cfg['basepath']
        self.loadZone(zone_name, basepath)

    # zone reload user interface
    
    # this gets called from our update loop when it detects that zone_reload_name has been set
    # we do this in this convoluted fashion in order to keep the main loop taskMgr updates ticking
    # because otherwise our status console output at various stages during the zone load would not
    # be displayed. Yes, this is hacky.
    def doReload(self, name):
        cfg = self.configurator.config
        basepath = cfg['basepath']
        self.loadZone(name, basepath)

    # form dialog callback
    # this gets called from the form when the user has entered a something
    # (hopefully a correct zone short name)
    def reloadZoneDialogCB(self, name):
        self.frmDialog.end()
        self.zone_reload_name = name
        self.toggleControls(1)

    # this is called when the user presses "l"
    # it disables normal controls and fires up our query form dialog
    def reloadZone(self):
        base.setBackgroundColor((0,0,0))
        self.toggleControls(0)
        self.consoleOn()
        self.frmDialog = FileDialog(
            "Please enter the shortname of the zone you wish to load:", 
            "Examples: qrg, blackburrow, freportn, crushbone etc.",
            self.reloadZoneDialogCB) 
        
        self.frmDialog.activate()   # relies on the main update loop to run

    #####################################
    # Custom methods
    #####################################


    # Handles populating the zone with spawn data from the EQEmu DB
    # also makes each spawner model pickable
    def PopulateSpawns(self, cursor, numrows):
        spawn_coords = list()
        globals.spawn_list = list()
        cfg = self.configurator.config
        for x in range(0, numrows):
            row = cursor.fetchone()
            point = Point3(long(row["Spawn2Y"]), long(row["Spawn2X"]), long(row["Spawn2Z"]))
            if cfg['ignore_duplicate_spawns'] == 'True':
                if point not in spawn_coords:
                    self.PlaceSpawnPointOn3dMap(row)
                    spawn_coords.append(point)
            else:
                self.PlaceSpawnPointOn3dMap(row)

    def PlaceSpawnPointOn3dMap(self, row):
        spawn = Spawn()
        self.InitSpawnData(spawn, row)
        spawn.model = loader.loadModel(spawn.modelname)
        spawn.initmodel()
        spawn.model.reparentTo(render)
        spawn.initheadingfromdb(row["Spawn2Heading"])
        spawn.placeintoworld(row["Spawn2Y"], row["Spawn2X"], row["Spawn2Z"])
        min, macks = spawn.model.getTightBounds()
        radius = max([macks.getY() - min.getY(), macks.getX() - min.getX()]) / 2
        cs = CollisionSphere(row["Spawn2X"], row["Spawn2Y"], row["Spawn2Z"], radius)
        csNode = spawn.model.attachNewNode(CollisionNode("modelCollide"))
        csNode.node().addSolid(cs)
        # TODO: ADD MORE TAGS??
        spawn.model.setTag("name", row["NpcName"])
        spawn.model.setTag("spawngroup_name", row["spawngroup_name"])
        spawn.model.setTag("spawn2id", str(row["Spawn2Id"]))
        spawn.model.setTag("type", "spawn")
        globals.picker.makePickable(spawn.model)
        globals.spawn_list.append(spawn)


    # Initializes a spawn object with database values
    def InitSpawnData(self, spawn, row):
        spawn.spawngroup_id = row["Spawngroup_id"]
        spawn.spawngroup_name = row["spawngroup_name"]
        spawn.spawngroup_minx = row["Spawngroup_minX"]
        spawn.spawngroup_maxx= row["Spawngroup_maxX"]
        spawn.spawngroup_miny = row["Spawngroup_minY"]
        spawn.spawngroup_maxy = row["Spawngroup_maxY"]
        spawn.spawngroup_dist = row["Spawngroup_dist"]
        spawn.spawngroup_mindelay = row["Spawngroup_mindelay"]
        spawn.spawngroup_delay = row["Spawngroup_delay"]
        spawn.spawngroup_despawn = row["Spawngroup_despawntimer"]
        spawn.spawngroup_despawntimer = row["Spawngroup_despawntimer"]
        spawn.spawngroup_spawnlimit = row["Spawngroup_spawnlimit"]


        spawn.spawnentry_id = row["Spawn2Id"]
        spawn.spawnentry_npcid = row["NpcId"]
        spawn.spawnentry_npcname = row["NpcName"]
        spawn.spawnentry_chance = row["Spawnentry_chance"]
        spawn.spawnentry_x = row["Spawn2X"]
        spawn.spawnentry_y = row["Spawn2Y"]
        spawn.spawnentry_z = row["Spawn2Z"]
        spawn.spawnentry_heading = row["Spawn2Heading"]
        spawn.spawnentry_respawn = row["Spawn2Respawn"]
        spawn.spawnentry_variance = row["Spawn2Variance"]
        spawn.spawnentry_pathgrid = row["Spawn2Grid"]
        spawn.spawnentry_condition = row["Spawn2Condition"]
        spawn.spawnentry_condvalue = row["Spawn2CondValue"]
        spawn.spawnentry_version = row["Spawn2Version"]
        spawn.spawnentry_enabled = row["Spawn2Enabled"]
        spawn.spawnentry_animation = row["Spawn2Animation"]
        spawn.spawnentry_zone = row["Spawn2Zone"]

        spawn.spawnentry_originalx = row["Spawn2X"]
        spawn.spawnentry_originaly = row["Spawn2Y"]
        spawn.spawnentry_originalz = row["Spawn2Z"]
        spawn.spawnentry_originalheading = row["Spawn2Heading"]


    # Initializes the camera position upon startup
    def InitCameraPosition(self):
        world.campos = Point3(-155.6, 41.2, 4.9 + world.eyeHeight)
        world.camHeading = 270.0

        base.camera.setPos(world.campos)

    def GetCamera(self):
        return base.camera
예제 #56
0
파일: usuario.py 프로젝트: PlumpMath/vinerx
class Usuario(object):
    '''
    Usuario
    '''
    def __init__(self, dadosUsuario, principal=False):
        self.key = dadosUsuario['key']
        self.nick = dadosUsuario['nick']
        self.vida_real = float(dadosUsuario['vida_real'])
        self.vida_total = float(dadosUsuario['vida_total'])
        self.mana_real = float(dadosUsuario['mana_real'])
        self.mana_total = float(dadosUsuario['mana_total'])
        self.forca = float(dadosUsuario['forca'])
        self.velocidade = float(dadosUsuario['velocidade'])
        self.velocidade_atack = float(dadosUsuario['velocidade_atack'])

        self.estaMovendo = False
        self.estaRodando = False

        self.__task_name = "Task Usuario - " + self.key

        self.keyMap = {
            TECLA_esquerda: EVENT_up,
            TECLA_direita: EVENT_up,
            TECLA_frente: EVENT_up,
            TECLA_traz: EVENT_up
        }

        pandaFileModelo = get_path_modelo("ralph")
        pandaFileAnimacaoRun = get_path_animacao("ralph-run")
        pandaFileAnimacaoWalk = get_path_animacao("ralph-walk")

        self.modelo = Actor(pandaFileModelo, {
            "run": pandaFileAnimacaoRun,
            "walk": pandaFileAnimacaoWalk
        })
        self.modelo.reparentTo(render)
        self.modelo.setScale(SCALE_MODELOS)

        self.set_pos((float(dadosUsuario['x']), float(dadosUsuario['y']),
                      float(dadosUsuario['z'])))
        self.set_h(float(dadosUsuario['h']))

        if not principal:
            self.text = Text(parent=self.modelo,
                             pos=(0, 0, 5.5),
                             scale=.5,
                             align='center',
                             cor=COR_VERDE,
                             text=self.nick)

            self.text.billboardEffect()

        self.__setup_collision()

        taskMgr.add(self.__task_movimentacao, self.__task_name, sort=1)

    def get_x(self):
        return self.modelo.getX()

    def get_y(self):
        return self.modelo.getY()

    def get_z(self):
        return self.modelo.getZ()

    def get_h(self):
        return self.modelo.getH()

    def get_pos(self):
        return self.modelo.getPos()

    def set_x(self, x):
        self.modelo.setX(x)

    def set_y(self, y):
        self.modelo.setY(y)

    def set_z(self, z):
        self.modelo.setZ(z)

    def set_h(self, h):
        self.modelo.setH(h)

    def set_pos(self, pos):
        self.modelo.setPos(pos)

    def delete(self):
        taskMgr.remove(self.__task_name)

        self.modelo.delete()

    def __setup_collision(self):
        #Colisao
        self.cTrav = CollisionTraverser('usuarioTraverser')

        self.ralphGroundRay = CollisionRay()
        self.ralphGroundRay.setOrigin(0, 0, 5)
        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.modelo.attachNewNode(self.ralphGroundCol)
        self.ralphGroundHandler = CollisionHandlerQueue()

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

        #self.ralphGroundColNp.show()
        #self.cTrav.showCollisions(render)
        #Colisao

    def __task_movimentacao(self, task):
        dt = globalClock.getDt()
        startpos = self.modelo.getPos()

        #movimentos usuario modelo
        if self.keyMap[TECLA_esquerda] == EVENT_down and self.keyMap[
                TECLA_direita] == EVENT_up:
            self.modelo.setH(self.modelo, ((self.velocidade * 5) * dt))

            if not self.estaRodando:
                self.estaRodando = True

        elif self.keyMap[TECLA_direita] == EVENT_down and self.keyMap[
                TECLA_esquerda] == EVENT_up:
            self.modelo.setH(self.modelo, ((self.velocidade * 5) * dt) * -1)

            if not self.estaRodando:
                self.estaRodando = True

        elif self.estaRodando:
            self.estaRodando = False

        if self.keyMap[TECLA_frente] == EVENT_down and self.keyMap[
                TECLA_traz] == EVENT_up:
            self.modelo.setY(self.modelo, ((self.velocidade * 2) * dt) * -1)

            if self.estaMovendo is False:
                self.modelo.loop("run")
                self.estaMovendo = True

        elif self.keyMap[TECLA_traz] == EVENT_down and self.keyMap[
                TECLA_frente] == EVENT_up:
            self.modelo.setY(self.modelo, (self.velocidade * dt))

            if self.estaMovendo is False:
                self.modelo.loop("walk")
                self.estaMovendo = True

        elif self.estaMovendo:
            self.modelo.stop()
            self.modelo.pose("walk", 5)
            self.estaMovendo = False
        #movimentos usuario modelo

        if self.estaMovendo:

            self.cTrav.traverse(render)

            if self.ralphGroundHandler.getNumEntries() == 1:
                entry = self.ralphGroundHandler.getEntry(0)
                if entry.getIntoNode().getName() == "terrain":
                    self.modelo.setZ(entry.getSurfacePoint(render).getZ())
            else:
                self.modelo.setPos(startpos)

        return task.cont
예제 #57
0
파일: polls.py 프로젝트: yglkings/PlaneNet
    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)
        base.setBackgroundColor(0, 0, 0)

        self.accept("escape", sys.exit)  # Escape quits
        self.disableMouse()
        camera.setPosHpr(0, 0, 0, 0, 0, 0)

        lens = PerspectiveLens()
        lens.setFov(90, 60)
        lens.setNear(0.01)
        lens.setFar(100000)
        self.cam.node().setLens(lens)

        self.ballSize = 0.025
        self.cueLength = 0.2
        # self.ballRoot = render.attachNewNode("ballRoot")
        # #self.ball = loader.loadModel("models/ball")
        # self.ball = loader.loadModel("models/ball_0_center.egg")
        # #self.ball = loader.loadModel("models/ball.dae")
        # self.ball.setScale(ballSize, ballSize, ballSize)
        # self.ball.reparentTo(self.ballRoot)
        # #print(self.ball.getBounds())
        # #exit(1)
        # #self.ballSphere = self.ball.find("**/ball")
        # #print(self.ball.getScale()[0])
        # cs = CollisionSphere(0, 0, 0, 1)
        # self.ballSphere = self.ball.attachNewNode(CollisionNode('ball'))
        # self.ballSphere.node().addSolid(cs)

        # self.ballSphere.node().setFromCollideMask(BitMask32.bit(0))
        # self.ballSphere.node().setIntoCollideMask(BitMask32.bit(1))

        self.sceneIndex = 2
        self.planeInfo = PlaneScene(self.sceneIndex)

        self.planeScene = self.planeInfo.generateEggModel()
        self.planeScene.setTwoSided(True)
        self.planeScene.reparentTo(render)
        self.planeScene.hide()

        planeTriangles, horizontalPlaneTriangles, self.gravityDirection = self.planeInfo.getPlaneTriangles(
        )

        self.ballRoots = []
        self.balls = []
        self.ballSpheres = []
        self.ballGroundRays = []
        for ballIndex in xrange(3):
            ballRoot = render.attachNewNode("ballRoot_" + str(ballIndex))
            ball = loader.loadModel("models/ball_" + str(ballIndex) +
                                    "_center.egg")
            ball.setScale(self.ballSize, self.ballSize, self.ballSize)

            cs = CollisionSphere(0, 0, 0, 1)
            ballSphere = ball.attachNewNode(
                CollisionNode('ball_' + str(ballIndex)))
            ballSphere.node().addSolid(cs)
            ballSphere.node().setFromCollideMask(
                BitMask32.bit(0) | BitMask32.bit(1) | BitMask32.bit(3)
                | BitMask32.bit(4))
            ballSphere.node().setIntoCollideMask(BitMask32.bit(1))

            ball.reparentTo(ballRoot)
            self.ballRoots.append(ballRoot)
            self.balls.append(ball)
            self.ballSpheres.append(ballSphere)

            ballGroundRay = CollisionRay()  # Create the ray
            ballGroundRay.setOrigin(0, 0, 0)  # Set its origin
            ballGroundRay.setDirection(
                self.gravityDirection[0], self.gravityDirection[1],
                self.gravityDirection[2])  # And its direction
            # Collision solids go in CollisionNode
            # Create and name the node
            ballGroundCol = CollisionNode('ball_ray_' + str(ballIndex))
            ballGroundCol.addSolid(ballGroundRay)  # Add the ray
            ballGroundCol.setFromCollideMask(
                BitMask32.bit(2))  # Set its bitmasks
            ballGroundCol.setIntoCollideMask(BitMask32.allOff())
            # Attach the node to the ballRoot so that the ray is relative to the ball
            # (it will always be 10 feet over the ball and point down)
            ballGroundColNp = ballRoot.attachNewNode(ballGroundCol)
            self.ballGroundRays.append(ballGroundColNp)

            ballRoot.hide()
            continue

        # Finally, we create a CollisionTraverser. CollisionTraversers are what
        # do the job of walking the scene graph and calculating collisions.
        # For a traverser to actually do collisions, you need to call
        # traverser.traverse() on a part of the scene. Fortunately, ShowBase
        # has a task that does this for the entire scene once a frame.  By
        # assigning it to self.cTrav, we designate that this is the one that
        # it should call traverse() on each frame.
        self.cTrav = CollisionTraverser()

        # Collision traversers tell collision handlers about collisions, and then
        # the handler decides what to do with the information. We are using a
        # CollisionHandlerQueue, which simply creates a list of all of the
        # collisions in a given pass. There are more sophisticated handlers like
        # one that sends events and another that tries to keep collided objects
        # apart, but the results are often better with a simple queue
        self.cHandler = CollisionHandlerQueue()
        # Now we add the collision nodes that can create a collision to the
        # traverser. The traverser will compare these to all others nodes in the
        # scene. There is a limit of 32 CollisionNodes per traverser
        # We add the collider, and the handler to use as a pair

        #self.cTrav.addCollider(self.ballSphere, self.cHandler)
        for ballSphere in self.ballSpheres:
            self.cTrav.addCollider(ballSphere, self.cHandler)
            continue
        for ballGroundRay in self.ballGroundRays:
            self.cTrav.addCollider(ballGroundRay, self.cHandler)
            continue
        #self.cTrav.addCollider(self.ballGroundColNp, self.cHandler)

        # Collision traversers have a built in tool to help visualize collisions.
        # Uncomment the next line to see it.
        #self.cTrav.showCollisions(render)

        # This section deals with lighting for the ball. Only the ball was lit
        # because the maze has static lighting pregenerated by the modeler
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.55, .55, .55, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 0, -1))
        directionalLight.setColor((0.375, 0.375, 0.375, 1))
        directionalLight.setSpecularColor((1, 1, 1, 1))

        for ballRoot in self.ballRoots:
            ballRoot.setLight(render.attachNewNode(ambientLight))
            ballRoot.setLight(render.attachNewNode(directionalLight))
            continue

        # This section deals with adding a specular highlight to the ball to make
        # it look shiny.  Normally, this is specified in the .egg file.
        m = Material()
        m.setSpecular((1, 1, 1, 1))
        m.setShininess(96)
        for ball in self.balls:
            ball.setMaterial(m, 1)
            continue

        self.original = False
        if self.original:
            camera.setPosHpr(0, 0, 25, 0, -90, 0)
            self.maze = loader.loadModel("models/maze")
            self.maze.reparentTo(render)
            self.walls = self.maze.find("**/wall_collide")
            self.walls.node().setIntoCollideMask(BitMask32.bit(0))
            self.walls.show()
            pass

        #planeTriangles, planeNormals = self.planeInfo.getPlaneGeometries()

        self.triNPs = []
        for triangleIndex, triangle in enumerate(planeTriangles):
            #print(triangleIndex)
            #for triangle in triangles:
            #print(triangle)
            tri = CollisionPolygon(
                Point3(triangle[0][0], triangle[0][1], triangle[0][2]),
                Point3(triangle[1][0], triangle[1][1], triangle[1][2]),
                Point3(triangle[2][0], triangle[2][1], triangle[2][2]))
            triNP = render.attachNewNode(
                CollisionNode('tri_' + str(triangleIndex)))
            triNP.node().setIntoCollideMask(BitMask32.bit(0))
            triNP.node().addSolid(tri)
            self.triNPs.append(triNP)
            #triNP.show()
            continue

        #print(horizontalPlaneTriangles)

        for triangleIndex, triangle in enumerate(horizontalPlaneTriangles):
            #print(triangleIndex)
            #for triangle in triangles:
            #print(triangle)
            tri = CollisionPolygon(
                Point3(triangle[0][0], triangle[0][1], triangle[0][2]),
                Point3(triangle[1][0], triangle[1][1], triangle[1][2]),
                Point3(triangle[2][0], triangle[2][1], triangle[2][2]))
            triNP = render.attachNewNode(
                CollisionNode('ground_' + str(triangleIndex)))
            triNP.node().setIntoCollideMask(BitMask32.bit(2))
            triNP.node().addSolid(tri)
            self.triNPs.append(triNP)
            #triNP.show()
            continue

        # tri = CollisionPolygon(Point3(-1, 4, -1), Point3(2, 4, -1), Point3(2, 4, 2))
        # triNP = render.attachNewNode(CollisionNode('tri'))
        # triNP.node().setIntoCollideMask(BitMask32.bit(0))
        # triNP.node().addSolid(tri)
        # triNP.show()

        #self.planeScene.node().setIntoCollideMask(BitMask32.bit(0))
        # roomRootNP = self.planeScene
        # roomRootNP.flattenLight()
        # mesh = BulletTriangleMesh()
        # polygons = roomRootNP.findAllMatches("**/+GeomNode")

        # # p0 = Point3(-10, 4, -10)
        # # p1 = Point3(-10, 4, 10)
        # # p2 = Point3(10, 4, 10)
        # # p3 = Point3(10, 4, -10)
        # # mesh.addTriangle(p0, p1, p2)
        # # mesh.addTriangle(p1, p2, p3)

        # print(polygons)
        # for polygon in polygons:
        #     geom_node = polygon.node()
        #     #geom_node.reparentTo(self.render)
        #     #print(geom_node.getNumGeoms())
        #     ts = geom_node.getTransform()
        #     #print(ts)
        #     for geom in geom_node.getGeoms():
        #         mesh.addGeom(geom, ts)
        #         continue
        #     continue
        # #self.scene = roomRootNP
        # shape = BulletTriangleMeshShape(mesh, dynamic=False)
        # #shape = BulletPlaneShape(Vec3(0, 0, 1), 1)
        # room = BulletRigidBodyNode('scene')
        # room.addShape(shape)
        # #room.setLinearDamping(0.0)
        # #room.setFriction(0.0)
        # print(shape)
        # room.setDeactivationEnabled(False)
        # roomNP = render.attachNewNode(room)
        # roomNP.setPos(0, 0, 0)
        # roomNP.node().setIntoCollideMask(BitMask32.bit(0))
        # self.world = BulletWorld()
        # self.world.setGravity(Vec3(0, 0, 0))
        # self.world.attachRigidBody(roomNP.node())
        #room.setRestitution(1)

        #self.roomNP = self.scene

        self.cueRoot = render.attachNewNode("cueRoot")
        self.cue = loader.loadModel("models/cue_center.egg")
        self.cue.setScale(self.cueLength * 3, self.cueLength * 3,
                          self.cueLength)
        self.cue.reparentTo(self.cueRoot)

        self.cuePos = (10, 0, 0)

        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 separate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(2))
        self.pickerNode.setIntoCollideMask(BitMask32.allOff())
        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.cTrav.addCollider(self.pickerNP, self.cHandler)

        self.accept("mouse1", self.hit)  # left-click grabs a piece

        self.holeLength = 0.06
        holePos, holeHpr = self.planeInfo.getHolePos()
        self.holeRoot = render.attachNewNode("holeRoot")
        #self.hole = loader.loadModel("models/hole_horizontal_center.egg")
        self.hole = loader.loadModel("models/hole_color.egg")
        #self.hole = loader.loadModel("models/billiards_hole_center.egg")
        self.hole.setScale(self.holeLength, self.holeLength, self.holeLength)
        self.hole.reparentTo(self.holeRoot)
        self.hole.setTwoSided(True)
        self.holeRoot.setPos(holePos[0], holePos[1], holePos[2])
        self.holeRoot.setHpr(holeHpr[0], holeHpr[1], holeHpr[2])
        #tex = loader.loadTexture('models/Black_Hole.jpg')
        #self.hole.setTexture(tex, 1)
        self.holeRoot.hide()

        ct = CollisionTube(0, 0, 0, 0, 0.001, 0, 0.5)
        self.holeTube = self.hole.attachNewNode(CollisionNode('hole'))
        self.holeTube.node().addSolid(ct)
        self.holeTube.node().setFromCollideMask(BitMask32.allOff())
        self.holeTube.node().setIntoCollideMask(BitMask32.bit(4))
        #self.holeTube.show()

        inPortalPos, inPortalHpr, outPortalPos, outPortalHpr, self.portalNormal = self.planeInfo.getPortalPos(
        )
        self.portalLength = 0.06
        self.inPortalRoot = render.attachNewNode("inPortalRoot")
        self.inPortal = loader.loadModel("models/portal_2_center.egg")
        self.inPortal.setScale(self.portalLength, self.portalLength,
                               self.portalLength)
        self.inPortal.reparentTo(self.inPortalRoot)
        self.inPortalRoot.setPos(inPortalPos[0], inPortalPos[1],
                                 inPortalPos[2])
        self.inPortalRoot.setHpr(inPortalHpr[0], inPortalHpr[1],
                                 inPortalHpr[2])
        self.inPortalRoot.hide()

        ct = CollisionTube(0, 0, 0, 0, 0.001, 0, 1)
        self.inPortalTube = self.inPortal.attachNewNode(
            CollisionNode('portal_in'))
        self.inPortalTube.node().addSolid(ct)
        self.inPortalTube.node().setFromCollideMask(BitMask32.allOff())
        self.inPortalTube.node().setIntoCollideMask(BitMask32.bit(3))
        #self.inPortalTube.hide()

        self.outPortalRoot = render.attachNewNode("outPortalRoot")
        self.outPortal = loader.loadModel("models/portal_2_center.egg")
        self.outPortal.setScale(self.portalLength, self.portalLength,
                                self.portalLength)
        self.outPortal.reparentTo(self.outPortalRoot)
        self.outPortalRoot.setPos(outPortalPos[0], outPortalPos[1],
                                  outPortalPos[2])
        self.outPortalRoot.setHpr(outPortalHpr[0], outPortalHpr[1],
                                  outPortalHpr[2])
        self.outPortalRoot.hide()

        ct = CollisionTube(0, 0, 0, 0, 0.001, 0, 1)
        self.outPortalTube = self.outPortal.attachNewNode(
            CollisionNode('portal_out'))
        self.outPortalTube.node().addSolid(ct)
        self.outPortalTube.node().setFromCollideMask(BitMask32.allOff())
        self.outPortalTube.node().setIntoCollideMask(BitMask32.bit(3))
        #self.outPortalTube.hide()
        #self.inPortalTube.show()
        #self.outPortalTube.show()
        #self.holeTube.show()

        #self.cTrav.addCollider(self.holeTube, self.cHandler)

        background_image = loader.loadTexture('dump/' + str(self.sceneIndex) +
                                              '_image.png')
        cm = CardMaker('background')
        cm.setHas3dUvs(True)
        info = np.load('dump/' + str(self.sceneIndex) + '_info.npy')
        #self.camera = getCameraFromInfo(self.info)
        depth = 10.0
        sizeU = info[2] / info[0] * depth
        sizeV = info[6] / info[5] * depth
        cm.setFrame(Point3(-sizeU, depth, -sizeV),
                    Point3(sizeU, depth, -sizeV), Point3(sizeU, depth, sizeV),
                    Point3(-sizeU, depth, sizeV))
        self.card = self.render.attachNewNode(cm.generate())
        self.card.setTransparency(True)
        self.card.setTexture(background_image)
        self.card.hide()

        self.ballGroundMap = {}
        self.ballBouncing = np.full(len(self.balls), 3)

        self.started = False
        self.start()

        self.hitIndex = 0

        self.showing = 'none'
        self.showingProgress = 0

        partsScene = PartsScene(self.sceneIndex)
        self.planeNPs, self.planeCenters = partsScene.generateEggModel()
        return
예제 #58
0
class Player():
    def __init__(self, camera, accept, render, loader, maxJPHeight):
        #initial variables and sounds

        self.developer = True  # Developer tools (building tools) will be accessible if this is turned on.
        self.gameMode = self.mode0  # the current playerUpdate function that is in use
        # self.playerModeParameters = () # the parameters being fed into the function above.
        self.groundContact = False  # if the player is on the ground or a surface, gravity will not pull the player below the surface
        self.jetPack_energy = 100
        self.maximumHeight = maxJPHeight  # maximum height in which the jetpack can fly to, this is dependent on the map loaded.
        self.jetPack_AUDIO = loader.loadSfx("assets/base/sounds/jetpack2.wav")
        self.jetPack_AUDIO.setLoop(True)
        self.vertical_velocity = 0  # Current Z velocity, positive = Upwards.
        self.z_velocity = 0  # Current Y velocity
        self.x_velocity = 0
        self.movingZ = False
        self.movingX = False

        #initiate GUI
        self.HUD = GUI()
        self.playerHolder = render.attachNewNode('player')

        # camera control - Hiding mouse and using it to rotate the camera
        props = WindowProperties()
        props.setCursorHidden(True)
        props.setMouseMode(WindowProperties.M_relative)
        base.win.requestProperties(props)

        # PLAYER MODEL SCENE GRAPH
        self.thirdPersonCamera_ZOOM = -50  # initial distance of third person camera.
        self.character = loader.loadModel(
            'assets/base/models/playerModel/player.bam')
        self.toggleFPCam = False  # Whether first person camera is on, this is initially off.
        self.character.setPos(0, 0, 0)
        self.character.reparentTo(self.playerHolder)
        self.playerBase = self.playerHolder.attachNewNode('camParent')
        self.thirdPersonNode = self.playerBase.attachNewNode('thirdPersonCam')
        camera.reparentTo(self.thirdPersonNode)
        self.mouseSeconds = []
        self.playerHolder.setScale(4)
        self.monitor = loader.loadModel(
            'assets/base/models/faces/playerMonitor.bam')
        self.monitor.reparentTo(self.playerHolder)
        self.cTrav = CollisionTraverser()

        # Horizontal collisions
        self.pusher = CollisionHandlerPusher()
        self.pusher.horizontal = True
        self.colliderNode = CollisionNode("player")
        self.colliderNode.addSolid(CollisionSphere(0, 0, 0, 2))
        self.colliderNode.setFromCollideMask(CollideMask.bit(1))
        self.colliderNode.setFromCollideMask(CollideMask.bit(0))
        self.colliderNode.setIntoCollideMask(BitMask32.allOff())
        collider = self.playerHolder.attachNewNode(self.colliderNode)
        collider.show()
        self.pusher.addCollider(collider, self.playerHolder)
        self.cTrav.addCollider(collider, self.pusher)

        # Vertical collisions - Downwards
        self.groundRay = CollisionRay()
        self.groundRay.setDirection(0, 0, -1)
        self.groundRayCol = CollisionNode('playerRay')
        self.groundRayCol.addSolid(self.groundRay)
        self.groundRayCol.setFromCollideMask(CollideMask.bit(1))
        self.groundRayCol.setIntoCollideMask(CollideMask.allOff())
        self.groundColNp = self.playerHolder.attachNewNode(self.groundRayCol)
        self.groundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.groundColNp, self.groundHandler)

        # Third Person Camera Collision
        self.cameraRay = CollisionSegment()
        self.cameraRayNode = CollisionNode('camerRay')
        self.cameraRayNode.addSolid(self.cameraRay)
        self.cameraRayNodePath = render.attachNewNode(self.cameraRayNode)
        self.cameraCollisionHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.cameraRayNodePath,
                               self.cameraCollisionHandler)

        # Vertical collisions - Upwards
        self.upwardsRay = CollisionRay()
        self.upwardsRay.setDirection(0, 0, 1)
        self.upwardsRayCol = CollisionNode('playerupRay')
        self.upwardsRayCol.addSolid(self.upwardsRay)
        self.upwardsRayCol.setFromCollideMask(CollideMask.bit(1))
        self.upwardsRayCol.setIntoCollideMask(CollideMask.allOff())
        self.upwardsColNp = self.playerHolder.attachNewNode(self.upwardsRayCol)
        self.upwardsHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.upwardsColNp, self.upwardsHandler)
        #self.cTrav.showCollisions(render)

        if self.developer == True:
            self.tool = buildingTool(
                "newbuildings", self.playerHolder, loader,
                accept)  # Load up building tool if developer modee is on.

        #self.setupLighting() # light
        #initial position
        self.playerHolder.setPos(45178.3, 43109.3, 0)
        self.keyMap = {
            "left": False,
            "right": False,
            "forward": False,
            "backwards": False,
            "change_camera": False,
            "leftClick": False,
            "space": False,
            "p": False,
            "scrollup": False,
            "scrolldown": False
        }

        accept("escape", sys.exit)
        accept("w", self.updateKey, ["forward", True])  #
        accept("w-up", self.updateKey, ["forward", False])

        accept("a", self.updateKey, ["left", True])
        accept("a-up", self.updateKey, ["left", False])

        accept("s", self.updateKey, ["backwards", True])
        accept("s-up", self.updateKey, ["backwards", False])

        accept("d", self.updateKey, ["right", True])
        accept("d-up", self.updateKey, ["right", False])

        accept("c", self.updateKey, ["change_camera", True])

        accept("wheel_up", self.updateKey, ["scrollup", True])

        accept("wheel_down", self.updateKey, ["scrolldown", True])

        accept("p", self.updateKey, ["p", True])
        accept("p-up", self.updateKey, ["p", False])

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

        self.playerMode = playerModes(
            self.playerBase, self.playerHolder, self.character,
            self.vertical_velocity, self.z_velocity, self.x_velocity,
            self.keyMap, self.monitor, self.thirdPersonNode,
            self.jetPack_energy, self.jetPack_AUDIO,
            self.thirdPersonCamera_ZOOM, self.toggleFPCam, self.HUD,
            self.cTrav, self.groundHandler, self.upwardsHandler,
            self.maximumHeight)

    def playerUpdate(self, task):  # our UPDATE TASK
        self.gameMode()
        return task.cont

    def updateKey(self, key, value):
        self.keyMap[key] = value
        if key == "change_camera":
            self.changeCamera()
        self.scrollFactor = 10
        if key == "scrollup":  # third person zoom in/out
            self.thirdPersonCamera_ZOOM += self.scrollFactor
        if key == "scrolldown":
            self.thirdPersonCamera_ZOOM -= self.scrollFactor

    def changeCamera(self):  # Toggle first person camera.
        if self.toggleFPCam == False:
            self.toggleFPCam = True
        else:
            self.toggleFPCam = False

    def recenterMouse(self):
        base.win.movePointer(0, int(base.win.getProperties().getXSize() / 2),
                             int(base.win.getProperties().getYSize() / 2))

    def setupLighting(self):
        plight = PointLight('plight')
        plight.setColor((1, 1, 1, 1))
        plnp = self.playerHolder.attachNewNode(plight)
        plnp.setPos(0, 1, 7)
        render.setLight(plnp)

# PLAYER MODES, HOW THE USER INTERACTS AND CONTROLS WITH THE USER

#   MODE 0
# Mode 0 is the default update mode, it allows WASD movement,
# mouse controlled camera rotations, first person and third
# person switching, it also has GUI display and player physics.

    def mode0(self):

        #THIRD PERSON CAMERA COLLISION

        # print("thirdpersonnode")
        # print(self.playerBase.getHpr())
        # print("pb")
        # print(self.character.getHpr())

        deltaTime = globalClock.getDt()
        self.movingZ = False
        self.movingX = False
        self.walkConstant = 25
        self.rotateConstant = 750

        # Keyboard controls
        # LEVITATION STUFF (FORMERLY CALLED JETPACK)

        if self.keyMap["space"] and self.jetPack_energy > 0:
            jetpack = 0.00001 * ((
                (self.playerHolder.getZ()) - self.maximumHeight)**2) + 9.81
            self.playerHolder.setZ(self.playerBase, jetpack)
            self.jetPack_energy -= 15 * deltaTime
            self.walkConstant = 70
            self.jetPack_AUDIO.play()
        else:
            self.jetPack_AUDIO.stop()
        if self.jetPack_energy < 100:
            self.jetPack_energy += 10 * deltaTime
        if self.jetPack_energy > 100:
            self.jetPack_energy = 100

        self.HUD.jetpackStatus.text = "Levitation Battery: " + str(
            int(self.jetPack_energy)) + "%"

        if (self.keyMap["forward"]
                or self.keyMap["backwards"]) and (self.keyMap["right"]
                                                  or self.keyMap["left"]):
            self.walkConstant = int(((self.walkConstant**2) / 2)**0.5)

        # WASD MOVEMENT
        if self.keyMap["forward"]:
            self.monitor.setH(self.playerBase.getH() - 90)
            self.movingZ = True
            self.z_velocity += 5
            if self.z_velocity > self.walkConstant:
                self.z_velocity = self.walkConstant

        if self.keyMap["right"]:
            self.monitor.setH(self.playerBase.getH() - 180)
            self.movingX = True
            self.x_velocity += 5
            if self.x_velocity > self.walkConstant:
                self.x_velocity = self.walkConstant
        if self.keyMap["p"]:
            print(self.playerHolder.getPos())
            print(self.thirdPersonCamera_ZOOM)
            self.gameMode = self.mode1
        if self.keyMap["left"]:
            self.monitor.setH(self.playerBase.getH())
            self.movingX = True
            self.x_velocity -= 5
            if self.x_velocity < -self.walkConstant:
                self.x_velocity = -self.walkConstant
        if self.keyMap["backwards"]:
            self.monitor.setH(self.playerBase.getH() + 90)
            self.movingZ = True
            self.z_velocity -= 20
            if self.z_velocity < -self.walkConstant:
                self.z_velocity = -self.walkConstant

        if self.movingZ == False:
            if self.z_velocity <= 7 or (
                    self.z_velocity >= -5
                    and self.z_velocity < 0):  # Shaking bug fix
                self.z_velocity = 0
            if self.z_velocity > 0:
                self.z_velocity -= 10
            elif self.z_velocity < 0:
                self.z_velocity += 10
        if self.movingX == False:
            if self.x_velocity <= 5 or (
                    self.x_velocity >= -5
                    and self.x_velocity < 0):  # Shaking bug fix
                self.x_velocity = 0
            if self.x_velocity > 0:
                self.x_velocity -= 10
            elif self.x_velocity < 0:
                self.x_velocity += 10
        # MONITOR HEADINGS FOR DOUBLE INPUT
        if self.keyMap["forward"] and self.keyMap["right"]:
            self.monitor.setH(self.playerBase.getH() - 135)
        elif self.keyMap["forward"] and self.keyMap["left"]:
            self.monitor.setH(self.playerBase.getH() - 45)
        elif self.keyMap["backwards"] and self.keyMap["left"]:
            self.monitor.setH(self.playerBase.getH() + 45)
        elif self.keyMap["backwards"] and self.keyMap["right"]:
            self.monitor.setH(self.playerBase.getH() + 135)

        # third person camera control
        if (self.toggleFPCam == False):  # third person camera controls
            if (base.mouseWatcherNode.hasMouse() == True):
                mouseposition = base.mouseWatcherNode.getMouse()
                self.thirdPersonNode.setP(mouseposition.getY() * 30)
                self.playerBase.setH(mouseposition.getX() * -50)
                if (mouseposition.getX() < 0.1
                        and mouseposition.getX() > -0.1):
                    self.playerBase.setH(self.playerBase.getH())

            if self.thirdPersonNode.getP() > 90:
                self.recenterMouse()
                self.thirdPersonNode.setP(90)  # TRACK MOUSE
            elif self.thirdPersonNode.getP() < -90:
                self.recenterMouse()
                self.thirdPersonNode.setP(-90)
            if self.thirdPersonCamera_ZOOM > -20:  # validate zoom
                self.thirdPersonCamera_ZOOM = -20
            elif self.thirdPersonCamera_ZOOM < -390:
                self.thirdPersonCamera_ZOOM = -390
        # CAMERA STUFF
        # FIRST PERSON CAMERA
        if self.toggleFPCam:  # first person camera controls
            camera.setPos(self.character.getPos())  # 0,-50,-10
            camera.setZ(camera.getZ() + 6)
            self.playerHolder.hide()
            if (base.mouseWatcherNode.hasMouse() == True):
                mouseposition = base.mouseWatcherNode.getMouse()
                camera.setP(mouseposition.getY() * 20)
                self.playerBase.setH(mouseposition.getX() * -50)
                if (mouseposition.getX() < 0.1
                        and mouseposition.getX() > -0.1):
                    self.playerBase.setH(self.playerBase.getH())
            if camera.getP() > 90:
                self.recenterMouse()
                camera.setP(90)  # TRACK MOUSE
            elif camera.getP() < -90:
                self.recenterMouse()
                camera.setP(-90)
        else:  # takes out of first person perspective if toggleFPS is turned off.
            self.playerHolder.show()
            camera.setPos(0, self.thirdPersonCamera_ZOOM, 0)  # 0,-50,-4
            camera.lookAt(self.character)
        # movement updates
        self.playerHolder.setY(self.playerBase, (self.z_velocity * deltaTime))
        self.playerHolder.setX(self.playerBase, (self.x_velocity * deltaTime))

        # forward/backward rolling
        axis = self.playerBase.getQuat().getRight()
        angle = (self.z_velocity * deltaTime * -8)
        quat = Quat()
        quat.setFromAxisAngle(angle, axis)
        newVec = self.character.getQuat() * quat
        # print(newVec.getHpr())
        self.character.setQuat(newVec)

        # sideways rolling
        axis = self.playerBase.getQuat().getForward()
        angle = (self.x_velocity * deltaTime * 8)
        quat = Quat()
        quat.setFromAxisAngle(angle, axis)
        newVec = self.character.getQuat() * quat
        # print(self.playerBase.getPos())
        self.character.setQuat(newVec)
        self.cameraRay.setPointA(self.playerBase.getPos())
        if camera.getPos() != (0, 0, 0):
            self.cameraRay.setPointB(camera.getPos(base.render))

        self.cTrav.traverse(render)

        # checking for camera collisions
        entries = list(self.cameraCollisionHandler.entries)
        for entry in entries:
            if str(entry.getIntoNodePath())[:19] != "render/worldTerrain":
                #camera.setPos(entry.getSurfacePoint(self.thirdPersonNode))
                self.thirdPersonCamera_ZOOM += 1

        # if len(entries) > 0:
        #     if (self.playerHolder.getZ() < entries[-1].getSurfacePoint(render).getZ() + 8):
        #         self.playerHolder.setZ(entries[-1].getSurfacePoint(render).getZ() + 8)
        #         self.vertical_velocity = 0

        # checking for collisions - downwards
        entries = list(self.groundHandler.entries)
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())
        self.performGravity = True
        if self.performGravity == True:
            self.vertical_velocity -= (deltaTime * 9.81)
            if self.vertical_velocity <= -15:
                self.vertical_velocity = -15
            self.playerHolder.setPos(self.playerHolder,
                                     Vec3(0, 0,
                                          self.vertical_velocity))  # Gravity
        if len(entries) > 0:
            if (self.playerHolder.getZ() <
                    entries[-1].getSurfacePoint(render).getZ() + 8):
                self.playerHolder.setZ(
                    entries[-1].getSurfacePoint(render).getZ() + 8)
                self.vertical_velocity = 0

        # checking for collisions - upwards
        entries = list(self.upwardsHandler.entries)
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())
        if len(entries) > 0:
            for entry in entries:
                if (self.playerHolder.getZ() >
                        entry.getSurfacePoint(render).getZ() - 70):
                    self.playerHolder.setZ(
                        entry.getSurfacePoint(render).getZ() - 130)

    # PLAYER MODES, HOW THE USER INTERACTS AND CONTROLS WITH THE USER
    #   MODE 1
    # Mode 1 is a test update loop used to test player loop switching.
    # it simply freezes the controls.

    def mode1(self):
        self.playerHolder.hide()
        self.playerHolder.setHpr(0, 0, 0)
        if self.keyMap["backwards"]:
            self.playerHolder.show()
            self.gameMode = self.mode0
예제 #59
0
class CogdoFlyingLegalEagle(DirectObject, FSM):
    CollSphereName = 'CogdoFlyingLegalEagleSphere'
    CollisionEventName = 'CogdoFlyingLegalEagleCollision'
    InterestCollName = 'CogdoFlyingLegalEagleInterestCollision'
    RequestAddTargetEventName = 'CogdoFlyingLegalEagleRequestTargetEvent'
    RequestAddTargetAgainEventName = 'CogdoFlyingLegalEagleRequestTargetAgainEvent'
    RequestRemoveTargetEventName = 'CogdoFlyingLegalEagleRemoveTargetEvent'
    ForceRemoveTargetEventName = 'CogdoFlyingLegalEagleForceRemoveTargetEvent'
    EnterLegalEagle = 'CogdoFlyingLegalEagleDamageToon'
    ChargingToAttackEventName = 'LegalEagleChargingToAttack'
    LockOnToonEventName = 'LegalEagleLockOnToon'
    CooldownEventName = 'LegalEagleCooldown'
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'CogdoFlyingLegalEagle')

    def __init__(self, nest, index, suitDnaName='le'):
        FSM.__init__(self, 'CogdoFlyingLegalEagle')
        self.defaultTransitions = {
            'Off': ['Roost'],
            'Roost': ['TakeOff', 'Off'],
            'TakeOff': ['LockOnToon', 'LandOnNest', 'Off'],
            'LockOnToon': ['RetreatToNest', 'ChargeUpAttack', 'Off'],
            'ChargeUpAttack': ['RetreatToNest', 'Attack', 'Off'],
            'Attack': ['RetreatToSky', 'Off'],
            'RetreatToSky': ['Cooldown', 'Off'],
            'Cooldown': ['LockOnToon', 'LandOnNest', 'Off'],
            'RetreatToNest': ['LandOnNest', 'Off'],
            'LandOnNest': ['Roost', 'Off']
        }
        self.index = index
        self.nest = nest
        self.target = None
        self.isEagleInterested = False
        self.collSphere = None
        self.suit = Suit.Suit()
        d = SuitDNA.SuitDNA()
        d.newSuit(suitDnaName)
        self.suit.setDNA(d)
        self.suit.reparentTo(render)
        swapAvatarShadowPlacer(self.suit, 'legalEagle-%sShadowPlacer' % index)
        self.suit.setPos(self.nest.getPos(render))
        self.suit.setHpr(-180, 0, 0)
        self.suit.stash()
        self.prop = None
        self.attachPropeller()
        head = self.suit.find('**/joint_head')
        self.interestConeOrigin = self.nest.attachNewNode('fakeHeadNodePath')
        self.interestConeOrigin.setPos(
            render,
            head.getPos(render) +
            Vec3(0, Globals.LegalEagle.InterestConeOffset, 0))
        self.attackTargetPos = None
        self.startOfRetreatToSkyPos = None
        pathModel = CogdoUtil.loadFlyingModel('legalEaglePaths')
        self.chargeUpMotionPath = Mopath.Mopath(name='chargeUpMotionPath-%i' %
                                                self.index)
        self.chargeUpMotionPath.loadNodePath(pathModel.find('**/charge_path'))
        self.retreatToSkyMotionPath = Mopath.Mopath(
            name='retreatToSkyMotionPath-%i' % self.index)
        self.retreatToSkyMotionPath.loadNodePath(
            pathModel.find('**/retreat_path'))
        audioMgr = base.cogdoGameAudioMgr
        self._screamSfx = audioMgr.createSfx('legalEagleScream', self.suit)
        self.initIntervals()
        self.suit.nametag3d.stash()
        self.suit.nametag.destroy()
        return

    def attachPropeller(self):
        if self.prop == None:
            self.prop = BattleProps.globalPropPool.getProp('propeller')
            head = self.suit.find('**/joint_head')
            self.prop.reparentTo(head)
        return

    def detachPropeller(self):
        if self.prop:
            self.prop.cleanup()
            self.prop.removeNode()
            self.prop = None
        return

    def _getAnimationIval(self,
                          animName,
                          startFrame=0,
                          endFrame=None,
                          duration=1):
        if endFrame == None:
            self.suit.getNumFrames(animName) - 1
        frames = endFrame - startFrame
        frameRate = self.suit.getFrameRate(animName)
        newRate = frames / duration
        playRate = newRate / frameRate
        ival = Sequence(ActorInterval(self.suit, animName, playRate=playRate))
        return ival

    def initIntervals(self):
        dur = Globals.LegalEagle.LiftOffTime
        nestPos = self.nest.getPos(render)
        airPos = nestPos + Vec3(0.0, 0.0, Globals.LegalEagle.LiftOffHeight)
        self.takeOffSeq = Sequence(Parallel(
            Sequence(
                Wait(dur * 0.6),
                LerpPosInterval(self.suit,
                                dur * 0.4,
                                startPos=nestPos,
                                pos=airPos,
                                blendType='easeInOut'))),
                                   Wait(1.5),
                                   Func(self.request, 'next'),
                                   name='%s.takeOffSeq-%i' %
                                   (self.__class__.__name__, self.index))
        self.landOnNestPosLerp = LerpPosInterval(self.suit,
                                                 1.0,
                                                 startPos=airPos,
                                                 pos=nestPos,
                                                 blendType='easeInOut')
        self.landingSeq = Sequence(Func(self.updateLandOnNestPosLerp),
                                   Parallel(self.landOnNestPosLerp),
                                   Func(self.request, 'next'),
                                   name='%s.landingSeq-%i' %
                                   (self.__class__.__name__, self.index))
        dur = Globals.LegalEagle.ChargeUpTime
        self.chargeUpPosLerp = LerpFunc(
            self.moveAlongChargeUpMopathFunc,
            fromData=0.0,
            toData=self.chargeUpMotionPath.getMaxT(),
            duration=dur,
            blendType='easeInOut')
        self.chargeUpAttackSeq = Sequence(
            Func(self.updateChargeUpPosLerp),
            self.chargeUpPosLerp,
            Func(self.request, 'next'),
            name='%s.chargeUpAttackSeq-%i' %
            (self.__class__.__name__, self.index))
        dur = Globals.LegalEagle.RetreatToNestTime
        self.retreatToNestPosLerp = LerpPosInterval(self.suit,
                                                    dur,
                                                    startPos=Vec3(0, 0, 0),
                                                    pos=airPos,
                                                    blendType='easeInOut')
        self.retreatToNestSeq = Sequence(Func(self.updateRetreatToNestPosLerp),
                                         self.retreatToNestPosLerp,
                                         Func(self.request, 'next'),
                                         name='%s.retreatToNestSeq-%i' %
                                         (self.__class__.__name__, self.index))
        dur = Globals.LegalEagle.RetreatToSkyTime
        self.retreatToSkyPosLerp = LerpFunc(
            self.moveAlongRetreatMopathFunc,
            fromData=0.0,
            toData=self.retreatToSkyMotionPath.getMaxT(),
            duration=dur,
            blendType='easeOut')
        self.retreatToSkySeq = Sequence(Func(self.updateRetreatToSkyPosLerp),
                                        self.retreatToSkyPosLerp,
                                        Func(self.request, 'next'),
                                        name='%s.retreatToSkySeq-%i' %
                                        (self.__class__.__name__, self.index))
        dur = Globals.LegalEagle.PreAttackTime
        self.preAttackLerpXY = LerpFunc(self.updateAttackXY,
                                        fromData=0.0,
                                        toData=1.0,
                                        duration=dur)
        self.preAttackLerpZ = LerpFunc(self.updateAttackZ,
                                       fromData=0.0,
                                       toData=1.0,
                                       duration=dur,
                                       blendType='easeOut')
        dur = Globals.LegalEagle.PostAttackTime
        self.postAttackPosLerp = LerpPosInterval(self.suit,
                                                 dur,
                                                 startPos=Vec3(0, 0, 0),
                                                 pos=Vec3(0, 0, 0))
        self.attackSeq = Sequence(
            Parallel(self.preAttackLerpXY, self.preAttackLerpZ),
            Func(self.updatePostAttackPosLerp),
            self.postAttackPosLerp,
            Func(self.request, 'next'),
            name='%s.attackSeq-%i' % (self.__class__.__name__, self.index))
        dur = Globals.LegalEagle.CooldownTime
        self.cooldownSeq = Sequence(Wait(dur),
                                    Func(self.request, 'next'),
                                    name='%s.cooldownSeq-%i' %
                                    (self.__class__.__name__, self.index))
        self.propTrack = Sequence(
            ActorInterval(self.prop, 'propeller', startFrame=0, endFrame=14))
        self.hoverOverNestSeq = Sequence(
            ActorInterval(self.suit,
                          'landing',
                          startFrame=10,
                          endFrame=20,
                          playRate=0.5),
            ActorInterval(self.suit,
                          'landing',
                          startFrame=20,
                          endFrame=10,
                          playRate=0.5))

    def initCollision(self):
        self.collSphere = CollisionSphere(0, 0, 0, 0)
        self.collSphere.setTangible(0)
        self.collNode = CollisionNode('%s-%s' %
                                      (self.CollSphereName, self.index))
        self.collNode.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.collNode.addSolid(self.collSphere)
        self.collNodePath = self.suit.attachNewNode(self.collNode)
        self.collNodePath.hide()
        self.accept('enter%s-%s' % (self.CollSphereName, self.index),
                    self.handleEnterSphere)
        self.setCollSphereToNest()

    def getInterestConeLength(self):
        return Globals.LegalEagle.InterestConeLength + Globals.LegalEagle.InterestConeOffset

    def isToonInView(self, toon):
        distanceThreshold = self.getInterestConeLength()
        angleThreshold = Globals.LegalEagle.InterestConeAngle
        toonPos = toon.getPos(render)
        nestPos = self.nest.getPos(render)
        distance = toon.getDistance(self.interestConeOrigin)
        if distance > distanceThreshold:
            return False
        if toonPos[1] > nestPos[1]:
            return False
        a = toon.getPos(render) - self.interestConeOrigin.getPos(render)
        a.normalize()
        b = Vec3(0, -1, 0)
        dotProduct = a.dot(b)
        angle = math.degrees(math.acos(dotProduct))
        if angle <= angleThreshold / 2.0:
            return True
        return False

    def update(self, dt, localPlayer):
        if Globals.Dev.NoLegalEagleAttacks:
            return
        inView = self.isToonInView(localPlayer.toon)
        if inView and not self.isEagleInterested:
            self.handleEnterInterest()
        else:
            if inView and self.isEagleInterested:
                self.handleAgainInterest()
            else:
                if not inView and self.isEagleInterested:
                    self.handleExitInterest()

    def updateLockOnTask(self):
        dt = globalClock.getDt()
        targetPos = self.target.getPos(render)
        suitPos = self.suit.getPos(render)
        nestPos = self.nest.getPos(render)
        attackPos = Vec3(targetPos)
        attackPos[1] = nestPos[1] + Globals.LegalEagle.LockOnDistanceFromNest
        attackPos[2] += Globals.LegalEagle.VerticalOffset
        if attackPos[2] < nestPos[2]:
            attackPos[2] = nestPos[2]
        attackChangeVec = (attackPos -
                           suitPos) * Globals.LegalEagle.LockOnSpeed
        self.suit.setPos(suitPos + attackChangeVec * dt)
        return Task.cont

    def updateAttackXY(self, value):
        if Globals.LegalEagle.EagleAttackShouldXCorrect:
            x = self.readyToAttackPos.getX() + (self.attackTargetPos.getX(
            ) - self.readyToAttackPos.getX()) * value
            self.suit.setX(x)
        y = self.readyToAttackPos.getY() + (
            self.attackTargetPos.getY() - self.readyToAttackPos.getY()) * value
        self.suit.setY(y)

    def updateAttackZ(self, value):
        z = self.readyToAttackPos.getZ() + (
            self.attackTargetPos.getZ() - self.readyToAttackPos.getZ()) * value
        self.suit.setZ(z)

    def moveAlongChargeUpMopathFunc(self, value):
        self.chargeUpMotionPath.goTo(self.suit, value)
        self.suit.setPos(self.suit.getPos() + self.startOfChargeUpPos)

    def moveAlongRetreatMopathFunc(self, value):
        self.retreatToSkyMotionPath.goTo(self.suit, value)
        self.suit.setPos(self.suit.getPos() + self.startOfRetreatToSkyPos)

    def updateChargeUpPosLerp(self):
        self.startOfChargeUpPos = self.suit.getPos(render)

    def updateLandOnNestPosLerp(self):
        self.landOnNestPosLerp.setStartPos(self.suit.getPos())

    def updateRetreatToNestPosLerp(self):
        self.retreatToNestPosLerp.setStartPos(self.suit.getPos())

    def updateRetreatToSkyPosLerp(self):
        self.startOfRetreatToSkyPos = self.suit.getPos(render)

    def updatePostAttackPosLerp(self):
        suitPos = self.suit.getPos(render)
        finalPos = suitPos + Vec3(0, -Globals.LegalEagle.PostAttackLength, 0)
        self.postAttackPosLerp.setStartPos(suitPos)
        self.postAttackPosLerp.setEndPos(finalPos)

    def handleEnterSphere(self, collEntry):
        self.notify.debug('handleEnterSphere:%i' % self.index)
        messenger.send(CogdoFlyingLegalEagle.EnterLegalEagle,
                       [self, collEntry])

    def handleEnterInterest(self):
        self.notify.debug('handleEnterInterestColl:%i' % self.index)
        self.isEagleInterested = True
        messenger.send(CogdoFlyingLegalEagle.RequestAddTargetEventName,
                       [self.index])

    def handleAgainInterest(self):
        self.isEagleInterested = True
        messenger.send(CogdoFlyingLegalEagle.RequestAddTargetAgainEventName,
                       [self.index])

    def handleExitInterest(self):
        self.notify.debug('handleExitInterestSphere:%i' % self.index)
        self.isEagleInterested = False
        messenger.send(CogdoFlyingLegalEagle.RequestRemoveTargetEventName,
                       [self.index])

    def hasTarget(self):
        if self.target != None:
            return True
        return False
        return

    def setTarget(self, toon, elapsedTime=0.0):
        self.notify.debug('Setting eagle %i to target: %s, elapsed time: %s' %
                          (self.index, toon.getName(), elapsedTime))
        self.target = toon
        if self.state == 'Roost':
            self.request('next', elapsedTime)
        if self.state == 'ChargeUpAttack':
            messenger.send(CogdoFlyingLegalEagle.ChargingToAttackEventName,
                           [self.target.doId])

    def clearTarget(self, elapsedTime=0.0):
        self.notify.debug('Clearing target from eagle %i, elapsed time: %s' %
                          (self.index, elapsedTime))
        messenger.send(CogdoFlyingLegalEagle.CooldownEventName,
                       [self.target.doId])
        self.target = None
        if self.state in ('LockOnToon', ):
            self.request('next', elapsedTime)
        return

    def leaveCooldown(self, elapsedTime=0.0):
        if self.state in ('Cooldown', ):
            self.request('next', elapsedTime)

    def shouldBeInFrame(self):
        if self.state in ('TakeOff', 'LockOnToon', 'ChargeUpAttack'):
            return True
        if self.state == 'Attack':
            distance = self.suit.getDistance(self.target)
            threshold = Globals.LegalEagle.EagleAndTargetDistCameraTrackThreshold
            suitPos = self.suit.getPos(render)
            targetPos = self.target.getPos(render)
            if distance > threshold and suitPos[1] > targetPos[1]:
                return True
        return False

    def getTarget(self):
        return self.target

    def onstage(self):
        self.suit.unstash()
        self.request('Roost')

    def offstage(self):
        self.suit.stash()
        self.request('Off')

    def gameStart(self, gameStartTime):
        self.gameStartTime = gameStartTime
        self.initCollision()

    def gameEnd(self):
        self.shutdownCollisions()

    def shutdownCollisions(self):
        self.ignoreAll()
        if self.collSphere != None:
            del self.collSphere
            self.collSphere = None
        if self.collNodePath != None:
            self.collNodePath.removeNode()
            del self.collNodePath
            self.collNodePath = None
        if self.collNode != None:
            del self.collNode
            self.collNode = None
        return

    def destroy(self):
        self.request('Off')
        self.detachPropeller()
        del self._screamSfx
        self.suit.cleanup()
        self.suit.removeNode()
        self.suit.delete()
        self.interestConeOrigin.removeNode()
        del self.interestConeOrigin
        self.nest = None
        self.target = None
        taskMgr.remove('updateLockOnTask-%i' % self.index)
        taskMgr.remove('exitLockOnToon-%i' % self.index)
        self.propTrack.clearToInitial()
        del self.propTrack
        del self.chargeUpMotionPath
        del self.retreatToSkyMotionPath
        self.takeOffSeq.clearToInitial()
        del self.takeOffSeq
        del self.landOnNestPosLerp
        self.landingSeq.clearToInitial()
        del self.landingSeq
        del self.chargeUpPosLerp
        self.chargeUpAttackSeq.clearToInitial()
        del self.chargeUpAttackSeq
        del self.retreatToNestPosLerp
        self.retreatToNestSeq.clearToInitial()
        del self.retreatToNestSeq
        del self.retreatToSkyPosLerp
        self.retreatToSkySeq.clearToInitial()
        del self.retreatToSkySeq
        del self.postAttackPosLerp
        self.attackSeq.clearToInitial()
        del self.attackSeq
        self.cooldownSeq.clearToInitial()
        del self.cooldownSeq
        self.hoverOverNestSeq.clearToInitial()
        del self.hoverOverNestSeq
        del self.preAttackLerpXY
        del self.preAttackLerpZ
        return

    def requestNext(self):
        self.request('next')

    def setCollSphereToNest(self):
        if hasattr(self, 'collSphere') and self.collSphere is not None:
            radius = Globals.LegalEagle.OnNestDamageSphereRadius
            self.collSphere.setCenter(
                Point3(0.0, -Globals.Level.LaffPowerupNestOffset[1],
                       self.suit.getHeight() / 2.0))
            self.collSphere.setRadius(radius)
        return

    def setCollSphereToTargeting(self):
        if hasattr(self, 'collSphere') and self.collSphere is not None:
            radius = Globals.LegalEagle.DamageSphereRadius
            self.collSphere.setCenter(Point3(0, 0, radius * 2))
            self.collSphere.setRadius(radius)
        return

    def enterRoost(self):
        self.notify.info("enter%s: '%s' -> '%s'" %
                         (self.newState, self.oldState, self.newState))
        self.hoverOverNestSeq.loop()
        self.propTrack.loop()
        self.setCollSphereToNest()

    def filterRoost(self, request, args):
        self.notify.debug("filter%s( '%s', '%s' )" %
                          (self.state, request, args))
        if request == self.state:
            return
        if request == 'next':
            return 'TakeOff'
        return self.defaultFilter(request, args)
        return

    def exitRoost(self):
        self.notify.debug("exit%s: '%s' -> '%s'" %
                          (self.oldState, self.oldState, self.newState))
        self.hoverOverNestSeq.pause()
        self.setCollSphereToTargeting()

    def enterTakeOff(self, elapsedTime=0.0):
        self.notify.info(
            "enter%s: '%s' -> '%s', elapsedTime:%s" %
            (self.newState, self.oldState, self.newState, elapsedTime))
        self.takeOffSeq.start(elapsedTime)
        self.hoverOverNestSeq.loop()

    def filterTakeOff(self, request, args):
        self.notify.debug("filter%s( '%s', '%s' )" %
                          (self.state, request, args))
        if request == self.state:
            return
        if request == 'next':
            if self.hasTarget():
                return 'LockOnToon'
            return 'LandOnNest'
        else:
            return self.defaultFilter(request, args)
        return

    def exitTakeOff(self):
        self.notify.debug("exit%s: '%s' -> '%s'" %
                          (self.oldState, self.oldState, self.newState))
        self.takeOffSeq.clearToInitial()
        self.hoverOverNestSeq.pause()

    def enterLockOnToon(self, elapsedTime=0.0):
        self.notify.info(
            "enter%s: '%s' -> '%s', elapsedTime:%s" %
            (self.newState, self.oldState, self.newState, elapsedTime))
        taskName = 'updateLockOnTask-%i' % self.index
        taskMgr.add(self.updateLockOnTask, taskName, 45, extraArgs=[])
        messenger.send(CogdoFlyingLegalEagle.LockOnToonEventName,
                       [self.target.doId])
        range = self.target.getDistance(
            self.interestConeOrigin) / self.getInterestConeLength()
        range = clamp(range, 0.0, 1.0)
        dur = Globals.LegalEagle.LockOnTime
        if self.oldState == 'TakeOff':
            dur *= range
        else:
            dur += Globals.LegalEagle.ExtraPostCooldownTime
        taskName = 'exitLockOnToon-%i' % self.index
        taskMgr.doMethodLater(dur, self.requestNext, taskName, extraArgs=[])

    def filterLockOnToon(self, request, args):
        self.notify.debug("filter%s( '%s', '%s' )" %
                          (self.state, request, args))
        if request == self.state:
            return
        if request == 'next':
            if self.hasTarget():
                return 'ChargeUpAttack'
            return 'RetreatToNest'
        else:
            return self.defaultFilter(request, args)
        return

    def exitLockOnToon(self):
        self.notify.debug("exit%s: '%s' -> '%s'" %
                          (self.oldState, self.oldState, self.newState))
        taskMgr.remove('updateLockOnTask-%i' % self.index)
        taskMgr.remove('exitLockOnToon-%i' % self.index)

    def enterChargeUpAttack(self, elapsedTime=0.0):
        self.notify.info(
            "enter%s: '%s' -> '%s', elapsedTime:%s" %
            (self.newState, self.oldState, self.newState, elapsedTime))
        self.chargeUpAttackSeq.start(elapsedTime)
        messenger.send(CogdoFlyingLegalEagle.ChargingToAttackEventName,
                       [self.target.doId])

    def filterChargeUpAttack(self, request, args):
        self.notify.debug("filter%s( '%s', '%s' )" %
                          (self.state, request, args))
        if request == self.state:
            return
        if request == 'next':
            if self.hasTarget():
                return 'Attack'
            return 'RetreatToNest'
        else:
            return self.defaultFilter(request, args)
        return

    def exitChargeUpAttack(self):
        self.notify.debug("exit%s: '%s' -> '%s'" %
                          (self.oldState, self.oldState, self.newState))
        self.chargeUpAttackSeq.clearToInitial()

    def enterAttack(self, elapsedTime=0.0):
        self.notify.info(
            "enter%s: '%s' -> '%s', elapsedTime:%s" %
            (self.newState, self.oldState, self.newState, elapsedTime))
        self.attackTargetPos = self.target.getPos(render)
        targetState = self.target.animFSM.getCurrentState().getName()
        self._screamSfx.play()
        if targetState == 'jumpAirborne':
            self.attackTargetPos[2] += Globals.LegalEagle.VerticalOffset
        else:
            self.attackTargetPos[
                2] += Globals.LegalEagle.PlatformVerticalOffset
        self.readyToAttackPos = self.suit.getPos(render)
        self.attackSeq.start(elapsedTime)

    def filterAttack(self, request, args):
        self.notify.debug("filter%s( '%s', '%s' )" %
                          (self.state, request, args))
        if request == self.state:
            return
        if request == 'next':
            return 'RetreatToSky'
        return self.defaultFilter(request, args)
        return

    def exitAttack(self):
        self.notify.debug("exit%s: '%s' -> '%s'" %
                          (self.oldState, self.oldState, self.newState))
        self.attackSeq.clearToInitial()
        taskMgr.remove('updateAttackPosTask-%i' % self.index)

    def enterRetreatToSky(self, elapsedTime=0.0):
        self.notify.info(
            "enter%s: '%s' -> '%s', elapsedTime:%s" %
            (self.newState, self.oldState, self.newState, elapsedTime))
        self.retreatToSkySeq.start(elapsedTime)

    def filterRetreatToSky(self, request, args):
        self.notify.debug("filter%s( '%s', '%s' )" %
                          (self.state, request, args))
        if request == self.state:
            return
        if request == 'next':
            return 'Cooldown'
        return self.defaultFilter(request, args)
        return

    def exitRetreatToSky(self):
        self.notify.debug("exit%s: '%s' -> '%s'" %
                          (self.oldState, self.oldState, self.newState))
        self.retreatToSkySeq.clearToInitial()

    def enterCooldown(self):
        if self.target != None:
            messenger.send(CogdoFlyingLegalEagle.CooldownEventName,
                           [self.target.doId])
        self.suit.stash()
        self.notify.info("enter%s: '%s' -> '%s'" %
                         (self.newState, self.oldState, self.newState))
        return

    def filterCooldown(self, request, args):
        self.notify.debug("filter%s( '%s', '%s' )" %
                          (self.state, request, args))
        if request == self.state:
            return
        if request == 'next':
            if self.hasTarget():
                return 'LockOnToon'
            return 'LandOnNest'
        else:
            return self.defaultFilter(request, args)
        return

    def exitCooldown(self):
        self.notify.debug("exit%s: '%s' -> '%s'" %
                          (self.oldState, self.oldState, self.newState))
        self.suit.unstash()
        self.cooldownSeq.clearToInitial()
        if self.newState != 'Off':
            heightOffNest = Globals.LegalEagle.PostCooldownHeightOffNest
            nestPos = self.nest.getPos(render)
            if self.newState in ('LandOnNest', ):
                self.suit.setPos(nestPos + Vec3(0, 0, heightOffNest))
            else:
                targetPos = self.target.getPos(render)
                attackPos = Vec3(targetPos)
                attackPos[1] = nestPos[1]
                attackPos[2] = nestPos[2] + heightOffNest
                self.suit.setPos(attackPos)

    def enterRetreatToNest(self, elapsedTime=0.0):
        self.notify.info(
            "enter%s: '%s' -> '%s', elapsedTime:%s" %
            (self.newState, self.oldState, self.newState, elapsedTime))
        self.retreatToNestSeq.start(elapsedTime)

    def filterRetreatToNest(self, request, args):
        self.notify.debug("filter%s( '%s', '%s' )" %
                          (self.state, request, args))
        if request == self.state:
            return
        if request == 'next':
            return 'LandOnNest'
        return self.defaultFilter(request, args)
        return

    def exitRetreatToNest(self):
        self.retreatToNestSeq.clearToInitial()

    def enterLandOnNest(self, elapsedTime=0.0):
        self.notify.info(
            "enter%s: '%s' -> '%s', elapsedTime:%s" %
            (self.newState, self.oldState, self.newState, elapsedTime))
        self.landingSeq.start(elapsedTime)

    def filterLandOnNest(self, request, args):
        self.notify.debug("filter%s( '%s', '%s' )" %
                          (self.state, request, args))
        if request == self.state:
            return
        if request == 'next':
            if self.hasTarget():
                return 'TakeOff'
            return 'Roost'
        else:
            return self.defaultFilter(request, args)
        return

    def exitLandOnNest(self):
        self.landingSeq.clearToInitial()
예제 #60
0
class World(DirectObject):
    global bk_text
    bk_text = ' '

    def __init__(self):
        global speed
        global maxspeed

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

        # Post the instructions
        self.title = addTitle(
            "HW2: Roaming Ralph Modified (Walking on the Moon) with friends")
        self.inst1 = addInstructions(0.95, "[ESC]: Quit")
        self.inst2 = addInstructions(0.90, "[A]: Rotate Ralph Left")
        self.inst3 = addInstructions(0.85, "[D]: Rotate Ralph Right")
        self.inst4 = addInstructions(0.80, "[W]: Move Ralph Forward")
        self.inst5 = addInstructions(0.75,
                                     "[P]: Increase Ralph Velocity (Run)")
        self.inst6 = addInstructions(0.70,
                                     "[O]: Decrease Ralph Velocity (Walk)")
        self.inst7 = addInstructions(0.60, "[Left Arrow]: Rotate Camera Left")
        self.inst8 = addInstructions(0.55,
                                     "[Right Arrow]: Rotate Camera Right")

        # Set up the environment
        self.environ = loader.loadModel("models/square")
        self.environ.reparentTo(render)
        self.environ.setPos(0, 0, 0)
        self.environ.setScale(100, 100, 1)
        self.moon_tex = loader.loadTexture("models/moon_1k_tex.jpg")
        self.environ.setTexture(self.moon_tex, 1)

        # Create the main character, Ralph

        if (v == [0]):
            print(model)
            self.ralph = Actor("models/ralph", {
                "run": "models/ralph-run",
                "walk": "models/ralph-walk"
            })
            self.ralph.setScale(.2)
        elif (v == [1]):
            print(model)
            self.ralph = Actor("models/panda-model",
                               {"walk": "models/panda-walk4"})
            speed = 100
            maxspeed = 10000
            self.ralph.setScale(0.0001, 0.00015, 0.0005)
            self.ralph.setScale(.002)

            self.ralph.setPlayRate(100.0, "models/panda-walk4")
            speed = 100
            maxspeed = 10000
            self.ralph.setScale(.0035)
        else:
            print(model)
            self.ralph = Actor("models/GroundRoamer.egg")
            self.ralph.setScale(.15)
            self.ralph.setHpr(180, 0, 0)
            self.Groundroamer_texture = loader.loadTexture(
                "models/Groundroamer.tif")
            self.ralph.setTexture(self.Groundroamer_texture)

        self.ralph.reparentTo(render)
        self.ralph.setPos(0, 0, 0)

        #creates Earth
        self.earth = Actor("models/planet_sphere.egg.pz")
        self.earth.reparentTo(render)
        self.earth.setScale(6.0)
        self.earth.setPos(40, 25, 6)
        self.earth_texture = loader.loadTexture("models/earth_1k_tex.jpg")
        self.earth.setTexture(self.earth_texture)

        #creates Mercury
        self.mercury = Actor("models/planet_sphere.egg.pz")
        self.mercury.reparentTo(render)
        self.mercury.setScale(2.0)
        self.mercury.setPos(-40, -25, 2)
        self.mercury_texture = loader.loadTexture("models/mercury_1k_tex.jpg")
        self.mercury.setTexture(self.mercury_texture)

        #creates Venus
        self.venus = Actor("models/planet_sphere.egg.pz")
        self.venus.reparentTo(render)
        self.venus.setScale(4.0)
        self.venus.setPos(40, -30, 4)
        self.venus_texture = loader.loadTexture("models/venus_1k_tex.jpg")
        self.venus.setTexture(self.venus_texture)

        # 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("a", self.setKey, ["left", 1])
        self.accept("d", self.setKey, ["right", 1])
        self.accept("w", self.setKey, ["forward", 1])
        self.accept("s", self.setKey, ["backward", 1])
        self.accept("arrow_left", self.setKey, ["cam-left", 1])
        self.accept("arrow_right", self.setKey, ["cam-right", 1])
        self.accept("a-up", self.setKey, ["left", 0])
        self.accept("d-up", self.setKey, ["right", 0])
        self.accept("w-up", self.setKey, ["forward", 0])
        self.accept("arrow_left-up", self.setKey, ["cam-left", 0])
        self.accept("arrow_right-up", self.setKey, ["cam-right", 0])
        self.accept("p", self.setKey, ["accelerate", 1])
        self.accept("o", self.setKey, ["decelerate", 1])
        self.accept("p-up", self.setKey, ["accelerate", 0])
        self.accept("o-up", self.setKey, ["decelerate", 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)

        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)

        # 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()

        # pring the inital position
        #print startpos

        global speed
        global maxspeed
        # 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):
            if (v == [2]):
                self.ralph.setY(self.ralph, speed * globalClock.getDt())
            else:
                self.ralph.setY(self.ralph, -speed * globalClock.getDt())

        if (self.keyMap["accelerate"] != 0):
            speed += 100
        if (speed > maxspeed):
            speed = maxspeed
        elif (self.keyMap["decelerate"] != 0):
            speed -= 1
        if (speed < 10.0):
            speed = 10.0

        # 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("walk")
                self.ralph.loop("run")
                self.isMoving = True
        else:
            if self.isMoving:
                self.ralph.stop()
                self.ralph.pose("walk", 5)
                self.isMoving = False
                speed = 10.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() - 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

        # 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