예제 #1
0
class Mouse(DirectObject):
    def __init__(self, levelNP):
        self.setCursor()
        # store the nodepath to the level collisions
        # will be used to check for intersections with the mouse ray
        self.levelNP = levelNP
        # 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))#GeomNode.getDefaultCollideMask())
        # 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)

    def setCursor(self):
        base.win.clearRejectedProperties()
        props = WindowProperties()
        if sys.platform.startswith('linux'):
            props.setCursorFilename("./assets/cursor.x11")
        else:
            props.setCursorFilename("./assets/cursor.ico")
        base.win.requestProperties(props)

    def getMousePos(self):
        # check if we have a mouse on the window
        if base.mouseWatcherNode.hasMouse():
            # get the mouse position on the screen
            mpos = base.mouseWatcherNode.getMouse()
            # set the ray's position
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            # Now call the traverse function to let the traverser check for collisions
            # with the added colliders and the levelNP
            self.picker.traverse(self.levelNP)
            # check if we have a collision
            if self.pq.getNumEntries() > 0:
                # sort the entries to get the closest first
                self.pq.sortEntries()
                # This is the point at where the mouse ray and the level plane intersect
                hitPos = self.pq.getEntry(0).getSurfacePoint(render)
                return hitPos
        return Point3(0, 0, 0)

        task.cont
 def get_dist_to_cell(self, pos):
     """Given a position, return the distance to the nearest cell
     below that position. If no cell is found, returns None."""
     self.ray.setOrigin(pos)
     queue = CollisionHandlerQueue()
     self.traverser.addCollider(self.ray_nodepath, queue)
     self.traverser.traverse(self.cell_picker_world)
     self.traverser.removeCollider(self.ray_nodepath)
     queue.sortEntries()
     if not queue.getNumEntries():
         return None
     entry = queue.getEntry(0)
     return (entry.getSurfacePoint(self.cell_picker_world) - pos).length()
예제 #3
0
class Projectile(NetEnt):
	def __init__(self, parent=None, pitch=None, id=None):
		NetEnt.__init__(self, id)
		self.node = NetNodePath(PandaNode('projectile'))
		if parent:
			self.parent = parent
			self.node.setPos(parent.node.getPos() + (0,0,1))
			self.node.setHpr(parent.node.getHpr())
			self.node.setP(pitch)
		self.node.reparentTo(render)
		ProjectilePool.add(self)
		#print 'there are',len(ProjectilePool.values()),'projectiles'
		self.flyTime = 0
		
		self.sprite = Sprite2d('resources/missile.png', rows=3, cols=1, rowPerFace=(0,1,2,1), anchorY=Sprite2d.ALIGN_CENTER)
		self.sprite.node.reparentTo(self.node)

		# set up 'from' collisions - for detecting projectile hitting things
		self.collisionHandler = CollisionHandlerQueue()
		self.fromCollider = self.node.attachNewNode(CollisionNode('fromCollider'))
		self.fromCollider.node().addSolid(CollisionRay(0,0,0,0,1,0))
		self.fromCollider.node().setIntoCollideMask(BITMASK_EMPTY)
		self.fromCollider.node().setFromCollideMask(BITMASK_TERRAIN | BITMASK_CHARACTER)
		if SHOW_COLLISIONS:
			self.fromCollider.show()
		Character.collisionTraverser.addCollider(self.fromCollider,self.collisionHandler)

	def getState(self):
		dataDict = NetObj.getState(self)
		dataDict[0] = self.node.getState()
		return dataDict
	def setState(self, weightOld, dataDictOld, weightNew, dataDictNew):
		oldNode = None if not dataDictOld else dataDictOld.get(0,None)
		self.node.setState(weightOld, oldNode, weightNew, dataDictNew[0])
	def movePostCollide(self, deltaT):
		desiredDistance = 30*deltaT
		self.collisionHandler.sortEntries()
		ch = self.collisionHandler
		for e in [ch.getEntry(i) for i in range(ch.getNumEntries())]:
			collisionDist = (self.node.getPos() - e.getSurfacePoint(render)).length()
			if collisionDist > desiredDistance:
				break
			# only accept collisions that aren't with parent
			if e.getIntoNode().getParent(0).getTag('ID') != str(self.parent.id):
				return False
		self.node.setY(self.node, desiredDistance)
		self.flyTime += deltaT
		return self.flyTime < 4
	def __del__(self):
		#print 'PROJECTILE BEING REMOVED'
		self.node.removeNode()
 def get_cell(self, pos):
     """Given a position, return the nearest cell below that position.
     If no cell is found, returns None."""
     self.ray.setOrigin(pos)
     queue = CollisionHandlerQueue()
     self.traverser.addCollider(self.ray_nodepath, queue)
     self.traverser.traverse(self.cell_picker_world)
     self.traverser.removeCollider(self.ray_nodepath)
     queue.sortEntries()
     if not queue.getNumEntries():
         return None
     entry = queue.getEntry(0)
     cnode = entry.getIntoNode()
     try:
         return self.cells_by_collider[cnode]
     except KeyError:
         raise Warning('collision ray collided with something '
                       'other than a cell: %s' % cnode)
예제 #5
0
class Player(GameObject):
    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.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.damagePerSecond = -5.0

        self.actor.loop("stand")

    def update(self, keys, dt):
        GameObject.update(self, dt)

        self.walking = False

        if keys["up"]:
            self.walking = True
            self.velocity.addY(self.acceleration * dt)
        if keys["down"]:
            self.walking = True
            self.velocity.addY(-self.acceleration * dt)
        if keys["left"]:
            self.walking = True
            self.velocity.addX(-self.acceleration * dt)
        if keys["right"]:
            self.walking = True
            self.velocity.addX(self.acceleration * dt)

        if self.walking:
            standControl = self.actor.getAnimControl("stand")
            if standControl.isPlaying():
                standControl.stop()

            walkControl = self.actor.getAnimControl("walk")
            if not walkControl.isPlaying():
                self.actor.loop("walk")
        else:
            standControl = self.actor.getAnimControl("stand")
            if not standControl.isPlaying():
                self.actor.stop("walk")
                self.actor.loop("stand")

        if keys["shoot"]:
            if self.rayQueue.getNumEntries() > 0:
                self.rayQueue.sortEntries()
                rayHit = self.rayQueue.getEntry(0)
                hitPos = rayHit.getSurfacePoint(render)

                hitNodePath = rayHit.getIntoNodePath()
                if hitNodePath.hasPythonTag("owner"):
                    hitObject = hitNodePath.getPythonTag("owner")
                    if not isinstance(hitObject, TrapEnemy):
                        hitObject.alterHealth(self.damagePerSecond * dt)

                beamLength = (hitPos - self.actor.getPos()).length()
                self.beamModel.setSy(beamLength)

                self.beamModel.show()
        else:
            self.beamModel.hide()

    def cleanup(self):
        base.cTrav.removeCollider(self.rayNodePath)

        GameObject.cleanup(self)
예제 #6
0
class Player(DirectObject):
    def __init__(self, _main):
        self.main = _main

        # Stats
        self.moveSpeed = 8
        self.inventory = []
        self.maxCarryWeight = 20.0 #kg ?
        self.currentInventoryWeight = 0.0

        # Inventory GUI
        self.inventoryGui = Inventory()
        self.inventoryGui.hide()
        self.inventoryActive = False
        self.craftInventory = CraftInventory()
        self.craftInventory.hide()

        # enable movements through the level
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0}
        self.player = NodePath("Player")#loader.loadModel("smiley")
        self.player.setPos(149.032, 329.324, 11.3384)
        self.player.setH(180)
        self.player.reparentTo(render)

        self.accept("w", self.setKey, ["forward",1])
        self.accept("w-up", self.setKey, ["forward",0])
        self.accept("a", self.setKey, ["left",1])
        self.accept("a-up", self.setKey, ["left",0])
        self.accept("s", self.setKey, ["backward",1])
        self.accept("s-up", self.setKey, ["backward",0])
        self.accept("d", self.setKey, ["right",1])
        self.accept("d-up", self.setKey, ["right",0])
        self.accept("mouse1", self.handleLeftMouse)
        self.accept("i", self.toggleInventory)
        self.accept("c", self.toggleCraftInventory)


        # screen sizes
        self.winXhalf = base.win.getXSize() / 2
        self.winYhalf = base.win.getYSize() / 2

        self.mouseSpeedX = 0.1
        self.mouseSpeedY = 0.1

        camera.setH(180)
        camera.reparentTo(self.player)
        camera.setZ(self.player, 2)
        base.camLens.setFov(75)
        base.camLens.setNear(0.8)

        # Mouse controls
        self.mouseNode = CollisionNode('mouseRay')
        self.mouseNodeNP = camera.attachNewNode(self.mouseNode)
        self.mouseNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
        self.mouseRay = CollisionRay()
        self.mouseNode.addSolid(self.mouseRay)
        self.mouseRayHandler = CollisionHandlerQueue()

        # Collision Traverser
        self.traverser = CollisionTraverser("Player Traverser")
        base.cTrav = self.traverser
        self.traverser.addCollider(self.mouseNodeNP, self.mouseRayHandler)

    def run(self):
        taskMgr.add(self.move, "moveTask", priority=-4)

    def pause(self):
        taskMgr.remove("moveTask")

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

    def move(self, task):
        if not base.mouseWatcherNode.hasMouse(): return task.cont

        pointer = base.win.getPointer(0)
        mouseX = pointer.getX()
        mouseY = pointer.getY()

        if base.win.movePointer(0, self.winXhalf, self.winYhalf):
            # calculate the looking up/down of the camera.
            # NOTE: for first person shooter, the camera here can be replaced
            # with a controlable joint of the player model
            p = camera.getP() - (mouseY - self.winYhalf) * self.mouseSpeedY
            if p <-80:
                p = -80
            elif p > 90:
                p = 90
            camera.setP(p)

            # rotate the player's heading according to the mouse x-axis movement
            h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX
            if h <-360:
                h = 360
            elif h > 360:
                h = -360
            self.player.setH(h)

        # basic movement of the player
        if self.keyMap["left"] != 0:
            self.player.setX(self.player, self.moveSpeed * globalClock.getDt())
        if self.keyMap["right"] != 0:
            self.player.setX(self.player, -self.moveSpeed * globalClock.getDt())
        if self.keyMap["forward"] != 0:
            self.player.setY(self.player, -self.moveSpeed * globalClock.getDt())
        if self.keyMap["backward"] != 0:
            self.player.setY(self.player, self.moveSpeed * globalClock.getDt())


        # keep the player on the ground
        elevation = self.main.t.terrain.getElevation(self.player.getX(), self.player.getY())
        self.player.setZ(elevation*self.main.t.zScale)

        return task.cont

    def toggleInventory(self):
        if self.inventoryActive:
            self.inventoryGui.hide()
            self.inventoryActive = False
            self.run()
        else:
            self.inventoryGui.show()
            self.inventoryActive = True
            self.pause()

    def toggleCraftInventory(self):
        if self.inventoryActive:
            self.craftInventory.hide()
            self.inventoryActive = False
            self.run()
        else:
            self.craftInventory.updateList(self.inventory)
            self.craftInventory.show()
            self.inventoryActive = True
            self.pause()

    def handleLeftMouse(self):
        # Do the mining
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.mouseRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())

            self.traverser.traverse(render)
            # Assume for simplicity's sake that myHandler is a CollisionHandlerQueue.
            if self.mouseRayHandler.getNumEntries() > 0:
            # This is so we get the closest object.
                self.mouseRayHandler.sortEntries()
                pickedObj = self.mouseRayHandler.getEntry(0).getIntoNodePath()

                # Range check
                if (self.player.getPos() - pickedObj.getPos(render)).length() <= 3.0:
                    self.mine(pickedObj)
                else:
                    print "You are to far, move closer!"


    def mine(self, _nodeNP):
        self.nodeNP = _nodeNP

        # get the object class
        for node in self.main.nodeGen.currentNodes:
            if self.main.nodeGen.currentNodes[node] in self.inventory:
                print "new Loot:", self.main.nodeGen.currentNodes[node].giveLoot()
                self.inventory.append(self.main.nodeGen.currentNodes[node])
                if self.main.nodeGen.currentNodes[node].lootLeft == 0:
                    self.main.nodeGen.currentNodes[node].removeModel()
                    break
                break


            # if mining node
            else:

                if self.main.nodeGen.currentNodes[node].model and self.main.nodeGen.currentNodes[node].model.getPos() == self.nodeNP.getPos(render):
                    #self.main.nodeGen.currentNodes[node].removeModel()
                    self.inventory.append(self.main.nodeGen.currentNodes[node])
                    self.currentInventoryWeight += self.main.nodeGen.currentNodes[node].weight
                    self.inventoryGui.updateList(self.inventory)
                    print "You received:", self.main.nodeGen.currentNodes[node].giveLoot(), self.main.nodeGen.currentNodes[node].giveType(), "Ores"
                    print "Inventory:", self.inventory
                    print "Current Weight:", self.currentInventoryWeight
                    break

        print self.player.getPos()
예제 #7
0
class Mouse():
    def __init__(self):
        self.enabled = False
        self.locked = False
        self.position = Vec3(0, 0, 0)
        self.delta = Vec3(0, 0, 0)
        self.prev_x = 0
        self.prev_y = 0
        self.velocity = Vec3(0, 0, 0)
        self.prev_click_time = time.time()
        self.double_click_distance = .5

        self.hovered_entity = None
        self.left = False
        self.right = False
        self.middle = False
        self.delta_drag = Vec3(0, 0, 0)

        self.i = 0
        self.update_rate = 10
        self._mouse_watcher = None
        self._picker = CollisionTraverser()  # Make a traverser
        self._pq = CollisionHandlerQueue()  # Make a handler
        self._pickerNode = CollisionNode('mouseRay')
        self._pickerNP = camera.attach_new_node(self._pickerNode)
        self._pickerRay = CollisionRay()  # Make our ray
        self._pickerNode.addSolid(self._pickerRay)
        self._picker.addCollider(self._pickerNP, self._pq)
        self.raycast = True
        self.collision = None
        self.enabled = True

    @property
    def x(self):
        if not self._mouse_watcher.has_mouse():
            return 0
        return self._mouse_watcher.getMouseX(
        ) / 2 * window.aspect_ratio  # same space as ui stuff

    @property
    def y(self):
        if not self._mouse_watcher.has_mouse():
            return 0
        return self._mouse_watcher.getMouseY() / 2

    def __setattr__(self, name, value):

        if name == 'visible':
            window.set_cursor_hidden(not value)
            application.base.win.requestProperties(window)

        if name == 'locked':
            try:
                object.__setattr__(self, name, value)
                window.set_cursor_hidden(value)
                application.base.win.requestProperties(window)
            except:
                pass

        try:
            super().__setattr__(name, value)
            # return
        except:
            pass

    def input(self, key):
        if not self.enabled:
            return

        if key.endswith('mouse down'):
            self.start_x = self.x
            self.start_y = self.y

        elif key.endswith('mouse up'):
            self.delta_drag = Vec3(self.x - self.start_x,
                                   self.y - self.start_y, 0)

        if key == 'left mouse down':
            self.left = True
            if self.hovered_entity:
                if hasattr(self.hovered_entity, 'on_click'):
                    self.hovered_entity.on_click()
                for s in self.hovered_entity.scripts:
                    if hasattr(s, 'on_click'):
                        s.on_click()
            # double click
            if time.time(
            ) - self.prev_click_time <= self.double_click_distance:
                base.input('double click')

                if self.hovered_entity:
                    if hasattr(self.hovered_entity, 'on_double_click'):
                        self.hovered_entity.on_double_click()
                    for s in self.hovered_entity.scripts:
                        if hasattr(s, 'on_double_click'):
                            s.on_double_click()

            self.prev_click_time = time.time()

        if key == 'left mouse up':
            self.left = False
        if key == 'right mouse down':
            self.right = True
        if key == 'right mouse up':
            self.right = False
        if key == 'middle mouse down':
            self.middle = True
        if key == 'middle mouse up':
            self.middle = False

    def update(self):
        if not self.enabled or not self._mouse_watcher.has_mouse():
            self.velocity = Vec3(0, 0, 0)
            return

        self.position = Vec3(self.x, self.y, 0)
        self.moving = self.x + self.y != self.prev_x + self.prev_y

        if self.moving:
            if self.locked:
                self.velocity = self.position
                application.base.win.move_pointer(0, int(window.size[0] / 2),
                                                  int(window.size[1] / 2))
            else:
                self.velocity = Vec3(self.x - self.prev_x,
                                     (self.y - self.prev_y) /
                                     window.aspect_ratio, 0)
        else:
            self.velocity = Vec3(0, 0, 0)

        if self.left or self.right or self.middle:
            self.delta = Vec3(self.x - self.start_x, self.y - self.start_y, 0)

        self.prev_x = self.x
        self.prev_y = self.y

        self.i += 1
        if self.i < self.update_rate:
            return
        # collide with ui
        self._pickerNP.reparent_to(scene.ui_camera)
        self._pickerRay.set_from_lens(camera._ui_lens_node,
                                      self.x * 2 / window.aspect_ratio,
                                      self.y * 2)
        self._picker.traverse(camera.ui)
        if self._pq.get_num_entries() > 0:
            # print('collided with ui', self._pq.getNumEntries())
            self.find_collision()
            return

        # collide with world
        self._pickerNP.reparent_to(camera)
        self._pickerRay.set_from_lens(scene.camera.lens_node,
                                      self.x * 2 / window.aspect_ratio,
                                      self.y * 2)
        self._picker.traverse(base.render)
        if self._pq.get_num_entries() > 0:
            # print('collided with world', self._pq.getNumEntries())
            self.find_collision()
            return
        # else:
        #     print('mouse miss', base.render)

        # unhover all if it didn't hit anything
        for entity in scene.entities:
            if hasattr(entity, 'hovered') and entity.hovered:
                entity.hovered = False
                self.hovered_entity = None
                if hasattr(entity, 'on_mouse_exit'):
                    entity.on_mouse_exit()
                for s in entity.scripts:
                    if hasattr(s, 'on_mouse_exit'):
                        s.on_mouse_exit()

    @property
    def normal(self):
        if not self.collision:
            return None
        if not self.collision.has_surface_normal():
            print('no surface normal')
            return None
        n = self.collision.get_surface_normal(
            self.collision.get_into_node_path().parent)
        return (n[0], n[2], n[1])

    @property
    def world_normal(self):
        if not self.collision:
            return None
        if not self.collision.has_surface_normal():
            print('no surface normal')
            return None
        n = self.collision.get_surface_normal(render)
        return (n[0], n[2], n[1])

    @property
    def point(self):
        if self.hovered_entity:
            p = self.collision.getSurfacePoint(self.hovered_entity)
            return Point3(p[0], p[2], p[1])
        else:
            return None

    @property
    def world_point(self):
        if self.hovered_entity:
            p = self.collision.getSurfacePoint(render)
            return Point3(p[0], p[2], p[1])
        else:
            return None

    def find_collision(self):
        if not self.raycast:
            return
        self._pq.sortEntries()
        if len(self._pq.get_entries()) == 0:
            self.collision = None
            return

        self.collisions = list()
        for entry in self._pq.getEntries():
            # print(entry.getIntoNodePath().parent)
            for entity in scene.entities:
                if entry.getIntoNodePath().parent == entity:
                    if entity.collision:
                        self.collisions.append(
                            Hit(
                                hit=entry.collided(),
                                entity=entity,
                                distance=0,
                                point=entry.getSurfacePoint(entity),
                                world_point=entry.getSurfacePoint(scene),
                                normal=entry.getSurfaceNormal(entity),
                                world_normal=entry.getSurfaceNormal(scene),
                            ))
                        break

        self.collision = self._pq.getEntry(0)
        nP = self.collision.getIntoNodePath().parent

        for entity in scene.entities:
            if not hasattr(entity, 'collision'
                           ) or not entity.collision or not entity.collider:
                continue
            # if hit entity is not hovered, call on_mouse_enter()
            if entity == nP:
                if not entity.hovered:
                    entity.hovered = True
                    self.hovered_entity = entity
                    # print(entity.name)
                    if hasattr(entity, 'on_mouse_enter'):
                        entity.on_mouse_enter()
                    for s in entity.scripts:
                        if hasattr(s, 'on_mouse_enter'):
                            s.on_mouse_enter()
            # unhover the rest
            else:
                if entity.hovered:
                    entity.hovered = False
                    if hasattr(entity, 'on_mouse_exit'):
                        entity.on_mouse_exit()
                    for s in entity.scripts:
                        if hasattr(s, 'on_mouse_exit'):
                            s.on_mouse_exit()
예제 #8
0
class Fighter():
    def __init__(self,characterPath , callOnDeath , side , name = None):
        #side indicates if the player is on the left or right side.
        #TODO: add collision tests against ring-out geometry in the arena, 
        

        self.fsm = FighterFsm(self,characterPath)    
        self.inputHandler = InputHandler(self.fsm,side)
        
        self.side = side
        
        self.wins = 0 #counting won rounds, a double-ko/draw counts as win for both.
        self.faceOpp = True  #looking at opponent
        self.callOnDeath = callOnDeath
        
        self.statusBitMask = BitMask32()
        self.defenseBitMask = BitMask32()    #active defense parts get a 1
        #the attack bitmask is generated by the fsm and passed to the attack method directly
    
        if not name:
            name = "player"+str(1+bool(side))
        
        self.healthBar = PlayerHud(side, name )
          
        self.fighterNP = render.attachNewNode(name)
        self.collTrav = CollisionTraverser(name)
        fromObject = self.fighterNP.attachNewNode(CollisionNode('colNode'+name))
        fromObject.node().addSolid(CollisionRay(0, 0, 2,0,0, -1))
        fromObject.node().setFromCollideMask(BitMask32.bit(1))
        fromObject.node().setIntoCollideMask(BitMask32.allOff())
        self.queue = CollisionHandlerQueue()
        self.collTrav.addCollider(fromObject, self.queue)
        
        self.fsm.getNP().reparentTo(self.fighterNP)
        #fromObject.show() #more debug collision visuals
        #self.collTrav.showCollisions(render) #debug visuals for collision     
        self.prepareFighter()
   
   
    def updateState(self,newState = None):
        if newState:
            if "enter" + state in dir(self.fsm):
                self.fsm.forceTransition(newState)
        else:
            self.inputHandler.pollEvents()          
        
    def prepareFighter(self):
        taskMgr.remove("player"+str(self.side))
        self.speed = (0,0)
        self.fsm.forceTransition("Idle")
        self.health= 100
        self.healthBar.setHealth(self.health)
        self.healthBar.setRoundIndicator('V'*self.wins)
        
        if self.side:
            self.fighterNP.setX(5)
        else:
            self.fighterNP.setX(-5)
        self.fighterNP.setY(0)
        taskMgr.add(self._playertask, "player"+str(self.side))
    
    def setStatusBitMask(self,bitmask):
        self.statusBitMask = bitmask
        
    def setDefenseBitMask(self,bitmask):
        self.defenseBitMask = bitmask 
   
    #getters and setters are a bit stupid here. properties from python 3 would be nice
    def fighterWin(self):
        #request a win-anim from the fsm if there are any
        self.wins += 1
        self.healthBar.setRoundIndicator('V'*self.wins)
    
    def getWins(self):
        return self.wins   
    
    def getHealth(self):
        return self.health
        
    def getNP(self):
        return self.fighterNP

    def setOpponent(self,opponent):
        self.opponent = opponent
        self.fighterNP.lookAt(self.opponent.getNP())
   
    def attack(self,attackBitMask,attackrange,damageHit,damageDodge=0,angle=30): #those variables will be supplied by the fsm states later on. 
                                                             #function is pretty redundant... for structure only, and for early days
        attackstatus = self.opponent.getAttacked(attackBitMask,attackrange,damageHit,damageDodge,angle)
        return attackstatus
    
    def _testHit(self,node1,node2,threshold=30, dist = 1):  #node1 which looks for a target , node2 is the target , threshold is the max-attack-angle, dist the dist
          dirVec = node1.getRelativePoint(node2,Vec3(0,0,0))
          dirVec = Vec3(dirVec[0],dirVec[1],dirVec[2])
          
          dirVec.normalize()
          angle = dirVec.angleDeg(Vec3(0,1,0))
          if angle < threshold and dist > node1.getDistance(node2):
            #print "hit at "+str(angle)+" degree!"
            return True
          else:
            #print angle,node1.getDistance(node2)
            return False
        
    def getAttacked(self,attackBitMask,attackrange,damageHit,damageDodge=0,angle = 30):
        """
        returns 0 if not hit, 1 if hit was blocked, 2 if hit, 3 for hit+KO 
        """
        if self.health <=0:
            return 4 #player is ko already
            

        if  not self._testHit(self.opponent.getNP(),self.fighterNP  ,angle,attackrange )  : #instead of 0, a sligtly positive values makes thinks look better.
            #attack misses due to out of range.
            return 0 

        if (self.statusBitMask & attackBitMask).getWord() == 0: # attak misses cause the player avoided it. went low or so.
            return 0
  
        if (self.defenseBitMask & attackBitMask).getWord():
            self.health -= damageDodge
            self.healthBar.setHealth(self.health)
            return 1 #hit,... but blocked so no combos 
            
        else:
            self.health -= damageHit
            self.healthBar.setHealth(self.health)
            if self.health <= 0 : #if KO
                taskMgr.remove("player"+str(self.side))
                self.fsm.forceTransition("Ko")
                #actually make the match.py allow the other player to KO (in case of doubleKO,befor calling round end.
                taskMgr.doMethodLater(0.5,self.callOnDeath,"RoundEnd") 
                return 3
            #TODO: requesting the same state as you are in doesnt work well.sorta need to re-enter the hit state
            if "Crouch" in self.fsm.state:
                self.fsm.forceTransition("CrouchHit")
            elif self.fsm.state:
                self.fsm.forceTransition("Hit")
            return 2 #regular hit
    
    def setSpeed(self,x,y):
        self.speed = (x,y)
    
    def faceOpponent(self,facing):
        self.faceOpp = facing #true if yuo look at the other player (usualy true unless attacking), so you can dodge an attack by evading.
    
    def _playertask(self,task):
        
        oldpos = self.fighterNP.getPos()
        
        dist = self.fighterNP.getY(self.opponent.getNP()) 

        if dist > 3 or self.speed[0]<0: #prevert players from walking throug each other , too troublesome atm
            self.fighterNP.setX(self.fighterNP,self.speed[1]*globalClock.getDt())
            self.fighterNP.setY(self.fighterNP,self.speed[0]*globalClock.getDt())
        else :
            self.speed = ( min(2,self.speed[0] ), self.speed[1])
            #also push back other player
            self.opponent.getNP().setY(self.opponent.getNP(),-self.speed[0]*globalClock.getDt() )
            
        self.collTrav.traverse(render)
        self.queue.sortEntries()
        for i in range(self.queue.getNumEntries()):
            entry = self.queue.getEntry(i)
            if "ground" in entry.getIntoNodePath().getName() :
                break
            if "out" in entry.getIntoNodePath().getName() :
                pass #ring out
                self.fighterNP.setPos(oldpos) #for now reset him as we have no ring-out anim yet #TODO: add ring out anim!
                break
            
        if self.queue.getNumEntries() == 0:
            #if there is no ground and no ring out, propably a wall or no thin like that. just reset the pos     
            self.fighterNP.setPos(oldpos)
            print "resetting fighter"
            
        if self.faceOpp:
            self.fighterNP.lookAt(self.opponent.getNP())      
                
        return task.cont
예제 #9
0
파일: editor.py 프로젝트: Gaku01/mcr3d
class Editor(DirectObject):
    # Конструктор
    def __init__(self, map_manager):
        # сохраняем ссылку на объект менеджера карты
        self.map_manager = map_manager

        # режим редактирования
        self.edit_mode = True

        # создание обходчика столкновений
        self.traverser = CollisionTraverser()
        # очередь обработки столкновений
        self.collisQueue = CollisionHandlerQueue()
        # узел для луча столкновений
        collisionNode = CollisionNode('centerRay')
        # устанавливаем маску проверки столкновений ОТ
        collisionNode.setFromCollideMask(BitMask32.bit(1))
        # сбрасываем маску проверки столкновений ДО
        collisionNode.setIntoCollideMask(BitMask32.allOff())
        # создаём луч
        self.collisRay = CollisionRay()
        # и прикрепляем к созданному ранее узлу
        collisionNode.addSolid(self.collisRay)
        # закрепляем узел на камере
        collisCamNode = base.camera.attachNewNode(collisionNode)
        # уведомляем обходчик о новом «объекте ОТ»
        self.traverser.addCollider(collisCamNode, self.collisQueue)
        # визуализируем столкновения (раскомментировать/закоментировать)
        #self.traverser.showCollisions(base.render)
        # позиция для добавления нового блока
        self.new_position = None
        # ключ выделенного блока
        self.selected_key = None
        # узел выделенного блока
        self.selected_node = None

        # запускаем задачу проверки выделения блоков
        taskMgr.doMethodLater(0.02, self.testBlocksSelection,
                              "test_block-task")

        # регистрируем на нажатие левой кнопки мыши
        # событие добавления блока
        self.accept('mouse1', self.addBlock)
        # регистрируем на нажатие правой кнопки мыши
        # событие удаления блока
        self.accept('mouse3', self.delBlock)

    #метод установки режима редактирования
    def setEditMode(self, mode):
        self.edit_mode = mode
        if self.edit_mode:
            # сбрасываем выделение
            self.resetSelectedBlock()
            # запускаем задачу проверки выделения блоков
            taskMgr.doMethodLater(0.02, self.testBlocksSelection,
                                  "test_block-task")
        else:
            # удаляем задачу проверки выделения блоков
            taskMgr.remove("test_block-task")
            # снимаем выделение со всех блоков
            self.map_manager.deselectAllBlocks()

    # Метод сброса свойств выделенного блока
    def resetSelectedBlock(self):
        self.new_position = None
        self.selected_key = None
        self.selected_node = None

    # Метод добавления блока
    def addBlock(self):
        # если есть позиция для нового блока
        if self.new_position:
            # добавляем блок в эту позицию
            self.map_manager.addBlock(self.new_position)
            # сбрасываем выделение
            self.resetSelectedBlock()

    # Метод удаления блока
    def delBlock(self):
        # удаляем выделенный блок
        self.map_manager.deleteSelectedBlock()
        # сбрасываем выделение
        self.resetSelectedBlock()

    # Метод проверки проверки выделения блоков
    def testBlocksSelection(self, task):
        # устанавливаем позицию луча столкновений в центр экрана
        self.collisRay.setFromLens(base.camNode, 0, 0)
        # запускаем обходчик на проверку
        self.traverser.traverse(base.render)

        # если обходчик обнаружил какие-то столкновения
        if self.collisQueue.getNumEntries() > 0:
            # сортируем их, чтобы получить ближайшее
            self.collisQueue.sortEntries()
            # получаем описание ближайшего столкновения
            collisionEntry = self.collisQueue.getEntry(0)
            # получаем узел с «объектом ДО» и ключ выделенного блока
            key = collisionEntry.getIntoNodePath().getTag('key')

            # если найден новый блок
            if key != self.selected_key:
                # обновляем ключ выделенного блока
                self.selected_key = key
                # выделяем новый блок
                self.selected_node = self.map_manager.selectBlock(key)

            # если есть выделенный блок
            if self.selected_node:
                # координаты выделенного блока
                selected_position = self.selected_node.getPos()
                # вектор нормали к поверхности на выделенном блоке
                normal = collisionEntry.getSurfaceNormal(self.selected_node)
                # позиция для добавления нового блока
                self.new_position = selected_position + normal
        else:
            # снимаем выделение со всех блоков
            self.map_manager.deselectAllBlocks()
            # сбрасываем выделение
            self.resetSelectedBlock()

        # сообщаем о необходимости повторного запуска задачи
        return task.again
예제 #10
0
class MousePicker(object):
    def __init__(self,
                 pickTag='MyPickingTag',
                 nodeName='pickRay',
                 showCollisions=False):
        self.pickTag = pickTag
        self.nodeName = nodeName
        self.showCollisions = showCollisions

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        mpos = base.mouseWatcherNode.getMouse()

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

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

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

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

        return None, None

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

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

        mpos = base.mouseWatcherNode.getMouse()

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

        self.mPickerTraverser2D.traverse(base.aspect2d)

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

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

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

        return None, None
예제 #11
0
class Physics:
    def __init__(self):
        self.rayCTrav = CollisionTraverser("collision traverser for ray tests")
        #self.pusher = PhysicsCollisionHandler()
        self.pusher = CollisionHandlerPusher()
        self.pusher.addInPattern('%fn-in-%in')
        self.pusher.addOutPattern('%fn-out-%in')
        self.pusher.addInPattern('%fn-in')
        self.pusher.addOutPattern('%fn-out')

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

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

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

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

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

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

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

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

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

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

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

    def getFirstCollisionInLine(self, pointA, pointB):
        """A simple raycast check which will return the first collision point as
        seen from point A towards pointB"""
        self.raytest_segment.setPointA(pointA)
        self.raytest_segment.setPointB(pointB)
        self.rayCTrav.traverse(render)
        self.raytest_queue.sortEntries()
        pos = None
        if self.raytest_queue.getNumEntries() > 0:
            pos = self.raytest_queue.getEntry(0).getSurfacePoint(render)
        return pos
예제 #12
0
class Picker(object):
    """
    Generic object picker class for Panda3d. Given a top Node Path to search,
    it finds the closest collision object under the mouse pointer.

    Picker takes a topNode to test for mouse ray collisions.

    the pick() method returns (NodePathPicked, 3dPosition, rawNode) underneath the mouse position.
    If no collision was detected, it returns None, None, None.

    'NodePathPicked' is the deepest NAMED node path that was collided with, this is
    usually what you want. rawNode is the deep node (such as geom) if you want to
    play with that. 3dPosition is where the mouse ray touched the surface.

    The picker object uses base.camera to collide, so if you have a custom camera,
    well, sorry bout that.

    pseudo code:
    p = Picker(mycollisionTopNode)
    thingPicked, positionPicked, rawNode = p.pick()
    if thingPicked:
        # do something here like
        thingPicked.ls()

    """
    def __init__(self, topNode, cameraObject = None):
        self.traverser = CollisionTraverser()
        self.handler = CollisionHandlerQueue()
        self.topNode = topNode
        self.cam = cameraObject

        pickerNode  = CollisionNode('MouseRay')

        #NEEDS to be set to global camera. boo hoo
        self.pickerNP = base.camera.attachNewNode(pickerNode)

        # this seems to enter the bowels of the node graph, making it
        # difficult to perform logic on
        pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())

        self.pickRay = CollisionRay()
        #pickerNode.setCollideMask(BitMask32.allOff())
        pickerNode.addSolid(self.pickRay)
        self.traverser.addCollider(self.pickerNP, self.handler)

    def setTopNode(self, topNode):
        """set the topmost node to traverse when detecting collisions"""
        self.topNode = topNode

    def destroy(self):
        """clean up my stuff."""
        self.ignoreAll()
        # remove colliders, subnodes and such
        self.pickerNP.remove()
        self.traverser.clearColliders()

    def pick(self):
        """
        pick closest object under the mouse if available.
        returns ( NodePathPicked, surfacePoint, rawNode )
        or (None, None None)
        """
        if not self.topNode:
            return None, None, None

        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()

            self.pickRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            self.traverser.traverse(self.topNode)

            if self.handler.getNumEntries() > 0:
                self.handler.sortEntries()
                picked = self.handler.getEntry(0).getIntoNodePath()
                thepoint = self.handler.getEntry(0).getSurfacePoint(self.topNode)
                return self.getFirstParentWithName(picked), thepoint, picked

        return None, None, None

    def getFirstParentWithName(self, pickedObject):
        """
        return first named object up the node chain from the picked node. This
        helps remove drudgery when you just want to find a simple object to
        work with. Normally, you wouldn't use this method directly.
        """
        name = pickedObject.getName()
        parent = pickedObject
        while not name:
            parent = parent.getParent()
            if not parent:
                raise Exception("Node '%s' needs a parent with a name to accept clicks." % (str(pickedObject)))

            name = parent.getName()
        if parent == self.topNode:
            raise Exception("Collision parent '%s' is top Node, surely you wanted to click something beneath it..." % (str(parent)))

        return parent
예제 #13
0
파일: selection.py 프로젝트: tgbugs/desc
class HasSelectables(HasKeybinds): #mixin see chessboard example
    def __init__(self):
        #selection detection
        self.picker = CollisionTraverser()
        self.pq = CollisionHandlerQueue()
        self.pickerNode = CollisionNode('mouseRay')
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        #self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) #TODO WOW geometry collision is SUPER slow...
        self.pickerNode.setFromCollideMask(BitMask32.bit(BITMASK_COLL_CLICK))
        #render.find('**selectable').node().setIntoCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()
        self.pickerNode.addSolid(self.pickerRay)
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)

        #box selection detection HINT: start with drawing the 2d thing yo!

        self.__shift__ = False
        self.accept("shift", self.shiftOn)
        self.accept("shift-up", self.shiftOff)

        self.__ctrl__ = False
        self.accept("control", self.ctrlOn)
        self.accept("control-up", self.ctrlOff)

        #mouse handling
        self.accept("mouse1", self.clickHandler)
        self.accept("shift-mouse1", self.clickHandler)
        self.accept("mouse1-up", self.releaseHandler)

        #dragging
        self.dragTask = taskMgr.add(self.dragTask, 'dragTask')

    def getClickTarget(self,rootSelNode=None):
        """ traverse from the root of the selectable tree """
        #print('getting target....')
        if rootSelNode == None:
            rootSelNode = render

        if base.mouseWatcherNode.hasMouse():
            self.pickerRay.setFromLens(base.camNode, *base.mouseWatcherNode.getMouse())

            self.picker.traverse(rootSelNode)
            if self.pq.getNumEntries() > 0: #if we got something sort it
                self.pq.sortEntries()
                return self.pq.getEntry(0)



        #nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin())
        #nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection())
        #thingToDrag.obj.setPos(PointAtZ(.5, nearPoint, nearVec)) #not sure how this works

    def ctrlOn(self):
        self.__ctrl__ = True

    def ctrlOff(self):
        self.__ctrl__ = False

    def shiftOn(self):
        self.__shift__ = True

    def shiftOff(self):
        self.__shift__ = False

    @event_callback
    def clickHandler(self):
        pass

    @event_callback
    def releaseHandler(self):
        pass

    def dragTask(self, task):
        pass

    def clickSelectObject(self): #shif to multiselect... ?? to unselect invidiual??
        pass

    def dragSelectObjects(self): #always drag in the plane of the camera
        pass
예제 #14
0
class World(DirectObject):
    def __init__(self):
        #turn off mouse control, otherwise camera is not repositionable
        self.lightables = []
        self.cameraPositions = [((0, 5000, 5300), (180, -35, 0)),((0, 3000, 1300), (180, -15, 0))]
        self.cameraIndex = 0
        base.disableMouse()
        base.enableParticles()
        self.setupLights()
        self.setupPicking()
        #Prepare the vehicular manslaughter!
        self.boosterLightNP = None
        self.flameLights = None
        self.player = Vehicle("models/panda-model", "panda-walk4", self)
        
        self.loadModels()
        # self.player.setPos(self.env.find("**/start_point").getPos())
        self.player.setPos(0,0,0)
        self.setupIntervals()
        camera.reparentTo(self.player)
        camera.setPosHpr(0, 5000, 5300, 180, -35, 0)
        self.setupCollisions()
        render.setShaderAuto() #you probably want to use this
        self.keyMap = {"left":0, "right":0, "forward":0, "backwards":0}
        taskMgr.add(self.player.move, "moveTask")
        
        #Give the vehicle direct access to the keyMap
        self.player.addKeyMap(self.keyMap)
        
        self.prevtime = 0
        self.isMoving = False
        self.speed_norm = 8
        self.speed = self.speed_norm
        self.accept("escape", sys.exit)
        
        self.accept("arrow_up", self.setKey, ["forward", 1])
        self.accept("w", self.setKey, ["forward", 1])
        self.accept("arrow_right", self.setKey, ["right", 1])
        self.accept("d", self.setKey, ["right", 1])
        self.accept("arrow_left", self.setKey, ["left", 1])
        self.accept("a", self.setKey, ["left", 1])
        self.accept("arrow_down", self.setKey, ["backwards", 1])
        self.accept("s", self.setKey, ["backwards", 1])
        
        self.accept("arrow_up-up", self.setKey, ["forward", 0])
        self.accept("w-up", self.setKey, ["forward", 0])
        self.accept("arrow_right-up", self.setKey, ["right", 0])
        self.accept("d-up", self.setKey, ["right", 0])
        self.accept("arrow_left-up", self.setKey, ["left", 0])
        self.accept("a-up", self.setKey, ["left", 0])
        self.accept("arrow_down-up", self.setKey, ["backwards", 0])
        self.accept("s-up", self.setKey, ["backwards", 0])
        
        self.accept("mouse1", self.startShoot)
        self.accept("mouse1-up", self.stopShoot)
        self.accept("tab", self.shiftCamera)   
        self.accept("space", self.player.startBoosters)
        
        self.accept("ate-smiley", self.eat)
        self.accept("ground_collide", self.player.collider)
        self.p1 = ParticleEffect()
        self.p2 = ParticleEffect()
        
        #Show collisiony stuff
        base.cTrav.showCollisions(render)
        
    
    def setupPicking(self):
        self.picker = CollisionTraverser()
        self.pq     = CollisionHandlerQueue()
        self.pickerNode = CollisionNode('mouseRay')
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()
        self.pickerNode.addSolid(self.pickerRay)
        self.picker.addCollider(self.pickerNP, self.pq)
        
        self.targetRoot = render.attachNewNode('targetRoot')
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
    
    def mouseTask(self, task):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            self.picker.traverse(self.targetRoot)
            if self.pq.getNumEntries() > 0:
                self.pq.sortEntries()
                i = int(self.pq.getEntry(0).getIntoNode().getTag('target'))
                print("Found target: " + str(i))
                  
        return Task.cont

    def setupIntervals(self):
        self.lightOn = LerpFunc(self.lightModify,
                            fromData=0,
                            toData=100,
                            duration=0.2,
                            blendType='noBlend',
                            extraArgs=[True],
                            name="LightUp")
        self.lightOff = LerpFunc(self.lightModify,
                            fromData=0,
                            toData=100,
                            duration=0.2,
                            blendType='noBlend',
                            extraArgs=[False],
                            name="LightDown")
                            
        self.cameraMove = None
        
    def setKey(self, key, value):
        self.keyMap[key] = value
        
    def setWorldLight(self, object):
        self.lightables.append(object)
        object.setLight(self.keyLightNP)
        object.setLight(self.fillLightNP)
        object.setLight(self.boosterLightNP)
        for light in self.flameLights:
            object.setLight(light[1])
        
    def shiftCamera(self):
        if self.cameraMove:
            self.cameraMove.finish()
        old = self.cameraIndex
        self.cameraIndex += 1
        if self.cameraIndex == len(self.cameraPositions):
            self.cameraIndex = 0
        self.cameraMove=LerpPosHprInterval(camera,
                                            .7, 
                                            self.cameraPositions[self.cameraIndex][0], 
                                            self.cameraPositions[self.cameraIndex][1],
                                            camera.getPos(), 
                                            camera.getHpr())
        self.cameraMove.start()
     
    def loadModels(self):
        """loads models into the world"""
        #eat no longer exists? Phooey
        
        self.flameLights = []
        shadowcam = Spotlight('shadowlight')
        shadowcam.setColor(VBase4(0,0,0,1))
        lens = PerspectiveLens()
        shadowcam.setLens(lens)
        shadowcam.setAttenuation(Point3(0, 0.001, 0.001))
        shadowNP = self.player.attachNewNode(shadowcam)
        shadowNP.setPos(0, -1400, 450)
        shadowNP.lookAt(self.player)
        shadowNP.setScale(200)
        shadowNP.node().setShadowCaster(True)
        self.flameLights.append((shadowcam, shadowNP))
        
        for i in range(2):
            slight = PointLight('plight')
            slight.setColor(VBase4(0, 0, 0, 1))
            slight.setAttenuation(Point3(0, 0.001, 0.001))
            slnp = self.player.attachNewNode(slight)
            slnp.setPos(0, -750 - (950 * i), 450)
            slnp.setHpr(180, 0, 0)
            slnp.setScale(200)
            self.flameLights.append((slight, slnp))
        
        self.player.setupBooster()
        
        #self.env = loader.loadModel("models/environment")
        #self.env.reparentTo(render)
        #self.env.setScale(.25)
        #self.env.setPos(-8, 42, 0)
        self.env = loader.loadModel("models/terrain2")      
        self.env.reparentTo(render)
        self.env.setPos(0,0,0)
        
        self.setWorldLight(self.env)
        
        #load targets
        self.targets = []
        for i in range (10):
            target = loader.loadModel("smiley")
            target.setScale(.5)
            target.setPos(random.uniform(-20, 20), random.uniform(-15, 15), 2)
            target.reparentTo(self.targetRoot)
            self.targets.append(target)
            self.setWorldLight(target)
        
    def setupLights(self):
        #ambient light
        self.ambientLight = AmbientLight("ambientLight")
        #four values, RGBA (alpha is largely irrelevent), value range is 0:1
        self.ambientLight.setColor((.10, .10, .10, 1))
        self.ambientLightNP = render.attachNewNode(self.ambientLight)
        #the nodepath that calls setLight is what gets illuminated by the light
        render.setLight(self.ambientLightNP)
        #call clearLight() to turn it off
        
        self.keyLight = DirectionalLight("keyLight")
        self.keyLight.setColor((.20,.20,.20, 1))
        self.keyLightNP = render.attachNewNode(self.keyLight)
        self.keyLightNP.setHpr(0, -26, 0)
        
        self.fillLight = DirectionalLight("fillLight")
        self.fillLight.setColor((.05,.05,.05, 1))
        self.fillLightNP = render.attachNewNode(self.fillLight)
        self.fillLightNP.setHpr(30, 0, 0)
        
    def drive(self):
        """compound interval for driveing"""
        #some interval methods:
        # start(), loop(), pause(), resume(), finish()
        # start() can take arguments: start(starttime, endtime, playrate)
        dist = 5
        angle = deg2Rad(self.player.getH())
        dx = dist * math.sin(angle)
        dy = dist * -math.cos(angle)
        playerdrive = Parallel(self.player.posInterval(1, (self.player.getX() + dx, self.player.getY() + dy, 0)), \
            self.player.actorInterval("drive", loop=1, duration=2))
        playerdrive.start()
        
    def setupCollisions(self):
        #instantiates a collision traverser and sets it to the default
        base.cTrav = CollisionTraverser()
        self.cHandler = CollisionHandlerEvent()
        #set pattern for event sent on collision
        # "%in" is substituted with the name of the into object
        self.cHandler.setInPattern("ate-%in")
        
        cSphere = CollisionSphere((0,0,200), 450) #because the player is scaled way down
        self.playerRay = CollisionRay()
        self.playerRay.setOrigin(0,0,2000)
        self.playerRay.setDirection(0,0,-1)
        self.playerNode = CollisionNode("playerRay")
        self.playerNode.addSolid(self.playerRay)
        self.playerNode.setFromCollideMask(BitMask32.bit(0))
        self.playerNode.setIntoCollideMask(BitMask32.allOff())
        self.playerNodePath = self.player.attachNewNode(self.playerNode)
        self.playerNodePath.show()
        self.playerGroundHandler = CollisionHandlerFloor()
        self.playerGroundHandler.addCollider(self.playerNodePath, self.player)
        base.cTrav.addCollider(self.playerNodePath, self.playerGroundHandler)
        
        cNode = CollisionNode("player")
        cNode.addSolid(cSphere)
        cNode.setIntoCollideMask(BitMask32.allOff()) #player is *only* a from object
        #cNode.setFromCollideMask(BitMask32.bit(0))
        cNodePath = self.player.attachNewNode(cNode)
        #registers a from object with the traverser with a corresponding handler
        base.cTrav.addCollider(cNodePath, self.cHandler)
        i = 0
        for target in self.targets:
            cSphere = CollisionSphere((0,0,0), 2)
            cNode = CollisionNode("smiley")
            cNode.addSolid(cSphere)
            cNode.setIntoCollideMask(BitMask32.bit(1))
            cNode.setTag('target', str(i))
            cNodePath = target.attachNewNode(cNode)
            i += 1
    
    def lightModify(self, t, which_way):
        if which_way: #which_way == true then make it brighter
            value = t/100 * MAX_LIGHT
        else: #which_way == true then make it darker
            value = (100 - t)/100 * MAX_LIGHT
        for light in self.flameLights:
            light[0].setColor(VBase4(value,value,value,1))
        
    def startShoot(self):
        self.loadParticleConfig('flamethrower4.ptf')
        self.lightOff.finish()
        self.lightOn.start()
        
    def stopShoot(self):
        self.p1.softStop()
        self.p2.softStop()
        self.lightOn.finish()
        self.lightOff.start()
        
    def loadParticleConfig(self, file):
        self.p1.reset()
        self.p1 = ParticleEffect()
        self.p1.loadConfig(Filename(file))        
        self.p1.start(self.player)
        self.p1.setPos(-250, -700, 275)
        self.p1.setHpr(0, 90, 0)
        self.p1.setScale(200)
        self.p1.setLightOff()
        self.p2.reset()
        self.p2 = ParticleEffect()
        self.p2.loadConfig(Filename(file))        
        self.p2.start(self.player)
        self.p2.setPos(250, -700, 275)
        self.p2.setHpr(0, 90, 0)
        self.p2.setScale(200)
        self.p2.setLightOff()
        
    def eat(self, cEntry):
        """handles the player eating a smiley"""
        #remove target from list of targets
        self.targets.remove(cEntry.getIntoNodePath().getParent())
        #remove from scene graph
        cEntry.getIntoNodePath().getParent().remove()
예제 #15
0
파일: start.py 프로젝트: sambiak/pandaMorp
class MyApp(ShowBase):
 
    def __init__(self):
        ShowBase.__init__(self)
        self.disableMouse()  
        camera.setPosHpr(0, -12, 8, 0, -35, 0)
        """
        self.environ = self.loader.loadModel("models/environment")
        # Reparent the model to render.
        self.environ.reparentTo(self.render)
        # Apply scale and position transforms on the model.
        self.environ.setScale(0.25, 0.25, 0.25)
        self.environ.setPos(-8, 42, 0)
        self.torus = loader.loadModel("torus.egg")
        self.torus.reparentTo(self.render)
        self.torus.setPos(circPos(0,1))
        self.torus.setColor(BLACK)
        self.torus.setScale(0.5,0.5,0.5)
        """
        self.setupLights()
        self.ended = False
        self.currentB = False
        self.firstTurn = True
        # Since we are using collision detection to do picking, we set it up like
        # any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  # Make a traverser
        self.pq = CollisionHandlerQueue()  # Make a handler
        # Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        # Attach that node to the camera since the ray will need to be positioned
        # relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        # Everything to be picked will use bit 1. This way if we were doing other
        # collision we could seperate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  # Make our ray
        # Add it to the collision node
        self.pickerNode.addSolid(self.pickerRay)
        # Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        self.picker.showCollisions(render)
        self.whiteTurn = True
        # Now we create the chess board and its pieces

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

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

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

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

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

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

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

    def __init__(self, cr):
        try:
            self.LocalToon_initialized
            return
        except:
            self.LocalToon_initialized = 1

        DistributedToon.__init__(self, cr)
        self.avatarChoice = cr.localAvChoice
        self.smartCamera = SmartCamera()
        self.chatInput = ChatInput()
        self.moneyGui = MoneyGui()
        self.laffMeter = LaffOMeter()
        self.positionExaminer = PositionExaminer()
        self.friendRequestManager = FriendRequestManager()
        self.friendsList = FriendsList()
        self.panel = ToonPanel()
        friendsgui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam')
        self.friendButton = DirectButton(geom=(friendsgui.find('**/FriendsBox_Closed'), friendsgui.find('**/FriendsBox_Rollover'), friendsgui.find('**/FriendsBox_Rollover')), text=('', 'Friends', 'Friends', ''), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_scale=0.065, text_pos=(0, -0.2), relief=None, parent=base.a2dTopRight, pos=(-0.18, 0.0, -0.17), command=self.friendsButtonClicked, scale=0.75)
        friendsgui.removeNode()
        del friendsgui
        self.hideFriendButton()
        self.runSfx = base.loadSfx('phase_3.5/audio/sfx/AV_footstep_runloop.wav')
        self.runSfx.setLoop(True)
        self.walkSfx = base.loadSfx('phase_3.5/audio/sfx/AV_footstep_walkloop.wav')
        self.walkSfx.setLoop(True)
        self.controlManager = ControlManager.ControlManager(True, False)
        self.offset = 3.2375
        self.movementKeymap = {'forward': 0,
         'backward': 0,
         'left': 0,
         'right': 0,
         'jump': 0}
        self.avatarMovementEnabled = False
        self.isMoving_forward = False
        self.isMoving_side = False
        self.isMoving_back = False
        self.isMoving_jump = False
        self.pieThrowBtn = None
        self.myBattle = None
        self.invGui = None
        self.pickerTrav = None
        self.pickerRay = None
        self.pickerRayNode = None
        self.pickerHandler = None
        self.rolledOverTag = None
        self.inTutorial = False
        self.hasDoneJump = False
        self.lastState = None
        self.lastAction = None
        return

    def hasDiscoveredHood(self, zoneId):
        return zoneId in self.hoodsDiscovered

    def hasTeleportAccess(self, zoneId):
        return zoneId in self.teleportAccess

    def tutorialCreated(self, zoneId):
        self.cr.tutorialCreated(zoneId)

    def friendsButtonClicked(self):
        self.hideFriendButton()
        self.friendsList.fsm.request('onlineFriendsList')

    def hideFriendButton(self):
        self.friendButton.hide()

    def showFriendButton(self):
        self.friendButton.show()

    def gotoNode(self, node, eyeHeight = 3):
        possiblePoints = (Point3(3, 6, 0),
         Point3(-3, 6, 0),
         Point3(6, 6, 0),
         Point3(-6, 6, 0),
         Point3(3, 9, 0),
         Point3(-3, 9, 0),
         Point3(6, 9, 0),
         Point3(-6, 9, 0),
         Point3(9, 9, 0),
         Point3(-9, 9, 0),
         Point3(6, 0, 0),
         Point3(-6, 0, 0),
         Point3(6, 3, 0),
         Point3(-6, 3, 0),
         Point3(9, 9, 0),
         Point3(-9, 9, 0),
         Point3(0, 12, 0),
         Point3(3, 12, 0),
         Point3(-3, 12, 0),
         Point3(6, 12, 0),
         Point3(-6, 12, 0),
         Point3(9, 12, 0),
         Point3(-9, 12, 0),
         Point3(0, -6, 0),
         Point3(-3, -6, 0),
         Point3(0, -9, 0),
         Point3(-6, -9, 0))
        for point in possiblePoints:
            pos = self.positionExaminer.consider(node, point, eyeHeight)
            if pos:
                self.setPos(node, pos)
                self.lookAt(node)
                self.setHpr(self.getH() + random.choice((-10, 10)), 0, 0)
                return

        self.setPos(node, 0, 0, 0)

    def setFriendsList(self, friends):
        DistributedToon.setFriendsList(self, friends)
        self.cr.friendsManager.d_requestFriendsList()
        self.panel.maybeUpdateFriendButton()

    def d_requestAddFriend(self, avId):
        self.sendUpdate('requestAddFriend', [avId])

    def setupPicker(self):
        self.pickerTrav = CollisionTraverser('LT.pickerTrav')
        self.pickerRay = CollisionRay()
        rayNode = CollisionNode('LT.pickerNode')
        rayNode.addSolid(self.pickerRay)
        rayNode.setCollideMask(BitMask32(0))
        rayNode.setFromCollideMask(CIGlobals.WallBitmask)
        self.pickerRayNode = base.camera.attachNewNode(rayNode)
        self.pickerHandler = CollisionHandlerQueue()
        self.pickerTrav.addCollider(self.pickerRayNode, self.pickerHandler)

    def enablePicking(self):
        self.accept('mouse1', self.pickedSomething_down)
        self.accept('mouse1-up', self.pickedSomething_up)
        base.taskMgr.add(self.__travMousePicker, 'LT.travMousePicker')

    def disablePicking(self):
        base.taskMgr.remove('LT.travMousePicker')
        self.ignore('mouse1')
        self.ignore('mouse1-up')

    def pickedSomething_down(self):
        if self.rolledOverTag:
            base.playSfx(DGG.getDefaultClickSound())
            avatar = self.cr.doId2do.get(self.rolledOverTag)
            avatar.nameTag.setPickerState('down')

    def pickedSomething_up(self):
        if self.rolledOverTag:
            avatar = self.cr.doId2do.get(self.rolledOverTag)
            avatar.nameTag.setPickerState('up')
            self.panel.makePanel(self.rolledOverTag)

    def __travMousePicker(self, task):
        if not base.mouseWatcherNode.hasMouse():
            return task.cont
        else:
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            self.pickerTrav.traverse(render)
            if self.pickerHandler.getNumEntries() > 0:
                self.pickerHandler.sortEntries()
                pickedObject = self.pickerHandler.getEntry(0).getIntoNodePath()
                avatarId = pickedObject.getParent().getPythonTag('avatar')
                if avatarId != None:
                    for do in self.cr.doId2do.values():
                        if do.__class__.__name__ == 'DistributedToon':
                            if do.doId == avatarId:
                                if do.nameTag.getClickable() == 1:
                                    if do.nameTag.fsm.getCurrentState().getName() != 'rollover' and do.nameTag.fsm.getCurrentState().getName() != 'down':
                                        do.nameTag.setPickerState('rollover')
                                        base.playSfx(DGG.getDefaultRolloverSound())
                                        self.rolledOverTag = avatarId
                                        break
                        elif do.__class__.__name__ == 'DistributedToon':
                            if do.nameTag.fsm.getCurrentState().getName() != 'up':
                                do.nameTag.setPickerState('up')

                elif self.rolledOverTag:
                    avatar = self.cr.doId2do.get(self.rolledOverTag)
                    if avatar:
                        if avatar.nameTag.fsm.getCurrentState().getName() != 'up':
                            avatar.nameTag.setPickerState('up')
                    self.rolledOverTag = None
            return task.cont

    def prepareToSwitchControlType(self):
        inputs = ['run',
         'forward',
         'reverse',
         'turnLeft',
         'turnRight',
         'slideLeft',
         'slideRight',
         'jump']
        for inputName in inputs:
            try:
                inputState.releaseInputs(inputName)
            except:
                pass

    def getBackpack(self):
        return DistributedToon.getBackpack(self)

    def setMyBattle(self, battle):
        self.myBattle = battle

    def getMyBattle(self):
        return self.myBattle

    def ghostOn(self):
        self.getGeomNode().setTransparency(1)
        self.getGeomNode().setColorScale(1, 1, 1, 0.25)

    def ghostOff(self):
        self.getGeomNode().setColorScale(1, 1, 1, 1)
        self.getGeomNode().setTransparency(0)

    def enterReadBook(self, ts = 0, callback = None, extraArgs = []):
        self.stopLookAround()
        self.b_lookAtObject(0, -45, 0)
        DistributedToon.enterReadBook(self, ts, callback, extraArgs)

    def exitReadBook(self):
        DistributedToon.exitReadBook(self)
        self.startLookAround()

    def getAirborneHeight(self):
        return self.offset + 0.025

    def setupControls(self):
        self.walkControls = GravityWalker(legacyLifter=False)
        self.walkControls.setWallBitMask(CIGlobals.WallBitmask)
        self.walkControls.setFloorBitMask(CIGlobals.FloorBitmask)
        self.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed)
        self.walkControls.initializeCollisions(base.cTrav, self, floorOffset=0.025, reach=4.0)
        self.walkControls.setAirborneHeightFunc(self.getAirborneHeight)

    def setWalkSpeedNormal(self):
        self.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed)

    def setWalkSpeedSlow(self):
        self.walkControls.setWalkSpeed(CIGlobals.ToonForwardSlowSpeed, CIGlobals.ToonJumpSlowForce, CIGlobals.ToonReverseSlowSpeed, CIGlobals.ToonRotateSlowSpeed)

    def setupCamera(self):
        base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4.0 / 3.0))
        base.camLens.setNearFar(CIGlobals.DefaultCameraNear, CIGlobals.DefaultCameraFar)
        camHeight = max(self.getHeight(), 3.0)
        heightScaleFactor = camHeight * 0.3333333333
        defLookAt = Point3(0.0, 1.5, camHeight)
        camPos = (Point3(0.0, -9.0 * heightScaleFactor, camHeight),
         defLookAt,
         Point3(0.0, camHeight, camHeight * 4.0),
         Point3(0.0, camHeight, camHeight * -1.0),
         0)
        self.smartCamera.initializeSmartCamera()
        self.smartCamera.setIdealCameraPos(camPos[0])
        self.smartCamera.setLookAtPoint(defLookAt)

    def setDNAStrand(self, dnaStrand):
        DistributedToon.setDNAStrand(self, dnaStrand)
        self.initCollisions()
        self.setupCamera()

    def setMoney(self, money):
        DistributedToon.setMoney(self, money)
        self.moneyGui.update(money)

    def setupNameTag(self, tempName = None):
        DistributedToon.setupNameTag(self, tempName)
        if self.nameTag:
            self.nameTag.setColorLocal()

    def d_broadcastPositionNow(self):
        self.d_clearSmoothing()
        self.d_broadcastPosHpr()

    def b_setAnimState(self, anim, callback = None, extraArgs = []):
        if self.anim != anim:
            self.d_setAnimState(anim)
            DistributedToon.setAnimState(self, anim, callback=callback, extraArgs=extraArgs)

    def attachCamera(self):
        camera.reparentTo(self)
        camera.setPos(self.smartCamera.getIdealCameraPos())

    def startSmartCamera(self):
        self.smartCamera.startUpdateSmartCamera()

    def resetSmartCamera(self):
        self.stopSmartCamera()
        self.startSmartCamera()

    def stopSmartCamera(self):
        self.smartCamera.stopUpdateSmartCamera()

    def detachCamera(self):
        camera.reparentTo(render)
        camera.setPos(0, 0, 0)
        camera.setHpr(0, 0, 0)

    def handleSuitAttack(self, attack_id, suit_id):
        DistributedToon.handleSuitAttack(self, attack_id, suit_id)
        if not self.isDead() and base.config.GetBool('want-sa-reactions'):
            base.taskMgr.remove('LT.attackReactionDone')
            attack = SuitAttacks.SuitAttackLengths.keys()[attack_id]
            suit = self.cr.doId2do.get(suit_id)
            animToPlay = None
            timeToWait = 3.0
            if attack not in ('pickpocket', 'fountainpen'):
                suitH = suit.getH(render) % 360
                myH = self.getH(render) % 360
                if -90.0 <= suitH - myH <= 90.0:
                    animToPlay = 'fallFWD'
                else:
                    animToPlay = 'fallBCK'
            elif attack in ('pickpocket',):
                animToPlay = 'cringe'
            elif attack in ('fountainpen',):
                animToPlay = 'conked'
                timeToWait = 5.0
            self.cr.playGame.getPlace().fsm.request('stop')
            self.b_setAnimState(animToPlay)
            base.taskMgr.doMethodLater(timeToWait, self.__attackReactionDone, 'LT.attackReactionDone')
        return

    def __attackReactionDone(self, task):
        self.cr.playGame.hood.loader.place.fsm.request('walk')
        self.b_setAnimState('neutral')
        return Task.done

    def enableAvatarControls(self):
        self.walkControls.enableAvatarControls()
        self.accept('control', self.updateMovementKeymap, ['jump', 1])
        self.accept('control-up', self.updateMovementKeymap, ['jump', 0])
        taskMgr.add(self.movementTask, 'avatarMovementTask')
        self.avatarMovementEnabled = True
        self.playMovementSfx(None)
        return

    def disableAvatarControls(self):
        self.walkControls.disableAvatarControls()
        self.ignore('arrow_up')
        self.ignore('arrow_up-up')
        self.ignore('arrow_down')
        self.ignore('arrow_down-up')
        self.ignore('arrow_left')
        self.ignore('arrow_left-up')
        self.ignore('arrow_right')
        self.ignore('arrow_right-up')
        self.ignore('control')
        self.ignore('control-up')
        taskMgr.remove('avatarMovementTask')
        self.isMoving_forward = False
        self.isMoving_side = False
        self.isMoving_back = False
        self.isMoving_jump = False
        self.avatarMovementEnabled = False
        self.playMovementSfx(None)
        for k, _ in self.movementKeymap.items():
            self.updateMovementKeymap(k, 0)

        return

    def updateMovementKeymap(self, key, value):
        self.movementKeymap[key] = value

    def getMovementKeyValue(self, key):
        return self.movementKeymap[key]

    def playMovementSfx(self, movement):
        if movement == 'run':
            self.walkSfx.stop()
            self.runSfx.play()
        elif movement == 'walk':
            self.runSfx.stop()
            self.walkSfx.play()
        else:
            self.runSfx.stop()
            self.walkSfx.stop()

    def __forward(self):
        self.resetHeadHpr()
        self.stopLookAround()
        if self.getHealth() < 1:
            self.playMovementSfx('walk')
            self.setPlayRate(1.2, 'dwalk')
            self.setAnimState('deadWalk')
        else:
            self.playMovementSfx('run')
            self.setAnimState('run')
        self.isMoving_side = False
        self.isMoving_back = False
        self.isMoving_forward = True
        self.isMoving_jump = False

    def __turn(self):
        self.resetHeadHpr()
        self.stopLookAround()
        self.playMovementSfx('walk')
        if self.getHealth() < 1:
            self.setPlayRate(1.2, 'dwalk')
            self.setAnimState('deadWalk')
        else:
            self.setPlayRate(1.0, 'walk')
            self.setAnimState('walk')
        self.isMoving_forward = False
        self.isMoving_back = False
        self.isMoving_side = True
        self.isMoving_jump = False

    def __reverse(self):
        self.resetHeadHpr()
        self.stopLookAround()
        self.playMovementSfx('walk')
        if self.getHealth() < 1:
            self.setPlayRate(-1.0, 'dwalk')
            self.setAnimState('deadWalk')
        else:
            self.setAnimState('walkBack')
        self.isMoving_side = False
        self.isMoving_forward = False
        self.isMoving_back = True
        self.isMoving_jump = False

    def __jump(self):
        self.playMovementSfx(None)
        if base.localAvatar.getHealth() > 0:
            if self.playingAnim == 'run' or self.playingAnim == 'walk':
                self.b_setAnimState('leap')
            else:
                self.b_setAnimState('jump')
        self.isMoving_side = False
        self.isMoving_forward = False
        self.isMoving_back = False
        self.isMoving_jump = True
        return

    def __neutral(self):
        self.resetHeadHpr()
        self.startLookAround()
        self.playMovementSfx(None)
        if base.localAvatar.getHealth() > 0:
            self.setAnimState('neutral')
        else:
            self.setPlayRate(1.0, 'dneutral')
            self.setAnimState('deadNeutral')
        self.isMoving_side = False
        self.isMoving_forward = False
        self.isMoving_back = False
        self.isMoving_jump = False
        return

    def movementTask(self, task):
        if self.getMovementKeyValue('jump') == 1:
            if not self.walkControls.isAirborne:
                if self.walkControls.mayJump:
                    self.__jump()
                    self.hasDoneJump = True
                elif self.hasDoneJump:
                    if self.getHealth() > 0:
                        self.b_setAnimState('Happy')
                    self.hasDoneJump = False
        elif not self.walkControls.isAirborne:
            if self.hasDoneJump:
                if self.getHealth() > 0:
                    self.b_setAnimState('Happy')
                self.hasDoneJump = False
        return task.cont

    def startTrackAnimToSpeed(self):
        base.taskMgr.add(self.trackAnimToSpeed, self.uniqueName('trackAnimToSpeed'))

    def stopTrackAnimToSpeed(self):
        base.taskMgr.remove(self.uniqueName('trackAnimToSpeed'))

    def trackAnimToSpeed(self, task):
        speed, rotSpeed, slideSpeed = self.walkControls.getSpeeds()
        state = None
        if self.getHealth() > 0:
            state = 'Happy'
        else:
            state = 'Sad'
        if state != self.lastState:
            self.lastState = state
            self.b_setAnimState(state)
            if state == 'Sad':
                self.setWalkSpeedSlow()
            else:
                self.setWalkSpeedNormal()
        action = self.setSpeed(speed, rotSpeed)
        if action != self.lastAction:
            self.lastAction = action
            if action == CIGlobals.WALK_INDEX or action == CIGlobals.REVERSE_INDEX:
                self.resetHeadHpr()
                self.stopLookAround()
                self.playMovementSfx('walk')
            elif action == CIGlobals.RUN_INDEX:
                self.resetHeadHpr()
                self.stopLookAround()
                self.playMovementSfx('run')
            else:
                self.resetHeadHpr()
                self.startLookAround()
                self.playMovementSfx(None)
        return task.cont

    def createLaffMeter(self):
        r, g, b, _ = self.getHeadColor()
        animal = self.getAnimal()
        maxHp = self.getMaxHealth()
        hp = self.getHealth()
        self.laffMeter.generate(r, g, b, animal, maxHP=maxHp, initialHP=hp)
        self.laffMeter.start()

    def disableLaffMeter(self):
        self.laffMeter.stop()
        self.laffMeter.disable()

    def deleteLaffMeter(self):
        self.laffMeter.delete()

    def setLoadout(self, gagIds):
        DistributedToon.setLoadout(self, gagIds)
        if base.cr.playGame.getPlace() and base.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'shtickerBook':
            if hasattr(base.cr.playGame.getPlace(), 'shtickerBookStateData'):
                if base.cr.playGame.getPlace().shtickerBookStateData.fsm.getCurrentState().getName() == 'inventoryPage':
                    base.cr.playGame.getPlace().shtickerBookStateData.gui.fsm.request('idle')

    def enablePies(self, andKeys = 0):
        if self.avatarMovementEnabled and andKeys:
            self.enablePieKeys()
        self.backpack = DistributedToon.getBackpack(self)
        self.invGui = InventoryGui()
        self.invGui.createGui()
        self.invGui.setBackpack(self.backpack)
        for gag in self.backpack.getGags():
            gag.setAvatar(self)

        self.backpack.setGagGUI(self.invGui)
        if self.backpack.getCurrentGag():
            self.invGui.setWeapon(self.backpack.getCurrentGag().getName(), playSound=False)

    def enablePieKeys(self):
        if self.pieThrowBtn:
            if not self.backpack:
                self.backpack = DistributedToon.getBackpack(self)
            self.pieThrowBtn.bind(DGG.B1PRESS, self.startGag)
            self.pieThrowBtn.bind(DGG.B1RELEASE, self.throwGag)
        self.accept('delete', self.startGag)
        self.accept('delete-up', self.throwGag)

    def disablePieKeys(self):
        if self.pieThrowBtn:
            self.pieThrowBtn.unbind(DGG.B1PRESS)
            self.pieThrowBtn.unbind(DGG.B1RELEASE)
        self.ignore('delete')
        self.ignore('delete-up')

    def disablePies(self):
        self.disablePieKeys()
        self.invGui.deleteGui()
        if hasattr(self, 'backpack'):
            if self.backpack:
                self.backpack.setCurrentGag(None)
        return

    def setWeaponType(self, weaponType):
        enableKeysAgain = 0
        if weaponType != self.weaponType:
            enableKeysAgain = 1
        self.weaponType = weaponType
        if enableKeysAgain:
            self.disablePieKeys()
            self.enablePieKeys()

    def createMoney(self):
        self.moneyGui.createGui()
        self.moneyGui.update(self.money)

    def handleMoneyChanged(self):
        self.moneyGui.update()

    def disableMoney(self):
        self.moneyGui.deleteGui()

    def resetHeadHpr(self):
        self.b_lookAtObject(0, 0, 0, blink=0)

    def startGag(self, start = True):
        if not self.backpack or not self.backpack.getCurrentGag():
            return
        if self.backpack.getSupply() > 0:
            if self.pieThrowBtn:
                self.pieThrowBtn.unbind(DGG.B1PRESS)
            if self.backpack.getActiveGag():
                if self.backpack.getActiveGag().getState() != GagState.LOADED:
                    return
            self.ignore('delete')
            self.backpack.getCurrentGag().setAvatar(self)
            self.resetHeadHpr()
            self.b_gagStart(self.backpack.getCurrentGag().getID())

    def throwGag(self, start = True):
        if not self.backpack or not self.backpack.getCurrentGag() or not self.backpack.getActiveGag():
            return
        if self.backpack.getSupply() > 0:
            if self.pieThrowBtn:
                self.pieThrowBtn.unbind(DGG.B1RELEASE)
            self.ignore('delete-up')
            if self.backpack.getActiveGag().getType() == GagType.SQUIRT and self.backpack.getActiveGag().getName() == CIGlobals.SeltzerBottle:
                self.b_gagRelease(self.backpack.getActiveGag().getID())
            else:
                self.b_gagThrow(self.backpack.getActiveGag().getID())
            activeGag = self.backpack.getActiveGag()
            if not activeGag:
                activeGag = self.backpack.getCurrentGag()
            if not activeGag.doesAutoRelease():
                Sequence(Wait(0.75), Func(self.releaseGag), Wait(0.3), Func(self.enablePieKeys)).start()

    def releaseGag(self):
        if not self.backpack or not self.backpack.getActiveGag():
            return
        if self.backpack.getSupply() > 0:
            gag = self.backpack.getActiveGag()
            if not gag:
                gag = self.backpack.getCurrentGag()
            if gag.getState() != GagState.RELEASED:
                gagName = gag.getName()
                self.b_gagRelease(GagGlobals.getIDByName(gagName))

    def checkSuitHealth(self, suit):
        pass

    def handleLookSpot(self, hpr):
        h, p, r = hpr
        self.d_lookAtObject(h, p, r, blink=1)

    def showPieButton(self):
        geom = CIGlobals.getDefaultBtnGeom()
        self.pieThrowBtn = DirectButton(geom=geom, geom_scale=(0.75, 1, 1), text='Throw Gag', text_scale=0.05, text_pos=(0, -0.01), relief=None, parent=base.a2dTopCenter, pos=(0, 0, -0.1))
        self.pieThrowBtn.setBin('gui-popup', 60)
        return

    def hidePieButton(self):
        self.pieThrowBtn.removeNode()
        self.pieThrowBtn = None
        return

    def showBookButton(self, inBook = 0):
        self.book_gui = loader.loadModel('phase_3.5/models/gui/sticker_open_close_gui.bam')
        self.book_btn = DirectButton(geom=(self.book_gui.find('**/BookIcon_CLSD'), self.book_gui.find('**/BookIcon_OPEN'), self.book_gui.find('**/BookIcon_RLVR')), relief=None, pos=(-0.175, 0, 0.163), command=self.bookButtonClicked, scale=(0.7, 0.8, 0.8), parent=base.a2dBottomRight)
        self.book_btn.setBin('gui-popup', 60)
        if inBook:
            self.book_btn['geom'] = (self.book_gui.find('**/BookIcon_OPEN'), self.book_gui.find('**/BookIcon_CLSD'), self.book_gui.find('**/BookIcon_RLVR2'))
            self.book_btn['command'] = self.bookButtonClicked
            self.book_btn['extraArgs'] = [0]
        return

    def hideBookButton(self):
        if hasattr(self, 'book_gui'):
            self.book_gui.removeNode()
            del self.book_gui
        if hasattr(self, 'book_btn'):
            self.book_btn.destroy()
            del self.book_btn

    def bookButtonClicked(self, openIt = 1):
        if openIt:
            base.cr.playGame.getPlace().fsm.request('shtickerBook')
        else:
            base.cr.playGame.getPlace().shtickerBookStateData.finished('resume')

    def startMonitoringHP(self):
        taskMgr.add(self.monitorHealth, 'localToon-monitorHealth')

    def monitorHealth(self, task):
        if self.isDead():
            base.taskMgr.remove('LT.attackReactionDone')
            if self.cr.playGame.hood.id != ZoneUtil.getHoodId(self.zoneId):
                self.cr.playGame.getPlace().fsm.request('died', [{}, self.diedStateDone])
            return task.done
        return task.cont

    def stopMonitoringHP(self):
        taskMgr.remove('localToon-monitorHealth')

    def setHealth(self, hp):
        if hp > 0 and self.getHealth() < 1:
            if self.cr.playGame.getPlace():
                if self.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'walk':
                    if self.cr.playGame.getPlace().walkStateData.fsm.getCurrentState().getName() == 'deadWalking':
                        self.cr.playGame.getPlace().walkStateData.fsm.request('walking')
            if self.animFSM.getCurrentState().getName() == 'deadNeutral':
                self.playMovementSfx(None)
                self.b_setAnimState('neutral')
            elif self.animFSM.getCurrentState().getName() == 'deadWalk':
                self.playMovementSfx('run')
                self.b_setAnimState('run')
        DistributedToon.setHealth(self, hp)
        return

    def diedStateDone(self, requestStatus):
        hood = self.cr.playGame.hood.id
        if hood == CIGlobals.BattleTTC:
            hood = CIGlobals.ToontownCentral
        toZone = ZoneUtil.getZoneId(hood)
        if self.zoneId != toZone:
            requestStatus = {'zoneId': toZone,
             'hoodId': hood,
             'where': ZoneUtil.getWhereName(toZone),
             'avId': self.doId,
             'loader': ZoneUtil.getLoaderName(toZone),
             'shardId': None,
             'wantLaffMeter': 1,
             'how': 'teleportIn'}
            self.cr.playGame.getPlace().doneStatus = requestStatus
            messenger.send(self.cr.playGame.getPlace().doneEvent)
        else:
            return
        return

    def teleportToCT(self):
        toZone = CIGlobals.CogTropolisId
        hood = CIGlobals.CogTropolis
        requestStatus = {'zoneId': toZone,
         'hoodId': hood,
         'where': ZoneUtil.getWhereName(toZone),
         'avId': self.doId,
         'loader': ZoneUtil.getLoaderName(toZone),
         'shardId': None,
         'wantLaffMeter': 1,
         'how': 'teleportIn'}
        self.cr.playGame.getPlace().fsm.request('teleportOut', [requestStatus])
        return

    def createChatInput(self):
        self.chatInput.load()
        self.chatInput.enter()

    def disableChatInput(self):
        self.chatInput.exit()
        self.chatInput.unload()

    def collisionsOn(self):
        self.controlManager.collisionsOn()

    def collisionsOff(self):
        self.controlManager.collisionsOff()

    def generate(self):
        DistributedToon.generate(self)

    def delete(self):
        DistributedToon.delete(self)
        self.deleteLaffMeter()

    def disable(self):
        base.camLens.setMinFov(CIGlobals.OriginalCameraFov / (4.0 / 3.0))
        self.friendsList.destroy()
        self.friendsList = None
        self.positionExaminer.delete()
        self.positionExaminer = None
        self.disablePicking()
        self.stopMonitoringHP()
        taskMgr.remove('resetHeadColorAfterFountainPen')
        taskMgr.remove('LT.attackReactionDone')
        self.stopLookAround()
        DistributedToon.disable(self)
        self.disableAvatarControls()
        self.disableLaffMeter()
        self.disablePies()
        self.disableChatInput()
        self.weaponType = None
        self.pieType = None
        self.myBattle = None
        self.ignore('gotLookSpot')
        return

    def announceGenerate(self):
        DistributedToon.announceGenerate(self)
        self.setupPicker()
        self.setupControls()
        self.startLookAround()
        self.friendRequestManager.watch()
        self.accept('gotLookSpot', self.handleLookSpot)

    def printAvPos(self):
        print 'Pos: %s, Hpr: %s' % (self.getPos(), self.getHpr())
class PositionExaminer(DirectObject, NodePath):

    def __init__(self):
        try:
            self.__initialized
            return
        except:
            self.__initialized = 1

        NodePath.__init__(self, hidden.attachNewNode('PositionExaminer'))
        self.cRay = CollisionRay(0.0, 0.0, 6.0, 0.0, 0.0, -1.0)
        self.cRayNode = CollisionNode('cRayNode')
        self.cRayNode.addSolid(self.cRay)
        self.cRayNodePath = self.attachNewNode(self.cRayNode)
        self.cRayNodePath.hide()
        self.cRayBitMask = CIGlobals.FloorBitmask
        self.cRayNode.setFromCollideMask(self.cRayBitMask)
        self.cRayNode.setIntoCollideMask(BitMask32.allOff())
        self.cSphere = CollisionSphere(0.0, 0.0, 0.0, 1.5)
        self.cSphereNode = CollisionNode('cSphereNode')
        self.cSphereNode.addSolid(self.cSphere)
        self.cSphereNodePath = self.attachNewNode(self.cSphereNode)
        self.cSphereNodePath.hide()
        self.cSphereBitMask = CIGlobals.WallBitmask
        self.cSphereNode.setFromCollideMask(self.cSphereBitMask)
        self.cSphereNode.setIntoCollideMask(BitMask32.allOff())
        self.ccLine = CollisionSegment(0.0, 0.0, 0.0, 1.0, 0.0, 0.0)
        self.ccLineNode = CollisionNode('ccLineNode')
        self.ccLineNode.addSolid(self.ccLine)
        self.ccLineNodePath = self.attachNewNode(self.ccLineNode)
        self.ccLineNodePath.hide()
        self.ccLineBitMask = CIGlobals.CameraBitmask
        self.ccLineNode.setFromCollideMask(self.ccLineBitMask)
        self.ccLineNode.setIntoCollideMask(BitMask32.allOff())
        self.cRayTrav = CollisionTraverser('PositionExaminer.cRayTrav')
        self.cRayTrav.setRespectPrevTransform(False)
        self.cRayQueue = CollisionHandlerQueue()
        self.cRayTrav.addCollider(self.cRayNodePath, self.cRayQueue)
        self.cSphereTrav = CollisionTraverser('PositionExaminer.cSphereTrav')
        self.cSphereTrav.setRespectPrevTransform(False)
        self.cSphereQueue = CollisionHandlerQueue()
        self.cSphereTrav.addCollider(self.cSphereNodePath, self.cSphereQueue)
        self.ccLineTrav = CollisionTraverser('PositionExaminer.ccLineTrav')
        self.ccLineTrav.setRespectPrevTransform(False)
        self.ccLineQueue = CollisionHandlerQueue()
        self.ccLineTrav.addCollider(self.ccLineNodePath, self.ccLineQueue)

    def delete(self):
        del self.cRay
        del self.cRayNode
        self.cRayNodePath.removeNode()
        del self.cRayNodePath
        del self.cSphere
        del self.cSphereNode
        self.cSphereNodePath.removeNode()
        del self.cSphereNodePath
        del self.ccLine
        del self.ccLineNode
        self.ccLineNodePath.removeNode()
        del self.ccLineNodePath
        del self.cRayTrav
        del self.cRayQueue
        del self.cSphereTrav
        del self.cSphereQueue
        del self.ccLineTrav
        del self.ccLineQueue

    def consider(self, node, pos, eyeHeight):
        self.reparentTo(node)
        self.setPos(pos)
        result = None
        self.cRayTrav.traverse(render)
        if self.cRayQueue.getNumEntries() != 0:
            self.cRayQueue.sortEntries()
            floorPoint = self.cRayQueue.getEntry(0).getSurfacePoint(self.cRayNodePath)
            if abs(floorPoint[2]) <= 4.0:
                pos += floorPoint
                self.setPos(pos)
                self.cSphereTrav.traverse(render)
                if self.cSphereQueue.getNumEntries() == 0:
                    self.ccLine.setPointA(0, 0, eyeHeight)
                    self.ccLine.setPointB(-pos[0], -pos[1], eyeHeight)
                    self.ccLineTrav.traverse(render)
                    if self.ccLineQueue.getNumEntries() == 0:
                        result = pos
        self.reparentTo(hidden)
        self.cRayQueue.clearEntries()
        self.cSphereQueue.clearEntries()
        self.ccLineQueue.clearEntries()
        return result
예제 #18
0
class ChessboardDemo():
    def __init__(self, mission):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        self.mission = mission
        self.player = mission.player
        self.menu = mission.menu
        self.state = 0
        self.frame = DirectFrame(frameColor=(0.1, 0.1, 0.1, 0.5),
                                 frameSize=(-2, 2, -2, 2),
                                 pos=(0, 0, 0))
        self.frame.hide()
        self.dr2 = base.win.makeDisplayRegion()
        #self.dr2.setActive(False)
        # self.frame.attachNewNode(self.dr2.node())
        #self.dr2.setActive(False)
        self.dr2.setClearColorActive(True)
        self.dr2.setClearColor(VBase4(0.1, 0.1, 0.1, 1))
        self.dr2.setClearDepthActive(True)
        # base.win.setClearColor(VBase4(0.1,0.1,0.1,1))
        # base.win.setClearDepthActive()
        # base.win.setClearDepth(1)
        self.render2 = NodePath("render2")
        self.camNode = Camera("cam2")
        self.cam2 = self.render2.attachNewNode(self.camNode)
        self.dr2.setCamera(self.cam2)
        self.cam2.setPosHpr(0, -18, 10, 0, -30, 0)

        # Escape quits
        base.disableMouse()  # Disble mouse camera control
        # camera.setPosHpr(0, -12, 8, 0, -35, 0)  # Set the camera
        self.setupLights()  # Setup default lighting

        # Since we are using collision detection to do picking, we set it up like
        # any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  # Make a traverser
        self.pq = CollisionHandlerQueue()  # Make a handler
        # Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        # Attach that node to the camera since the ray will need to be positioned
        # relative to it
        # self.pickerNP = camera.attachNewNode(self.pickerNode)
        self.pickerNP = self.cam2.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(1))
        self.pickerRay = CollisionRay()  # Make our ray
        # Add it to the collision node
        self.pickerNode.addSolid(self.pickerRay)
        # Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        # self.picker.showCollisions(render)

        # Now we create the chess board and its pieces

        # We will attach all of the squares to their own root. This way we can do the
        # collision pass just on the squares and save the time of checking the rest
        # of the scene
        self.squareRoot = self.render2.attachNewNode("squareRoot")

        # For each square
        self.squares = [None for i in range(64)]
        self.pieces = [None for i in range(64)]
        for i in range(64):
            # Load, parent, color, and position the model (a single square
            # polygon)
            # self.squares[i] = loader.loadModel("../res/models/Scene3/Scene3Cat/hall/square")
            self.squares[i] = loader.loadModel(
                "res/models/Scene3/Scene3Cat/hall/square")
            self.squares[i].reparentTo(self.squareRoot)
            self.squares[i].setPos(SquarePos(i))
            self.squares[i].setColor(SquareColor(i))
            # Set the model itself to be collideable with the ray. If this model was
            # any more complex than a single polygon, you should set up a collision
            # sphere around it instead. But for single polygons this works
            # fine.
            self.squares[i].find("**/polygon").node().setIntoCollideMask(
                BitMask32.bit(1))
            # Set a tag on the square's node so we can look up what square this is
            # later during the collision pass
            self.squares[i].find("**/polygon").node().setTag('square', str(i))

            # We will use this variable as a pointer to whatever piece is currently
            # in this square

        # The order of pieces on a chessboard from white's perspective. This list
        # contains the constructor functions for the piece classes defined
        # below
        pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook)

        self.pieces[40] = Queen(self, 40, WHITE)
        self.pieces[51] = Bishop(self, 51, PIECEBLACK)
        self.pieces[33] = Knight(self, 33, PIECEBLACK)
        self.pieces[9] = Rook(self, 9, PIECEBLACK)
        self.pieces[20] = Rook(self, 20, PIECEBLACK)
        # This will represent the index of the currently highlited square
        self.hiSq = False
        # This wil represent the index of the square where currently dragged piece
        # was grabbed from
        self.dragging = False

        # self.eight = OnscreenText(text="8", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                           pos=(-0.9, 0.35), scale=.07)
        # self.seven = OnscreenText(text="7", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                           pos=(-0.93, 0.27), scale=.07)
        # self.six = OnscreenText(text="6", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                         pos=(-0.97, 0.18), scale=.07)
        # self.five = OnscreenText(text="5", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                          pos=(-1.02, 0.1), scale=.07)
        # self.four = OnscreenText(text="4", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                          pos=(-1.06, 0.02), scale=.07)
        # self.three = OnscreenText(text="3", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                           pos=(-1.12, -0.1), scale=.07)
        # self.two = OnscreenText(text="2", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                         pos=(-1.16, -0.18), scale=.07)
        # self.one = OnscreenText(text="1", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                         pos=(-1.23, -0.32), scale=.07)
        x = -0.91
        y = 0.33
        dx = 0.04
        dy = 0.09
        self.eight = OnscreenText(text="8",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  shadow=(0, 0, 0, 1),
                                  pos=(x, y),
                                  scale=.07)
        x -= dx
        y -= dy
        self.seven = OnscreenText(text="7",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  shadow=(0, 0, 0, 1),
                                  pos=(x, y),
                                  scale=.07)
        x -= dx
        y -= dy
        self.six = OnscreenText(text="6",
                                style=1,
                                fg=(1, 1, 1, 1),
                                shadow=(0, 0, 0, 1),
                                pos=(x, y),
                                scale=.07)
        x -= dx
        y -= dy
        self.five = OnscreenText(text="5",
                                 style=1,
                                 fg=(1, 1, 1, 1),
                                 shadow=(0, 0, 0, 1),
                                 pos=(x, y),
                                 scale=.07)
        x -= dx
        y -= dy
        self.four = OnscreenText(text="4",
                                 style=1,
                                 fg=(1, 1, 1, 1),
                                 shadow=(0, 0, 0, 1),
                                 pos=(x, y),
                                 scale=.07)
        x -= dx
        y -= dy
        self.three = OnscreenText(text="3",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  shadow=(0, 0, 0, 1),
                                  pos=(x, y),
                                  scale=.07)
        x -= dx
        y -= dy
        self.two = OnscreenText(text="2",
                                style=1,
                                fg=(1, 1, 1, 1),
                                shadow=(0, 0, 0, 1),
                                pos=(x, y),
                                scale=.07)
        x -= dx
        y -= dy
        self.one = OnscreenText(text="1",
                                style=1,
                                fg=(1, 1, 1, 1),
                                shadow=(0, 0, 0, 1),
                                pos=(x, y),
                                scale=.07)

        self.A = OnscreenText(text="A",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(-1.05, -0.5),
                              scale=.07)
        self.B = OnscreenText(text="B",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(-0.75, -0.5),
                              scale=.07)
        self.C = OnscreenText(text="C",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(-0.45, -0.5),
                              scale=.07)
        self.D = OnscreenText(text="D",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(-0.15, -0.5),
                              scale=.07)
        self.E = OnscreenText(text="E",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(0.15, -0.5),
                              scale=.07)
        self.F = OnscreenText(text="F",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(0.45, -0.5),
                              scale=.07)
        self.G = OnscreenText(text="G",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(0.75, -0.5),
                              scale=.07)
        self.H = OnscreenText(text="H",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(1.05, -0.5),
                              scale=.07)
        self.A.reparentTo(self.frame)
        self.B.reparentTo(self.frame)
        self.C.reparentTo(self.frame)
        self.D.reparentTo(self.frame)
        self.E.reparentTo(self.frame)
        self.F.reparentTo(self.frame)
        self.G.reparentTo(self.frame)
        self.H.reparentTo(self.frame)
        self.one.reparentTo(self.frame)
        self.two.reparentTo(self.frame)
        self.three.reparentTo(self.frame)
        self.four.reparentTo(self.frame)
        self.five.reparentTo(self.frame)
        self.six.reparentTo(self.frame)
        self.seven.reparentTo(self.frame)
        self.eight.reparentTo(self.frame)
        self.hide()
        # Start the task that handles the picking
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        base.accept("mouse1", self.grabPiece)  # left-click grabs a piece
        base.accept("mouse1-up", self.releasePiece)  # releasing places it
        base.accept("escape", self.hide)

    def hide(self):
        self.frame.hide()
        self.dr2.setActive(False)
        self.A.hide()
        self.B.hide()
        self.C.hide()
        self.D.hide()
        self.E.hide()
        self.F.hide()
        self.G.hide()
        self.H.hide()
        self.one.hide()
        self.two.hide()
        self.three.hide()
        self.four.hide()
        self.five.hide()
        self.six.hide()
        self.seven.hide()
        self.eight.hide()
        base.accept("escape", self.menu.game.pauseGame)
        base.accept("mouse1", self.player.__setattr__, ["LeftButton", 1])
        base.accept("mouse1-up", self.player.__setattr__, ["LeftButton", 0])
        self.mission.resume()
        self.player.initTask()

    def show(self):
        self.frame.show()
        self.dr2.setActive(True)
        self.A.show()
        self.B.show()
        self.C.show()
        self.D.show()
        self.E.show()
        self.F.show()
        self.G.show()
        self.H.show()
        self.one.show()
        self.two.show()
        self.three.show()
        self.four.show()
        self.five.show()
        self.six.show()
        self.seven.show()
        self.eight.show()
        base.accept("escape", self.hide)

    # This function swaps the positions of two pieces
    def swapPieces(self, fr, to):
        temp = self.pieces[fr]
        self.pieces[fr] = self.pieces[to]
        self.pieces[to] = temp
        if self.pieces[fr]:
            self.pieces[fr].square = fr
            self.pieces[fr].obj.setPos(SquarePos(fr))
        if self.pieces[to]:
            self.pieces[to].square = to
            self.pieces[to].obj.setPos(SquarePos(to))

    def mouseTask(self, task):
        # This task deals with the highlighting and dragging based on the mouse

        # First, clear the current highlight
        if self.hiSq is not False:
            self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
            self.hiSq = False

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

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

            # If we are dragging something, set the position of the object
            # to be at the appropriate point over the plane of the board
            if self.dragging is not False:
                # Gets the point described by pickerRay.getOrigin(), which is relative to
                # camera, relative instead to render
                # nearPoint = render.getRelativePoint(
                #     camera, self.pickerRay.getOrigin())
                nearPoint = render.getRelativePoint(self.cam2,
                                                    self.pickerRay.getOrigin())
                # Same thing with the direction of the ray
                # nearVec = render.getRelativeVector(
                #     camera, self.pickerRay.getDirection())
                nearVec = render.getRelativeVector(
                    self.cam2, self.pickerRay.getDirection())
                self.pieces[self.dragging].obj.setPos(
                    PointAtZ(.5, nearPoint, nearVec))

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

        return Task.cont

    def grabPiece(self):
        # If a square is highlighted and it has a piece, set it to dragging
        # mode
        if self.hiSq is not False and self.pieces[self.hiSq]:
            self.dragging = self.hiSq
            self.hiSq = False

    def releasePiece(self):
        # Letting go of a piece. If we are not on a square, return it to its original
        # position. Otherwise, swap it with the piece in the new square
        # Make sure we really are dragging something

        if self.dragging is not False:
            # We have let go of the piece, but we are not on a square
            if self.hiSq is False:
                self.pieces[self.dragging].obj.setPos(SquarePos(self.dragging))
            else:
                if self.state == 0:
                    if self.dragging == 51 and self.hiSq == 58:
                        self.swapPieces(self.dragging, self.hiSq)
                        self.swapPieces(40, 32)
                        self.state = self.state + 1
                        self.mission.manager.GoodsIta[
                            'studydoor_box'].state = 'unlockedOpen'
                        self.mission.manager.GoodsIta[
                            'studydoor_box'].OpenDoor()
                        self.menu.infoDialog.show()
                        self.menu.infoLabel['text'] = '似乎传来咔嚓一声开锁的声音'
                        self.mission.skip()
                        self.hide()
                    else:
                        self.pieces[self.dragging].obj.setPos(
                            SquarePos(self.dragging))
                        if self.dragging != self.hiSq:
                            self.player.EROSION += 10
                        self.player.erosionUpdateTemp()

                elif self.state == 1:
                    if self.dragging == 33 and self.hiSq == 18:
                        self.swapPieces(self.dragging, self.hiSq)
                        self.state = self.state + 1
                        self.mission.manager.GoodsIta[
                            'chessdoor_box'].state = 'unlockedOpen'
                        self.mission.manager.GoodsIta[
                            'chessdoor_box'].OpenDoor()
                        self.mission.menu.infoDialog.show()
                        self.mission.menu.infoLabel['text'] = '棋盘上弹出一张纸条「pass。这又不是\n' \
                                                              '真的国际象棋,我选择PASS你又能怎样?\n' \
                                                              '你是无法将死我的。」'
                        self.mission.skip()
                        self.hide()
                    else:
                        self.pieces[self.dragging].obj.setPos(
                            SquarePos(self.dragging))
                        if self.dragging != self.hiSq:
                            self.player.EROSION += 10
                        self.player.erosionUpdateTemp()
                elif self.state == 2:
                    if self.dragging == 20 and self.hiSq == 36:
                        self.swapPieces(self.dragging, self.hiSq)
                        self.state = self.state + 1
                        self.mission.manager.GoodsIta[
                            'exit_box'].state = 'unlockedOpen'
                        self.mission.menu.infoDialog.show()
                        self.mission.menu.infoLabel[
                            'text'] = '可恶 失策了……这里居然…还有一个城堡么…'
                        self.mission.skip()
                        if self.mission.hiddenState:
                            self.mission.end('hiddenEnd')
                        self.hide()
                    else:
                        self.pieces[self.dragging].obj.setPos(
                            SquarePos(self.dragging))
                        if self.dragging != self.hiSq:
                            self.player.EROSION += 10
                        self.player.erosionUpdateTemp()
                elif self.state == 3:
                    self.pieces[self.dragging].obj.setPos(
                        SquarePos(self.dragging))
        # We are no longer dragging anything
        self.dragging = False

    def setupLights(self):  # This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 45, -45))
        directionalLight.setColor((0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))

    def initPos(self, state):
        if state == 0:
            self.pieces[40] = Queen(self, 40, WHITE)
            self.pieces[51] = Bishop(self, 51, PIECEBLACK)
            self.pieces[33] = Knight(self, 33, PIECEBLACK)
            self.pieces[9] = Rook(self, 9, PIECEBLACK)
            self.pieces[20] = Rook(self, 20, PIECEBLACK)
        elif state == 1:
            self.pieces[32] = Queen(self, 32, WHITE)
            self.pieces[58] = Bishop(self, 58, PIECEBLACK)
            self.pieces[33] = Knight(self, 33, PIECEBLACK)
            self.pieces[9] = Rook(self, 9, PIECEBLACK)
            self.pieces[20] = Rook(self, 20, PIECEBLACK)
        elif state == 2:
            self.pieces[32] = Queen(self, 32, WHITE)
            self.pieces[58] = Bishop(self, 58, PIECEBLACK)
            self.pieces[18] = Knight(self, 18, PIECEBLACK)
            self.pieces[9] = Rook(self, 9, PIECEBLACK)
            self.pieces[20] = Rook(self, 20, PIECEBLACK)
        elif state == 3:
            self.pieces[32] = Queen(self, 32, WHITE)
            self.pieces[58] = Bishop(self, 58, PIECEBLACK)
            self.pieces[18] = Knight(self, 18, PIECEBLACK)
            self.pieces[9] = Rook(self, 9, PIECEBLACK)
            self.pieces[36] = Rook(self, 36, PIECEBLACK)
예제 #19
0
class CogdoFlyingCameraManager:
    def __init__(self, cam, parent, player, level):
        self._toon = player.toon
        self._camera = cam
        self._parent = parent
        self._player = player
        self._level = level
        self._enabled = False

    def enable(self):
        if self._enabled:
            return
        self._toon.detachCamera()
        self._prevToonY = 0.0
        levelBounds = self._level.getBounds()
        l = Globals.Camera.LevelBoundsFactor
        self._bounds = ((levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]),
                        (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]),
                        (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2]))
        self._lookAtZ = self._toon.getHeight(
        ) + Globals.Camera.LookAtToonHeightOffset
        self._camParent = NodePath('CamParent')
        self._camParent.reparentTo(self._parent)
        self._camParent.setPos(self._toon, 0, 0, 0)
        self._camParent.setHpr(180, Globals.Camera.Angle, 0)
        self._camera.reparentTo(self._camParent)
        self._camera.setPos(0, Globals.Camera.Distance, 0)
        self._camera.lookAt(self._toon, 0, 0, self._lookAtZ)
        self._cameraLookAtNP = NodePath('CameraLookAt')
        self._cameraLookAtNP.reparentTo(self._camera.getParent())
        self._cameraLookAtNP.setPosHpr(self._camera.getPos(),
                                       self._camera.getHpr())
        self._levelBounds = self._level.getBounds()
        self._enabled = True
        self._frozen = False
        self._initCollisions()

    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)

    def _destroyCollisions(self):
        self._collTrav.removeCollider(self._camCollNP)
        self._camCollNP.removeNode()
        del self._camCollNP
        del self._camCollRay
        del self._collHandler
        del self._collOffset
        del self._betweenCamAndToon
        self._transNP.removeNode()
        del self._transNP

    def freeze(self):
        self._frozen = True

    def unfreeze(self):
        self._frozen = False

    def disable(self):
        if not self._enabled:
            return
        self._destroyCollisions()
        self._camera.wrtReparentTo(render)
        self._cameraLookAtNP.removeNode()
        del self._cameraLookAtNP
        self._camParent.removeNode()
        del self._camParent
        del self._prevToonY
        del self._lookAtZ
        del self._bounds
        del self._frozen
        self._enabled = False

    def update(self, dt=0.0):
        self._updateCam(dt)
        self._updateCollisions()

    def _updateCam(self, dt):
        toonPos = self._toon.getPos()
        camPos = self._camParent.getPos()
        x = camPos[0]
        z = camPos[2]
        toonWorldX = self._toon.getX(render)
        maxX = Globals.Camera.MaxSpinX
        toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX)
        spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / (
            maxX * maxX)
        newH = 180.0 + spinAngle
        self._camParent.setH(newH)
        spinAngle = spinAngle * (pi / 180.0)
        distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle)
        distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle)
        d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0])
        if abs(d) > Globals.Camera.LeewayX:
            if d > Globals.Camera.LeewayX:
                x = toonPos[0] + Globals.Camera.LeewayX
            else:
                x = toonPos[0] - Globals.Camera.LeewayX
        x = self._toon.getX(render) + distToRightOfToon
        boundToonZ = min(toonPos[2], self._bounds[2][1])
        d = z - boundToonZ
        if d > Globals.Camera.MinLeewayZ:
            if self._player.velocity[2] >= 0 and toonPos[
                    1] != self._prevToonY or self._player.velocity[2] > 0:
                z = boundToonZ + d * INVERSE_E**(dt *
                                                 Globals.Camera.CatchUpRateZ)
            elif d > Globals.Camera.MaxLeewayZ:
                z = boundToonZ + Globals.Camera.MaxLeewayZ
        elif d < -Globals.Camera.MinLeewayZ:
            z = boundToonZ - Globals.Camera.MinLeewayZ
        if self._frozen:
            y = camPos[1]
        else:
            y = self._toon.getY(render) - distBehindToon
        self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z))
        if toonPos[2] < self._bounds[2][1]:
            h = self._cameraLookAtNP.getH()
            if d >= Globals.Camera.MinLeewayZ:
                self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ)
            elif d <= -Globals.Camera.MinLeewayZ:
                self._cameraLookAtNP.lookAt(self._camParent, 0, 0,
                                            self._lookAtZ)
            self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0)
            self._camera.setHpr(
                smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr()))
        self._prevToonY = toonPos[1]

    def _updateCollisions(self):
        pos = self._toon.getPos(self._camera) + self._collOffset
        self._camCollRay.setOrigin(pos)
        direction = -Vec3(pos)
        direction.normalize()
        self._camCollRay.setDirection(direction)
        self._collTrav.traverse(render)
        nodesInBetween = {}
        if self._collHandler.getNumEntries() > 0:
            self._collHandler.sortEntries()
            for entry in self._collHandler.getEntries():
                name = entry.getIntoNode().getName()
                if name.find('col_') >= 0:
                    np = entry.getIntoNodePath().getParent()
                    if np not in nodesInBetween:
                        nodesInBetween[np] = np.getParent()

        for np in nodesInBetween.keys():
            if np in self._betweenCamAndToon:
                del self._betweenCamAndToon[np]
            else:
                np.setTransparency(True)
                np.wrtReparentTo(self._transNP)
                if np.getName().find('lightFixture') >= 0:
                    if not np.find('**/*floor_mesh').isEmpty():
                        np.find('**/*floor_mesh').hide()
                elif np.getName().find('platform') >= 0:
                    if not np.find('**/*Floor').isEmpty():
                        np.find('**/*Floor').hide()

        for np, parent in self._betweenCamAndToon.items():
            np.wrtReparentTo(parent)
            np.setTransparency(False)
            if np.getName().find('lightFixture') >= 0:
                if not np.find('**/*floor_mesh').isEmpty():
                    np.find('**/*floor_mesh').show()
            elif np.getName().find('platform') >= 0:
                if not np.find('**/*Floor').isEmpty():
                    np.find('**/*Floor').show()

        self._betweenCamAndToon = nodesInBetween
class p3dApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self);
        
        # setup the environment or model
        self.model = \
            self.loader.loadModel("/usr/share/panda3d/models/box");
        self.model.reparentTo(self.render);
        self.model.setTag('Model', '1');
        self.model.setScale(1.5, 1.5, 1.5);
        
        # setup camera
        self.camera.setPos(5,5,5)
        self.camera.lookAt(0,0,0)
        
        # Disable mouse control
        self.disableMouse();
        
        # Handle mouse events.
        self.accept('mouse1', self.mouse_down);
        
        # convert image from opencv to panda3d texture
#         self.taskMgr.add(self.read_image_cv, "cvImageTask");
        
        # Setup collision handler
        self.handler = CollisionHandlerQueue()
        self.traverser = CollisionTraverser('ColTraverser')
        self.traverser.traverse(self.model)
        self.ray = CollisionRay()
        pickerNode = CollisionNode('MouseRay')
        pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
        pickerNP = self.camera.attachNewNode(pickerNode)
        pickerNode.addSolid(self.ray)
        self.traverser.addCollider(pickerNP, self.handler)
        
        self.load_shader();
        
        self.first_frame_loaded = False;

    def read_image_cv(self):
        """
        Pulls the next frame from the opencv part, and converts to a panda3d
        texture and display it on the screen.
        """
        cvim = self.cvapp.pull_frame()
        w = cvim.shape[1];
        h = cvim.shape[0];
        
        cvim = cv2.flip(cvim, 0);
        self.im = Texture("cvIm");
        self.im.setCompression(Texture.CMOff);
        self.im.setup2dTexture(w, h, Texture.TUnsignedByte, Texture.FLuminance);
        self.im.setRamImage(cvim);
         
        self.screen_im = OnscreenImage(parent=self.render2d, image=self.im, scale=(1, 1, 1), pos=(0, 0, 0));
        self.cam2d.node().getDisplayRegion(0).setSort(-20);
    
    def load_shader(self):
        """
        The function loads the vertex and fragment shader.
        It provides an example of sending the model-view-projection matrix
        to the shader program when it's calculated.
        """
        self.shader = Shader.load(Shader.SL_GLSL, "vertex.glsl", "fragment.glsl");
        self.model.set_shader(self.shader)
        self.model.set_shader_input("my_ModelViewProjectionMatrix", LMatrix4f())

    def mouse_down(self):
        """
        This function is called as a result of a mouse click.
        It gets the vertex that was clicked by the mouse.
        It sends the mouse position and the vertex position to the cv app.
        """
        if (self.first_frame_loaded == False):
            self.first_frame_loaded = True
            self.read_image_cv()
            return;
        
        xPos = self.mouseWatcherNode.getMouseX()
        yPos = self.mouseWatcherNode.getMouseY()
        self.ray.setFromLens(self.camNode, xPos, yPos)
        self.traverser.traverse(self.model)
        self.handler.sortEntries()
        if (self.handler.getNumEntries() > 0):
            entry = self.handler.getEntry(0) # CollisionEntry
            vpos = entry.getSurfacePoint(self.model)
            res = self.cvapp.mouse_clicked(LPoint3f(xPos, yPos), vpos)
            if (res == 1):
                self.read_image_cv()
        
    def set_cv_app(self, cvapp):
        self.cvapp = cvapp;
class DistributedLevel(DistributedObject):

    """ An instance of these is created and placed in the middle of
    the zone.  It serves to illustrate the creation of AI-side objects
    to populate the world, and a general mechanism for making them
    react to the avatars. """

    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)

    def announceGenerate(self):
        """ This method is called after generate(), after all of the
        required fields have been filled in.  At the time of this call,
        the distributed object is ready for use. """
        DistributedObject.announceGenerate(self)

        # Now that the object has been fully manifested, we can parent
        # it into the scene.
        print "render the model"
        self.model.reparentTo(render)

    def disable(self):
        # Take it out of the scene graph.
        self.detachNode()

        DistributedObject.disable(self)

    def checkMousePos(self, mpos, camPos, camHpr):
        lens = LenseNode.copyLens(base.camNode)
        lens.setPos(camPos)
        lens.setHpr(camHpr)
        help(mpos)
        mpos = Point2(mpos.x, mpos.y)
        pos = self.getClickPosition(mpos, lens)
        print "mouse clicked at:", pos

    def mouseClick(self):
        """Send an event to the server that will check where the mouse
        will hit and what action needs to be done"""
        hitPos = (0, 0, 0)
        # check if we have a mouse on the window
        if base.mouseWatcherNode.hasMouse():
            # get the mouse position on the screen
            mpos = base.mouseWatcherNode.getMouse()
            print mpos
            # set the ray's position
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            # Now call the traverse function to let the traverser check for collisions
            # with the added colliders and the levelNP
            self.picker.traverse(self.planeNP)
            # check if we have a collision
            if self.pq.getNumEntries() > 0:
                # sort the entries to get the closest first
                self.pq.sortEntries()
                # This is the point at where the mouse ray and the level plane intersect
                hitPos = self.pq.getEntry(0).getSurfacePoint(render)
        base.messenger.send("clickPosition", [hitPos])
예제 #22
0
class Projectile(NetEnt):
    def __init__(self, parent=None, pitch=None, id=None):
        NetEnt.__init__(self, id)
        self.node = NetNodePath(PandaNode('projectile'))
        if parent:
            self.parent = parent
            self.node.setPos(parent.node.getPos() + (0, 0, 1))
            self.node.setHpr(parent.node.getHpr())
            self.node.setP(pitch)
        self.node.reparentTo(render)
        ProjectilePool.add(self)
        #print 'there are',len(ProjectilePool.values()),'projectiles'
        self.flyTime = 0

        self.sprite = Sprite2d('resources/missile.png',
                               rows=3,
                               cols=1,
                               rowPerFace=(0, 1, 2, 1),
                               anchorY=Sprite2d.ALIGN_CENTER)
        self.sprite.node.reparentTo(self.node)

        # set up 'from' collisions - for detecting projectile hitting things
        self.collisionHandler = CollisionHandlerQueue()
        self.fromCollider = self.node.attachNewNode(
            CollisionNode('fromCollider'))
        self.fromCollider.node().addSolid(CollisionRay(0, 0, 0, 0, 1, 0))
        self.fromCollider.node().setIntoCollideMask(BITMASK_EMPTY)
        self.fromCollider.node().setFromCollideMask(BITMASK_TERRAIN
                                                    | BITMASK_CHARACTER)
        if SHOW_COLLISIONS:
            self.fromCollider.show()
        Character.collisionTraverser.addCollider(self.fromCollider,
                                                 self.collisionHandler)

    def getState(self):
        dataDict = NetObj.getState(self)
        dataDict[0] = self.node.getState()
        return dataDict

    def setState(self, weightOld, dataDictOld, weightNew, dataDictNew):
        oldNode = None if not dataDictOld else dataDictOld.get(0, None)
        self.node.setState(weightOld, oldNode, weightNew, dataDictNew[0])

    def movePostCollide(self, deltaT):
        desiredDistance = 30 * deltaT
        self.collisionHandler.sortEntries()
        ch = self.collisionHandler
        for e in [ch.getEntry(i) for i in range(ch.getNumEntries())]:
            collisionDist = (self.node.getPos() -
                             e.getSurfacePoint(render)).length()
            if collisionDist > desiredDistance:
                break
            # only accept collisions that aren't with parent
            if e.getIntoNode().getParent(0).getTag('ID') != str(
                    self.parent.id):
                return False
        self.node.setY(self.node, desiredDistance)
        self.flyTime += deltaT
        return self.flyTime < 4

    def __del__(self):
        #print 'PROJECTILE BEING REMOVED'
        self.node.removeNode()
class GameEngine( DirectObject ):
    def __init__(self):
        print 'Game Engine Started'
        self.lastBlock = 0
        self.map = []
        self.startBlock = 0
        self.endBlock = 0
        self.mapName = 'test2'
        
        self.loadEnvironment(self.mapName)
        self.loadCursorPicker()
        self.camera = RTS_Camera()
        self.loadSimpleLighting()
        
        self.waveController = WaveController(self.mapName, self.startBlock, self.map)
        self.towerController = TowerController(self.waveController)
        
        self.setupKeyListeners()
        self.EFT = taskMgr.add(self.everyFrameTask, "everyFrameTask")
        
    # The task that is run every frame
    def everyFrameTask(self, task):
        self.camera.handleMouseInput()
        self.checkCursorCollision()
        self.towerController.updateTowers()
        
        return task.cont
    
    # Loads the level from the text file. Puts each
    # row into an array then creates the rows in the
    # 1st quadrant
    def loadEnvironment(self, file):
        fileName = 'maps/' + file + '.map'
        rows = []
        self.environmentRoot = render.attachNewNode('environmentRoot')
        
        FILE = open(fileName, 'r')
        while( 1 ):
            line = FILE.readline()
            if( not line ):
                break
            print line,
            if( line[-1] == '\n' ):
                line = line[:-1]
            rows.append(line)
            
        rows.reverse()
        for i, row in enumerate(rows):
            self.createRow( i, row )
            
    # Loads the models corresponding to the
    # characters in the map file for an entire row
    def createRow(self, rowIndex, row):
        mapRow = []
        
        for colIndex, block in enumerate(row):
            block = BLOCK_CHAR_TO_MODEL[block]( self.environmentRoot, colIndex + 0.5, rowIndex + 0.5 )
            mapRow.append( block )
            block.setIndex( str(rowIndex) + ' ' + str(colIndex) )
            
            if( block.isType(StartBlock) ):
                self.startBlock = block
            elif( block.isType(EndBlock) ):
                self.endBlock = block
                
        self.map.append(mapRow)
            
    # Creates necessary collision parts to determine what object
    # the cursor is hovering
    def loadCursorPicker(self):
        self.picker = CollisionTraverser()
        self.pq     = CollisionHandlerQueue()
        self.pickerNode = CollisionNode('mouseRay')
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()
        self.pickerNode.addSolid(self.pickerRay)
        self.picker.addCollider(self.pickerNP, self.pq)
        
    def checkCursorCollision(self):
        if base.mouseWatcherNode.hasMouse():
              mpos = base.mouseWatcherNode.getMouse()
              self.pickerRay.setFromLens( base.camNode, mpos.getX(), mpos.getY() )
              
        self.picker.traverse( self.environmentRoot )
        if( self.pq.getNumEntries() > 0 ):
            self.pq.sortEntries()
            (row, ignore, col) = self.pq.getEntry(0).getIntoNode().getTag('index').partition(' ')
            row = int(row)
            col = int(col)
            block = self.map[row][col]
            if( block != self.lastBlock ):
                block.highlight()
                if( self.lastBlock ):
                    self.lastBlock.unHighlight()
            self.lastBlock = block
        else:
            if( self.lastBlock ):
                self.lastBlock.unHighlight()
                self.lastBlock = 0
            
    def mouseClick(self):
        if( self.lastBlock ):
            self.towerController.addTower(self.lastBlock)
            
    def spawnEnemy(self):
        e = Enemy(self.startBlock, self.map)
        e.moveToEnd()
        
    def setTowerType(self, type):
        self.towerController.currentTowerType = type
    
    def setupKeyListeners(self):
        self.accept('mouse1', self.mouseClick)
        self.accept('q', self.waveController.start)
        
        self.accept('1', self.setTowerType, [NormalTower])
        self.accept('2', self.setTowerType, [SlowTower])
        self.accept('3', self.setTowerType, [StunTower])
            
    def loadSimpleLighting(self):
        ambientLight = AmbientLight( "ambientLight" )
        ambientLight.setColor( Vec4(.8, .8, .8, 1) )
        directionalLight = DirectionalLight( "directionalLight" )
        directionalLight.setDirection( Vec3( 0, 45, -45 ) )
        directionalLight.setColor( Vec4( 0.2, 0.2, 0.2, 0.6 ) )
        render.setLight(render.attachNewNode( directionalLight ) )
        render.setLight(render.attachNewNode( ambientLight ) )
예제 #24
0
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        # Create a traverser and a handler
        self.cTrav = CollisionTraverser()
        self.cQueue = CollisionHandlerQueue()

        # Create the collision node that will store the collision
        # ray solid
        self.pickerNode = CollisionNode('mouseRay')
        # Set bitmask for efficiency, only hit from objects with same mask
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        # Attach collision node to camera, since that is the source
        self.pickerNP = camera.attachNewNode(self.pickerNode)

        # Add collision solid(ray) to collision node
        self.pickerRay = CollisionRay()
        self.pickerNode.addSolid(self.pickerRay)
        # Add collidable node(pickerNP) to the traverser
        # Collisions detected when traversed will go to cQueue
        self.cTrav.addCollider(self.pickerNP, self.cQueue)

        # Create visible sphere
        self.tmpSphere = self.loader.loadModel("models/misc/sphere")
        self.tmpSphere.reparentTo(self.render)
        self.tmpSphere.setColor(1, 1, 1, 1)
        self.tmpSphere.setPos(0, 100, 0)

        # Create collision sphere and attach to tmpSphere
        cSphere = CollisionSphere(0, 0, 0, 3)
        cnodePath = self.tmpSphere.attachNewNode(CollisionNode('cnode'))
        # Add collision solid(sphere) to collision node
        # Because tmpSphere/cSphere is child of render, which we traverse
        # later, it becomes a from collider automatically, we don't
        # need to addCollider since that is only for from collision nodes
        cnodePath.node().addSolid(cSphere)
        # Set bitmask to match the from collisionnode mask for efficiency
        cnodePath.setCollideMask(BitMask32.bit(1))
        # Show the collision sphere visibly, for debugging.
        cnodePath.show()
        # Set a custom tag on the collision node which becomes available
        # inside the collision event stored in the collision handler
        cnodePath.setTag('someTag', '1')

        # Add task to run every frame - set collision solid(ray)
        # to start at the current camera position,
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')

    def mouseTask(self, task):
        if self.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            # Set collision ray to start at camera lens and endpoint at mouse
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            # Perform the collision traverse - follows the ray and logs
            # all collisions to the handler set earlier
            self.cTrav.traverse(self.render)
            # Get info from entries and use them
            if self.cQueue.getNumEntries() > 0:
                self.cQueue.sortEntries()
                print("Collision!")
                entry = self.cQueue.getEntry(0)
                print(entry)
                someTag = int(entry.getIntoNode().getTag('someTag'))
                print(someTag)
                # Collision detected, mouse must be over sphere
                self.tmpSphere.setColor(0, 1, 0, 1)
            else:
                # No collisions, mouse is not over sphere, unset color
                # Not ideal to "unset" the color each frame
                self.tmpSphere.setColor(1, 1, 1, 1)
        return task.cont
예제 #25
0
파일: mouse.py 프로젝트: jtiai/ursina
class Mouse():
    def __init__(self):
        self.enabled = False
        self.locked = False
        self.position = Vec3(0, 0, 0)
        self.delta = Vec3(0, 0, 0)
        self.prev_x = 0
        self.prev_y = 0
        self.start_x = 0
        self.start_y = 0
        self.velocity = Vec3(0, 0, 0)
        self.prev_click_time = time.time()
        self.double_click_distance = .5

        self.hovered_entity = None
        self.left = False
        self.right = False
        self.middle = False
        self.delta_drag = Vec3(0, 0, 0)

        self.update_step = 1
        self.traverse_target = scene
        self._i = 0
        self._mouse_watcher = None
        self._picker = CollisionTraverser()  # Make a traverser
        self._pq = CollisionHandlerQueue()  # Make a handler
        self._pickerNode = CollisionNode('mouseRay')
        self._pickerNP = camera.attach_new_node(self._pickerNode)
        self._pickerRay = CollisionRay()  # Make our ray
        self._pickerNode.addSolid(self._pickerRay)
        self._picker.addCollider(self._pickerNP, self._pq)
        self._pickerNode.set_into_collide_mask(0)

        self.raycast = True
        self.collision = None
        self.collisions = list()
        self.enabled = True

    @property
    def x(self):
        if not self._mouse_watcher.has_mouse():
            return 0
        return self._mouse_watcher.getMouseX(
        ) / 2 * window.aspect_ratio  # same space as ui stuff

    @x.setter
    def x(self, value):
        self.position = (value, self.y)

    @property
    def y(self):
        if not self._mouse_watcher.has_mouse():
            return 0

        return self._mouse_watcher.getMouseY() / 2

    @y.setter
    def y(self, value):
        self.position = (self.x, value)

    @property
    def position(self):
        return Vec3(self.x, self.y, 0)

    @position.setter
    def position(self, value):
        base.win.move_pointer(
            0,
            round(value[0] + (window.size[0] / 2) +
                  (value[0] / 2 * window.size[0]) *
                  1.124),  # no idea why I have * with 1.124
            round(value[1] + (window.size[1] / 2) -
                  (value[1] * window.size[1])),
        )

    def __setattr__(self, name, value):

        if name == 'visible':
            window.set_cursor_hidden(not value)
            application.base.win.requestProperties(window)

        if name == 'locked':
            try:
                object.__setattr__(self, name, value)
                window.set_cursor_hidden(value)
                if value:
                    window.set_mouse_mode(window.M_relative)
                else:
                    window.set_mouse_mode(window.M_absolute)

                application.base.win.requestProperties(window)
            except:
                pass

        try:
            super().__setattr__(name, value)
            # return
        except:
            pass

    def input(self, key):
        if not self.enabled:
            return

        if key.endswith('mouse down'):
            self.start_x = self.x
            self.start_y = self.y

        elif key.endswith('mouse up'):
            self.delta_drag = Vec3(self.x - self.start_x,
                                   self.y - self.start_y, 0)

        if key == 'left mouse down':
            self.left = True
            if self.hovered_entity:
                if hasattr(self.hovered_entity, 'on_click'):
                    self.hovered_entity.on_click()
                for s in self.hovered_entity.scripts:
                    if hasattr(s, 'on_click'):
                        s.on_click()
            # double click
            if time.time(
            ) - self.prev_click_time <= self.double_click_distance:
                base.input('double click')

                if self.hovered_entity:
                    if hasattr(self.hovered_entity, 'on_double_click'):
                        self.hovered_entity.on_double_click()
                    for s in self.hovered_entity.scripts:
                        if hasattr(s, 'on_double_click'):
                            s.on_double_click()

            self.prev_click_time = time.time()

        if key == 'left mouse up':
            self.left = False
        if key == 'right mouse down':
            self.right = True
        if key == 'right mouse up':
            self.right = False
        if key == 'middle mouse down':
            self.middle = True
        if key == 'middle mouse up':
            self.middle = False

    def update(self):
        if not self.enabled or not self._mouse_watcher.has_mouse():
            self.velocity = Vec3(0, 0, 0)
            return

        self.moving = self.x + self.y != self.prev_x + self.prev_y

        if self.moving:
            if self.locked:
                self.velocity = self.position
                self.position = (0, 0)
            else:
                self.velocity = Vec3(self.x - self.prev_x,
                                     (self.y - self.prev_y) /
                                     window.aspect_ratio, 0)
        else:
            self.velocity = Vec3(0, 0, 0)

        if self.left or self.right or self.middle:
            self.delta = Vec3(self.x - self.start_x, self.y - self.start_y, 0)

        self.prev_x = self.x
        self.prev_y = self.y

        self._i += 1
        if self._i < self.update_step:
            return
        # collide with ui
        self._pickerNP.reparent_to(scene.ui_camera)
        self._pickerRay.set_from_lens(camera._ui_lens_node,
                                      self.x * 2 / window.aspect_ratio,
                                      self.y * 2)
        self._picker.traverse(camera.ui)
        if self._pq.get_num_entries() > 0:
            # print('collided with ui', self._pq.getNumEntries())
            self.find_collision()
            return

        # collide with world
        self._pickerNP.reparent_to(camera)
        self._pickerRay.set_from_lens(scene.camera.lens_node,
                                      self.x * 2 / window.aspect_ratio,
                                      self.y * 2)
        try:
            self._picker.traverse(self.traverse_target)
        except:
            # print('error: mouse._picker could not traverse', self.traverse_target)
            return

        if self._pq.get_num_entries() > 0:
            self.find_collision()
        else:
            # print('mouse miss', base.render)
            # unhover all if it didn't hit anything
            for entity in scene.entities:
                if hasattr(entity, 'hovered') and entity.hovered:
                    entity.hovered = False
                    self.hovered_entity = None
                    if hasattr(entity, 'on_mouse_exit'):
                        entity.on_mouse_exit()
                    for s in entity.scripts:
                        if hasattr(s, 'on_mouse_exit'):
                            s.on_mouse_exit()

    @property
    def normal(self):
        if not self.collision:
            return None
        return self.collision.normal

    @property
    def world_normal(self):
        if not self.collision:
            return None
        return self.collision.world_normal

    @property
    def point(self):
        if self.collision:
            return self.collision.point
        return None

    @property
    def world_point(self):
        if self.collision:
            return self.collision.world_point
        return None

    def find_collision(self):
        self.collisions = list()
        self.collision = None
        if not self.raycast or self._pq.get_num_entries() == 0:
            self.unhover_everything_not_hit()
            return False

        self._pq.sortEntries()

        for entry in self._pq.getEntries():
            for entity in scene.entities:
                if entry.getIntoNodePath(
                ).parent == entity and entity.collision:
                    if entity.collision:
                        hit = HitInfo(
                            hit=entry.collided(),
                            entity=entity,
                            distance=distance(entry.getSurfacePoint(scene),
                                              camera.getPos()),
                            point=entry.getSurfacePoint(entity),
                            world_point=entry.getSurfacePoint(scene),
                            normal=entry.getSurfaceNormal(entity),
                            world_normal=entry.getSurfaceNormal(scene),
                        )
                        self.collisions.append(hit)
                        break

        if self.collisions:
            self.collision = self.collisions[0]
            self.hovered_entity = self.collision.entity
            if not self.hovered_entity.hovered:
                self.hovered_entity.hovered = True
                if hasattr(self.hovered_entity, 'on_mouse_enter'):
                    self.hovered_entity.on_mouse_enter()
                for s in self.hovered_entity.scripts:
                    if hasattr(s, 'on_mouse_enter'):
                        s.on_mouse_enter()

        self.unhover_everything_not_hit()

    def unhover_everything_not_hit(self):
        for e in scene.entities:
            if e == self.hovered_entity:
                continue

            if e.hovered:
                e.hovered = False
                if hasattr(e, 'on_mouse_exit'):
                    e.on_mouse_exit()
                for s in e.scripts:
                    if hasattr(s, 'on_mouse_exit'):
                        s.on_mouse_exit()
예제 #26
0
class Life(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        base.disableMouse()
        base.setFrameRateMeter(True)

        mydir = os.path.abspath(sys.path[0])
        mydir = Filename.fromOsSpecific(mydir).getFullpath()

        self.bgmusic = self.loader.loadMusic(mydir + '/../sounds/bgmusic.ogg')
        self.bgmusic.play()

        # Setup collision for 3d picking
        self.picker = CollisionTraverser()
        self.pq = CollisionHandlerQueue()
        # Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        # Attach that node to the camera since the ray will need to be positioned
        #   relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        # Everything to be picked will use bit 1. This way if we were doing other
        #   collision we could separate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()
        self.pickerNode.addSolid(self.pickerRay)
        # Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)

        # Configure boxes and textures
        self.box = [[None for x in range(CELL_WIDTH)] for x in range(CELL_HEIGHT)]
        self.textureempty = self.loader.loadTexture(mydir + '/../textures/box.png')
        self.texturefull = self.loader.loadTexture(mydir + '/../textures/boxfull.png')

        self.textureempty.setMagfilter(Texture.FTLinear)
        self.textureempty.setMinfilter(Texture.FTLinearMipmapLinear)
        self.texturefull.setMagfilter(Texture.FTLinear)
        self.texturefull.setMinfilter(Texture.FTLinearMipmapLinear)

        self.worldnode = render.attachNewNode('worldnode')
        self.boxnode = self.worldnode.attachNewNode('boxnode')

        self.worldnode.setPos(0, 200, 0)

        for row in range(CELL_HEIGHT):
            for col in range(CELL_WIDTH):
                box = self.loader.loadModel(mydir + '/../models/cube')
                box.reparentTo(self.boxnode)
                box.setPos((CELL_WIDTH * -1) + (col * 2), 0, CELL_HEIGHT - (row * 2))
                box.setTexture(self.textureempty)

                # Cube is the name of the polygon set in blender
                box.find("**/Cube").node().setIntoCollideMask(BitMask32.bit(1))
                box.find("**/Cube").node().setTag('square', str(row) + '-' + str(col))

                self.box[row][col] = box

        # Configure cell data
        self.cells = [[0 for x in range(CELL_WIDTH)] for x in range(CELL_HEIGHT)]
        self.cells[3][6] = 1
        self.cells[4][7] = 1
        self.cells[5][5] = 1
        self.cells[5][6] = 1
        self.cells[5][7] = 1

        self.editmode = False

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

        # Setup initial event handling
        self.accept('escape', sys.exit)
        self.accept('enter', self.startgame)
        self.accept('mouse1', self.startgame)

        # Prep the main screen
        self.boxnode.setPosHpr(self.worldnode, -5, -160, 0, 60, -25, 0)
        self.readyText = OnscreenText(text='Life', pos=(0.91, 0.7), scale=0.2, fg=(255, 255, 255, 255),
                                      shadow=(0, 0, 0, 100))

    def mouserotation(self, task):
        if not self.editmode and base.mouseWatcherNode.hasMouse():
            self.boxnode.setH(self.worldnode, base.mouseWatcherNode.getMouseX() * 60)
            self.boxnode.setP(self.worldnode, -base.mouseWatcherNode.getMouseY() * 60)

        return task.cont

    def startgame(self):
        # Transition to the game start state
        taskMgr.add(self.transition, 'transition')
        interval = LerpPosHprInterval(self.boxnode, TRANSITIONPERIOD, Point3(0, 0, 0), Point3(0, 0, 0),
                                      other=self.worldnode, blendType='easeInOut')
        interval.start()

    def transition(self, task):
        self.ignore('enter')
        self.ignore('mouse1')
        self.readyText.setFg((255, 255, 255, (max(0, TRANSITIONPERIOD - task.time) / TRANSITIONPERIOD)))
        self.readyText.setShadow((0, 0, 0, (max(0, TRANSITIONPERIOD - task.time) / TRANSITIONPERIOD)))

        if task.time > TRANSITIONPERIOD:
            self.accept('enter', self.handleenter)
            self.accept('mouse1', self.selectpiece)
            taskMgr.add(self.mouserotation, 'mouserotation')
            return task.done
        else:
            return task.cont

    def selectpiece(self):
        if self.editmode:
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())

            #Do the actual collision pass (Do it only on the squares for
            #efficiency purposes)
            self.picker.traverse(self.boxnode)
            if self.pq.getNumEntries() > 0:
                # If we have hit something, sort the hits so that the closest
                #   is first, and highlight that node
                self.pq.sortEntries()
                tag = self.pq.getEntry(0).getIntoNode().getTag('square')
                tagsplit = tag.split('-')
                row = int(tagsplit[0])
                col = int(tagsplit[1])

                # Set the highlight on the picked square
                self.cells[row][col] = (0 if self.cells[row][col] == 1 else 1)

    def start(self, task):
        if not self.editmode:
            self.processcells(self.cells)

        for row in range(CELL_HEIGHT):
            for col in range(CELL_WIDTH):
                if self.cells[row][col] == 1:
                    self.box[row][col].setTexture(self.texturefull)
                else:
                    self.box[row][col].setTexture(self.textureempty)

        return task.cont

    def handleenter(self):
        self.editmode = not self.editmode

    @staticmethod
    def countsiblingcells(cells, x, y):
        return cells[y - 1][x - 1] + \
               cells[y][x - 1] + \
               cells[(y + 1) % CELL_HEIGHT][x - 1] + \
               cells[y - 1][x] + \
               cells[(y + 1) % CELL_HEIGHT][x] + \
               cells[y - 1][(x + 1) % CELL_WIDTH] + \
               cells[y][(x + 1) % CELL_WIDTH] + \
               cells[(y + 1) % CELL_HEIGHT][(x + 1) % CELL_WIDTH]

    def processcells(self, cells):
        newcells = copy.deepcopy(cells)

        for row in range(CELL_HEIGHT):
            for col in range(CELL_WIDTH):
                neighbours = self.countsiblingcells(newcells, col, row)

                if newcells[row][col] == 1:
                    if neighbours < 2:
                        cells[row][col] = 0
                    elif 2 <= neighbours <= 3:
                        pass
                    elif neighbours > 3:
                        cells[row][col] = 0
                else:
                    if neighbours == 3:
                        cells[row][col] = 1
예제 #27
0
class Grabber(object):
    def __init__( self, levitNP):
        """ A widget to position, rotate, and scale Panda 3D Models and Actors
            * handleM1 decides what to do with a mouse1 click
            -- object selection by calling handleSelection when the grabModel is inactive (hidden)
            -- object manipulation by calling handleManipulationSetup (sets the stage for and launches the dragTask)

            isHidden() when nothing is selected
            isDragging means not running collision checks for selection setup and LMB is pressed

            call handleM1 from another class to push control up
            in the program hierarchy (remove inner class calls)
        """
        # TODO remove selection functionality from grabber and put it in a selector class
        self.levitorNP = levitNP  # TODO remove this and use barebonesNP
        self.selected = None
        self.initialize()

    def initialize(self):
        """Reset everything except LevitorNP and selected, also called inside __init__"""
        self.notify = DirectNotify().newCategory('grabberErr')
        self.currPlaneColNorm = Vec3(0.0)
        self.isCameraControlOn = False
        self.isDragging = False
        self.isMultiselect = False
        self.grabScaleFactor = .075
        self.currTransformDir = Point3(0.0)
        self.interFrameMousePosition = Point3(0.0)
        self.init3DemVal = Point3(0.0)
        # initCommVal holds the value before a command operation has taken place
        self.initialCommandTrgVal = None
        # To load the grabber model, this climbs up the absolute path to /barebones/ to gain access to the model folder
        self.grabModelNP = loader.loadModel(Filename.fromOsSpecific(
                                            ntpath.split( ntpath.split(inspect.stack()[0][1])[0] )[0])
                                            + '/EditorModels/widget')
        self.grabModelNP.setPos(0.0, 0.0, 0.0)
        self.grabModelNP.setBin("fixed", 40)
        self.grabModelNP.setDepthTest(False)
        self.grabModelNP.setDepthWrite(False)
        self.transformOpEnum = Enum('rot, scale, trans')
        self.currTransformOperation = None
        # TODO For readability, use this enum in the nested if/else as was the original intent.
        self.grabInd = Enum('xRot, yRot, zRot, xScaler, yScaler, zScaler, xTrans, yTrans, zTrans, xyTrans, xzTrans, zyTrans, grabCore')
        grbrNodLst = [self.grabModelNP.find("**/XRotator;+h-s-i"),       # 0
                       self.grabModelNP.find("**/YRotator;+h-s-i"),      # 1
                       self.grabModelNP.find("**/ZRotator;+h-s-i"),      # 2 end rotate
                       self.grabModelNP.find("**/XScaler;+h-s-i"),       # 3
                       self.grabModelNP.find("**/YScaler;+h-s-i"),       # 4
                       self.grabModelNP.find("**/ZScaler;+h-s-i"),       # 5 end scale
                       self.grabModelNP.find("**/XTranslator;+h-s-i"),   # 6
                       self.grabModelNP.find("**/YTranslator;+h-s-i"),   # 7
                       self.grabModelNP.find("**/ZTranslator;+h-s-i"),   # 8 end translate / end single dir operations
                       self.grabModelNP.find("**/XYTranslator;+h-s-i"),  # 9
                       self.grabModelNP.find("**/XZTranslator;+h-s-i"),  # 10
                       self.grabModelNP.find("**/ZYTranslator;+h-s-i"),  # 11 end bi-directional operations
                       self.grabModelNP.find("**/WidgetCore;+h-s-i")]    # 12
        #Mat4.yToZUpMat()  # change coordinate to z up
        grbrNodLst[12].getParent().setHprScale(0, 0, 0, 1, 1, -1)
        self.grabModelNP.setPythonTag('grabberRoot', grbrNodLst)
        self.grabModelNP.reparentTo(BBGlobalVars.bareBonesObj.levitorNP)
        self.grabModelNP.hide()
        #self.grabIntoBitMask = COLLISIONMASKS
        self.grabModelNP.setCollideMask(COLLISIONMASKS['default'])
        self.grabModelNP.setPythonTag('grabber', self)

        ##############################################################################
        # This whole section is the basics for setting up mouse selection
        # --The mouse events are added in the events section (next)

        # Create the collision node for the picker ray to add traverser as a 'from' collider
        self.grabberColNode = CollisionNode('grabberMouseRay')
        # Set the collision bitmask
        # TODO: define collision bitmask (let user define thiers? likely not)
        self.defaultBitMask = GeomNode.getDefaultCollideMask()
        self.grabberColNode.setFromCollideMask(self.defaultBitMask)
        self.grabberRayColNP = camera.attachNewNode(self.grabberColNode)
        # Create the grabberRay and add it to the picker CollisionNode
        self.grabberRay = CollisionRay(0.0, 0.0, 0.0,
                                       0.0, 1.0, 0.0)
        self.grabberRayNP = self.grabberColNode.addSolid(self.grabberRay)
        # create a collision queue for the traverser
        self.colHandlerQueue = CollisionHandlerQueue()
        # Create collision traverser
        self.colTraverser = CollisionTraverser('grabberTraverser')
        # Set the collision traverser's 'fromObj' and handler
        # e.g. trav.addCollider( fromObj, handler )
        self.colTraverser.addCollider(self.grabberRayColNP, self.colHandlerQueue)


        ############################################################
        # setup event handling with the messenger
        # URGENT remove all of this messenger code throughout Grabber, especially the camera control
        # disable the mouse when the ~ is pressed (w/o shift)
        self.disableCamera()                            # disable camera control by the mouse
        messenger.accept('`', self, self.enableCamera)  # enable camera control when the ~ key is pressed w/o shift
        messenger.accept('`-up', self, self.disableCamera)  # disable camera control when the ~ key is released

        # handle mouse selection/deselection & manipulating the scene
        messenger.accept('mouse1', self, self.handleM1, persistent=1)  # deselect in event handler

        taskMgr.add(self.scaleGrabber, 'scaleGrabber')
        # ////////////////////////////////////////////////////////////////////
        # comment out: good for debug info
        #taskMgr.add(self.watchMouseColl, name='grabberDebug')
        #this is only good for seeing types and hierarchy
        #self.grabModelNP.ls()
        #render.ls()
        # self.frames = 0  #remove
        # self.axis = loader.loadModel("zup-axis")
        # self.axis.reparentTo(self.grabModelNP)
        # self.axis.setScale(.15)
        # self.axis.setPos(0.0)
        # self.grabModelNP.append( 'newAttrib', self)
        # setattr( self.grabModelNP, 'newAttrib', self)


    def prepareForPickle(self):
        self.colTraverser = None     # Traversers are not picklable
        self.defaultBitMask = None   # BitMasks "..."
        # self.grabIntoBitMask = None  # "..."
        self.colHandlerQueue = None  # CollisonHandlerQueue "..."
        self.grabModelNP.removeNode()
        self.grabModelNP = None
        taskMgr.remove('scaleGrabber')


    def recoverFromPickle(self):
        self.initialize()
        if self.selected is not None:
            self.grabModelNP.setPos(render, self.selected.getPos(render))
            self.grabModelNP.show()
        print "grabber sel ", self.selected, " isHidden() ", self.grabModelNP.isHidden(), '\n'
        taskMgr.add(self.scaleGrabber, 'scaleGrabber')

    #### May use to gain control over pickling.
    # def __repr__(self): # for pickling purposes
    #     if self.colTraverser:
    #         self.colTraverser = None
    #
    #     dictrepr = dict.__repr__(self.__dict__)
    #     dictrepr = '%r(%r)' % (type(self).__name__, dictrepr)
    #     print dictrepr  # REMOVE
    #     return dictrepr


    def watchMouseColl(self, task):
        """ This exists for debugging purposes to perpetually watch mouse collisions.
        """
        # TODO make this highlight objects under the mouse for predictable object selection/grabber operations
        self.colTraverser.showCollisions(render)
        if base.mouseWatcherNode.hasMouse() and False == self.isCameraControlOn:
            # This gives the screen coordinates of the mouse.
            mPos = base.mouseWatcherNode.getMouse()
            # This makes the ray's origin the camera and makes the ray point
            # to the screen coordinates of the mouse.
            self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY())
            # traverses the graph for collisions
            self.colTraverser.traverse(render)
        return task.cont


    def scaleGrabber(self, task):
        if self.grabModelNP.isHidden():
            return task.cont
        coreLst = self.grabModelNP.getPythonTag('grabberRoot')
        camPos = self.grabModelNP.getRelativePoint(self.grabModelNP, camera.getPos())

        if camPos.z >= 0:        # 1-4
            if camPos.x > 0.0 <= camPos.y:    # quad 1
                coreLst[12].getParent().setScale( 1, 1, -1)

            elif camPos.x < 0.0 <= camPos.y:  # quad 2
                coreLst[12].getParent().setScale( -1, 1, -1)

            elif camPos.x < 0.0 >= camPos.y:  # quad 3
                coreLst[12].getParent().setScale( -1, -1, -1)

            elif camPos.x > 0.0 >= camPos.y:  # quad 4
                coreLst[12].getParent().setScale( 1, -1, -1)

            else:
                self.notify.warning("if-else default, scaleGrabber cam.z > 0")

        else:      # 5-8
            if camPos.x > 0.0 <= camPos.y:    # quad 5
                coreLst[12].getParent().setScale( 1, 1, 1)

            elif camPos.x < 0.0 <= camPos.y:  # quad 6
                coreLst[12].getParent().setScale( -1, 1, 1)

            elif camPos.x < 0.0 >= camPos.y:  # quad 7
                coreLst[12].getParent().setScale( -1, -1, 1)

            elif camPos.x > 0.0 >= camPos.y:  # quad 8
                coreLst[12].getParent().setScale( 1, -1, 1)

            else:
                self.notify.warning("if-else default, scaleGrabber cam.z z < 0")


        distToCam = (camera.getPos() - render.getRelativePoint(BBGlobalVars.currCoordSysNP, self.grabModelNP.getPos())).length()
        self.grabModelNP.setScale(self.grabScaleFactor * distToCam,
                                  self.grabScaleFactor * distToCam,
                                  self.grabScaleFactor * distToCam)
        # keep the position identical to the selection
        # for when outside objects like undo/redo move selected
        self.grabModelNP.setPos(render, self.selected.getPos(render))
        return task.cont

    # TODO find a way to move camera control to a proper camera handler, perhaps move these to a global
    def enableCamera(self):
        self.isCameraControlOn = True
        PanditorEnableMouseFunc()

    def disableCamera(self):
        self.isCameraControlOn = False
        PanditorDisableMouseFunc()


    def handleM3(self):
        """Deselect the selected object."""
        if not self.grabModelNP.isHidden() and not self.isCameraControlOn:
            # if the grab model is in the scene and the camera is not in control
            if base.mouseWatcherNode.hasMouse() and not self.isDragging:
                # we're ignoring accidental mouse3 clicks while dragging here with not isDragging
                self.selected = None              # empty the selected, will be turned back on once something's selected
                messenger.ignore('mouse3', self)  # turn the deselect event off
                self.grabModelNP.hide()           # hide the grab model and set it back to render's pos
                self.grabModelNP.setPos(0.0)


    def handleM1Up(self):
        """Stop dragging the selected object."""
        taskMgr.remove('mouse1Dragging')
        self.isDragging = False
        self.currTransformOperation = None  # NOTE other references have been added, but no other object references them
        # record the mouse1 operation
        BBGlobalVars.undoHandler.record(self.selected, CommandUndo([self.initialCommandTrgVal],
                                                                    self.selected.setMat, self.selected.getMat(render)))
        messenger.ignore('mouse1-up', self)


    def handleM1(self):
        """Decides how to handle a mouse1 click."""
        if self.isCameraControlOn:
            return

        if base.mouseWatcherNode.hasMouse():
            # give the grabber first chance
            if self.grabModelNP.isHidden():
                # no collisions w/ grabber or nothing selected
                # handle selection with scene objects
                self.handleSelection()

            elif not self.isDragging:
                # The grabber is in place but not dragging. Get ready to drag.
                self.handleManipulationSetup()  # it'll call self.handleSelection() if no collision w/ grabber
                # TODO (if warranted) make self.handleManipulationSetup() return false if no col w/ grabber, call selection here instead


    def handleManipulationSetup(self):
        """Sets up all the attributes needed for the mouse dragging task."""
        # This makes the ray's origin the camera and makes the ray point
        # to the screen coordinates of the mouse.
        if self.isDragging:
            return
        camVec = self.grabModelNP.getRelativeVector(self.grabModelNP, camera.getPos())
        mPos = base.mouseWatcherNode.getMouse()
        self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY())
        self.colTraverser.traverse(self.grabModelNP)  # look for collisions on the grabber

        if not self.isCameraControlOn and self.colHandlerQueue.getNumEntries() > 0 and not self.grabModelNP.isHidden():
            # see if collided with the grabber if not handle re or multi selection
            self.colHandlerQueue.sortEntries()
            grabberObj = self.colHandlerQueue.getEntry(0).getIntoNodePath()
            grabberLst = self.grabModelNP.getPythonTag('grabberRoot')  # see __init__

            # the index gives the operations rot < 3 scale < 6 trans < 9 trans2D < 12
            # mod index gives axis 0 == x, 1 == y, 2 == z
            ind = -1
            for i in range(0, 13):
                if grabberObj == grabberLst[i]:
                    ind = i
                    grabberObj = grabberLst[i]
            # ensure we are not picking ourselves, ahem, the grabber
            assert(not self.grabModelNP.isAncestorOf(self.selected))
            mPos3D = Point3(0.0)
            xVec = Vec3(1, 0, 0)
            yVec = Vec3(0, 1, 0)
            zVec = Vec3(0, 0, 1)
            # TODO: ??? break this up into translate rotate and scale function to make it readable
            if -1 < ind < 3:             # rotate
                if ind % 3 == 0:    # x
                    self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.rot,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))
                elif ind % 3 == 1:  # y
                    self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.rot,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))
                else:               # z
                    self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.rot,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))

            elif ind < 6:                 # scale
                if ind % 3 == 0:    # x
                    self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.scale,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))
                elif ind % 3 == 1:  # y
                    # self.currTransformDir = Point3( 0.0, 1.0, 0.0)
                    self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.scale,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))
                else:               # z
                    # self.currTransformDir = Point3( 0.0, 0.0, 1.0)
                    self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.scale,
                                             Point3(mPos.getX(), mPos.getY(), 0.0))

            elif ind < 9:                 # translate
                if ind % 3 == 0:    # x
                    # if the camera's too flat to the collision plane bad things happen
                    if camVec.angleDeg( zVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, zVec):
                        self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec)

                    elif self.getMousePlaneIntersect(mPos3D, yVec):
                        self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.trans, mPos3D, yVec)

                elif ind % 3 == 1:  # y
                    if camVec.angleDeg( zVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, zVec):
                        self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec)

                    elif self.getMousePlaneIntersect(mPos3D, xVec):
                        self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, xVec)

                else:               # z
                    if camVec.angleDeg( yVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, yVec):
                        self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, yVec)

                    elif self.getMousePlaneIntersect(mPos3D, xVec):
                        self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, xVec)

            elif ind < 12:            # translate 2D
                if ind % 3 == 0:    # xy
                    if self.getMousePlaneIntersect(mPos3D, zVec):
                        self.initializeManipVars(Point3(1.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec)

                elif ind % 3 == 1:  # xz
                    if self.getMousePlaneIntersect(mPos3D, yVec):
                        self.initializeManipVars(Point3(1.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, yVec)
                else:               # zy
                    if self.getMousePlaneIntersect(mPos3D, xVec):
                        self.initializeManipVars(Point3(0.0, 1.0, 1.0), self.transformOpEnum.trans, mPos3D, xVec)

            elif ind == 12:  # scale in three directions
                self.initializeManipVars(Point3(1.0, 1.0, 1.0), self.transformOpEnum.scale,
                                         Point3(mPos.getX(), mPos.getY(), 0.0))

            else:
                self.notify.warning("Grabber Err: no grabber collision when col entries > 0 AND grabber not hidden")

            # Save initial value for save/undo.
            # The end result of the operation is sent to the undo handler on mouse up event.
            if self.selected:
                self.initialCommandTrgVal = self.selected.getMat(render)
        else:
            # no collisions w/ grabber or nothing selected
            # handle reselection or multi-selection (not yet implemented) with other scene obj
            self.handleSelection()


    def handleSelection(self):
        if self.isDragging:
            return

        # First check that the mouse is not outside the screen.
        if base.mouseWatcherNode.hasMouse() and False == self.isCameraControlOn:

            self.grabberColNode.setFromCollideMask(self.defaultBitMask)
            # This gives the screen coordinates of the mouse.
            mPos = base.mouseWatcherNode.getMouse()

            # This makes the ray's origin the camera and makes the ray point
            # to the screen coordinates of the mouse.
            self.colHandlerQueue.clearEntries()
            self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY())
            self.colTraverser.traverse(render)  # look for collisions

            if self.colHandlerQueue.getNumEntries() > 0:
                self.colHandlerQueue.sortEntries()
                grabbedObj = self.colHandlerQueue.getEntry(0).getIntoNodePath()
                if not grabbedObj.findNetTag('pickable').isEmpty():
                    grabbedObj = grabbedObj.findNetTag('pickable')
                    self.selected = grabbedObj
                    self.grabModelNP.setPos(render,
                                            grabbedObj.getPos(render).x,
                                            grabbedObj.getPos(render).y,
                                            grabbedObj.getPos(render).z)
                    self.grabModelNP.show()
                    messenger.accept('mouse3', self, self.handleM3)

    def handleDragging(self, task):
        """ Does the actual work of manipulating objects,
            once the needed attributes have been setup by handleManipulationSetup().
        """

        if not self.isDragging:
            return task.done
        mPos3D = Point3(0.0)
        #
        # This section handles the actual translating rotating or scale after it's been set up in mouse1SetupManip...()
        # ONLY one operation is preformed per frame
        if self.currTransformOperation == self.transformOpEnum.trans:
            # 1st translation, rotation's section is at next elif
            if self.getMousePlaneIntersect(mPos3D, self.currPlaneColNorm):

                # get the difference between the last mouse and this frames mouse
                selectedNewPos = mPos3D - self.interFrameMousePosition
                # store this frames mouse
                self.interFrameMousePosition = mPos3D
                # add the difference to the selected object's pos
                self.selected.setPos(render, self.selected.getPos(render).x + self.currTransformDir.x * selectedNewPos.x,
                                             self.selected.getPos(render).y + self.currTransformDir.y * selectedNewPos.y,
                                             self.selected.getPos(render).z + self.currTransformDir.z * selectedNewPos.z)

                self.grabModelNP.setPos(render, self.selected.getPos(render))

        elif self.currTransformOperation == self.transformOpEnum.rot:
            # 2nd rotation, followed finally by scaling
            # if operating on the z-axis, use the y (vertical screen coordinates otherwise use x (horizontal)
            mPos = base.mouseWatcherNode.getMouse()
            #rotMag = 0.0
            if self.currTransformDir == Vec3( 0.0, 0.0, 1.0):
                rotMag = (mPos.x - self.interFrameMousePosition.x) * 1000
            else:
                rotMag = (self.interFrameMousePosition.y - mPos.y) * 1000

            initPos = self.selected.getPos()
            initPar = self.selected.getParent()
            self.selected.wrtReparentTo(render)
            self.selected.setMat(self.selected.getMat() * Mat4.rotateMat(rotMag, self.currTransformDir))
            self.selected.wrtReparentTo(initPar)
            self.selected.setPos(initPos)

            self.interFrameMousePosition = Point3(mPos.x, mPos.y, 0.0)

        elif self.currTransformOperation == self.transformOpEnum.scale:
            # 3rd and final is scaling
            mPos = base.mouseWatcherNode.getMouse()
            # TODO: make dragging away from the object larger and to the object smaller (not simply left right up down)
            # td The problem with this MAY come if negative, mirrored, scaling is implemented.

            # if operating on the z-axis, use the y (vertical screen coordinates otherwise use x (horizontal)
            if self.currTransformDir == Point3( 0.0, 0.0, 1.0):
                sclMag = (mPos.y - self.interFrameMousePosition.y) * 5.5
            elif self.currTransformDir == Point3( 0.0, 1.0, 0.0):
                sclMag = (mPos.x - self.interFrameMousePosition.x) * 5.5
            else:
                sclMag = (self.interFrameMousePosition.x - mPos.x) * 5.5

            # This is the line that prevents scaling past the origin. Flipping the faces doesn't seem to work.
            if -0.0001 < sclMag < 0.0001:
                sclMag = 0.000001

            # create a dummy node to parent to and position such that applying scale to it will scale selected properly
            dummy = self.levitorNP.attachNewNode('dummy')
            initScl = dummy.getScale()
            # Don't forget the parent. Selected needs put back in place
            initPar = self.selected.getParent()
            initPos = self.selected.getPos()
            self.selected.wrtReparentTo(dummy)

            dummy.setScale(initScl.x + sclMag * self.currTransformDir.x,
                           initScl.y + sclMag * self.currTransformDir.y,
                           initScl.z + sclMag * self.currTransformDir.z)

            # reset selected's parent then destroy dummy
            self.selected.wrtReparentTo(initPar)
            self.selected.setPos(initPos)
            dummy.removeNode()
            dummy = None

            self.interFrameMousePosition = Point3( mPos.x, mPos.y, 0.0)
        else:
            self.notify.error("Err: Dragging with invalid curTransformOperation enum in handleDragging")

        return task.cont  # ended by handleM1Up(), the mouse1-up event handler


    def initializeManipVars(self, transformDir, transformOp, mPos3D, planeNormVec=None):
        self.currTransformDir = transformDir
        self.currPlaneColNorm = planeNormVec  # set the norm for the collision plane to be used in mouse1Dragging
        self.interFrameMousePosition = mPos3D
        self.currTransformOperation = transformOp
        self.isDragging = True
        taskMgr.add(self.handleDragging, 'mouse1Dragging')
        messenger.accept('mouse1-up', self, self.handleM1Up)


    def getMousePlaneIntersect(self, mPos3Dref, normVec):
        mPos = base.mouseWatcherNode.getMouse()
        plane = Plane(normVec, self.grabModelNP.getPos())
        nearPoint = Point3()
        farPoint = Point3()
        base.camLens.extrude(mPos, nearPoint, farPoint)
        if plane.intersectsLine(mPos3Dref,
            render.getRelativePoint(camera, nearPoint),
            render.getRelativePoint(camera, farPoint)):
            return True
        return False



    def destroy(self):
        raise NotImplementedError('Make sure messenger etc are cleared of refs and the model node is deleted')
        self.grabModelNP.clearPythonTag('grabberRoot')
        self.grabModelNP.clearPythonTag('grabber')
        self.grabModelNP = None
        messenger.ignoreAll(self)
예제 #28
0
class CameraManager():
  ZOOM_SPEED = 50

  CAM_X = 'camX'
  CAM_Y = 'camY'
  CAM_Z = 'camZ'

  def __init__(self, showBase, camDict):
    self.showBase = showBase
    self.showBase.disableMouse()
    self.setSettings(camDict)
    self.initMouseToWorldCoordConversion()
    self.initMouseRayCollision()
    self.savedCollisionPoint = Vec3(0, 0, 0)
  # End
  
  """ init helpers """
  def setSettings(self, camDict):
    cam = self.showBase.camera
    cam.setPos(50, 0, -1000)
    self.camPos = cam.getPos()
    cam.setHpr(0, 90, 0)
    self.showBase.camLens.setFov(10)
    self.dragging = False
    self.loadSettings(camDict)
    
    
  
  def initMouseRayCollision(self):
    z = 0
    self.plane = Plane(Vec3(0, 0, 1), Point3(0, 0, z))

  def initMouseToWorldCoordConversion(self):
    self.picker = CollisionTraverser()
    self.pq = CollisionHandlerQueue()

    self.pickerNode = CollisionNode('mouseRay')
    self.pickerNP = self.showBase.camera.attachNewNode(self.pickerNode)

    self.pickerNode.setFromCollideMask(BitMask32.bit(1))
    self.pickerRay = CollisionRay()

    self.pickerNode.addSolid(self.pickerRay)
    self.picker.addCollider(self.pickerNP, self.pq)
  
  
  """ Events """
  def zoomIn(self):
    camera = self.showBase.camera
    curPos = camera.getPos()
    curPos.z += CameraManager.ZOOM_SPEED

    camera.setPos(curPos)
    self.saveSettings(self.camDict)

  def zoomOut(self):
    camera = self.showBase.camera
    curPos = camera.getPos()
    curPos.z += -CameraManager.ZOOM_SPEED

    camera.setPos(curPos)
    self.saveSettings(self.camDict)

  def mouse1Down(self):
    self.savedCollisionPoint = self.getMouseCollisionToPlane(self.plane)
    # print("mouse1Down")
    
  def mouseMove(self, task):
    collisionPoint = self.getMouseCollisionToPlane(self.plane)
    delta = self.getDelta(collisionPoint, self.savedCollisionPoint)

    self.addToCameraPos(delta) # Collision point changes if camera position changes

    collisionPoint = self.getMouseCollisionToPlane(self.plane)
    self.savedCollisionPoint = collisionPoint
    return Task.cont


  """ mouse1Down and mouseMove helpers """
  def getMouseCollisionToPlane(self, plane):
    mouseWatcherNode = self.showBase.mouseWatcherNode
    if mouseWatcherNode.hasMouse():
      mpos = mouseWatcherNode.getMouse()

      pos3d = Point3()
      nearPoint = Point3()
      farPoint = Point3()
      self.showBase.camLens.extrude(mpos, nearPoint, farPoint)

      render = self.showBase.render
      camera = self.showBase.camera
      if plane.intersectsLine(pos3d,
        render.getRelativePoint(camera, nearPoint),
        render.getRelativePoint(camera, farPoint)):
        return pos3d
    return None
  
  
  
  """ mouseMove helpers """
  def getDelta(self, point1, point2):
    delta = Vec3()
    if point1 is not None:
      if point1.almostEqual(point2) is False:
        delta = point2 - point1
    return delta

  def addToCameraPos(self, delta):
    camera = self.showBase.camera
    curPos = camera.getPos()
    camera.setPos(curPos + delta)

    self.saveSettings(self.camDict)

  def setViewBasedOnNodePos(self, pos):
    camera = self.showBase.camera
    newPos = Vec3(camera.getPos())
    newPos.x = pos.x
    newPos.y = pos.y
    camera.setPos(newPos)
    
  # NodePath datection is manage internally in Panda3D, NodeManager should have been
  # managing NodePath, but it can be handled by communication with Camera and 
  # Panda3D already, so NodeManager is not needed anymore here
  # TODO: Refactor
  def getClickedNodePath(self):
    mouseWatcherNode = self.showBase.mouseWatcherNode
    if mouseWatcherNode.hasMouse():
      mpos = mouseWatcherNode.getMouse()
      
      self.pickerRay.setFromLens(self.showBase.camNode, mpos.getX(), mpos.getY())
      
      self.picker.traverse(self.showBase.render)
      
      if self.pq.getNumEntries() > 0:
        self.pq.sortEntries()
        return self.pq.getEntry(0).getIntoNodePath()
    return None

  def getCoordinates(self):
    mouseWatcherNode = self.showBase.mouseWatcherNode
    mpos = mouseWatcherNode.getMouse()

    self.pickerRay.setFromLens(self.showBase.camNode, 
      mpos.getX(), mpos.getY())

    render = self.showBase.render
    camera = self.showBase.camera
    nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin())

    return mpos, nearPoint

  def saveSettings(self, camDict):
    self.camDict = camDict
    cam = self.showBase.camera
    pos = cam.getPos()

    camDict[CameraManager.CAM_X] = pos.x
    camDict[CameraManager.CAM_Y] = pos.y
    camDict[CameraManager.CAM_Z] = pos.z

  def loadSettings(self, camDict):
    self.camDict = camDict
    if camDict is None:
      self.camDict = {}
    if camDict.get(CameraManager.CAM_X) is not None:
      camera = self.showBase.camera
      camera.setPos(camDict[CameraManager.CAM_X], 
        camDict[CameraManager.CAM_Y], 
        camDict[CameraManager.CAM_Z])
    


  def showValues(self):
    print("camera pos " + str(self.showBase.camera.getPos()))
    print("camera hpr " + str(self.showBase.camera.getHpr()))
    print("camera x " + str(self.showBase.camera.getX()))
    print("camera y " + str(self.showBase.camera.getY()))
    print("camera z " + str(self.showBase.camera.getZ()))
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
예제 #29
0
class World(DirectObject):
	def __init__(self, mode, ip=None):
		
		if mode==CLIENT and not ip:
			#Don't let this happen.
			print "WTF programmer"
			sys.exit()
		
		#current dialog box
		self.d = None
		
		#top-left of screen; contains instructions on how to exit the game.
		self.quitInstructions = OnscreenText(text='Press ESC to exit.', pos=(-1, 0.95), scale=0.05, fg=(1,1,1,1), bg=(0,0,0,0), mayChange=False)
		
		#bottom of screen
		self.turnIndicator = OnscreenText(text='', pos=(0,-0.8), scale=0.1, fg=(1,1,1,1), bg=(0,0,0,0), mayChange=True)
		
		#Saving some values, some default values
		self.mode = mode
		self.player = {SERVER: PIECEWHITE, CLIENT: PIECEBLACK}[self.mode]
		self.ip = ip
		
		#Panda3D, by default, allows for camera control with the mouse.
		base.disableMouse()
		
		self.setupMouse()
		self.setupBoard()
		self.setupCamera()
		self.setupPieces()
		self.setupNetwork()
		self.setupLights()
		
		#some internal state for making clicky moves
		self.hiSq = None
		self.dragOrigin = None
		
		#keyboard, mouse
		self.mouseTask = taskMgr.add(self.tskMouse, 'mouseTask')
		self.accept('mouse1', self.handleClick)
		self.accept('f2', lambda: base.setFrameRateMeter(True))
		self.accept('f3', lambda: base.setFrameRateMeter(False))
		self.accept('escape', sys.exit)
		
		
		#first turn
		self.turn = PIECEWHITE
	
	#### INITIALIZATION ####
	
	def setupBoard(self):
		#We will attach all of the squares to their own root. This way we can do the
		#collision pass just on the sqaures and save the time of checking the rest
		#of the scene
		self.squareRoot = render.attachNewNode("squareRoot")

		#For each square
		self.squares = dict(((i,j), None) for i in range(8) for j in range(8))
		for place in self.squares:
			#Load, parent, color, and position the model (a single square polygon)
			self.squares[place] = loader.loadModel("models/square")
			self.squares[place].reparentTo(self.squareRoot)
			self.squares[place].setPos(SquarePos(place))
			self.squares[place].setColor(SquareColor(place))
			#Set the model itself to be collideable with the ray. If this model was
			#any more complex than a single polygon, you should set up a collision
			#sphere around it instead. But for single polygons this works fine.
			self.squares[place].find("**/polygon").node().setIntoCollideMask(
			  BitMask32.bit(1))
			#Set a tag on the square's node so we can look up what square this is
			#later during the collision pass
			self.squares[place].find("**/polygon").node().setTag('square', ' '.join(map(str,place)))
			self.squares[place].setTransparency(TransparencyAttrib.MAlpha)

	def setupPieces(self):
		#Default dictionaries work decently well as an easy two-dimensional array.
		self.pieces = defaultdict(lambda: None)
		
		#The order of pieces on a chessboard from white's perspective
		pieceOrder = [Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook]
		
		for i in xrange(8):
			#load white pawns
			self.pieces[i, 1] = Pawn((i,1), PIECEWHITE)
			
			#load black pawns
			self.pieces[i, 6] = Pawn((i, 6), PIECEBLACK)
			
			#load white specials
			self.pieces[i, 0] = pieceOrder[i]((i,0), PIECEWHITE)
			
			#load black specials
			self.pieces[i, 7] = pieceOrder[i]((i,7), PIECEBLACK)
		for p in self.pieces.values():
			p.obj.setTransparency(TransparencyAttrib.MAlpha)
	
	# TODO: Notice when the other side disconnects
	def setupNetwork(self):
		if self.mode == CLIENT:
			self.setupClient(self.ip)
		else:
			self.setupServer()
	
	# A lot of the below two methods is boilerplate straight from Panda3D documentation.
	def setupServer(self):
		self.cManager = QueuedConnectionManager()
		self.cListener = QueuedConnectionListener(self.cManager, 0)
		self.cReader = QueuedConnectionReader(self.cManager, 0)
		self.cWriter = ConnectionWriter(self.cManager,0)
		
		self.oppConnection = None
		port = 15905 # Chosen by fair dice roll.
		             # Guaranteed to be random.
		backlog = 1000
		tcpSocket = self.cManager.openTCPServerRendezvous(port, backlog)
		
		self.cListener.addConnection(tcpSocket)
		
		def tskListenerPoll(task):
			if self.cListener.newConnectionAvailable() and not self.oppConnection:
				rendezvous = PointerToConnection()
				addr = NetAddress()
				newCon = PointerToConnection()
				
				if self.cListener.getNewConnection(rendezvous, addr, newCon):
					newConnection = newCon.p()
					print "Received connection from %s" % newConnection.getAddress()
					self.oppConnection = newConnection
					self.cReader.addConnection(newConnection)
					
					#server starts the game
					self.turnIndicator['text'] = 'Your turn!'
					self.showVisibleSquares()
					
					#remove the dialog node from below
					if self.d: self.d.removeNode()
					
					return Task.done
			if not self.d: self.d = DirectDialog(text="Waiting for client to connect...", buttonTextList=[], buttonValueList=[])
			return Task.cont
			
		taskMgr.add(tskListenerPoll, "Poll the connection listener")
		taskMgr.add(self.tskReaderPoll, "Poll the connection reader")
	
	def setupClient(self, ip):
		self.cManager = QueuedConnectionManager()
		self.cReader = QueuedConnectionReader(self.cManager, 0)
		self.cWriter = ConnectionWriter(self.cManager,0)
		
		self.oppConnection = None
		
		port = 15905
		timeout = 3000
		myConnection = self.cManager.openTCPClientConnection(ip, port, timeout)
		if myConnection:
			self.cReader.addConnection(myConnection)
			self.oppConnection = myConnection
			
			taskMgr.add(self.tskReaderPoll, "Poll the connection reader")
			self.showVisibleSquares()
		else:
			self.d = OkDialog(text="Could not connect to server at '%s'" % ip, command=sys.exit)
	
	# Makes sure player gets a decent view of the game board, and *not* of the hidden pieces below the board. Shhhh...
	def setupCamera(self):
		if self.player == PIECEWHITE:
			camera.setPos(0, -13.75, 8)
			camera.lookAt(self.squareRoot)
			camera.setH(0)
		else:
			camera.setPos(0, 13.75, 8)
			camera.lookAt(self.squareRoot)
			camera.setH(180)
	
	# Adds some ambient lights and a directional light
	def setupLights(self):
		#This is one area I know hardly anything about. I really don't know how to get this to behave nicely.
		#The black pieces are hardly distinguishable.
		ambientLight = AmbientLight( "ambientLight" )
		ambientLight.setColor( Vec4(.8, .8, .8, 1) )
		directionalLight = DirectionalLight( "directionalLight" )
		directionalLight.setDirection( Vec3( 0, 45, -45 ) )
		directionalLight.setColor( Vec4( 0.2, 0.2, 0.2, 1 ) )
		render.setLight(render.attachNewNode( directionalLight ) )
		render.setLight(render.attachNewNode( ambientLight ) )
	
	# Sets up collision detection for the mouse cursor.
	def setupMouse(self):
		#Since we are using collision detection to do picking, we set it up like
		#any other collision detection system with a traverser and a handler
		self.picker = CollisionTraverser()            #Make a traverser
		self.pq     = CollisionHandlerQueue()         #Make a handler
		#Make a collision node for our picker ray
		self.pickerNode = CollisionNode('mouseRay')
		#Attach that node to the camera since the ray will need to be positioned
		#relative to it
		self.pickerNP = camera.attachNewNode(self.pickerNode)
		#Everything to be picked will use bit 1. This way if we were doing other
		#collision we could seperate it
		self.pickerNode.setFromCollideMask(BitMask32.bit(1))
		self.pickerRay = CollisionRay()               #Make our ray
		self.pickerNode.addSolid(self.pickerRay)      #Add it to the collision node
		#Register the ray as something that can cause collisions
		self.picker.addCollider(self.pickerNP, self.pq)
	
	#### TASKS ####
	
	# Checks for incoming data on the connection
	def tskReaderPoll(self, task):
		if self.cReader.dataAvailable():
			datagram = NetDatagram()
			if self.cReader.getData(datagram):
				self.receiveData(datagram)
		return Task.cont
	
	# Runs every frame, checks whether the mouse is highlighting something or another
	def tskMouse(self, task):
		#This task deals with the highlighting and dragging based on the mouse
		
		#First, clear the current highlight
		if self.hiSq:
			self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
			self.hiSq = None
			
		#Check to see if we can access the mouse. We need it to do anything else
		if base.mouseWatcherNode.hasMouse():
			#get the mouse position
			mpos = base.mouseWatcherNode.getMouse()
			
			#Set the position of the ray based on the mouse position
			self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
			
			#If we are dragging something, set the position of the object
			#to be at the appropriate point over the plane of the board
			if self.dragOrigin:
				#camera, relative instead to render
				#Gets the point described by pickerRay.getOrigin(), which is relative to
				nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin())
				#Same thing with the direction of the ray
				nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection())
				self.pieces[self.dragOrigin].obj.setPos(
					PointAtZ(.5, nearPoint, nearVec))

			#Do the actual collision pass (Do it only on the squares for
			#efficiency purposes)
			self.picker.traverse(self.squareRoot)
			if self.pq.getNumEntries() > 0:
				#if we have hit something, sort the hits so that the closest
				#is first, and highlight that node
				self.pq.sortEntries()
				p = tuple(map(int, (self.pq.getEntry(0).getIntoNode().getTag('square')).split()))
				
				if self.pieces[p] and self.pieces[p].color == self.turn == self.player and not self.dragOrigin or self.dragOrigin and self.pieces[self.dragOrigin].isValidMove(p, self.pieces):
					#Set the highlight on the picked square
					self.hiSq = p
					self.squares[self.hiSq].setColor(HIGHLIGHT)
			    
		return Task.cont		
	
	def handleClick(self):
		# Disabled when a dialog box is on-screen. Pay attention to what I'm telling you, user!
		if not self.d:
			if self.dragOrigin:
				self.releasePiece()
			else:
				self.grabPiece()
	
	# Comes from handleClick
	def grabPiece(self):
		#If a square is highlighted and it has a piece, set it to dragging mode
		if self.hiSq and self.pieces[self.hiSq] and self.pieces[self.hiSq].color == self.turn:
			self.dragOrigin = self.hiSq
			self.hiSq = None
	
	def releasePiece(self):
		#Letting go of a piece. If we are not on a square, return it to its original
		#position.
		if self.dragOrigin:   #Make sure we really are dragging something
			if self.hiSq and self.hiSq != self.dragOrigin and self.pieces[self.dragOrigin].isValidMove(self.hiSq, self.pieces):
				
				# Verify that this doesn't put the king in check
				# Make backup of the pieces dictionary
				oldPieces = self.pieces.copy()
				
				self.pieces[self.hiSq] = self.pieces[self.dragOrigin]
				self.pieces[self.dragOrigin] = None
				
				if self.inCheck(self.turn):
					self.pieces = oldPieces
					self.pieces[self.dragOrigin].obj.setPos(SquarePos(self.dragOrigin))
					print "Invalid move -- King is in check"
					
					def closeDialog():
						self.d.removeNode()
					self.d = OkDialog(text="That move would put your King in check!", command=closeDialog)
				else:
					self.pieces = oldPieces
					
					self.makeMove(self.dragOrigin, self.hiSq, dt=0, callback=self.showVisibleSquares).start()
					self.sendMove(self.dragOrigin, self.hiSq)
					self.squares[self.dragOrigin].setColor(SquareColor(self.dragOrigin))
					
					#no longer our turn
					self.turnIndicator['text'] = ''
			else:
				self.pieces[self.dragOrigin].obj.setPos(SquarePos(self.dragOrigin))
				print "Invalid move"
			  
		#We are no longer dragging anything
		self.dragOrigin = False
	
	#### CHESS UPDATES ####
	
	# Moves a piece from one space to another.
	# This should be called to update internal state, whether the piece is already in the correct location or not.
	# Also handles captures.
	def makeMove(self, fr, to, dt=1, callback=None):
		print "Making move %s -> %s" % (str(fr), str(to))
		frP = self.pieces[fr]
		toP = self.pieces[to]
		
		if not frP:
			return False
		if toP and frP.color == toP.color:
			return False
		if not frP.isValidMove(to, self.pieces):
			return False
		
		# Callback function for the movement.
		# Updates pieces' internal state, as well as the true state of the board (self.pieces)
		def updateState():
			self.destroy(toP)
			frP.square = to
			frP.haveMoved = True
			self.pieces[fr] = None
			self.pieces[to] = frP
			self.turn = flip[self.turn]
			
			if self.inCheck(self.player):
				def dismiss(val):
					self.d.removeNode()
				self.d = OkDialog(text="You are in check!", command=dismiss)

		s = Sequence(
			frP.obj.posInterval(dt, self.squares[to].getPos()),
			Func(updateState)
		)
		if callback: s.append(Func(callback))
		return s
	
	# Removes the piece. This method is passed a Piece object, not a location!
	# Possible improvements: Particle effects! :D
	def destroy(self, piece):
		if piece:
			piece.obj.removeNode()
		
	# Determines whether the player specified by "color" is in check at the current time
	# Future improvements: Calculate the same thing for possible future moves (i.e. if I move here am I therefore in check?)
	def inCheck(self, color):
		#find the king
		kingPlace = [p for p in self.pieces if self.pieces[p] and self.pieces[p].color == color and self.pieces[p].model == "models/king"][0]
		for p in self.pieces:
			if self.pieces[p] and self.pieces[p].color != color and self.pieces[p].isValidMove(kingPlace, self.pieces):
				return True
		return False

	# Currently unused, but could be useful in an (extremely primitive) AI in the future.
	# I ran out of time to put it in this version.
	def makeRandomMove(self):
		move = None
		while not move:
			chosenPiece = random.choice([(x,y) for (x,y) in self.pieces if 0 <= x < 8 and 0 <= y < 8 and self.pieces[x,y] and self.pieces[x,y].color == self.turn])
			if not self.pieces[chosenPiece].validMoves(self.pieces):
				continue
			destSquare = random.choice([s for s in self.pieces[chosenPiece].validMoves(self.pieces)])
			move = (chosenPiece, destSquare)
		self.makeMove(*move).start()
	
	#### VISIBILITY UPDATES ####
	
	def isVisible(self, sq):
		return self.squares[sq].getColorScale()[3] == 1.0
		
	# The next two methods deal with hiding and showing the squares of the board.
	def hideSquare(self, sq, dt="default", callback=None):
			
		if self.squares[sq] and self.isVisible(sq):
			if dt == "default": dt = 1.0
			
			par = Parallel(
				LerpFunctionInterval(self.squares[sq].setAlphaScale, toData=0.0, fromData=1.0, duration=dt),
			)
			if self.pieces[sq]:
				par.append(LerpFunctionInterval(self.pieces[sq].obj.setAlphaScale, toData=0.0, fromData=1.0, duration=dt))
			s = Sequence(par)
			if callback: s.append(Func(callback))
			return s
		else:
			s = Sequence()
			if callback: s.append(Func(callback))
			return s
	
	def showSquare(self, sq, dt="default", callback=None):
			
		if self.squares[sq] and not self.isVisible(sq):
			if dt == "default": dt = 1.0
			
			par = Parallel(
				LerpFunctionInterval(self.squares[sq].setAlphaScale, toData=1.0, fromData=0.0, duration=dt),
			)
			if self.pieces[sq]:
				par.append(LerpFunctionInterval(self.pieces[sq].obj.setAlphaScale, toData=1.0, fromData=0.0, duration=dt))
			s = Sequence(par)
			if callback: s.append(Func(callback))
			return s
		else:
			s = Sequence()
			if callback: s.append(Func(callback))
			return s

	# Shows the path that a piece takes on its way IF any part of it is visible to the current player
	def showPathIfVisible(self, fr, to):
		if self.pieces[fr]:
			path = set()
			showSquareSequences = Parallel()
			if self.pieces[fr]:
				path.update(self.pieces[fr].path(to))
			if any(self.isVisible(sq) for sq in path):
				for sq in path:
					showSquareSequences.append(self.showSquare(sq))
			return showSquareSequences
		else:
			return Parallel()
	# Shows the path that a piece takes on its path from its origin to its destination
	def showPath(self, fr, to):
		path = set()
		showSquareSequences = Parallel()
		if self.pieces[fr]:
			path.update(self.pieces[fr].path(to))
		for sq in path:
			showSquareSequences.append(self.showSquare(sq))
		return showSquareSequences
	
	# Updates the board to show only the squares that are visible at the current time.
	def showVisibleSquares(self, dt="default"):
		visibles = defaultdict(lambda: False)
		for p in [(x,y) for (x,y) in self.pieces if 0 <= x < 8 and 0 <= y < 8]:
			if self.pieces[p]:
				if self.pieces[p].color == self.player:
					for s in self.pieces[p].visibleSquares(self.pieces):
						visibles[s] = True

		par = Parallel()
		for s in self.squares:
			if visibles[s]:
				par.append(self.showSquare(s, dt))
			else:
				par.append(self.hideSquare(s, dt))
		par.start()
		return par
	
	#### NETWORK I/O ####
	def sendMove(self, fr, to):
		dg = PyDatagram()
		dg.addUint8(fr[0])
		dg.addUint8(fr[1])
		dg.addUint8(to[0])
		dg.addUint8(to[1])
		
		print "Sent move (%d, %d) -> (%d, %d)" % (fr[0], fr[1], to[0], to[1])
		self.cWriter.send(dg, self.oppConnection)
	
	def receiveData(self, dg):
		dg = PyDatagramIterator(dg)
		fr = (dg.getUint8(), dg.getUint8())
		to = (dg.getUint8(), dg.getUint8())
		print "Received move %s -> %s" % (fr, to)

		def indicate():
			self.turnIndicator['text'] = 'Your turn!'
			self.sfx = loader.loadSfx('audio/ding.wav')
			self.sfx.play()

		seq = Sequence()
		seq.append(self.showPathIfVisible(fr, to))
		seq.append(self.makeMove(fr, to))
		seq.append(Func(indicate))
		seq.append(Func(self.showVisibleSquares))

		seq.start()
class SmartCamera:
    UPDATE_TASK_NAME = 'update_smartcamera'
    notify = directNotify.newCategory('SmartCamera')

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

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

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

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

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

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

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

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

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

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

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

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

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

    def get_default_pos(self):
        return self.default_pos

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

    def get_parent(self):
        return self.parent

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def handleCameraFloorInteraction(self):
        self.putCameraFloorRayOnCamera()
        self.ccTravFloor.traverse(self.__geom)
        if self.__onLevelGround:
            return
        if self.camFloorCollisionQueue.getNumEntries() == 0:
            return
        self.camFloorCollisionQueue.sortEntries()
        camObstrCollisionEntry = self.camFloorCollisionQueue.getEntry(0)
        camHeightFromFloor = camObstrCollisionEntry.getSurfacePoint(self.ccRayNodePath)[2]
        self.cameraZOffset = camera.getPos()[2] + camHeightFromFloor
        if self.cameraZOffset < 0:
            self.cameraZOffset = 0
        if self.__floorDetected == 0:
            self.__floorDetected = 1
            self.popCameraToDest()
예제 #31
0
파일: picker.py 프로젝트: jhamrick/scenesim
class Picker(Viewer):
    """ View and click objects in a scene."""

    def __init__(self):
        # Parent init.
        super(Picker, self).__init__()
        self.disableMouse()
        # Picker stuff.
        self.contact_margin = Vec3(0.01, 0.01, 0.01)
        self.parser = None
        self.marked = None
        self.attached_pairs = set()
        self.contacts = None
        self.contact_points = None
        self.contact_bottoms = None
        self.compound_components = []
        self.compound_objects = []
        self.joints = JointManager()
        self.wire_attrib = RenderModeAttrib.make(
            RenderModeAttrib.MWireframe, 4.)
        self.attachment_colors = (Vec4(0.1, 0.1, 1., 1.),
                                  Vec4(0.1, 0.8, 0.1, 1.),
                                  Vec4(1., 0.1, 1., 1.),
                                  Vec4(1., 0.5, 0.1, 1.),
                                  Vec4(1., 1., 1., 1.))
        self.max_attach = 999
        self.permanent_events += ["mouse1"]
        # Make cursor dot.
        self.cursor = self._build_cursor("cross")
        s = 0.08
        self.cursor.setScale(s, s, s)
        self.cursor.setColor(1, 1, 1, 1)
        self.cursor.reparentTo(self.aspect2d)
        self.taskMgr.add(self.draw_cursor2d, "draw_cursor2d")
        self.permanent_tasks.append("draw_cursor2d")

    def init_ssos(self, *args, **kwargs):
        super(Picker, self).init_ssos(*args, **kwargs)

    def init_physics(self, *args, **kwargs):
        super(Picker, self).init_physics(*args, **kwargs)
        self.joints.bbase = self.bbase

    def init_picker(self):
        # Collision traverser
        self.traverser = CollisionTraverser("traverser")
        # Collision handler
        self.handler = CollisionHandlerQueue()
        # Initialize and set up picker ray node and NodePath
        self.picker = CollisionNode("mouse_ray")
        self.pickerNP = self.camera.attachNewNode(self.picker)
        self.picker.setFromCollideMask(GeomNode.getDefaultCollideMask())
        self.picker_ray = CollisionRay()
        self.picker.addSolid(self.picker_ray)
        self.traverser.addCollider(self.pickerNP, self.handler)
        mark_color = (1, 1, 1, 0.3)
        self.base_mark = self.create_mark(color=mark_color)
        connector_color = (1, 1, 1, 1)
        self.base_connector = self.create_connector(color=connector_color)

    def _build_cursor(self, shape="sphere"):
        if shape == "sphere":
            cursor = self._load("sphere.bam")
        elif shape == "cross":
            cursor = LineNodePath()
            lines = [[Point3(-0.5, 0, 0), Point3(0.5, 0, 0)],
                     [Point3(0, 0, -0.5), Point3(0, 0, 0.5)]]
            cursor.drawLines(lines)
            cursor.setThickness(1)
            cursor.create()
            # cursor = NodePath("cross")
            # S = {"cylinderX.bam": ((0., 0., 0.), (1., 0.1, 0.1)),
            #      "cylinderY.bam": ((0., 0., 0.), (0.1, 1., 0.1)),
            #      "cylinderZ.bam": ((0., 0., 0.), (0.1, 0.1, 1.))}
            # for k, v in S.iteritems():
            #     m = self._load(k)
            #     m.setName(k)
            #     m.setPos(*v[0])
            #     m.setScale(*v[1])
            #     m.reparentTo(cursor)
        #BP()
        return cursor

    def create_mark(self, color):
        """ Makes a graphical mark object."""
        # Make a graphical box.
        props = dict(name="mark", color=color, model="box-round.egg")
        obj = GSO(props=props)
        return obj

    def create_connector(self, color):
        """ Makes a graphical connector object."""
        # Make a graphical box.
        props = dict(name="connector", color=color, model="connector.egg")
        obj = GSO(props=props)
        return obj

    def start_picker(self, pickables):
        # Set pickable objs.
        for i, obj in enumerate(pickables):
            obj.setTag("pickable", str(i))
        # Add mouse events.
        self.accept("mouse1", self.clicked, extraArgs=[1])
        # Start contact detector.
        detector = ContactDetector(self.bbase.world, self.scene,
                                   margin=self.contact_margin)
        self.contacts = detector.contacts
        self.contact_bodies = detector.bodies
        self.contact_points = detector.points
        parser = Parser(self.contacts, self.contact_bodies)
        self.contact_bottoms = parser.bottom_bodies
        self.connectors = {}

    def stop_picker(self):
        self.removeTask("mouse1")

    def goto_sso(self, *args, **kwargs):
        self.clear_attachments()
        self.stop_picker()
        super(Picker, self).goto_sso(*args, **kwargs)
        self.remove_physics()
        # Start picker.
        pickables = self.sso.descendants(type_=PSO)
        self.start_picker(pickables)
        self.attach_physics()

    def get_picked_obj(self):
        mpos = self.mouseWatcherNode.getMouse()
        self.picker_ray.setFromLens(self.cam.node(), mpos.getX(), mpos.getY())
        self.traverser.traverse(self.render)
        if self.handler.getNumEntries() > 0:
            # This is so we get the closest object
            self.handler.sortEntries()
            entries = self.handler.getEntries()
            for entry in entries:
                picked_obj = entry.getIntoNodePath().findNetTag("pickable")
                if not picked_obj.isEmpty():
                    break
            if picked_obj.isEmpty():
                picked_obj = None
        else:
            picked_obj = None
        return picked_obj

    def clicked(self, button):
        """ Mouse click handler."""
        if self.mouseWatcherNode.hasMouse():
            # Get picked object
            picked_obj = self.get_picked_obj()
            if picked_obj is not None:
                if self.marked is None:
                    # New mark activated.
                    self.marked = picked_obj
                    self.show_marked(picked_obj, True)
                    event = "mark"
                elif picked_obj == self.marked:
                    # Existing mark deactivated.
                    self.show_marked(picked_obj, False)
                    self.marked = None
                    event = "unmark"
                else:
                    # New attachment or detachment.
                    pair = tuple(sorted((self.marked, picked_obj)))
                    ij = tuple(sorted((self.contact_bodies.index(pair[0]),
                                       self.contact_bodies.index(pair[1]))))
                    if ij in self.contacts:
                        f_add = (ij, pair) not in self.attached_pairs
                        if (not f_add or len(self.attached_pairs) <
                            self.max_attach):
                            self.store_attachment(ij, pair, f_add)
                            self.show_marked(self.marked, False)
                            self.marked = None
                            event = "attach" if f_add else "detach"
                        else:
                            print("Max attachments already reached.")
                            event = "max-attach"
                    else:
                        event = "non-contact"
            else:
                event = "non-pick"
            return picked_obj, event

    def store_attachment(self, ij, pair, f_add):
        """ Stores the attached objects, and draws them."""
        if f_add:
            self.attached_pairs.add((ij, pair))
            self.show_attachment(ij, True)
            self.attach_pair(pair, True)
        else:
            try:
                self.attached_pairs.remove((ij, pair))
            except KeyError:
                pass
            else:
                self.attach_pair(pair, False)
                self.show_attachment(ij, False)

    def clear_attachments(self):
        """ Clear all attachments."""
        if self.marked:
            self.show_marked(self.marked, False)
            self.marked = None
            self.mark = None
        for ij, pair in self.attached_pairs:
            self.attach_pair(pair, False)
            self.show_attachment(ij, False)
        self.attached_pairs = set()
        #
        self.reset_compounds()
        self.contacts = None
        self.contact_bodies = None
        self.contact_points = None
        self.contact_bottoms = None

    def _make_mark(self, node, extent, name):
        """ Makes a mark GSO."""
        mark = self.base_mark.copy()
        mat = node.getMat(self.scene)
        mark.apply_prop(dict(name=name), other=self.scene)
        mark.setMat(self.scene, mat)
        mark.setScale(self.scene, mark.getScale(self.scene) + extent)
        mark.wrtReparentTo(node)
        return mark

    def show_marked(self, node, f_on):
        """ Turns on/off marked graphic."""
        if f_on:
            extent = Vec3(0.15, 0.15, 0.15)
            name = "mark"
            self.mark = self._make_mark(node, extent, name)
            self.mark.init_tree(tags=("model",))
            # Exclude object from casting shadows
            self.mark.hide(self.shadow_mask)
            self.mark.setTransparency(TransparencyAttrib.MAlpha)
            self.mark.setDepthWrite(False)
            self.mark.setBin("fixed", 0, priority=5)
        else:
            self.mark.removeNode()

    def _make_connector(self, parent, points, extent, name):
        """ Makes connector object."""
        connector = self.base_connector.copy()
        scale = Vec3(*(np.ptp(points, axis=0)))
        scale_extended = scale + extent
        pos = Point3(*(np.min(points, axis=0) + scale / 2.))
        connector.apply_prop(dict(name=name, scale=scale_extended, pos=pos),
                             other=self.scene)
        connector.wrtReparentTo(parent)
        return connector

    def show_attachment(self, ij, f_on):
        """ Turns on/off attachment graphic."""
        if f_on:
            parent = self.contact_bottoms[ij]
            points = self.contact_points[ij]
            extent = Vec3(0.15, 0.15, 0.15)
            name = "connector_%d-%d" % ij
            self.connectors[ij] = self._make_connector(parent, points,
                                                       extent, name)
            self.connectors[ij].init_tree(tags=("model",))
        else:
            self.connectors.pop(ij).removeNode()

    # def attach_pair(self, pair, f_on):
    #     """ Adds/removes physical attachment between a pair of nodes."""
    #     key = tuple(sorted(p.node() for p in pair))
    #     # key = frozenset(pair)
    #     if f_on:
    #         # Create the joint and add it.
    #         self.joints[key] = self.joints.make_fixed(*pair)
    #     else:
    #         # Remove it.
    #         del self.joints[key]

    def attach_physics(self):
        # Attach `self.scene` to the physics world.
        try:
            exclude = zip(*self.compound_components)[0]
        except IndexError:
            exclude = []
        bnodes = [bnode for bnode in self.scene.descendants(type_=PSO)
                  if bnode not in exclude]
        for bnode in bnodes:
            bnode.init_resources(tags=("shape",))
            bnode.setCollideMask(BitMask32.allOn())
            bnode.node().setDeactivationEnabled(False)
        self.bbase.attach(bnodes)

    def reset_compounds(self):
        for n, p in self.compound_components:
            n.wrtReparentTo(p)
        self.compound_components = []
        for cnode in self.compound_objects:
            cnode.destroy_resources()
            cnode.removeNode()
        self.compound_objects = []

    def make_attachment_graph(self):
        if not self.contact_bodies:
            return None
        n = len(self.contact_bodies)
        mtx = np.zeros((n, n), dtype="i")
        for (i, j), _ in self.attached_pairs:
            # i = self.contact_bodies.index(pair[0])
            # j = self.contact_bodies.index(pair[1])
            mtx[i, j] = 1
            # mtx[j, i] = 1
        graph = nx.from_numpy_matrix(mtx)
        return graph

    def attach_pair(self, pair, f_on):
        """ Adds/removes physical attachment between a pair of nodes."""
        # Get the connected subgroups.
        graph = self.make_attachment_graph()
        sgs = [sg for sg in nx.connected_components(graph) if len(sg) > 1]
        self.reset_compounds()
        # Iterate over subgroups, creating compound shapes.
        for sg in sgs:
            nodes = [self.contact_bodies[i] for i in sg]
            parents = [c.getParent() for c in nodes]
            self.compound_components.extend(zip(nodes, parents))
            cname = "+".join([str(i) for i in sorted(sg)])
            cnode = CPSO(cname)
            cnode.reparentTo(self.scene)
            cnode.add(nodes)
            cnode.init_tree(tags=("shape",))
            cnode.destroy_component_shapes()
            self.compound_objects.append(cnode)
예제 #32
0
class World(DirectObject):
  mySound = base.loader.loadSfx("trial.mp3")
#Used for adding a virus at a randomly generated position 
  def random_vgen(self):
    print 'I am in random'
    for i in range(0,5):
      
      self.a[random.randint(0,7)][random.randint(0,7)] = 1
  

  def initializer(self,level):
    
  
    self.turns = 0
      
##   Level Definition 
    
    def levelone():
        self.a[4][4] = 1
        self.a[4][5] = 1
        self.a[4][6] = 1
        self.a[5][2] = 1
        self.a[3][5] = 1
        self.a[4][6] = 1
        self.a[5][5] = 1
    def leveltwo():
        self.a[4][3] = 1
        self.a[4][5] = 1
        self.a[4][7] = 1
        self.a[5][2] = 1
        self.a[3][5] = 1
        self.a[2][2] = 1
        self.a[5][3] = 1
        self.a[1][2] = 1

    def levelthree():
        self.a[4][4] = 1
        self.a[4][5] = 1
        self.a[4][6] = 1
        self.a[5][2] = 1
        self.a[3][5] = 1
        self.a[4][6] = 1
        self.a[5][5] = 1
        self.a[4][3] = 1
        self.a[4][5] = 1
        self.a[4][7] = 1
        self.a[5][2] = 1
        self.a[3][5] = 1
        self.a[2][2] = 1
        self.a[5][3] = 1


    options = {1: levelone,
               2: leveltwo,
               3: levelthree
            
            }

    options[level]()
    
    print self.a
    temp = []
    count = 0
    for element in reversed(self.a):
        for ele in element:
            #print 'cheking element is 1 : ' + str(ele)
            if ele == 1:
                temp.append(count)
                self.pieces[count] = Monster(count,WHITE)
                #self.squares[count].setColor(HIGHLIGHT)
            count = count + 1
    self.list=temp
    
  def showscore(self):
        try:
            self.score.destroy()
        except:
            pass
        self.score = OnscreenText(text = 'Number of Turns : %s'%(self.turns), pos = (0.5, 0.95), scale = 0.07, mayChange = True)
  def menuscreen(self):
      
      # Callback function to set  text
    def setText():
        b.destroy()
        helptext.destroy()
        
    
    # Add button
    b = DirectButton(text = ("START", "START", "START", "disabled"), scale=0.15, command=setText, pos=(0,0,0.85))

    helptext = OnscreenText(text ='''
    STORY:
    Hello Mad Scientist!
    You are so close to finding the cure to aids!
    You understood the behaviour and can finally manipulate the virus to kill itself!
    But time is running out!
    You have a red and white blood cell sample infected with AIDS Virus.

    INSTRUCTIONS:
    The AIDS Virus obeys the Conway's Game of Life. Who would have guessed?
    1.  If virus is surrounded by more than 3 viruses, it dies of suffocation
    2.  If virus is surrounded by less than 2 viruses, it dies of underpopulation
    3.  If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned due to breeding.

    AIM:
    To kill all the viruses, by moving one of them every turn.

    ''', pos = (-0.90,0.72),frame = (123,123,123,1), wordwrap = 25, align = TextNode.ALeft, bg = (0.23,0.243,0.13,0.9))

  def endscreen(self):     
    def restart():
        taskMgr.remove(self.mouseTask)
        for i in range(64):
            self.squares[i].setColor(SquareColor(i))
        scorecard.destroy()
        restartb.destroy()
        end.destroy()
        nextlevelb.destroy()
        self.reference.destroy()
        self.mySound.stop()
        try:            
            self.score.destroy()
        except:
            pass
        print 'restarting'
        print self.a
        print self.list
  
            
        World()
        
    def quitgame():
        sys.exit()

    def nextLevel():
        self.currlevel = self.currlevel + 1
        nextlevelb.destroy()
        scorecard.destroy()
        restartb.destroy()
        end.destroy()
        self.score.destroy()
        self.initializer(self.currlevel)

    

    # Add button

    scorecard = OnscreenText(text = 'You finished it in %s turns! '%(self.turns),frame = (123,123,123,0), wordwrap = 25, bg = (0.2,0,0.8,1))

    nextlevelb = DirectButton(text = ("NEXT LEVEL", "NEXT LEVEL", "NEXT LEVEL", "disabled"), scale=0.15, command=nextLevel, pos=(0,0,-0.15))
    restartb = DirectButton(text = ("RESTART", "RESTART", "RESTART", "disabled"), scale=0.15, command=restart, pos=(0,0,-0.35))
    end = DirectButton(text = ("QUIT", "QUIT", "QUIT", "disabled"), scale=0.15, command=quitgame, pos=(0,0,-0.55))
    if self.currlevel == self.maxlevel:
      nextlevelb.destroy()


  def __init__(self):
    #music
    
    
    self.mySound.play()
      

    print 'I am being initialized'
    
          
    self.menuscreen()
    self.list = []
    self.turns = 0
    self.maxlevel = 3
    self.currlevel = 1
    self.a =[[0 for x in range(8)] for y in range(8)]
    
    
        
    #This code puts the standard title and instruction text on screen
    self.title = OnscreenText(text="Game of Life : Help in ending AIDS!",
                              style=1, fg=(1,1,1,1),
                              pos=(0,-0.95), scale = .07)
    self.escapeEvent = OnscreenText( 
      text="ESC: Quit",
      style=1, fg=(1,1,1,1), pos=(-1.3, 0.95),
      align=TextNode.ALeft, scale = .05)
##    self.mouse1Event = OnscreenText(
##      text="Left-click and drag: Pick up virus and drag it to a new bloodcell",
##      style=1, fg=(1,1,1,1), pos=(-1.3, 0.90),
##      align=TextNode.ALeft, scale = .05)
##    
    
        
    
    self.accept('escape', sys.exit)              #Escape quits
    
    base.disableMouse()                          #Disble mouse camera control
    camera.setPosHpr(0, -13.75, 6, 0, -25, 0)    #Set the camera
    self.setupLights()                           #Setup default lighting
    
    #Since we are using collision detection to do picking, we set it up like
    #any other collision detection system with a traverser and a handler
    self.picker = CollisionTraverser()            #Make a traverser
    self.pq     = CollisionHandlerQueue()         #Make a handler
    #Make a collision node for our picker ray
    self.pickerNode = CollisionNode('mouseRay')
    #Attach that node to the camera since the ray will need to be positioned
    #relative to it
    self.pickerNP = camera.attachNewNode(self.pickerNode)
    #Everything to be picked will use bit 1. This way if we were doing other
    #collision we could seperate it
    self.pickerNode.setFromCollideMask(BitMask32.bit(1))
    self.pickerRay = CollisionRay()               #Make our ray
    self.pickerNode.addSolid(self.pickerRay)      #Add it to the collision node
    #Register the ray as something that can cause collisions
    self.picker.addCollider(self.pickerNP, self.pq)
    #self.picker.showCollisions(render)

    #We will attach all of the squares to their own root. This way we can do the
    #collision pass just on the sqaures and save the time of checking the rest
    #of the scene
    self.squareRoot = render.attachNewNode("squareRoot")
    
    #For each square
    self.squares = [None for i in range(64)]
    self.pieces = [None for i in range(64)]

    
    for i in range(64):
      #Load, parent, color, and position the model (a single square polygon)
      self.squares[i] = loader.loadModel("models/square")
      self.squares[i].reparentTo(self.squareRoot)
      self.squares[i].setPos(SquarePos1(i))
      self.squares[i].setColor(SquareColor(i))
      #Set the model itself to be collideable with the ray. If this model was
      #any more complex than a single polygon, you should set up a collision
      #sphere around it instead. But for single polygons this works fine.
      self.squares[i].find("**/polygon").node().setIntoCollideMask(
        BitMask32.bit(1))
      #Set a tag on the square's node so we can look up what square this is
      #later during the collision pass
      self.squares[i].find("**/polygon").node().setTag('square', str(i))

      #We will use this variable as a pointer to whatever piece is currently
      #in this square

    
    self.initializer(self.currlevel)
    
    
          

    

    #This will represent the index of the currently highlited square
    self.hiSq = False
    #This wil represent the index of the square where currently dragged piece
    #was grabbed from
    self.dragging = False

    #Start the task that handles the picking
    self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
    #self.trial = taskMgr.add(self.trial,'trial')
    self.accept("mouse1", self.grabPiece)       #left-click grabs a piece
    self.accept("mouse1-up", self.releasePiece) #releasing places it
    
   

  #This function swaps the positions of two pieces
  def swapPieces(self, fr, to):
    temp = self.pieces[fr]
    self.pieces[fr] = self.pieces[to]
    self.pieces[to] = temp
    if self.pieces[fr]:
      print 'imma swapping'  
      self.pieces[fr].square = fr
      print fr
      print SquarePos(fr)
      try:
          self.pieces[fr].obj.setPos(SquarePos(fr))
      except:
          pass
      print 'done'
    if self.pieces[to]:
      self.pieces[to].square = to
      try:
          self.pieces[to].obj.setPos(SquarePos(to))
      except:
          pass
  def trial(self):
      self.turns = self.turns + 1
      try:
        self.reference.destroy()
      except:
        pass
      self.reference = OnscreenText( 
      text='''
Reference:
virus is surrounded by more than 3 viruses, it dies
virus is surrounded by less than 2 viruses, it dies
If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned.
'''  ,
      style=1, fg=(1,1,1,1), pos=(-1, 0.95),
      align=TextNode.ALeft, scale = .05)
      
      
      self.showscore()
      a = self.a
      while True:
          for i in self.list:
              #insert deletion code
              print 'imma deleting the sq : ' + str(i)
              self.pieces[i].obj.delete()
              
              self.squares[i].setColor(SquareColor(i))
          count = 0
          a=[[([[sum(b[y1][x1] for b in [[[((-1<x2+dx<len(a[0])) and (-1<y2+dy<len(a))) and a[y2+dy][x2+dx] or 0 for x2 in range(len(a[0]))] for y2 in range(len(a))] for (dx,dy) in [(dx,dy) for dx in [-1,0,1] for dy in [-1,0,1] if (dy!=0 or dx!=0)]]) for x1 in range(len(a[0]))] for y1 in range(len(a))][y][x]== 3 or ([[sum(c[y3][x3] for c in [[[((-1<x4+dx<len(a[0])) and (-1<y4+dy<len(a))) and a[y4+dy][x4+dx] or 0 for x4 in range(len(a[0]))] for y4 in range(len(a))] for (dx,dy) in [(dx,dy) for dx in [-1,0,1] for dy in [-1,0,1] if (dy!=0 or dx!=0)]]) for x3 in range(len(a[0]))] for y3 in range(len(a))][y][x] == 2 and a[y][x]==1)) and 1 or 0 for x in range(len(a[0]))] for y in range(len(a))]
          lis = []
          #insert a random virus at a probability of 1/5
          diceroll = random.randint(0,5)
          if diceroll == 2:
            
            self.random_vgen()
          for element in reversed(a):
              
              for ele in element:
                  #print 'cheking element is 1 : ' + str(ele)
                  if ele == 1:
                      lis.append(count)
                  count = count + 1
          print lis  
          self.list = lis
          
          self.a = a
          print self.list
          
          for i in self.list:
              self.pieces[i] = Monster(i,WHITE)
              #self.squares[i].setColor(HIGHLIGHT)
          print 'leaving trial'  
          if len(self.list)==0:
              self.endscreen()
          break
        
      return
  def mouseTask(self, task):
    #This task deals with the highlighting and dragging based on the mouse
    
    #First, clear the current highlight
    if self.hiSq is not False:
      self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
      self.hiSq = False
      
    #Check to see if we can access the mouse. We need it to do anything else
    if base.mouseWatcherNode.hasMouse():
      #get the mouse position
      mpos = base.mouseWatcherNode.getMouse()
      
      #Set the position of the ray based on the mouse position
      self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
      
      #If we are dragging something, set the position of the object
      #to be at the appropriate point over the plane of the board
      if self.dragging is not False:
        #Gets the point described by pickerRay.getOrigin(), which is relative to
        #camera, relative instead to render
        nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin())
        #Same thing with the direction of the ray
        nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection())
        try:
            self.pieces[self.dragging].obj.setPos(PointAtZ(.5, nearPoint, nearVec))
        except:
            pass
      #Do the actual collision pass (Do it only on the squares for
      #efficiency purposes)
      self.picker.traverse(self.squareRoot)
      if self.pq.getNumEntries() > 0:
        #if we have hit something, sort the hits so that the closest
        #is first, and highlight that node
        self.pq.sortEntries()
        i = int(self.pq.getEntry(0).getIntoNode().getTag('square'))
        #Set the highlight on the picked square
        self.squares[i].setColor(HIGHLIGHT)
        self.hiSq = i
        #print 'selected is ' + str(i)

    return Task.cont

  def grabPiece(self):
    #If a square is highlighted and it has a piece, set it to dragging mode
    if (self.hiSq is not False and
      self.pieces[self.hiSq]):
      self.dragging = self.hiSq
      self.hiSq = False
    
  def releasePiece(self):
    #Letting go of a piece. If we are not on a square, return it to its original
    #position. Otherwise, swap it with the piece in the new square
    if self.dragging is not False:   #Make sure we really are dragging something
      #We have let go of the piece, but we are not on a square
      if self.hiSq is False:
        try:
            self.pieces[self.dragging].obj.setPos(SquarePos(self.dragging))
        except:
            pass
      else:
        #Otherwise, swap the pieces
        self.swapPieces(self.dragging, self.hiSq)
        #self.draggin is the from
        print self.list
        print 'you picked this, so Imma deleting this ' + str(self.dragging)
        #deletion of i after picking it up.
        try:
            self.list.remove(self.dragging)
        except:
            pass
        temp2 = []
        temp2 = SquarePosTuple(self.dragging)
        self.a[temp2[0]][temp2[1]] = 0
        
        i = self.hiSq
        print self.list
        print 'highlighted sq is ' + str(i)
        templis = []
        templis = SquarePosTuple(i)
        print templis
        self.list.append(i)
        print self.list
        print templis
        self.a[templis[0]][templis[1]] = 1

        
        
        for line in self.a:
            print line
        self.trial()
        
    #We are no longer dragging anything
    self.dragging = False

  def setupLights(self):    #This function sets up some default lighting
    ambientLight = AmbientLight( "ambientLight" )
    ambientLight.setColor( Vec4(.8, .8, .8, 1) )
    directionalLight = DirectionalLight( "directionalLight" )
    directionalLight.setDirection( Vec3( 0, 45, -45 ) )
    directionalLight.setColor( Vec4( 0.2, 0.2, 0.2, 1 ) )
    render.setLight(render.attachNewNode( directionalLight ) )
    render.setLight(render.attachNewNode( ambientLight ) )
예제 #33
0
class MouseHandler(object):
	def __init__(self,pandaScene):
		self.pandaScene = pandaScene

	def setupMouseCollisionWM(self):
		self.mouseTraverser = CollisionTraverser()
		self.mouseCollisionQueue    = CollisionHandlerQueue()
		self.mouseRay = CollisionRay()
		self.mouseRay.setOrigin(self.pandaScene.worldMapCam.getPos(self.pandaScene.render))
		self.mouseRay.setDirection(self.pandaScene.render.getRelativeVector(self.pandaScene.worldMapCam, Vec3(0,1,0)))
		self.mouseNode = CollisionNode('mouseRay')
		self.mouseNode.addSolid(self.mouseRay)
		self.mouseNodePath = self.pandaScene.worldMapCam.attachNewNode(self.mouseNode)
		self.mouseNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
		self.mouseTraverser.addCollider(self.mouseNodePath, self.mouseCollisionQueue)

		# uncomment to see the collisions
		# self.mouseTraverser.showCollisions(self.pandaScene.render)	


	def selectedObjectIdWM(self):
		if (self.pandaScene.worldMapMouse.hasMouse() == False):
			return 0,None
		mpos = self.pandaScene.worldMapMouse.getMouse()
		self.mouseRay.setFromLens(self.pandaScene.camNode, mpos.getX(), mpos.getY())
		self.mouseTraverser.traverse(self.pandaScene.render)

		if (self.mouseCollisionQueue.getNumEntries() > 0):
			self.mouseCollisionQueue.sortEntries()
			entry     = self.mouseCollisionQueue.getEntry(0);
			selectedObj = entry.getIntoNodePath()
			selectedObj = selectedObj.findNetTag('selectable')
			if not selectedObj.isEmpty():
				return selectedObj.getTag('id'),selectedObj
			else:
				return 0,None
		return 0,None

	def selectedObjectId(self):
		if (self.pandaScene.mouseWatcherNode.hasMouse() == False):
			return 0,None
		mpos = base.mouseWatcherNode.getMouse()
		self.mouseRay.setFromLens(self.pandaScene.camNode, mpos.getX(), mpos.getY())
		self.mouseTraverser.traverse(self.pandaScene.render)

		if (self.mouseCollisionQueue.getNumEntries() > 0):
			self.mouseCollisionQueue.sortEntries()
			entry     = self.mouseCollisionQueue.getEntry(0);
			selectedObj = entry.getIntoNodePath()
			selectedObj = selectedObj.findNetTag('selectable')
			if not selectedObj.isEmpty():
				return selectedObj.getTag('id'),selectedObj
			else:
				return 0,None	
		return 0,None

	def setupMouseCollision(self):
		self.mouseTraverser = CollisionTraverser()
		self.mouseCollisionQueue    = CollisionHandlerQueue()
		self.mouseRay = CollisionRay()
		self.mouseRay.setOrigin(self.pandaScene.camera.getPos(self.pandaScene.render))
		self.mouseRay.setDirection(self.pandaScene.render.getRelativeVector(self.pandaScene.camera, Vec3(0,1,0)))
		self.mouseNode = CollisionNode('mouseRay')
		self.mouseNode.addSolid(self.mouseRay)
		self.mouseNodePath = self.pandaScene.camera.attachNewNode(self.mouseNode)
		self.mouseNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
		self.mouseTraverser.addCollider(self.mouseNodePath, self.mouseCollisionQueue)
예제 #34
0
class World(DirectObject):
    def __init__(self):
        self.winprops=WindowProperties()
        self.winprops.setCursorFilename(Filename.binaryFilename("question-icon.ico"))
        
        base.win.setClearColorActive(True)
        base.win.setClearColor(VBase4(0, 0, 0, 1))
        
        base.win.requestProperties(self.winprops) 
        self.enemyLights = []
        self.cameraPositions = [((0, 95, 75), (180, -27, 0)),((0, 55, 25), (180, -15, 0)),((0, -55, 25), (0, -15, 0))]
        self.cameraIndex = 0
        base.disableMouse()
        base.enableParticles()
        self.setupLights()
        self.setupPicking()
        #Prepare the vehicular manslaughter!
        self.boosterLightNP = None
        self.flameLights = None
        self.player = Vehicle("ralph_models/vampire_car", "ralph_models/vampire_car", self, "player")

        self.finalGas = None

        self.livesFrame = DirectFrame(frameColor=(0, 0, 0, 0), parent = base.a2dTopLeft)

        self.livesSprites = list()
        for i in range(0,self.player.health):
            sprite = OnscreenImage(image = 'images/healthicon.png', parent = self.livesFrame, scale = 0.08, pos = (0.2*i+0.1,0,-0.1))
            sprite.setTransparency(TransparencyAttrib.MAlpha)
            self.livesSprites.append(sprite)

        self.progressFrame = DirectFrame(frameColor=(0, 0, 0, 0), parent = base.a2dpTopRight)
        gasIcon = OnscreenImage(image = 'images/gas_icon.png', parent = self.progressFrame, scale = 0.04, pos = (-1,0,-0.05))
        # gasIcon.reparentTo(aspect2d)
        gasIcon.setTransparency(TransparencyAttrib.MAlpha)
                    
        # gasBar = OnscreenImage(image = 'images/gas_bar.png', parent = self.progressFrame, scale = 0.4)#, pos = (-0.9,0,-0.05))
        self.gasMax = DirectFrame(frameColor=(.133, .149, .149, 1),frameSize=(-1, 1, -1, 1), parent = self.progressFrame, scale = (0.432,1,0.055625), pos = (-.5,0,-0.04))
        self.gasLevel = DirectFrame(frameColor=(.433, .149, .149, 1),frameSize=(-1, -1, -1, 1), parent = self.progressFrame, scale = (0.432,1,0.055625), pos = (-.5,0,-0.04))
        gasBar = OnscreenImage(image = 'images/gas_bar_border.png', scale = (1,1,.9), pos = (-.0005,0,-0.04))
        gasBar.reparentTo(self.gasLevel)
        gasBar.setTransparency(TransparencyAttrib.MAlpha)

        timeBar = OnscreenImage(image = 'images/time_bar.png', parent = self.progressFrame, scale = (0.44,1,0.0525), pos = (-.47,0,-0.15))
        self.timePointer = OnscreenImage(image = 'images/time_bar_marker.png', parent = timeBar, scale = (0.05, 0, .2222), pos = (-.83,0,-0.15))
        # self.timePointer = OnscreenImage(image = 'images/time_bar_marker.png', parent = self.timeBar, scale = (0.44,1,0.0525), pos = (-.47,0,-0.2))
        timeBar.setTransparency(TransparencyAttrib.MAlpha)


        taskMgr.add(self.updateGasBar, "Update gas")

        self.loadModels()
        self.player.setPos(0,0,0)
        self.setupIntervals()
        camera.reparentTo(self.player)
        camera.setPos(self.cameraPositions[0][0][0],self.cameraPositions[0][0][1],self.cameraPositions[0][0][2])
        camera.setHpr(self.cameraPositions[0][1][0],self.cameraPositions[0][1][1],self.cameraPositions[0][1][2])
        self.setupCollisions()
        render.setShaderAuto() #you probably want to use this
        self.keyMap = {"left":0, "right":0, "forward":0, "backwards":0}
        taskMgr.add(self.player.move, "moveTask")
        
        #Give the vehicle direct access to the keyMap
        self.player.addKeyMap(self.keyMap)
        
        #Player Death
        taskMgr.add(self.deathChecker, "deathTask")
        
        #Sounds!
        self.loadSounds()
        self.currIcon = ""
        self.prevtime = 0
        self.isMoving = False
        self.accept("escape", sys.exit)
        
        self.accept("arrow_up", self.setKey, ["forward", 1])
        self.accept("w", self.setKey, ["forward", 1])
        self.accept("arrow_right", self.setKey, ["right", 1])
        self.accept("d", self.setKey, ["right", 1])
        self.accept("arrow_left", self.setKey, ["left", 1])
        self.accept("a", self.setKey, ["left", 1])
        self.accept("arrow_down", self.setKey, ["backwards", 1])
        self.accept("s", self.setKey, ["backwards", 1])
        
        self.accept("arrow_up-up", self.setKey, ["forward", 0])
        self.accept("w-up", self.setKey, ["forward", 0])
        self.accept("arrow_right-up", self.setKey, ["right", 0])
        self.accept("d-up", self.setKey, ["right", 0])
        self.accept("arrow_left-up", self.setKey, ["left", 0])
        self.accept("a-up", self.setKey, ["left", 0])
        self.accept("arrow_down-up", self.setKey, ["backwards", 0])
        self.accept("s-up", self.setKey, ["backwards", 0])
        
        self.accept("mouse1", self.startShoot)
        self.accept("mouse1-up", self.stopShoot)
        self.accept("mouse3", self.startDrain )
        self.accept("mouse3-up" , self.stopDrain)
        
        self.accept("tab", self.shiftCamera)   
        self.accept("space", self.player.startBoosters)
        
        self.accept("ate-smiley", self.eat)
        self.p1 = ParticleEffect()
        self.p2 = ParticleEffect()
        self.alan_var = False
        #Show collisiony stuff
        if DEBUG:
            base.cTrav.showCollisions(render)
        
        #f = open('testLog.txt', 'r+')
        #self.dfs(file = f)
        
        self.gasPlaying = False
        self.setLights()
    
        self.draining = False
        taskMgr.add(self.drain, 'drain')
        self.drainTime = 0.0
    
        self.flamethrowerActive = False
        self.gasLossTime = 0.0
        self.gasLossRate = 1.0    
        taskMgr.add(self.loseHealth, "loseGas")
        
        #After all the loading, we need to calculate our start time
        self.startTime = datetime.datetime.now()
        self.timeLimit = datetime.timedelta(seconds=175)
        
        timeInterval = LerpPosInterval(self.timePointer,
                                      self.timeLimit.seconds,
                                      (.8,0,-0.2))
        timeInterval.start()
    
        
        
    def setupPicking(self):
        self.picker = CollisionTraverser()
        self.pq     = CollisionHandlerQueue()
        self.pickerNode = CollisionNode('mouseRay')
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()
        self.pickerNode.addSolid(self.pickerRay)
        self.picker.addCollider(self.pickerNP, self.pq)
        
        self.staticRoot = render.attachNewNode('staticRoot')
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        
    def dfs(self, item = render, depth = 0, file = None):
        if file:
            file.write(("-" * depth) + item.getName() + ": \n")
        # print(("-" * depth) + item.getName() + ": ")
        for i in range(item.getNumNodes()):
            if file:
                file.write((" " * depth) + "+" + item.getNode(i).getName() + ": " + str(item.getNode(i).getClassType()) + "\n")
            # print((" " * depth) + "+" + item.getNode(i).getName() + ": " + str(item.getNode(i).getClassType()))
        for i in range(item.getNumChildren()):
            self.dfs(item.getChild(i), depth + 1, file)
            
    def startDrain(self):
        if not self.flamethrowerActive:
            prevDraining = self.draining #previous value of draining
            if base.mouseWatcherNode.hasMouse():
                mpos = base.mouseWatcherNode.getMouse()
                self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
                self.picker.traverse(self.staticRoot)
                if self.pq.getNumEntries() > 0:
                    self.pq.sortEntries()
                    for i in range(self.pq.getNumEntries()):
                        if self.pq.getEntry(i).getIntoNode().getTag('car') != "":
                            self.target = int(self.pq.getEntry(i).getIntoNode().getTag('car'))
                            self.draining = True
            #Start sounds if self.draining started
            if self.draining and not prevDraining:
                self.drainSound.play()

    def drain(self, task):
        if self.draining and task.time - self.drainTime > DRAIN_DELAY:
            carpos = self.staticCars[self.target].getPos()
            playerpos = self.player.getPos()
            dist = math.sqrt( (carpos[0] - playerpos[0])**2 + (carpos[1] - playerpos[1])**2 + (carpos[2] - playerpos[2])**2 )
            if self.gasList[self.target] > 0 and dist < DRAIN_DIST:
                if not self.gasPlaying:
                    self.gasP.reset()
                    self.gasP = ParticleEffect()  
                    self.gasP.loadConfig(Filename('oil.ptf'))        
                    self.gasP.start(self.player)
                    self.gasNode.lookAt(self.staticCars[self.target])
                    self.gasP.setPos(0,0,2)
                    self.gasP.setScale(1.5)
                    self.gasP.setLightOff()
                    self.gasPlaying = True
                    self.alan_var = False
                self.gasNode.lookAt(self.staticCars[self.target])
                self.gasP.setHpr(self.gasNode.getH() + 180, 90, 0)
                self.player.totalGas = self.player.totalGas + 1
                self.gasList[self.target] = self.gasList[self.target] - 1
            else:
                self.alan_var = True
            # print "TotalGas: " + str(self.player.totalGas)
            self.drainTime = task.time
        elif not self.draining or self.alan_var:
            self.gasP.softStop()
            self.drainSound.stop()
            self.gasPlaying = False
        return Task.cont
                     
    def stopDrain(self):
        self.draining = False
           
    def loseHealth(self, task):
        if task.time - self.gasLossTime > GAS_TIME:
            if self.player.direction != 0:
                self.player.totalGas = self.player.totalGas - self.gasLossRate
            elif self.flamethrowerActive:
                self.player.totalGas = self.player.totalGas - self.gasLossRate
            self.gasLossTime = task.time
            # print self.player.totalGas
        return Task.cont
           
    def mouseTask(self, task):
        j = -1
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            self.picker.traverse(self.staticRoot)
            if self.pq.getNumEntries() > 0:
                self.pq.sortEntries()
                for i in range(self.pq.getNumEntries()):
                    if self.pq.getEntry(i).getIntoNode().getTag('car') != "":
                        j = int(self.pq.getEntry(i).getIntoNode().getTag('car'))
                        carpos = self.staticCars[j].getPos()  
                        playerpos = self.player.getPos()
                        dist = math.sqrt( (carpos[0] - playerpos[0])**2 + (carpos[1] - playerpos[1])**2 + (carpos[2] - playerpos[2])**2 )
                        if self.gasList[j] > 0 and dist < DRAIN_DIST:
                            self.winprops.setCursorFilename(Filename.binaryFilename("vamp-icon.ico"))
                            base.win.requestProperties(self.winprops)
                        elif self.gasList[j] > 0:
                            self.winprops.setCursorFilename(Filename.binaryFilename("vamp-off.ico"))
                            base.win.requestProperties(self.winprops)
                        else:
                            self.winprops.setCursorFilename(Filename.binaryFilename("empty-icon.ico"))
                            base.win.requestProperties(self.winprops)
                        break
        if j == -1:
            self.winprops.setCursorFilename(Filename.binaryFilename("question-icon.ico"))
            base.win.requestProperties(self.winprops)
        #print j
        return Task.cont
    
    def setupIntervals(self):
        self.lightOn = LerpFunc(self.lightModify,
                            fromData=0,
                            toData=100,
                            duration=0.2,
                            blendType='noBlend',
                            extraArgs=[True],
                            name="LightUp")
        self.lightOff = LerpFunc(self.lightModify,
                            fromData=0,
                            toData=100,
                            duration=0.2,
                            blendType='noBlend',
                            extraArgs=[False],
                            name="LightDown")
                            
        self.cameraMove = None
 
    def setKey(self, key, value):
        self.keyMap[key] = value
        
    def setWorldLight(self, object):
        object.setLight(self.keyLightNP)
        object.setLight(self.fillLightNP)
        object.setLight(self.boosterLightNP)
        for light in self.enemyLights:
            object.setLight(light)
        
    def setLights(self):
        self.setWorldLight(self.player)
        self.setWorldLight(self.env)
        for enemy in self.enemies:
            self.setWorldLight(enemy)
        for car in self.staticCars:
            self.setWorldLight(car)
        
    def shiftCamera(self):
        if self.cameraMove:
            self.cameraMove.finish()
        old = self.cameraIndex
        self.cameraIndex += 1
        if self.cameraIndex == len(self.cameraPositions):
            self.cameraIndex = 0
        self.cameraMove=LerpPosHprInterval(camera,
                                            .7, 
                                            self.cameraPositions[self.cameraIndex][0], 
                                            self.cameraPositions[self.cameraIndex][1],
                                            camera.getPos(), 
                                            camera.getHpr())
        self.cameraMove.start()
      
    def loadModels(self):
        self.player.setupBooster()
        self.env = loader.loadModel("ralph_models/final_terrain")      
        self.env.reparentTo(render)
        self.env.setScale(8)
        
        # Gas particles
        self.gasP = ParticleEffect()
        self.gasNode = self.player.attachNewNode('gasNode')
        
        # Node Map
        map = Node.NodeMap("nodes.txt")
            
        # enemies    
        self.enemies = []
        file = open('levels/enemies.txt' )
        line = file.readline().rstrip()
        
        self.staticCars = []
        self.gasList = []
        for currCar in carLocations.cars:
            target = loader.loadModel("ralph_models/" + currCar['color'] + "_car")
            target.setPos(currCar['position'])
            target.setHpr(currCar['direction'])
            target.reparentTo(self.staticRoot)
            self.staticCars.append(target)
            self.gasList.append(currCar['gas'])
            
        while line != "" :
            nums = line.split(',')
            convertedNums = []
            for i in range(len(nums)):
                if i != 0:
                    convertedNums.append(int(nums[i]))
            nodePos = map.nodeList[int(nums[0])].getPos()
            newEnemy = Enemy.Enemy(map, convertedNums, self, nodePos[0], nodePos[1], nodePos[2] )
            self.enemies.append( newEnemy )
            taskMgr.add(newEnemy.move, "Enemy Move " + str(i), extraArgs = [map], appendTask = True)
            line = file.readline().rstrip()
            i = i + 1
                  
    def loadSounds(self):
        self.flamethrowerSound = base.loader.loadSfx("sound/dragonflameloop2.wav")
        self.flamethrowerEndSound = base.loader.loadSfx("sound/dragonflameend.wav")
        self.collideSound = base.loader.loadSfx("sound/collide.wav")
        self.drainSound = base.loader.loadSfx("sound/gas_pump.wav")
        self.drainSound.setLoop(True)
        
    def setupLights(self):
        #ambient light
        self.ambientLight = AmbientLight("ambientLight")
        #four values, RGBA (alpha is largely irrelevent), value range is 0:1
        self.ambientLight.setColor((.30, .30, .30, 1))
        self.ambientLightNP = render.attachNewNode(self.ambientLight)
        #the nodepath that calls setLight is what gets illuminated by the light
        render.setLight(self.ambientLightNP)
        #call clearLight() to turn it off
        
        self.keyLight = DirectionalLight("keyLight")
        self.keyLight.setColor((.50,.50,.50, 1))
        self.keyLightNP = render.attachNewNode(self.keyLight)
        self.keyLightNP.setHpr(0, -26, 0)
        
        self.fillLight = DirectionalLight("fillLight")
        self.fillLight.setColor((.05,.05,.05, 1))
        self.fillLightNP = render.attachNewNode(self.fillLight)
        self.fillLightNP.setHpr(30, 0, 0)
               
    def setupCollisions(self):       
        base.cTrav = CollisionTraverser() 
        self.playerRay = CollisionRay()
        self.playerRay.setOrigin(0,0,1000)
        self.playerRay.setDirection(0,0,-1)
        self.playerNode = CollisionNode("playerRay")
        self.playerNode.addSolid(self.playerRay)
        self.playerNode.setFromCollideMask(BitMask32.bit(0))
        self.playerNode.setIntoCollideMask(BitMask32.allOff())
        self.playerNodePath = self.player.attachNewNode(self.playerNode)
        self.playerNodePath.show()
        self.playerGroundHandler = CollisionHandlerQueue()
        base.cTrav.addCollider(self.playerNodePath, self.playerGroundHandler)
        
        envcNode1 = CollisionNode("lot_bottom")
        envcNode1.setFromCollideMask(BitMask32.bit(0))
        temp = CollisionPolygon(Point3(12.56, 19.182, 0), Point3(12.56, -21.261, 0),
                                Point3(-13.217, -21.261, 0), Point3(-13.217, 19.182, 0))
        envcNode1.addSolid(temp)
        
        envcNode2 = CollisionNode("lot_ramp_bottom")
        envcNode2.setFromCollideMask(BitMask32.bit(0))
        temp = CollisionPolygon(Point3(32.715, -14.923, 3.5), Point3(32.715, -21.261, 3.5),
                                Point3(12.56, -21.261, 0), Point3(12.56, -14.923, 0))
        envcNode2.addSolid(temp)
        
        envcNode3 = CollisionNode("lot_middle")
        envcNode3.setFromCollideMask(BitMask32.bit(0))
        temp = CollisionPolygon(Point3(42.715, -14.923, 3.5), Point3(42.715, -21.261, 3.5),
                                Point3(32.715, -21.261, 3.5), Point3(32.715, -14.923, 3.5))
        envcNode3.addSolid(temp)
        
        envcNode4 = CollisionNode("lot_ramp_top")
        envcNode4.setFromCollideMask(BitMask32.bit(0))
        temp = CollisionPolygon(Point3(42.715, -8.845, 6), Point3(42.715, -14.923, 3.5),
                                Point3(32.715, -14.923, 3.5), Point3(32.715, -8.845, 6))
        envcNode4.addSolid(temp)
        
        envcNode5 = CollisionNode("lot_top")
        envcNode5.setFromCollideMask(BitMask32.bit(0))
        temp = CollisionPolygon(Point3(42.715, 16.155, 6), Point3(42.715, -8.845, 6),
                                Point3(17.715, -8.845, 6), Point3(17.715, 16.155, 6))
        envcNode5.addSolid(temp)
        
        wallCNode = CollisionNode("fence")
        wallCNode.setFromCollideMask(BitMask32.bit(0))
        temp = CollisionPolygon(Point3(12.56, 19.182, 0), Point3(12.56, -14.923, 0),
                                Point3(12.56, -14.923, 10), Point3(12.56, 19.182, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(12.56, -14.923, 0), Point3(32.715, -14.923, 3.5),
                                Point3(32.715, -14.923, 10), Point3(12.56, -14.923, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(32.715, -14.923, 3.5), Point3(32.715, -8.845, 6),
                                Point3(32.715, -8.845, 10), Point3(32.715, -14.923, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(32.715, -8.845, 6), Point3(17.715, -8.845, 6),
                                Point3(17.715, -8.845, 10), Point3(32.715, -8.845, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(17.715, -8.845, 6), Point3(17.715, 16.155, 6),
                                Point3(17.715, 16.155, 10), Point3(17.715, -8.845, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(17.715, 16.155, 6), Point3(42.715, 16.155, 6),
                                Point3(42.715, 16.155, 10), Point3(17.715, 16.155, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(42.715, 16.155, 6), Point3(42.715, -8.845, 6),
                                Point3(42.715, -8.845, 10), Point3(42.715, 16.155, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(42.715, -8.845, 6), Point3(42.715, -14.923, 3.5),
                                Point3(42.715, -14.923, 10), Point3(42.715, -8.845, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(42.715, -14.923, 3.5), Point3(42.715, -21.261, 3.5),
                                Point3(42.715, -21.261, 10), Point3(42.715, -14.923, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(42.715, -21.261, 3.5), Point3(32.715, -21.261, 3.5),
                                Point3(32.715, -21.261, 10), Point3(42.715, -21.261, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(32.715, -21.261, 3.5), Point3(12.56, -21.261, 0),
                                Point3(12.56, -21.261, 10), Point3(32.715, -21.261, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(12.56, -21.261, 0), Point3(-13.217, -21.261, 0),
                                Point3(-13.217, -21.261, 10), Point3(12.56, -21.261, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(-13.217, -21.261, 0), Point3(-13.217, 19.182, 0),
                                Point3(-13.217, 19.182, 10), Point3(-13.217, -21.261, 10))
        wallCNode.addSolid(temp)
        temp = CollisionPolygon(Point3(-13.217, 19.182, 0), Point3(12.56, 19.182, 0),
                                Point3(12.56, 19.182, 10), Point3(-13.217, 19.182, 10))
        wallCNode.addSolid(temp)
        
        
        envcNodePath1 = self.env.attachNewNode(envcNode1)
        envcNodePath2 = self.env.attachNewNode(envcNode2)
        envcNodePath3 = self.env.attachNewNode(envcNode3)
        envcNodePath4 = self.env.attachNewNode(envcNode4)
        envcNodePath5 = self.env.attachNewNode(envcNode5)
        
        self.cHandler = CollisionHandlerEvent()
        pusher = CollisionHandlerPusher()
        
        self.wallNode = self.env.attachNewNode('wallNode')
        wallCNodePath = self.wallNode.attachNewNode(wallCNode)
        if DEBUG:
            wallCNodePath.show()
            
        cNode = CollisionNode("player")
        temp = CollisionSphere((0,-5.5,10), 4)
        cNode.addSolid(temp)
        temp = CollisionSphere((0,-0.5,10), 4)
        cNode.addSolid(temp)
        temp = CollisionSphere((0,3.5,10), 4)
        cNode.addSolid(temp)
        cNode.setIntoCollideMask(BitMask32.allOff()) #player is *only* a from object
        cNodePath = self.player.attachNewNode(cNode)
        
        if DEBUG:
            cNodePath.show()
            
        base.cTrav.addCollider(cNodePath, pusher)
        pusher.addCollider(cNodePath, self.player)
        pusher.addInPattern('%fn-into-%in')
        self.accept('player-into-fence', self.collideWithFence)
        self.accept('player-into-staticCar', self.collideOther)
        self.accept('player-into-droneNode', self.collideOther)
        
        self.playerLightCollision = CollisionHandlerEvent()
        self.playerLightCollision.addInPattern('into-%in')
        
        cNode2 = CollisionNode("playerinto")
        
        #cNode.addSolid(segment1)
        #cNode.addSolid(segment2)
        #cNode.addSolid(segment3)
        #cNode.addSolid(segment4)
        temp = CollisionSphere((0,-5.5,1), 4)
        cNode2.addSolid(temp)
        temp = CollisionSphere((0,-0.5,1), 4)
        cNode2.addSolid(temp)
        temp = CollisionSphere((0,3.5,1), 4)
        cNode2.addSolid(temp)
        cNode2.setFromCollideMask(BitMask32.allOff()) #player is *only* a from object
        cNodePath2 = self.player.attachNewNode(cNode2)
        if DEBUG:
            cNodePath2.show()
        
        # FLAMETHROWER COLLISIONS
        # left
        flamethrowerLeft = CollisionSegment()
        flamethrowerLeft.setPointA(-2 , -4, 10)
        flamethrowerLeft.setPointB( -2 , -20 , 10 ) 
        
        # middle
        flamethrowerMiddle = CollisionSegment()
        flamethrowerMiddle.setPointA(0 , -4, 10)
        flamethrowerMiddle.setPointB( 0 , -20 , 10 ) 
        
        # right
        flamethrowerRight = CollisionSegment()
        flamethrowerRight.setPointA(2, -4, 10)
        flamethrowerRight.setPointB( 2 , -20 , 10 ) 
        
        flamethrowerNode = CollisionNode("flamethrower")
        flamethrowerNode.addSolid(flamethrowerLeft)
        flamethrowerNode.addSolid(flamethrowerMiddle)
        flamethrowerNode.addSolid(flamethrowerRight)
        flamethrowerNode.setIntoCollideMask(BitMask32.allOff())
        flamethrowerNode.setFromCollideMask(BitMask32.allOn())
        flamethrowerNodePath = self.player.attachNewNode(flamethrowerNode)
        
        #flamethrowerNodePath.show()
        
        self.flamethrowerCollision = CollisionHandlerEvent()
        self.flamethrowerCollision.addInPattern('into-%in')
        base.cTrav.addCollider(flamethrowerNodePath, self.flamethrowerCollision)
        self.accept('into-droneNode', self.hitEnemy)
        
        for i in range(len(self.staticCars)):
            staticNode = CollisionNode("staticCar")
            temp = CollisionSphere((0,-5.2,10), 4)
            staticNode.addSolid(temp)
            temp = CollisionSphere((0,-0.5,10), 4)
            staticNode.addSolid(temp)
            temp = CollisionSphere((0,5.5,10), 4)
            staticNode.addSolid(temp)
            staticNode.setIntoCollideMask(BitMask32.bit(1))
            staticNode.setFromCollideMask(BitMask32.bit(0))
            staticNodePath = self.staticCars[i].attachNewNode(staticNode)
            temp = CollisionTube(0,7,3,0,-6,3,3.5)
            sN = CollisionNode("staticTube")
            sN.addSolid(temp)
            staticNode.setFromCollideMask(BitMask32.bit(0))
            sNP = self.staticCars[i].attachNewNode(sN)
            sN.setTag('car', str(i))
            
        self.enemyHandler = CollisionHandlerEvent()    
        for i in range(len(self.enemies)):
            collideNode = CollisionNode("droneNode")
            temp = CollisionSphere((0,0,10), 4)
            collideNode.addSolid(temp)
            collideNode.setIntoCollideMask(BitMask32.bit(1))
            collideNode.setFromCollideMask(BitMask32.bit(0))
            enemycollideNodePath = self.enemies[i].attachNewNode(collideNode)
            
            collideNode.setTag('enemy',str(i))
            
            self.enemies[i].lightRay = CollisionSegment()
            self.enemies[i].lightRay.setPointA(0, -4, 4)
            self.enemies[i].lightRay.setPointB( 0 , -100 , 0 ) 
            
            # left
            self.enemies[i].lightRayLeft = CollisionSegment()
            self.enemies[i].lightRayLeft.setPointA(0, -4, 4)
            self.enemies[i].lightRayLeft.setPointB( -5 , -100 , 0 ) 
            
            # right
            self.enemies[i].lightRayRight = CollisionSegment()
            self.enemies[i].lightRayRight.setPointA(0, -4, 4)
            self.enemies[i].lightRayRight.setPointB( 5 , -100 , 0 ) 
            
            self.enemies[i].lightRayNode = CollisionNode("lightRay")
            self.enemies[i].lightRayNode.addSolid(self.enemies[i].lightRay)
            self.enemies[i].lightRayNode.addSolid(self.enemies[i].lightRayLeft)
            self.enemies[i].lightRayNode.addSolid(self.enemies[i].lightRayRight)
            
            self.enemies[i].lightRayNode.setTag('enemy',str(i))
            
            self.enemies[i].lightRayNode.setIntoCollideMask(BitMask32.allOff())
            self.enemies[i].lightRayNodePath = self.enemies[i].attachNewNode(self.enemies[i].lightRayNode)
            if DEBUG:
                self.enemies[i].lightRayNodePath.show()
            
            base.cTrav.addCollider(self.enemies[i].lightRayNodePath, self.playerLightCollision)
        self.accept('into-playerinto', self.player.takeHit)
    
    def collideWithFence(self, entry):
        self.player.speed = self.player.speed * 0.9
        if self.collideSound.status() != AudioSound.PLAYING:
            self.collideSound.play()
    
    def collideOther(self, entry):
        self.player.speed = self.player.speed * 0.9
        if self.collideSound.status() != AudioSound.PLAYING:
            self.collideSound.play()
        
    def lightModify(self, t, which_way):

        if which_way: #which_way == true then make it brighter
            value = t/100 * MAX_LIGHT
        else: #which_way == true then make it darker
            value = (100 - t)/100 * MAX_LIGHT
        for light in self.flameLights:
            light[0].setColor(VBase4(value,value,value,1))
        
    def startShoot(self):
        self.loadParticleConfig('flamethrower6.ptf')
        #self.lightOff.finish()
        #self.lightOn.start()
        
        #Get the flame noise started!
        self.flamethrowerSound.setLoop(True)
        self.flamethrowerSound.play()
        self.flamethrowerActive = True
        self.draining = False
        self.gasLossRate = 2.0
        
    def stopShoot(self):
        self.p1.softStop()
        self.p2.softStop()
        #self.lightOn.finish()
        #self.lightOff.start()
        
        self.flamethrowerSound.stop()
        self.flamethrowerEndSound.play()
        self.flamethrowerActive = False
        self.gasLossRate = 1.0
        
    def hitEnemy(self, entry):
        if self.flamethrowerActive:
            index = int(entry.getIntoNode().getTag('enemy'))
            if self.enemies[index].phase != STOPPED:
                self.enemies[index].prevPhase = self.enemies[index].phase
                self.enemies[index].phase = STOPPED
                self.enemies[index].headlight1.setColor(VBase4(0, 0, 0, 0))
        
    def loadParticleConfig(self, file):
        self.p1.reset()
        self.p1 = ParticleEffect()
        self.p1.loadConfig(Filename(file))        
        self.p1.start(self.player)
        self.p1.setPos(-1.75, -10, 1.375)
        self.p1.setHpr(0, 90, 0)
        self.p1.setScale(2.0)
        self.p1.setLightOff()
        self.p2.reset()
        self.p2 = ParticleEffect()
        self.p2.loadConfig(Filename(file))        
        self.p2.start(self.player)
        self.p2.setPos(1.75, -10, 1.375)
        self.p2.setHpr(0, 90, 0)
        self.p2.setScale(2.0)
        self.p2.setLightOff()
        
    def eat(self, cEntry):
        """handles the player eating a smiley"""
        #remove target from list of targets
        self.targets.remove(cEntry.getIntoNodePath().getParent())
        #remove from scene graph
        cEntry.getIntoNodePath().getParent().remove()
           
    def changeMouseCursor(self, cursorFile):
        if self.currIcon != cursorFile:
            self.currIcon = cursorFile
            # winprops.getParentWindow().getXSize()
            # print winprops.getXSize()
            # print "test"
            self.winprops.setCursorFilename(Filename.binaryFilename(cursorFile))
    
    def deathChecker(self, task):
        font = loader.loadFont('fonts/beneg.ttf')

        #Check for out of time
        currTime = datetime.datetime.now()
        if currTime > self.startTime + self.timeLimit or self.player.totalGas >= MAX_GAS:
            #print "OUT OF TIME!!!!!!!!!!!"

            if self.finalGas is None:
                self.finalGas = self.player.totalGas
            
            taskMgr.doMethodLater(5, self.STOPGAME, 'tickTask')
            self.loading = OnscreenImage(image = 'images/victory.png', scale = (1.3333333,0, 1))
            self.text = OnscreenText(text = "Gas Collected%s" %(self.finalGas), font = font, pos = (0,.2), fg = (255,255,255,1))
        #Check for death
        elif self.player.dead:
            if self.finalGas is None:
                self.finalGas = self.player.totalGas

            #print "THE PLAYER IS DEAD!!!!!!!!!!"
            taskMgr.doMethodLater(5, self.STOPGAME, 'tickTask')
            self.loading = OnscreenImage(image = 'images/lose_death.png', scale = (1.3333333,0, 1))
            self.text = OnscreenText(text = "Gas Collected %s" %(self.finalGas), font = font, pos = (0,.1), fg = (255,255,255,1))
        elif self.player.totalGas <= 0:
            #print "YOU SUCK. YOU RAN OUT OF GAS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
            taskMgr.doMethodLater(5, self.STOPGAME, 'tickTask')
            self.loading = OnscreenImage(image = 'images/lose_nogas.png', scale = (1.3333333,0, 1))
        return Task.cont

        
    def updateGasBar(self, task):
        self.gasLevel['frameSize'] = (-1,(self.player.totalGas / MAX_GAS)*2 - 1, -1, 1)
        return Task.cont
    def STOPGAME(self, SOMETHNG):
        taskMgr.stop()
예제 #35
0
class CollisionAvatar():
    """Collision for avatar
    """
    def __init__(self, game):
        self.game = game
        self.enable = False
        self.camera = self.game.gui.camera
        self.debug = False

        self.sphere_node = CollisionNode('Sphere')
        self.sphere_nodepath = self.game.world.avatar.attachNewNode(self.sphere_node)
        self.sphere_node.setFromCollideMask(BitMask32.bit(2))
        self.sphere_node.setIntoCollideMask(BitMask32.bit(4))
        self.sphere = CollisionSphere(0, 0, 0.5, 0.5)
        self.sphere_node.addSolid(self.sphere)
        self.sphere_handler = CollisionHandlerQueue()

        self.ray_node = CollisionNode('downRay')
        self.ray_nodepath = self.game.world.avatar.attachNewNode(self.ray_node)
        self.ray_node.setFromCollideMask(BitMask32.bit(1))
        self.ray_node.setIntoCollideMask(BitMask32.bit(3))
        self.ray = CollisionRay()
        self.ray.setOrigin(0, 0, 5)
        self.ray.setDirection(0, 0, -1)
        self.ray_node.addSolid(self.ray)
        self.ray_handler = CollisionHandlerQueue()

    def set_debug(self, value):
        """docstring for debug
        """
        self.debug = value
        if self.debug:
            self.ray_nodepath.show()
            self.sphere_nodepath.show()
        else:
            self.ray_nodepath.hide()
            self.sphere_nodepath.hide()

    def set_enable(self, value, Fly = True):
        self.enable = value
        self.fly = Fly
        if self.enable:
            self.game.gui.cTrav.addCollider(self.ray_nodepath, self.ray_handler)
            self.game.gui.cTrav.addCollider(self.sphere_nodepath, self.sphere_handler)
        else:
            self.game.gui.cTrav.removeCollider(self.ray_nodepath)
            self.game.gui.cTrav.removeCollider(self.sphere_nodepath)

    def detector(self):
        if not self.enable:
            return

        self.game.gui.cTrav.traverse(self.game.world.root_node)

        if self.sphere_handler.getNumEntries() > 0:
            #self.sphere_handler.sortEntries()
            self.game.world.avatar.setPos(self.game.world.root_node, self.lastpos)

        if self.ray_handler.getNumEntries() > 0:
            self.ray_handler.sortEntries()
            pickedObj = self.ray_handler.getEntry(0).getIntoNodePath()
            pickedObj = pickedObj.findNetTag('Chunk')
            if not pickedObj.isEmpty():
                Z = self.ray_handler.getEntry(0).\
                                            getSurfacePoint(self.game.world.root_node).getZ()
                if self.fly:
                    if Z > self.game.world.avatar.getZ(self.game.world.root_node):
                        self.game.world.avatar.setZ(self.game.world.root_node, Z)
                else:
                    self.game.world.avatar.setZ(self.game.world.root_node, Z)
예제 #36
0
class World(DirectObject):
    mySound = base.loader.loadSfx("trial.mp3")

    def random_vgen(self):
        print 'I am in random'
        for i in range(0, 5):

            self.a[random.randint(0, 7)][random.randint(0, 7)] = 1

    def initializer(self, level):

        self.turns = 0

        ##   Level Definition

        def levelone():
            self.a[4][4] = 1
            self.a[4][5] = 1
            self.a[4][6] = 1
            self.a[5][2] = 1
            self.a[3][5] = 1
            self.a[4][6] = 1
            self.a[5][5] = 1

        def leveltwo():
            self.a[4][3] = 1
            self.a[4][5] = 1
            self.a[4][7] = 1
            self.a[5][2] = 1
            self.a[3][5] = 1
            self.a[2][2] = 1
            self.a[5][3] = 1
            self.a[1][2] = 1

        def levelthree():
            self.a[4][4] = 1
            self.a[4][5] = 1
            self.a[4][6] = 1
            self.a[5][2] = 1
            self.a[3][5] = 1
            self.a[4][6] = 1
            self.a[5][5] = 1
            self.a[4][3] = 1
            self.a[4][5] = 1
            self.a[4][7] = 1
            self.a[5][2] = 1
            self.a[3][5] = 1
            self.a[2][2] = 1
            self.a[5][3] = 1

        options = {1: levelone, 2: leveltwo, 3: levelthree}

        options[level]()

        temp = []
        count = 0
        for element in reversed(self.a):
            for ele in element:
                #print 'cheking element is 1 : ' + str(ele)
                if ele == 1:
                    temp.append(count)
                    self.pieces[count] = Pawn(count, WHITE)
                    #self.squares[count].setColor(HIGHLIGHT)
                count = count + 1
        self.list = temp

    def showscore(self):
        try:
            self.score.destroy()
        except:
            pass
        self.score = OnscreenText(text='Number of Turns : %s' % (self.turns),
                                  pos=(0.5, 0.95),
                                  scale=0.07,
                                  mayChange=True)

    def menuscreen(self):

        # Callback function to set  text
        def setText():
            b.destroy()
            helptext.destroy()

        # Add button
        b = DirectButton(text=("START", "START", "START", "disabled"),
                         scale=0.15,
                         command=setText,
                         pos=(0, 0, 0.85))

        helptext = OnscreenText(text='''
    STORY:
    Hello Mad Scientist!
    You are so close to finding the cure to aids!
    You understood the behaviour and can finally manipulate the virus to kill itself!
    But time is running out!
    You have a red and white blood cell sample infected with AIDS Virus.

    INSTRUCTIONS:
    The AIDS Virus obeys the Conway's Game of Life. Who would have guessed?
    1.  If virus is surrounded by more than 3 viruses, it dies of suffocation
    2.  If virus is surrounded by less than 2 viruses, it dies of underpopulation
    3.  If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned due to breeding.

    AIM:
    To kill all the viruses, by moving one of them every turn.

    ''',
                                pos=(-0.90, 0.72),
                                frame=(123, 123, 123, 1),
                                wordwrap=25,
                                align=TextNode.ALeft,
                                bg=(0.23, 0.243, 0.13, 0.9))

    def endscreen(self):
        def restart():
            scorecard.destroy()
            restartb.destroy()
            end.destroy()
            nextlevelb.destroy()
            self.reference.destroy()
            self.mySound.stop()
            try:
                self.score.destroy()
            except:
                pass

            World()

        def quitgame():
            sys.exit()

        def nextLevel():
            self.currlevel = self.currlevel + 1
            nextlevelb.destroy()
            scorecard.destroy()
            restartb.destroy()
            end.destroy()
            self.score.destroy()
            self.initializer(self.currlevel)

        # Add button

        scorecard = OnscreenText(text='You finished it in %s turns! ' %
                                 (self.turns),
                                 frame=(123, 123, 123, 0),
                                 wordwrap=25,
                                 bg=(0.2, 0, 0.8, 1))

        nextlevelb = DirectButton(text=("NEXT LEVEL", "NEXT LEVEL",
                                        "NEXT LEVEL", "disabled"),
                                  scale=0.15,
                                  command=nextLevel,
                                  pos=(0, 0, -0.15))
        restartb = DirectButton(text=("RESTART", "RESTART", "RESTART",
                                      "disabled"),
                                scale=0.15,
                                command=restart,
                                pos=(0, 0, -0.35))
        end = DirectButton(text=("QUIT", "QUIT", "QUIT", "disabled"),
                           scale=0.15,
                           command=quitgame,
                           pos=(0, 0, -0.55))
        if self.currlevel == self.maxlevel:
            nextlevelb.destroy()

    def __init__(self):
        #music

        self.mySound.play()

        print 'I am being initialized'

        self.menuscreen()
        self.list = []
        self.turns = 0
        self.maxlevel = 3
        self.currlevel = 1
        self.a = [[0 for x in range(8)] for y in range(8)]

        #This code puts the standard title and instruction text on screen
        self.title = OnscreenText(text="Game of Life : Help in ending AIDS!",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  pos=(0, -0.95),
                                  scale=.07)
        self.escapeEvent = OnscreenText(text="ESC: Quit",
                                        style=1,
                                        fg=(1, 1, 1, 1),
                                        pos=(-1.3, 0.95),
                                        align=TextNode.ALeft,
                                        scale=.05)
        ##    self.mouse1Event = OnscreenText(
        ##      text="Left-click and drag: Pick up virus and drag it to a new bloodcell",
        ##      style=1, fg=(1,1,1,1), pos=(-1.3, 0.90),
        ##      align=TextNode.ALeft, scale = .05)
        ##

        self.accept('escape', sys.exit)  #Escape quits

        base.disableMouse()  #Disble mouse camera control
        camera.setPosHpr(0, -13.75, 6, 0, -25, 0)  #Set the camera
        self.setupLights()  #Setup default lighting

        #Since we are using collision detection to do picking, we set it up like
        #any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  #Make a traverser
        self.pq = CollisionHandlerQueue()  #Make a handler
        #Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        #Attach that node to the camera since the ray will need to be positioned
        #relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        #Everything to be picked will use bit 1. This way if we were doing other
        #collision we could seperate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  #Make our ray
        self.pickerNode.addSolid(self.pickerRay)  #Add it to the collision node
        #Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)

        #Now we create the chess board and its pieces

        #We will attach all of the squares to their own root. This way we can do the
        #collision pass just on the sqaures and save the time of checking the rest
        #of the scene
        self.squareRoot = render.attachNewNode("squareRoot")

        #For each square
        self.squares = [None for i in range(64)]
        self.pieces = [None for i in range(64)]

        for i in range(64):
            #Load, parent, color, and position the model (a single square polygon)
            self.squares[i] = loader.loadModel("models/square")
            self.squares[i].reparentTo(self.squareRoot)
            self.squares[i].setPos(SquarePos1(i))
            self.squares[i].setColor(SquareColor(i))
            #Set the model itself to be collideable with the ray. If this model was
            #any more complex than a single polygon, you should set up a collision
            #sphere around it instead. But for single polygons this works fine.
            self.squares[i].find("**/polygon").node().setIntoCollideMask(
                BitMask32.bit(1))
            #Set a tag on the square's node so we can look up what square this is
            #later during the collision pass
            self.squares[i].find("**/polygon").node().setTag('square', str(i))

            #We will use this variable as a pointer to whatever piece is currently
            #in this square

        #The order of pieces on a chessboard from white's perspective. This list
        #contains the constructor functions for the piece classes defined below

        self.initializer(self.currlevel)

        #Load the white pawns

        #This will represent the index of the currently highlited square
        self.hiSq = False
        #This wil represent the index of the square where currently dragged piece
        #was grabbed from
        self.dragging = False

        #Start the task that handles the picking
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        #self.trial = taskMgr.add(self.trial,'trial')
        self.accept("mouse1", self.grabPiece)  #left-click grabs a piece
        self.accept("mouse1-up", self.releasePiece)  #releasing places it

    #This function swaps the positions of two pieces
    def swapPieces(self, fr, to):
        temp = self.pieces[fr]
        self.pieces[fr] = self.pieces[to]
        self.pieces[to] = temp
        if self.pieces[fr]:
            print 'imma swapping'
            self.pieces[fr].square = fr
            print fr
            print SquarePos(fr)
            try:
                self.pieces[fr].obj.setPos(SquarePos(fr))
            except:
                pass
            print 'done'
        if self.pieces[to]:
            self.pieces[to].square = to
            try:
                self.pieces[to].obj.setPos(SquarePos(to))
            except:
                pass

    def trial(self):
        self.turns = self.turns + 1
        try:
            self.reference.destroy()
        except:
            pass
        self.reference = OnscreenText(text='''
Reference:
virus is surrounded by more than 3 viruses, it dies
virus is surrounded by less than 2 viruses, it dies
If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned.
''',
                                      style=1,
                                      fg=(1, 1, 1, 1),
                                      pos=(-1, 0.95),
                                      align=TextNode.ALeft,
                                      scale=.05)

        self.showscore()
        a = self.a
        while True:
            for i in self.list:
                #insert deletion code
                print 'imma deleting the sq : ' + str(i)
                self.pieces[i].obj.delete()

                self.squares[i].setColor(SquareColor(i))
            count = 0
            a = [[([[
                sum(b[y1][x1]
                    for b in [[[(
                        (-1 < x2 + dx < len(a[0])) and
                        (-1 < y2 + dy < len(a))) and a[y2 + dy][x2 + dx] or 0
                                for x2 in range(len(a[0]))]
                               for y2 in range(len(a))]
                              for (dx, dy) in [(dx, dy) for dx in [-1, 0, 1]
                                               for dy in [-1, 0, 1] if
                                               (dy != 0 or dx != 0)]])
                for x1 in range(len(a[0]))
            ] for y1 in range(len(a))][y][x] == 3 or ([[
                sum(c[y3][x3]
                    for c in [[[(
                        (-1 < x4 + dx < len(a[0])) and
                        (-1 < y4 + dy < len(a))) and a[y4 + dy][x4 + dx] or 0
                                for x4 in range(len(a[0]))]
                               for y4 in range(len(a))]
                              for (dx, dy) in [(dx, dy) for dx in [-1, 0, 1]
                                               for dy in [-1, 0, 1] if
                                               (dy != 0 or dx != 0)]])
                for x3 in range(len(a[0]))
            ] for y3 in range(len(a))][y][x] == 2 and a[y][x] == 1)) and 1 or 0
                  for x in range(len(a[0]))] for y in range(len(a))]
            lis = []
            diceroll = random.randint(0, 5)
            if diceroll == 2:

                self.random_vgen()
            for element in reversed(a):

                for ele in element:
                    #print 'cheking element is 1 : ' + str(ele)
                    if ele == 1:
                        lis.append(count)
                    count = count + 1
            print lis
            self.list = lis

            self.a = a
            print self.list

            for i in self.list:
                self.pieces[i] = Pawn(i, WHITE)
                #self.squares[i].setColor(HIGHLIGHT)
            print 'leaving trial'
            if len(self.list) == 0:
                self.endscreen()
            break

        return

    def mouseTask(self, task):
        #This task deals with the highlighting and dragging based on the mouse

        #First, clear the current highlight
        if self.hiSq is not False:
            self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
            self.hiSq = False

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

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

            #If we are dragging something, set the position of the object
            #to be at the appropriate point over the plane of the board
            if self.dragging is not False:
                #Gets the point described by pickerRay.getOrigin(), which is relative to
                #camera, relative instead to render
                nearPoint = render.getRelativePoint(camera,
                                                    self.pickerRay.getOrigin())
                #Same thing with the direction of the ray
                nearVec = render.getRelativeVector(
                    camera, self.pickerRay.getDirection())
                try:
                    self.pieces[self.dragging].obj.setPos(
                        PointAtZ(.5, nearPoint, nearVec))
                except:
                    pass
            #Do the actual collision pass (Do it only on the squares for
            #efficiency purposes)
            self.picker.traverse(self.squareRoot)
            if self.pq.getNumEntries() > 0:
                #if we have hit something, sort the hits so that the closest
                #is first, and highlight that node
                self.pq.sortEntries()
                i = int(self.pq.getEntry(0).getIntoNode().getTag('square'))
                #Set the highlight on the picked square
                self.squares[i].setColor(HIGHLIGHT)
                self.hiSq = i
                #print 'selected is ' + str(i)

        return Task.cont

    def grabPiece(self):
        #If a square is highlighted and it has a piece, set it to dragging mode
        if (self.hiSq is not False and self.pieces[self.hiSq]):
            self.dragging = self.hiSq
            self.hiSq = False

    def releasePiece(self):
        #Letting go of a piece. If we are not on a square, return it to its original
        #position. Otherwise, swap it with the piece in the new square
        if self.dragging is not False:  #Make sure we really are dragging something
            #We have let go of the piece, but we are not on a square
            if self.hiSq is False:
                try:
                    self.pieces[self.dragging].obj.setPos(
                        SquarePos(self.dragging))
                except:
                    pass
            else:
                #Otherwise, swap the pieces
                self.swapPieces(self.dragging, self.hiSq)
                #self.draggin is the from
                print self.list
                print 'you picked this, so Imma deleting this ' + str(
                    self.dragging)
                #deletion of i after picking it up.
                try:
                    self.list.remove(self.dragging)
                except:
                    pass
                temp2 = []
                temp2 = SquarePosTuple(self.dragging)
                self.a[temp2[0]][temp2[1]] = 0

                i = self.hiSq
                print self.list
                print 'highlighted sq is ' + str(i)
                templis = []
                templis = SquarePosTuple(i)
                print templis
                self.list.append(i)
                print self.list
                print templis
                self.a[templis[0]][templis[1]] = 1

                for line in self.a:
                    print line
                self.trial()

        #We are no longer dragging anything
        self.dragging = False

    def setupLights(self):  #This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0, 45, -45))
        directionalLight.setColor(Vec4(0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
예제 #37
0
class Player(GameObject, ArmedObject):
    def __init__(self, shipSpec):
        GameObject.__init__(self, Vec3(0, 0,
                                       0), None, None, shipSpec.maxShields,
                            shipSpec.maxSpeed, "player", MASK_INTO_PLAYER, 2)
        ArmedObject.__init__(self)

        self.acceleration = shipSpec.acceleration
        self.turnRate = shipSpec.turnRate

        self.numGuns = len(shipSpec.gunPositions)
        self.numMissiles = shipSpec.numMissiles
        self.maxEnergy = shipSpec.maxEnergy
        self.energyRechargeRate = shipSpec.energyRechargeRate
        self.shieldRechargeRate = shipSpec.shieldRechargeRate

        self.energy = shipSpec.maxEnergy

        for gunPos in shipSpec.gunPositions:
            np = self.actor.attachNewNode(PandaNode("gun node"))
            np.setPos(gunPos)

            gun = BlasterWeapon()
            self.addWeapon(gun, 0, np)

        missileSetCounter = 1
        for missilePos in shipSpec.missilePositions:
            np = self.actor.attachNewNode(PandaNode("missile node"))
            np.setPos(missilePos)

            gun = RocketWeapon()
            self.addWeapon(gun, missileSetCounter, np)
            missileSetCounter += 1

        self.numMissileSets = missileSetCounter - 1
        self.missileSetIndex = 0

        light = PointLight("basic light")
        light.setColor(Vec4(1, 1, 1, 1))
        light.setAttenuation((1, 0.01, 0.001))
        self.lightNP = self.root.attachNewNode(light)
        self.lightNP.setZ(1)
        Common.framework.showBase.render.setLight(self.lightNP)

        self.colliderNP.node().setFromCollideMask(MASK_WALLS
                                                  | MASK_FROM_PLAYER)

        Common.framework.pusher.addCollider(self.colliderNP, self.root)
        Common.framework.traverser.addCollider(self.colliderNP,
                                               Common.framework.pusher)

        Common.framework.showBase.camera.reparentTo(self.actor)
        Common.framework.showBase.camera.setPos(0, 0, 0)
        Common.framework.showBase.camera.setHpr(0, 0, 0)

        lens = Common.framework.showBase.camLens

        lens.setNear(0.03)

        ratio = lens.getAspectRatio()

        lens.setFov(75 * ratio)

        self.lastMousePos = Vec2(0, 0)
        self.mouseSpeedHori = 50.0
        self.mouseSpeedVert = 30.0
        self.mouseSensitivity = 1.0

        self.targetingRay = CollisionSegment(0, 0, 0, 0, 100, 0)
        self.targetingRayNode = CollisionNode("lock ray")
        self.targetingRayNode.addSolid(self.targetingRay)
        self.targetingRayNode.setFromCollideMask(MASK_ENEMY_LOCK_SPHERE)
        self.targetingRayNode.setIntoCollideMask(0)
        self.targetingRayNP = self.actor.attachNewNode(self.targetingRayNode)
        self.targetingQueue = CollisionHandlerQueue()

        self.prospectiveLockTarget = None
        self.lockTargetTimer = 0
        self.lockDuration = 1

        Common.framework.traverser.addCollider(self.targetingRayNP,
                                               self.targetingQueue)

        #rayNodePath.show()

        self.uiRoot = aspect2d.attachNewNode(PandaNode("player UI"))

        cardMaker = CardMaker("UI maker")
        cardMaker.setFrame(-1, 1, -1, 1)

        self.centreSpot = self.uiRoot.attachNewNode(cardMaker.generate())
        self.centreSpot.setTexture(
            Common.framework.showBase.loader.loadTexture(
                "../Section2SpaceflightDocking/UI/spot.png"))
        self.centreSpot.setTransparency(True)
        self.centreSpot.setPos(0, 0, 0)
        self.centreSpot.setScale(0.01)
        self.centreSpot.setAlphaScale(0.5)

        self.directionIndicator = self.uiRoot.attachNewNode(
            cardMaker.generate())
        self.directionIndicator.setTexture(
            Common.framework.showBase.loader.loadTexture(
                "../Section2SpaceflightDocking/UI/directionIndicator.png"))
        self.directionIndicator.setTransparency(True)
        self.directionIndicator.setScale(0.05)
        self.directionIndicator.hide()

        self.lockMarkerRoot = self.uiRoot.attachNewNode(
            PandaNode("lock marker root"))
        for i in range(4):
            markerRotationNP = self.lockMarkerRoot.attachNewNode(
                PandaNode("lock marker rotation"))
            marker = markerRotationNP.attachNewNode(cardMaker.generate())
            marker.setTexture(
                Common.framework.showBase.loader.loadTexture(
                    "../Section2SpaceflightDocking/UI/lockMarker.png"))
            marker.setTransparency(True)
            markerRotationNP.setScale(0.04)
            markerRotationNP.setR(i * 90)
        self.lockMarkerRoot.hide()

        self.lockBar = Common.framework.showBase.loader.loadModel(
            "../Section2SpaceflightDocking/UI/uiLockBar")
        self.lockBar.reparentTo(self.uiRoot)
        self.lockBar.setScale(0.15)
        #self.lockBar.hide()

        cardMaker.setFrame(-1, 1, 0, 1)

        self.cockpit = Common.framework.showBase.loader.loadModel(
            "../Section2SpaceflightDocking/Models/{0}".format(
                shipSpec.cockpitModelFile))
        self.cockpit.reparentTo(self.actor)

        healthBarRoot = self.cockpit.find("**/healthBar")
        if healthBarRoot is None or healthBarRoot.isEmpty():
            healthBarRoot = self.uiRoot.attachNewNode(
                PandaNode("health bar root"))
            print("No health bar root found!")

        energyBarRoot = self.cockpit.find("**/energyBar")
        if energyBarRoot is None or energyBarRoot.isEmpty():
            energyBarRoot = self.uiRoot.attachNewNode(
                PandaNode("energy bar root"))
            print("No energy bar root found!")

        missileCounterRoot = self.cockpit.find("**/missileCounter")
        if missileCounterRoot is None or missileCounterRoot.isEmpty():
            missileCounterRoot = self.uiRoot.attachNewNode(
                PandaNode("missile counter root"))
            print("No missile counter root found!")

        radarRoot = self.cockpit.find("**/radar")
        if radarRoot is None or radarRoot.isEmpty():
            radarRoot = self.uiRoot.attachNewNode(PandaNode("radar root"))
            print("No radar root found!")

        speedometerRoot = self.cockpit.find("**/speedometer")
        if speedometerRoot is None or speedometerRoot.isEmpty():
            speedometerRoot = self.uiRoot.attachNewNode(
                PandaNode("speedometer root"))
            print("No speedometer root found!")

        self.radarDrawer = MeshDrawer()
        self.radarDrawer.setBudget(4096)

        self.radarDrawerNP = self.radarDrawer.getRoot()
        self.radarDrawerNP.reparentTo(radarRoot)
        self.radarDrawerNP.setTwoSided(True)
        self.radarDrawerNP.setLightOff()
        self.radarDrawerNP.setDepthWrite(False)
        self.radarDrawerNP.setTransparency(True)

        self.healthBar = healthBarRoot.attachNewNode(cardMaker.generate())
        self.healthBar.setSx(0.05)

        self.energyBar = energyBarRoot.attachNewNode(cardMaker.generate())
        self.energyBar.setSx(0.05)

        self.healthBarScalar = 0.00175
        self.energyBarScalar = 0.00175

        self.missileCounter = DirectLabel(text="",
                                          text_mayChange=True,
                                          scale=0.09,
                                          relief=None,
                                          parent=missileCounterRoot)

        self.maxRadarRange = 700
        self.radarSize = 0.3

        self.speedometer = DirectLabel(text="",
                                       text_mayChange=True,
                                       scale=0.09,
                                       relief=None,
                                       parent=speedometerRoot)

        self.updateHealthUI()
        self.updateEnergyUI()
        self.updateMissileUI()
        self.updateRadar()
        self.updateSpeedometer()

        self.updatingEffects = []

    def update(self, keys, dt):
        GameObject.update(self, dt)

        self.updateSpeedometer()

        self.walking = False

        quat = self.root.getQuat(Common.framework.showBase.render)
        forward = quat.getForward()
        right = quat.getRight()
        up = quat.getUp()

        if keys["up"]:
            self.walking = True
            self.velocity += forward * self.acceleration * dt
        if keys["down"]:
            self.walking = True
            self.velocity -= forward * self.acceleration * dt
        if keys["left"]:
            self.walking = True
            self.velocity -= right * self.acceleration * dt
        if keys["right"]:
            self.walking = True
            self.velocity += right * self.acceleration * dt
        if self.walking:
            self.inControl = True

        mouseWatcher = base.mouseWatcherNode
        if mouseWatcher.hasMouse():
            xSize = base.win.getXSize()
            ySize = base.win.getYSize()
            xPix = float(xSize % 2) / xSize
            yPix = float(ySize % 2) / ySize
            mousePos = Vec2(base.mouseWatcherNode.getMouse())
            mousePos.addX(-xPix)
            mousePos.addY(-yPix)
            if abs(mousePos.x) < xPix:
                mousePos.x = 0
            if abs(mousePos.y) < yPix:
                mousePos.y = 0

        else:
            mousePos = self.lastMousePos

        if mousePos.length() > 0.01:
            axis = right * (mousePos.y) + up * (-mousePos.x)
            axis.normalize()
            angle = mousePos.length() * self.turnRate * dt

            rotQuat = Quat()
            rotQuat.setFromAxisAngle(angle, axis)

            self.root.setQuat(quat * rotQuat)

        if not self.weaponSets[0][0].active:
            self.alterEnergy(
                math.sin(1.071 * self.energy / self.maxEnergy + 0.5) *
                self.energyRechargeRate * dt)

        self.updateEnergyUI()
        self.updateHealthUI()
        self.updateRadar()

        #self.root.setH(self.root.getH() - mousePos.x*self.mouseSpeedHori*self.mouseSensitivity)
        #self.actor.setP(self.actor.getP() + mousePos.y*self.mouseSpeedVert*self.mouseSensitivity)

        if keys["shoot"]:
            self.startFiringSet(0)
        else:
            self.ceaseFiringSet(0)

        if keys["shootSecondary"]:
            self.startFiringSet(self.missileSetIndex + 1)
        else:
            for i in range(self.numMissileSets):
                self.ceaseFiringSet(i + 1)

        [effect.update(self, dt) for effect in self.updatingEffects]
        [
            effect.cleanup() for effect in self.updatingEffects
            if not effect.active
        ]
        self.updatingEffects = [
            effect for effect in self.updatingEffects if effect.active
        ]

        if self.targetingQueue.getNumEntries() > 0:
            self.targetingQueue.sortEntries()
            entry = self.targetingQueue.getEntry(0)
            intoNP = entry.getIntoNodePath()
            if intoNP.hasPythonTag(TAG_OWNER):
                other = intoNP.getPythonTag(TAG_OWNER)
                if other is self.prospectiveLockTarget and other is not self.lockedTarget:
                    self.lockTargetTimer += dt
                    if self.lockTargetTimer >= self.lockDuration:
                        self.lockedTarget = other
                else:
                    self.lockTargetTimer = 0
                self.prospectiveLockTarget = other
            else:
                self.lockTargetTimer = 0
        else:
            self.lockTargetTimer = 0

        perc = self.lockTargetTimer / self.lockDuration
        self.lockBar.setTexOffset(TextureStage.getDefault(), 0, -perc * 1.1)

        if self.lockedTarget is not None:
            if self.lockedTarget.health <= 0:
                self.lockedTarget = None
            else:
                relPos = self.lockedTarget.root.getPos(self.root)
                planarVec = relPos.getXz()
                relDist = relPos.length()

                if relDist == 0:
                    angle = 0
                else:
                    angle = math.acos(relPos.y / relDist)

                if relDist > 200 or angle > 1.7453:
                    self.lockedTarget = None
                else:

                    if self.lockMarkerRoot.isHidden():
                        self.lockMarkerRoot.show()

                    camPt = Point2()
                    convertedPt = Common.framework.showBase.cam.getRelativePoint(
                        Common.framework.showBase.render,
                        self.lockedTarget.root.getPos(
                            Common.framework.showBase.render))
                    if Common.framework.showBase.camLens.project(
                            convertedPt, camPt):
                        self.lockMarkerRoot.setPos(
                            Common.framework.showBase.render2d, camPt.x, 0,
                            camPt.y)
                        if self.lockMarkerRoot.isHidden():
                            self.lockMarkerRoot.show()
                        for child in self.lockMarkerRoot.getChildren():
                            child.getChild(0).setZ(
                                (1.0 - min(1, relDist / 100)) * 5 + 0.2)
                    elif not self.lockMarkerRoot.isHidden():
                        self.lockMarkerRoot.hide()

                    if relPos.y < 0 or angle > 0.6:
                        planarVec.normalize()

                        self.directionIndicator.setPos(planarVec.x * 0.4, 0,
                                                       planarVec.y * 0.4)

                        angle = math.degrees(
                            math.atan2(planarVec.x, planarVec.y))
                        self.directionIndicator.setR(angle)

                        if self.directionIndicator.isHidden():
                            self.directionIndicator.show()
                    elif not self.directionIndicator.isHidden():
                        self.directionIndicator.hide()
        else:
            if not self.directionIndicator.isHidden():
                self.directionIndicator.hide()
            if not self.lockMarkerRoot.isHidden():
                self.lockMarkerRoot.hide()

    def weaponReset(self, weapon):
        ArmedObject.weaponFired(self, weapon)

        if isinstance(weapon, RocketWeapon):
            self.ceaseFiringSet(self.missileSetIndex + 1)
            self.missileSetIndex += 1
            if self.missileSetIndex >= self.numMissileSets:
                self.missileSetIndex = 0

    def attackPerformed(self, weapon):
        ArmedObject.attackPerformed(self, weapon)

    def postTraversalUpdate(self, dt):
        ArmedObject.update(self, dt)

    def alterHealth(self,
                    dHealth,
                    incomingImpulse,
                    knockback,
                    flinchValue,
                    overcharge=False):
        GameObject.alterHealth(self, dHealth, incomingImpulse, knockback,
                               flinchValue, overcharge)

        self.updateHealthUI()

        #self.hurtSound.play()

    def alterEnergy(self, dEnergy):
        self.energy += dEnergy
        if self.energy < 0:
            self.energy = 0
        elif self.energy > self.maxEnergy:
            self.energy = self.maxEnergy

    def alterMissileCount(self, dMissiles):
        self.numMissiles += dMissiles
        if self.numMissiles < 0:
            self.numMissiles = 0
        self.updateMissileUI()

    def updateHealthUI(self):
        perc = self.health / self.maxHealth
        newVal = max(0.01, self.health * self.healthBarScalar)
        self.healthBar.setSz(newVal)
        self.healthBar.setColorScale(1.0 - (perc - 0.5) / 0.5,
                                     min(1, perc / 0.5), 0, 1)
        #self.healthCounter.setText("{0:-.0f}".format(self.health))
        #self.healthCounter.setColorScale(1.0 - (perc - 0.5)/0.5, min(1, perc/0.5), 0, 1)

    def updateEnergyUI(self):
        perc = self.energy / self.maxEnergy
        newVal = max(0.01, self.energy * self.energyBarScalar)
        self.energyBar.setSz(newVal)
        self.energyBar.setColorScale(1.0 - (perc - 0.5) / 0.5,
                                     min(1, perc / 0.5), 0, 1)

    def updateMissileUI(self):
        self.missileCounter["text"] = "Missiles:\n{0}".format(self.numMissiles)
        self.missileCounter.setText()
        self.missileCounter.resetFrameSize()

    def updateSpeedometer(self):
        self.speedometer["text"] = "Speed:\n{0:0=2.0f}m/s".format(
            self.velocity.length() * 2)
        self.speedometer.setText()
        self.speedometer.resetFrameSize()

    def updateRadar(self):
        if Common.framework.currentLevel is not None:
            self.radarDrawer.begin(Common.framework.showBase.cam,
                                   Common.framework.showBase.render)

            uvs = Vec2(0, 0)

            spotSize = 0.015

            self.radarDrawer.tri(Vec3(-spotSize, 0,
                                      -spotSize), Vec4(0, 1, 0, 1), uvs,
                                 Vec3(spotSize, 0,
                                      -spotSize), Vec4(0, 1, 0, 1), uvs,
                                 Vec3(-spotSize, 0, spotSize),
                                 Vec4(0, 1, 0, 1), uvs)
            self.radarDrawer.tri(Vec3(-spotSize, 0,
                                      spotSize), Vec4(0, 1, 0, 1), uvs,
                                 Vec3(spotSize, 0,
                                      -spotSize), Vec4(0, 1, 0, 1), uvs,
                                 Vec3(spotSize, 0, spotSize), Vec4(0, 1, 0, 1),
                                 uvs)

            selfForward = Vec3(0, 1, 0)

            for enemy in Common.framework.currentLevel.enemies:
                enemyPos = enemy.root.getPos(self.root)
                dist = enemyPos.length()
                if dist < self.maxRadarRange:
                    distPerc = dist / self.maxRadarRange
                    enemyPos.normalize()
                    anglePerc = selfForward.angleDeg(enemyPos) / 180
                    enemyPos.setY(0)
                    enemyPos.normalize()
                    enemyPos *= anglePerc * self.radarSize
                    colour = Vec4(1, 0, 0,
                                  math.sin(max(0, 1 - distPerc) * 1.571))

                    self.radarDrawer.tri(
                        Vec3(-spotSize, 0, 0) + enemyPos, colour, uvs,
                        Vec3(spotSize, 0, 0) + enemyPos, colour, uvs,
                        Vec3(0, 0, spotSize) + enemyPos, colour, uvs)
                    self.radarDrawer.tri(
                        Vec3(spotSize, 0, 0) + enemyPos, colour, uvs,
                        Vec3(-spotSize, 0, 0) + enemyPos, colour, uvs,
                        Vec3(0, 0, -spotSize) + enemyPos, colour, uvs)

            self.radarDrawer.end()

    def addUpdatingEffect(self, effect):
        self.updatingEffects.append(effect)
        effect.start(self)

    def cleanup(self):
        if self.uiRoot is not None:
            self.uiRoot.removeNode()
            self.uiRoot = None
        self.healthBar = None

        if self.lightNP is not None:
            Common.framework.showBase.render.clearLight(self.lightNP)
            self.lightNP.removeNode()
            self.lightNP = None

        for effect in self.updatingEffects:
            effect.cleanup()
        self.updatingEffects = []

        ArmedObject.cleanup(self)
        GameObject.cleanup(self)
예제 #38
0
class Player(object):
    """
        Player is the main actor in the fps game
    """
    FORWARD = Vec3(0,2,0)
    BACK = Vec3(0,-1,0)
    LEFT = Vec3(-1,0,0)
    RIGHT = Vec3(1,0,0)
    FLYUP = Vec3(0,0,1)
    FLYDN = Vec3(0,0,-1)
    STOP = Vec3(0)
    PORTAL_CYCLE = {
        'blue' : 'orange',
        'orange' : 'blue',
        }

    def __init__(self, base, fps, osd):
        self.base = base
        self.fps = fps
        self.osd = osd
        self.speed = RUN_SPEED
        self.walk = self.STOP
        self.readyToJump = False
        self.intoPortal = None
        self.mass = Mass()
        self.origin = self.fps.level.settings.origin
        self.bporigin = (999,999,999)
        self.oporigin = (999,999,999)
        self.current_target = None
        self.canPortal = []
        self.canSetTarget = True
        self.selectedCubes = []
        self.editorTextureStage = TextureStage('editor')
        self.editorSelectedTexture = loader.loadTexture('models/tex/selected.png')
        self.selectingForMulti = False
        # Init functions
        self.loadModel()
        self.makePortals()
        self.setUpCamera()
        if self.fps.editor_mode:
            self.createMouseCollisions()
            self.speed = self.speed * 5
            self.attachEditorControls()
            self.attachEditorTasks()
        else:
            self.createCollisions()
            self.attachStandardControls()
            self.attachStandardTasks()

    def loadModel(self):
        """ make the nodepath for player """
        self.node = NodePath('player')
        self.node.reparentTo(render)
        self.node.setPos(*self.origin)
        self.node.setScale(0.05)
        self.mass.pos = VBase3(self.node.getX(), self.node.getY(), self.node.getZ())

    def makePortals(self):
        # The BLUE CUBE
        bpor = loader.loadModel("cube_nocol")
        bpor.setTag('noportals', '1')
        bpor.reparentTo(render)
        bpor.setPos(*self.bporigin)
        bpor.setScale(0.3,0.02,0.5)
        # The BLUE CUBE's camera
        bbuffer = self.base.win.makeTextureBuffer("B Buffer", 512, 512)
        bbuffer.setSort(-100)
        bcamera = self.base.makeCamera(bbuffer)
        bcamera.node().getLens().setAspectRatio(0.3/0.5)
        bcamera.node().getLens().setFov(15)
        bcamera.reparentTo(bpor)
        bcamera.node().setScene(render)

        # The ORANGE CUBE
        opor = loader.loadModel("cube_nocol")
        opor.setTag('noportals', '1')
        opor.reparentTo(render)
        opor.setPos(*self.oporigin)
        opor.setScale(0.3,0.02,0.5)
        # The ORANGE CUBE's camera
        obuffer = self.base.win.makeTextureBuffer("O Buffer", 512, 512)
        obuffer.setSort(-100)
        ocamera = self.base.makeCamera(obuffer)
        ocamera.node().getLens().setAspectRatio(0.3/0.5)
        ocamera.node().getLens().setFov(15)
        ocamera.reparentTo(opor)
        ocamera.node().setScene(render)

        # Assign the textures
        bpor.setTexture(obuffer.getTexture())
        opor.setTexture(bbuffer.getTexture())
        # Store the portals and theirs cameras
        self.bluePortal = bpor
        self.bluePortal.setHpr(0,90,0)
        self.orangePortal = opor
        self.orangePortal.setHpr(0,-90,0)
        self.bcamera = bcamera
        self.ocamera = ocamera

    def setUpCamera(self):
        """ puts camera at the players node """
        pl =  self.base.cam.node().getLens()
        pl.setFov(70)
        self.base.cam.node().setLens(pl)
        self.base.camera.reparentTo(self.node)
        self.base.camLens.setFov(100)
        if self.fps.editor_mode:
            self.node.lookAt(self.fps.level.cubes_hash.keys()[0])

    def createCollisions(self):
        self.createPlayerCollisions()
        self.createMouseCollisions()
        self.createPortalCollisions()

    def createPlayerCollisions(self):
        """ create a collision solid and ray for the player """
        cn = CollisionNode('player')
        cn.setFromCollideMask(COLLISIONMASKS['geometry'])
        cn.setIntoCollideMask(COLLISIONMASKS['portals'] | COLLISIONMASKS['exit'] | COLLISIONMASKS['lava'])
        cn.addSolid(CollisionSphere(0,0,0,3))
        solid = self.node.attachNewNode(cn)
        # TODO : find a way to remove that, it's the cause of the little
        # "push me left" effect we see sometime when exiting a portal
        self.base.cTrav.addCollider(solid,self.base.pusher)
        self.base.pusher.addCollider(solid,self.node, self.base.drive.node())
        # init players floor collisions
        ray = CollisionRay()
        ray.setOrigin(0,0,-.2)
        ray.setDirection(0,0,-1)
        cn = CollisionNode('playerRay')
        cn.setFromCollideMask(COLLISIONMASKS['player'])
        cn.setIntoCollideMask(BitMask32.allOff())
        cn.addSolid(ray)
        solid = self.node.attachNewNode(cn)
        self.nodeGroundHandler = CollisionHandlerQueue()
        self.base.cTrav.addCollider(solid, self.nodeGroundHandler)
        # init players ceil collisions
        ray = CollisionRay()
        ray.setOrigin(0,0,.2)
        ray.setDirection(0,0,1)
        cn = CollisionNode('playerUpRay')
        cn.setFromCollideMask(COLLISIONMASKS['player'])
        cn.setIntoCollideMask(BitMask32.allOff())
        cn.addSolid(ray)
        solid = self.node.attachNewNode(cn)
        self.ceilGroundHandler = CollisionHandlerQueue()
        self.base.cTrav.addCollider(solid, self.ceilGroundHandler)

    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)

    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)

    def attachCommonControls(self):
        self.base.accept( "z" if AZERTY else "w" , self.addWalk,[self.FORWARD])
        self.base.accept( "z-up" if AZERTY else "w-up" , self.addWalk,[-self.FORWARD] )
        self.base.accept( "s" , self.addWalk,[self.BACK] )
        self.base.accept( "s-up" , self.addWalk,[-self.BACK] )
        self.base.accept( "q" if AZERTY else "a" , self.addWalk,[self.LEFT])
        self.base.accept( "q-up" if AZERTY else "a-up" , self.addWalk,[-self.LEFT] )
        self.base.accept( "d" , self.addWalk,[self.RIGHT] )
        self.base.accept( "d-up" , self.addWalk,[-self.RIGHT] )
        self.base.accept( "r-up" , self.resetPosition )
        self.base.accept( "p-up" , self.showPosition )
        self.base.accept( "b-up" , self.deBug )

    def attachStandardControls(self):
        self.attachCommonControls()
        self.base.accept( "space" , self.__setattr__,["readyToJump",True])
        self.base.accept( "space-up" , self.__setattr__,["readyToJump",False])
        self.base.accept( "c-up" , self.__setattr__,["intoPortal",None] )
        self.base.accept( "e-up" , self.erasePortals )
        self.base.accept( "mouse1" , self.fireBlue )
        self.base.accept( "mouse3" , self.fireOrange )
        # Events
        self.base.accept( "bluePortal-into-player" , self.enterPortal, ["blue"] )
        self.base.accept( "orangePortal-into-player" , self.enterPortal, ["orange"] )
        self.base.accept( "bluePortal-outof-player" , self.exitPortal, ["blue"] )
        self.base.accept( "orangePortal-outof-player" , self.exitPortal, ["orange"] )
        self.base.accept( "levelExit-into-player" , self.levelExit)
        self.base.accept( "lava-into-player" , self.fallIntoLava)

    def attachStandardTasks(self):
        taskMgr.add(self.mouseUpdate, 'mouse-task')
        taskMgr.add(self.moveUpdate, 'move-task')
        taskMgr.add(self.jumpUpdate, 'jump-task')

    def attachEditorControls(self):
        self.attachCommonControls()
        self.base.accept( "space" , self.__setattr__, ['selectingForMulti', 1])
        self.base.accept( "space-up" , self.__setattr__, ['selectingForMulti', 0])
        self.base.accept( "shift-space" , self.__setattr__, ['selectingForMulti', 2])
        self.base.accept( "shift-space-up" , self.__setattr__, ['selectingForMulti', 0])
        self.base.accept( "c-up" , self.clearMultiSelectedCubes)
        self.base.accept( "mouse1" , self.selectCubeForCopy, [1])
        self.base.accept( "wheel_up" , self.selectCubeForChange, [1] )
        self.base.accept( "wheel_down" , self.selectCubeForChange, [-1] )
        self.base.accept( "mouse3" , self.selectCubeForDelete )
        self.base.accept("f11", self.saveLevel)
        self.base.accept("x", self.selectCubeForRectangle)
        self.base.accept("shift-x", self.selectCubeForRectangle, [True])
        self.base.accept("l", self.addLightHere)
        self.base.accept("u", self.fps.level.undo, [1])
        for i in range(1,10):
            self.base.accept( "%i-up" % (i,), self.selectCubeForCopy, [i])
        for key, vec in [("a" if AZERTY else "q", self.FLYUP),("w" if AZERTY else "z", self.FLYDN)]:
            self.base.accept(key, self.addWalk, [vec])
            self.base.accept(key + "-up", self.addWalk, [-vec])

    def attachEditorTasks(self):
        taskMgr.add(self.mouseUpdate, 'mouse-task')
        taskMgr.add(self.moveInEditor, 'move-task')

    def deBug(self):
        import pdb
        pdb.set_trace()
    def showPosition(self):
        print self.node.getPos()
        print self.mass
    def fallIntoLava(self, *args, **kwargs):
        # TODO : sound and message + little delay
        self.erasePortals()
        self.resetPosition()
    def resetPosition(self, *args, **kwargs):
        self.node.setHpr(VBase3(0,0,0))
        self.mass.pos = VBase3(*self.origin)
        self.mass.vel = VBase3(0,0,0)
        self.mass.force = VBase3(0,0,0)
        self.node.setPos(self.mass.pos)
    def erasePortals(self):
        self.bluePortal.setPos(*self.bporigin)
        self.orangePortal.setPos(*self.oporigin)
        self.bluePortal.detachNode()
        self.orangePortal.detachNode()
        self.intoPortal = None
        self.canPortal = []
    #@oldpostracker
    def mouseUpdate(self,task):
        """ this task updates the mouse """
        md = self.base.win.getPointer(0)
        x = md.getX()
        y = md.getY()
        if self.base.win.movePointer(0, self.base.win.getXSize()/2, self.base.win.getYSize()/2):
            self.node.setH(self.node.getH() -  (x - self.base.win.getXSize()/2)*0.1)
            if self.fps.editor_mode:
                self.node.setP(self.node.getP() - (y - self.base.win.getYSize()/2)*0.1)
            else:
                self.base.camera.setP(self.base.camera.getP() - (y - self.base.win.getYSize()/2)*0.1)
            self.canSetTarget = True
            self.bcamera.lookAt(self.bluePortal, self.node.getPos(self.orangePortal))
            self.ocamera.lookAt(self.orangePortal, self.node.getPos(self.bluePortal))
            #self.canPortal = ['blue','orange']
            if self.fps.editor_mode:
                cube, point, normal = self.selectCube()
                self.osd.updateTargetPosition(cube)
        if self.selectingForMulti:
            self.selectCubeForMulti()
        return task.cont

    def addWalk(self, vec):
        self.walk += vec

    def moveUpdate(self,task):
        """ this task makes the player move """
        # move where the keys set it
        self.node.setPos(self.node, self.walk*globalClock.getDt()*self.speed)
        return task.cont

    #@oldpostracker
    def jumpUpdate(self,task):
        """ this task simulates gravity and makes the player jump """
        # get the highest Z from the down casting ray
        highestZ = -100
        lowestZ = 100
        for i in range(self.nodeGroundHandler.getNumEntries()):
            entry = self.nodeGroundHandler.getEntry(i)
            z = entry.getSurfacePoint(render).getZ()
            if z > highestZ and entry.getIntoNode().getName() in ( "CollisionStuff", "Plane", "Cube" ):
                highestZ = z
        for i in range(self.ceilGroundHandler.getNumEntries()):
            entry = self.ceilGroundHandler.getEntry(i)
            z = entry.getSurfacePoint(render).getZ()
            if z < lowestZ and entry.getIntoNode().getName() in ( "CollisionStuff", "Plane", "Cube" ):
                lowestZ = z
        # gravity effects and jumps
        self.mass.simulate(globalClock.getDt())
        self.node.setZ(self.mass.pos.getZ())
        if highestZ > self.node.getZ()-PLAYER_TO_FLOOR_TOLERANCE:
            self.mass.zero()
            self.mass.pos.setZ(highestZ+PLAYER_TO_FLOOR_TOLERANCE)
            self.node.setZ(highestZ+PLAYER_TO_FLOOR_TOLERANCE)
        if lowestZ < self.node.getZ()+PLAYER_TO_FLOOR_TOLERANCE:
            self.mass.zero()
            self.mass.pos.setZ(lowestZ-PLAYER_TO_FLOOR_TOLERANCE)
            self.node.setZ(lowestZ-PLAYER_TO_FLOOR_TOLERANCE)
        if self.readyToJump and self.node.getZ() < highestZ + PLAYER_TO_FLOOR_TOLERANCE_FOR_REJUMP:
            self.mass.jump(JUMP_FORCE)
        return task.cont

    def firePortal(self, name, node):
        def hasTagValue(node, tag, value):
            if node.getTag(tag) == value:
                return True
            for pnum in range(node.getNumParents()):
                return hasTagValue(node.getParent(pnum), tag, value)
            return False
        self.firingHandler.sortEntries()
        if self.firingHandler.getNumEntries() > 0:
            closest = self.firingHandler.getEntry(0)
            if hasTagValue(closest.getIntoNode(), 'noportals', '1'):
                return
            point = closest.getSurfacePoint(render)
            normal = closest.getSurfaceNormal(render)
            node.setPos(point)
            node.lookAt(point + normal)
            node.reparentTo(render)
            dest = self.PORTAL_CYCLE[name]
            if dest not in self.canPortal:
                self.canPortal.append(dest)

    def fireBlue(self, *arg, **kwargs):
        self.firePortal("blue", self.bluePortal)

    def fireOrange(self, *arg, **kwargs):
        self.firePortal("orange", self.orangePortal)

    #@oldpostracker
    def enterPortal(self, color, collision):
        if self.intoPortal is None and color in self.canPortal:
            self.intoPortal = color
            portal = {"orange": self.bluePortal, "blue": self.orangePortal}.get(color)
            otherportal = {"orange": self.orangePortal, "blue": self.bluePortal}.get(color)
            # Handle horizontal portals :
            if portal.getH() == 0:
                self.node.setP(0)
                self.node.setR(0)
            elif otherportal.getH() == 0:
                self.node.setH(portal.getH())
                self.node.setP(0)
                self.node.setR(0)
            else:
                # New HPR is relative to 'new' portal but it the 'same' value
                # as the old HPR seen from the 'other' portal
                oldh_fromportal = self.node.getH(otherportal)
                self.node.setHpr(Vec3(0,0,0))
                self.node.setH(portal, 180-oldh_fromportal)
                newh_fromportal = self.node.getH(portal)
            self.node.setPos(portal, self.walk * 10.)
            self.mass.pos = self.node.getPos()
            # Make half a turn (only if we straffing without walking)
            if self.walk.getY() == 0 and self.walk.getX() != 0:
                self.node.setH(self.node, 180)
                self.node.setPos(self.node, self.walk * 10)
    #@oldpostracker
    def exitPortal(self, color, collision):
        # When you entered the blue portal, you have to exit the orange one
        if self.intoPortal != color:
            self.intoPortal = None

    def levelExit(self, event):
        if self.fps.level.settings.next_level:
            self.fps.level.loadlevel(self.fps.level.settings.next_level)
            self.origin = self.fps.level.settings.origin
            self.resetPosition()
            self.erasePortals()
            self.walk = self.STOP
        else:
            print "You won !"
            sys.exit(0)

    # EDITOR MODE
    def selectCube(self):
        self.firingHandler.sortEntries()
        if self.firingHandler.getNumEntries() > 0:
            closest = self.firingHandler.getEntry(0)
            return closest.getIntoNodePath().getParent().getParent(), closest.getSurfacePoint(render), closest.getSurfaceNormal(render) # render/cube.egg/-PandaNode/-GeomNode
        else:
            return None, None, None

    def clearMultiSelectedCubes(self):
        for c in self.selectedCubes:
            c.clearTexture(self.editorTextureStage)
        self.selectedCubes = []

    def selectCubeForMulti(self):
        cube, point, normal = self.selectCube()
        if cube:
            if self.selectingForMulti == 1:
                cube.setTexture(self.editorTextureStage, self.editorSelectedTexture)
                if cube not in self.selectedCubes:
                    self.selectedCubes.append(cube)
            elif cube in self.selectedCubes:
                cube.clearTexture(self.editorTextureStage)
                self.selectedCubes.remove(cube)

    def selectCubeForCopy(self, qty = 1):
        cube, point, normal = self.selectCube()
        if not (cube and point and normal):
            return
        if self.selectedCubes:
            for c in self.selectedCubes:
                self.fps.level.copyCube(c, normal, qty)
            self.clearMultiSelectedCubes()
        else:
            self.fps.level.copyCube(cube, normal, qty)

    def selectCubeForDelete(self):
        cube, point, normal = self.selectCube()
        if not (cube and point and normal):
            return
        if self.selectedCubes:
            for c in self.selectedCubes:
                self.fps.level.deleteCube(c)
            self.clearMultiSelectedCubes()
        else:
            self.fps.level.deleteCube(cube)

    def selectCubeForChange(self, step = 1):
        cube, point, normal = self.selectCube()
        if not (cube and point and normal):
            return
        if self.selectedCubes:
            for c in self.selectedCubes:
                self.fps.level.changeCube(c, step)
        else:
            self.fps.level.changeCube(cube, step)

    def selectCubeForRectangle(self, makeRoom = False):
        cube, point, normal = self.selectCube()
        if makeRoom:
            self.fps.level.createRoom(cube, self.node) # creates a room from the selected cube to the player(camera) position
        else:
            self.fps.level.createRectangle(cube, self.node) # creates a rectangle from the selected cube to the player(camera) position

    def saveLevel(self):
        camerapos = [self.node.getX(), self.node.getY(), self.node.getZ()]
        levelname = self.fps.levelname
        self.fps.level.savelevel(levelname, camerapos)

    def addLightHere(self):
        camerapos = [self.node.getX(), self.node.getY(), self.node.getZ()]
        self.fps.level.addLightHere(camerapos)

    def moveInEditor(self,task):
        self.node.setPos(self.node, self.walk*globalClock.getDt()*self.speed)
        self.osd.updatePosition(self.node)
        return task.cont
예제 #39
0
파일: gamingcam.py 프로젝트: onze/goLive
class GamingCam(object,DirectObject):
   yshift,zshift=5,5
   ymin,ymax=10,70
   zmin,zmax=10,70
   zoom_speed=.1
   move_speed=.5
   def __init__(self,gmap,gaming_zone):
      DirectObject.__init__(self)
      #gaming zone (used for mouse movement), as a tools.Rectangle
      self.gaming_zone=gaming_zone
      #actual camera node
      self.p3dcam=base.camera
      #what the cam is oriented to
      self._target=base.render.attachNewNode('GaminCam.target')
      #range=[0,1] between min and max closeness to ground
      self.level=.7
      #
      #keys_down acts as a pool containing keys (+mouse buttons) currently down
      self.keys_down=[]
      update_list.append(self.update)
      #setup for mouse picking
      picker_node=CollisionNode('gcam_to_mouse_ray')#general collision node
      picker_node.setFromCollideMask(GeomNode.getDefaultCollideMask())
      self.picker_ray=CollisionRay()#solid ray to attach to coll node
      picker_node.addSolid(self.picker_ray)
      self.picker_np=self.p3dcam.attachNewNode(picker_node)#attach this node to gcam
      self.collision_queue=CollisionHandlerQueue()#stores collisions
      self.collision_traverser=CollisionTraverser('gcam_traverser')#actual computer
      self.collision_traverser.addCollider(self.picker_np,self.collision_queue)
      base.cTrav=self.collision_traverser
      self.gmap=gmap
      #stack of states (state=pos+zoom)
      self.states_stack=[]
      #enable the cam to move according to keyboard and mouse
      self.move_enabled=True

   def __del__(self):
      update_list.remove(self.update)
      self.ignoreAll()
      
   def center(self):
      self._target.setPos(0,0,0)
      
   def disable_move(self):
      self.move_enabled=False

   def enable_move(self):
      self.move_enabled=True

   def get_level(self):
      return self._level
   
   def get_picked_tile(self):
      '''
      returns
      '''
      if base.mouseWatcherNode.hasMouse():
         #get the mouse position
         mpos = base.mouseWatcherNode.getMouse()
         #Set the position of the ray based on the mouse position
#         self.picker_ray.setFromLens(self.p3dcam.node().getLens(), mpos.getX(), mpos.getY())
         self.picker_ray.setFromLens(base.camNode, mpos.getX(), mpos.getY())
         self.collision_traverser.traverse(self.gmap.tile_matrix_node)
         if self.collision_queue.getNumEntries()>0:
            #useless since collision test is done against a single object
            self.collision_queue.sortEntries()
            entry=self.collision_queue.getEntry(0)
            x,y,_=entry.getSurfacePoint(self.gmap.tile_matrix_node)
            x=(x+self.gmap.resx)/2.
            y=(y+self.gmap.resy)/2.
            x=max(x,0)
            x=min(x,self.gmap.resx)
            y=max(y,0)
            y=min(y,self.gmap.resy)
            x=int(x)
            y=int(y)
            #out(pos=(x,y,z))
            return self.gmap.tile_matrix[x][y]
      return None
   
   def get_picked_unit(self):
      if base.mouseWatcherNode.hasMouse():
         #get the mouse position
         mpos = base.mouseWatcherNode.getMouse()
         #Set the position of the ray based on the mouse position
#         self.picker_ray.setFromLens(self.p3dcam.node().getLens(), mpos.getX(), mpos.getY())
         self.picker_ray.setFromLens(base.camNode, mpos.getX(), mpos.getY())
         self.collision_traverser.traverse(self.gmap.units_node)
         if self.collision_queue.getNumEntries()>0:
            #useless since collision test is done against a single object
            self.collision_queue.sortEntries()
            entry=self.collision_queue.getEntry(0)
            return entry.getIntoNodePath().findNetTag('GUnit-pickable')
      return None
      

   def get_target(self):
      return self._target
   
   def mouse_up(self,btn):
      if btn=='left':
         target=self.get_picked_tile()
         #out(target)
         #print NodePath(self.gmap.tile_matrix_node).ls()
         #print render.analyze()
         if target:
            network.serverproxy.send({network.cts_dbg_dump_entity:{'eid':target.eid}})
      elif btn=='middle':
         self.set_level(.7)
         self.set_target(Vec3(0,-9,0))

   def move(self,dx=0,dy=0):
      self._target.setPos(self._target,dx,dy,0)
      self.update_cam()

   def push_state(self):
      out('GCam.push_state()')
      pos,zoom=self._target.getPos(),self.level
      self.states_stack.append((pos,zoom))
      
   def pop_state(self):
      out('GCam.pop_state()')
      pos,zoom=self.states_stack.pop(-1)
      self._target.setPos(*pos)
      self.level=zoom
      self.update_cam()

   def set_level(self,level):
      self._level=level
      self.update_cam()

   def set_target(self,target):
      '''
      make the cam look at the given target.
      target can be a set of coordinates, or a node/nodepath.
      '''
      if isinstance(target,PandaNode) or isinstance(target,NodePath):
         self._target.setPos(target,0,0,0)
      if isinstance(target,tuple):
         self._target.setPos(Vec3(*target))
      else:
         self._target.setPos(target)
      self.update_cam()

   def start_accepting(self):
      '''
      the gaming cam is created at gmap creation, so it has to wait
      until all data structures are created before accepting events.
      '''
      self.accept(ConfigVariableString('key-cam-zoom-in').getValue()+'-up',self.zoom,extraArgs=[-GamingCam.zoom_speed])
      self.accept(ConfigVariableString('key-cam-zoom-out').getValue()+'-up',self.zoom,extraArgs=[GamingCam.zoom_speed])
      self.accept(ConfigVariableString('key-cam-right').getValue(),self.keys_down.append,extraArgs=['r'])
      self.accept(ConfigVariableString('key-cam-right').getValue()+'-up',self.keys_down.remove,extraArgs=['r'])
      self.accept(ConfigVariableString('key-cam-up').getValue(),self.keys_down.append,extraArgs=['u'])
      self.accept(ConfigVariableString('key-cam-up').getValue()+'-up',self.keys_down.remove,extraArgs=['u'])
      self.accept(ConfigVariableString('key-cam-left').getValue(),self.keys_down.append,extraArgs=['l'])
      self.accept(ConfigVariableString('key-cam-left').getValue()+'-up',self.keys_down.remove,extraArgs=['l'])
      self.accept(ConfigVariableString('key-cam-down').getValue(),self.keys_down.append,extraArgs=['d'])
      self.accept(ConfigVariableString('key-cam-down').getValue()+'-up',self.keys_down.remove,extraArgs=['d'])
      self.accept('mouse1-up',self.mouse_up,extraArgs=['left'])
      self.accept('mouse2-up',self.mouse_up,extraArgs=['middle'])
      

   def update(self):
      dx,dy=0,0
      for k in self.keys_down:
         if k=='r':dx+=GamingCam.move_speed
         if k=='l':dx-=GamingCam.move_speed
         if k=='u':dy+=GamingCam.move_speed
         if k=='d':dy-=GamingCam.move_speed
         if k=='m':
            pass
            #dx+=mouse.getMouseX()
            #dy+=mouse.getMouseY()
      if self.move_enabled:
         self.move(dx,dy)

   def update_cam(self):
      self.p3dcam.setPos(   self._target,
                     0,
                     -(GamingCam.ymin+GamingCam.yshift+self._level*GamingCam.ymax),
                     GamingCam.zmin+GamingCam.zshift+self._level*GamingCam.zmax
                     )
      self.p3dcam.lookAt(self._target)

   def zoom(self,delta):
      #TODO: smoothen the zoom with a task (interpolation)
      if 0<self._level+delta<1.:
         self.level+=delta

   level=property(get_level,set_level)
   target=property(get_target,set_target)
예제 #40
0
class MyApp(ShowBase):

  

    def __init__(self):
	global collide
        ShowBase.__init__(self)

	self.traverser = CollisionTraverser('traverser1')
	base.cTrav = self.traverser
	#traverser.addCollider(cnode1, handler)

	entry = 1

	imageObject = OnscreenImage(image = '/Users/devanshi/Downloads/sky.png', pos = (0, 0, 0), scale = 2)
	imageObject.setTransparency(TransparencyAttrib.MAlpha)
	base.cam.node().getDisplayRegion(0).setSort(20)
		
	self.forest=NodePath(PandaNode("Forest Root"))
        self.forest.reparentTo(render)
        loader.loadModel("models/background").reparentTo(self.forest)
        loader.loadModel("models/foliage01").reparentTo(self.forest)
        loader.loadModel("models/foliage02").reparentTo(self.forest)
        loader.loadModel("models/foliage03").reparentTo(self.forest)
        loader.loadModel("models/foliage04").reparentTo(self.forest)
        loader.loadModel("models/foliage05").reparentTo(self.forest)
        loader.loadModel("models/foliage06").reparentTo(self.forest)
        loader.loadModel("models/foliage07").reparentTo(self.forest)
        loader.loadModel("models/foliage08").reparentTo(self.forest)
        loader.loadModel("models/foliage09").reparentTo(self.forest)
	
	
	self.forest1=NodePath(PandaNode("Forest Root"))
        self.forest1.reparentTo(render)
        
        loader.loadModel("models/foliage01").reparentTo(self.forest1)
        loader.loadModel("models/foliage02").reparentTo(self.forest1)
        loader.loadModel("models/foliage03").reparentTo(self.forest1)
        loader.loadModel("models/foliage04").reparentTo(self.forest1)
        loader.loadModel("models/foliage05").reparentTo(self.forest1)
        loader.loadModel("models/foliage06").reparentTo(self.forest1)
        loader.loadModel("models/foliage07").reparentTo(self.forest1)
        loader.loadModel("models/foliage08").reparentTo(self.forest1)
        loader.loadModel("models/foliage09").reparentTo(self.forest1)

        self.forest.hide(BitMask32.bit(1))
	
        self.forest.setScale(2.5, 2.5, 2.5)
        self.forest.setPos(0, 0, -2)

        self.forest1.hide(BitMask32.bit(1))
	
        self.forest1.setScale(1.5, 1.5, 1.5)
        self.forest1.setPos(-1,-1, 0)

	self.forest2=NodePath(PandaNode("Forest Root"))
        self.forest2.reparentTo(render)
        
        loader.loadModel("models/foliage01").reparentTo(self.forest2)
        loader.loadModel("models/foliage02").reparentTo(self.forest2)
        loader.loadModel("models/foliage03").reparentTo(self.forest2)
        loader.loadModel("models/foliage04").reparentTo(self.forest2)
        loader.loadModel("models/foliage05").reparentTo(self.forest2)
        loader.loadModel("models/foliage06").reparentTo(self.forest2)
        loader.loadModel("models/foliage07").reparentTo(self.forest2)
        loader.loadModel("models/foliage08").reparentTo(self.forest2)
        loader.loadModel("models/foliage09").reparentTo(self.forest2)

        self.forest2.hide(BitMask32.bit(1))

        self.forest1.setScale(1.5, 1.5, 1.5)
        self.forest1.setPos(1,1, 0)

	self.stall = self.loader.loadModel("models/patch/cornfield")
	self.stall.reparentTo(self.render)
	self.stall.setScale(0.5)
	self.stall.setPos(40,0,1)
	self.stall.setHpr(0,0,0)
	self.tex1=self.loader.loadTexture("models/water.png")
	self.stall.setTexture(self.tex1,1)

	self.flock = Actor("models/goose/goosemodelonly",  {"gfly":"models/goose/gooseanimationonly"
                       })

        self.flock.setScale(0.05, 0.05, 0.05)
	self.flock.setPos(0,-30,13)
        self.flock.reparentTo(self.render)
	self.flock.loop("gfly")
	self.tex2=self.loader.loadTexture("models/orange.jpg")
	self.flock.setTexture(self.tex2,1)

	self.camera.setPos(0,0,0)
	self.camera.setHpr(90,0,0)

       # Create the four lerp intervals needed for the panda to
        # walk back and forth.
        pandaPosInterval1 = self.flock.posInterval(13,
                                                        Point3(-5, -30, 13),
                                                        startPos=Point3(5, -30, 13))
        pandaPosInterval2 = self.flock.posInterval(13,
                                                        Point3(5, -30, 13),
                                                        startPos=Point3(-5, -30, 13))
        pandaHprInterval1 = self.flock.hprInterval(3,
                                                        Point3(0, 0, 0),
                                                        startHpr=Point3(180, 0, 0))
        pandaHprInterval2 = self.flock.hprInterval(3,
                                                        Point3(180, 0, 0),
                                                        startHpr=Point3(0, 0, 0))
 
        # Create and play the sequence that coordinates the intervals.
        self.pandaPace = Sequence(pandaPosInterval1,
                                  pandaHprInterval1,
                                  pandaPosInterval2,
                                  pandaHprInterval2,
                                  name="pandaPace")
        self.pandaPace.loop()

		
	
	
        # Disable the camera trackball controls.
        #self.disableMouse()
 
        # Load the environment model.
        self.environ = self.loader.loadModel("models/environment1")
        # Reparent the model to render.
        self.environ.reparentTo(self.render)
        # Apply scale and position transforms on the model.
        self.environ.setScale(0.25, 0.25, 0.25)
        self.environ.setPos(-8, 42, 0)

	self.boy =  Actor("models/trex/trex",  {"run":"models/trex/trex-run",
                                  "eat":"models/trex/trex-eat"})
	self.boy.reparentTo(self.render)
	self.boy.setPos(0,0,0)
	self.boy.setScale(0.5)
	self.isMoving = False
	self.myAnimControl = self.boy.getAnimControl('run')
				
	base.camera.setPos(self.boy.getX(),self.boy.getY()+10,20)
	self.floater = NodePath(PandaNode("floater"))
	self.floater.reparentTo(render)
		
	self.cBoy = self.boy.attachNewNode(CollisionNode('cBoyNode'))
	self.cBoy.node().addSolid(CollisionSphere(0, 0, 3, 8.5))
	#self.cBoy.show()
		
	#self.cPond = self.stall.attachNewNode(CollisionNode('cPond'))
	#self.cPond.node().addSolid(CollisionSphere(40, 0, 1, 70))
	#self.cPond.show()
	
 
        # Add the spinCameraTask procedure to the task manager.
        #self.taskMgr.add(self.spinCameraTask,"asdsad")
	self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0}

	cs1 = CollisionSphere(0, 0, 0, 2)
	self.cnodePath1 = render.attachNewNode(CollisionNode('cnode1'))
	self.cnodePath1.node().addSolid(cs1)
	#self.cnodePath1.setCollideMask(BitMask32(0x10))
	#self.cnodePath1.show()

	
	self.taskMgr.add(self.moveSphere1, "sfasdasf")
 

	cs2 = CollisionSphere(0, 0, 0, 1)
	self.cnodePath2 = render.attachNewNode(CollisionNode('cnode2'))
	self.cnodePath2.node().addSolid(cs2)
	#self.cnodePath2.reparentTo(self.render)
	#self.cnodePath2.node().setFromCollideMask(BitMask32.bit(0))
        #self.cnodePath2.node().setIntoCollideMask(BitMask32.allOff())
	#self.cnodePath2.show()

	self.taskMgr.add(self.moveSphere2, "sfasd")


	handler = CollisionHandlerEvent()
	handler.addInPattern('cnode1-into-cnode2')
	handler.addAgainPattern('cnode1-again-cnode2')
	handler.addOutPattern('cs1-out-cs2')


	self.accept('cnode1-into-cnode2', self.collide)
	#self.accept('cs1-out-cs2', self.collide)
	#self.accept('cnode1-again-cnode2', self.collide)


	self.traverser.addCollider(self.cnodePath1, handler)

        # Load and transform the panda actor.
        self.pandaActor = Actor("models/panda-model",
                                {"walk": "models/panda-walk4"})
        self.pandaActor.setScale(0.005, 0.005, 0.005)
        self.pandaActor.reparentTo(self.render)
        # Loop its animation.
        self.pandaActor.loop("walk")

	self.taskMgr.add(self.movePanda, "Sasdas")
	
	self.pandaActor2 = Actor("models/panda-model",{"walk": "models/panda-walk4"})
        self.pandaActor2.setScale(0.003, 0.003, 0.003)
        self.pandaActor2.reparentTo(self.render)
        # Loop its animation.
        self.pandaActor2.loop("walk")

	self.taskMgr.add(self.movePanda2, "Sak")

	self.camera.setPos(0,0,0)
	self.camera.setHpr(90,0,0)

	self.cTrav1=CollisionTraverser()
	self.collisionHandler1 = CollisionHandlerQueue()
	self.cTrav1.addCollider(self.cBoy, self.collisionHandler1)

	self.taskMgr.add(self.boyMoveTask, "BoyMoveTask")
		
	#self.accept("v",self.switchView)
	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])

	self.cTrav2=CollisionTraverser()
	self.collisionHandler2 = CollisionHandlerQueue()
	self.cTrav2.addCollider(self.cBoy, self.collisionHandler2)
		
		
		

    # Define a procedure to move the camera.
    def spinCameraTask(self, task):
        angleDegrees = task.time * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        self.camera.setPos(0,0,50)
	self.camera.setHpr(0, -90, 0)
        return Task.cont

    def movePanda(self, task):
        angleDegrees = (task.time) * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        self.pandaActor.setPos(10 * sin(angleRadians), -10.0 * cos(angleRadians), 0)
        self.pandaActor.setHpr(90+angleDegrees, 0, 0)
        return Task.cont
	
    def movePanda2(self, task):
        angleDegrees = (task.time) * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        self.pandaActor2.setPos(10.0 * sin(angleRadians), 10.0 * cos(angleRadians), 0)
        self.pandaActor2.setHpr(-270-angleDegrees, 0, 0)
        return Task.cont

    def moveSphere2(self, task):
        angleDegrees = (task.time) * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        self.cnodePath2.setPos(10.0 * sin(angleRadians), 10.0 * cos(angleRadians), 1)
        self.cnodePath2.setHpr(90+angleDegrees, 0, 0)
        return Task.cont

    def moveSphere1(self, task):
        angleDegrees = (task.time) * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        self.cnodePath1.setPos(10 * sin(angleRadians), -10.0 * cos(angleRadians), 1)
        self.cnodePath1.setHpr(90+angleDegrees, 0, 0)
	return Task.cont

    def fly(self, task):
	angleDegrees = task.time * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
	x = self.pandaActor2.getX()
	y = self.pandaActor2.getY()
	p = self.pandaActor2.getH()
	self.pandaActor2.setPos(x, ((task.time)*(task.time))+20 * sin(angleRadians), 10.0 * sin(angleRadians))
	self.cnodePath2.setPos(x, ((task.time)*(task.time))+20 * sin(angleRadians), 10.0 * sin(angleRadians))
	self.pandaActor2.setHpr(p, -(angleDegrees*10), 0)
	return Task.cont

    def collide(self, entry):
	print "abc"
	#self.pandaActor2.setPos(0,0,2)
	self.taskMgr.remove("Sak")
	self.taskMgr.remove("sfasd")
	self.taskMgr.add(self.fly, "Sasopi")
	#self.pandaActor3 = Actor("models/panda-model",
        #               {"walk": "models/panda-walk4"})
       	#self.pandaActor3.setScale(0.005, 0.005, 0.005)
	#self.pandaActor3.setPos(0, 0, 1)
	#self.camera.setPos(0,0,50)


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

    def boyMoveTask(self, task):
		base.camera.reparentTo(self.boy)	
		base.camera.setPos(0,40,0)
		
		
		base.camera.lookAt(self.boy)
		if (self.keyMap["cam-left"]!=0):
			self.camera.setX(base.camera, -20 * globalClock.getDt())
		if (self.keyMap["cam-right"]!=0):
			self.camera.setX(base.camera, +20 * globalClock.getDt())

		self.startPos = self.boy.getPos()

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

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

		camvec = self.boy.getPos() - base.camera.getPos()
		camvec.setZ(20)
		camdist = camvec.length()
		camvec.normalize()
		if (camdist > 50):
			base.camera.setPos(base.camera.getPos() + camvec*(camdist-50))
			camdist = 50.0
		if (camdist < 25.0):
			base.camera.setPos(base.camera.getPos() - camvec*(25-camdist))
			camdist = 25.0
		
		self.cTrav1.traverse(render)
		self.collisionHandler1.sortEntries()
		if self.collisionHandler1.getNumEntries() == 0:
			self.startPos = self.boy.getPos()
			#self.boy.loop("eat")
		else:
			self.boy.setPos(self.startPos);
			
			#print self.collisionHandler1.getEntry(0)
		

		base.camera.setZ(self.boy.getZ() + 10)
예제 #41
0
파일: picker.py 프로젝트: westmark/redpanda
class MousePicker(object):
    def __init__(self, pickTag="MyPickingTag", nodeName="pickRay", showCollisions=False):
        self.pickTag = pickTag
        self.nodeName = nodeName
        self.showCollisions = showCollisions

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        mpos = base.mouseWatcherNode.getMouse()

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

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

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

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

        return None, None

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

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

        mpos = base.mouseWatcherNode.getMouse()

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

        self.mPickerTraverser2D.traverse(base.aspect2d)

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

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

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

        return None, None
예제 #42
0
class Player(GameObject, Walker, ArmedObject):
    def __init__(self):
        GameObject.__init__(self, Vec3(0, 0, 0), None, None, 100, 15, "player",
                            1, MASK_INTO_PLAYER)
        Walker.__init__(self)
        ArmedObject.__init__(self)

        self.weaponNP = self.actor

        light = PointLight("basic light")
        light.setColor(Vec4(1, 1, 1, 1))
        light.setAttenuation((1, 0.01, 0.005))
        self.lightNP = self.root.attachNewNode(light)
        self.lightNP.setZ(1)
        render.setLight(self.lightNP)

        self.collider.node().setFromCollideMask(MASK_WALLS | MASK_FROM_PLAYER)

        self.actor.setZ(self.height)

        base.camera.reparentTo(self.actor)
        base.camera.setPos(0, 0, 0)
        base.camera.setHpr(0, 0, 0)

        lens = base.camLens
        ratio = lens.getAspectRatio()

        lens.setFov(80 * ratio)
        lens.setNear(0.03)

        self.lastMousePos = Vec2(0, 0)
        self.mouseSpeedHori = 50.0
        self.mouseSpeedVert = 30.0
        self.mouseSensitivity = 1.0

        self.healthLeft = -0.9
        self.healthRight = 0.9
        self.healthWidth = self.healthRight - self.healthLeft

        self.uiRoot = base.a2dBottomCenter.attachNewNode(
            PandaNode("player UI"))

        self.healthBar = loader.loadModel("UI/healthBar")
        self.healthBar.reparentTo(self.uiRoot)
        self.healthBar.setZ(0.05)
        self.healthBar.setX(self.healthLeft)
        self.healthBar.getChild(0).setScale(self.healthWidth / 6.0)

        self.weaponUIRoot = self.uiRoot.attachNewNode(
            PandaNode("player weapon UI"))
        self.weaponUIRoot.setPos(0, 0, 0.1)

        self.addWeapon(RapidShotgunWeapon(self.weaponUIRoot))
        self.addWeapon(BlasterWeapon(self.weaponUIRoot))

        self.weapons[0].setAvailable(True)

        self.setCurrentWeapon(0)

        self.updateHealthUI()

        self.inventory = []

        self.updatingEffects = []

        self.interactionSegment = CollisionSegment(0, 0, 0, 0, 1.5, 0)

        rayNode = CollisionNode("player interaction ray")
        rayNode.addSolid(self.interactionSegment)

        rayNode.setFromCollideMask(MASK_WALLS | MASK_FLOORS | MASK_INTO_ENEMY)
        rayNode.setIntoCollideMask(0)

        self.interactionSegmentNodePath = self.actor.attachNewNode(rayNode)
        #self.interactionSegmentNodePath.show()
        self.interactionSegmentQueue = CollisionHandlerQueue()

        self.interactionSegmentTraverser = CollisionTraverser()
        self.interactionSegmentTraverser.addCollider(
            self.interactionSegmentNodePath, self.interactionSegmentQueue)

        #self.hurtSound = loader.loadSfx("Sounds/FemaleDmgNoise.ogg")

    def update(self, keys, dt):
        GameObject.update(self, dt)

        self.walking = False

        quat = self.root.getQuat(render)
        forward = quat.getForward()
        right = quat.getRight()

        if keys["up"]:
            self.walking = True
            self.velocity += forward * self.acceleration * dt
        if keys["down"]:
            self.walking = True
            self.velocity -= forward * self.acceleration * dt
        if keys["left"]:
            self.walking = True
            self.velocity -= right * self.acceleration * dt
        if keys["right"]:
            self.walking = True
            self.velocity += right * self.acceleration * dt
        if self.walking:
            self.inControl = True

        mouseWatcher = base.mouseWatcherNode
        if mouseWatcher.hasMouse():
            xSize = base.win.getXSize()
            ySize = base.win.getYSize()
            xPix = float(xSize % 2) / xSize
            yPix = float(ySize % 2) / ySize
            mousePos = Vec2(base.mouseWatcherNode.getMouse())
            mousePos.addX(-xPix)
            mousePos.addY(-yPix)
            if abs(mousePos.x) < xPix:
                mousePos.x = 0
            if abs(mousePos.y) < yPix:
                mousePos.y = 0

            base.win.movePointer(0, xSize // 2, ySize // 2)
        else:
            mousePos = self.lastMousePos

        self.root.setH(self.root.getH() - mousePos.x * self.mouseSpeedHori *
                       self.mouseSensitivity)
        self.actor.setP(self.actor.getP() + mousePos.y * self.mouseSpeedVert *
                        self.mouseSensitivity)

        if self.currentWeapon is not None:
            if keys["shoot"]:
                self.startAttacking()
            else:
                self.endAttacking()

        [effect.update(self, dt) for effect in self.updatingEffects]
        [
            effect.cleanup() for effect in self.updatingEffects
            if not effect.active
        ]
        self.updatingEffects = [
            effect for effect in self.updatingEffects if effect.active
        ]

    def attackPerformed(self, weapon):
        ArmedObject.attackPerformed(self, weapon)

    def postTraversalUpdate(self, dt):
        Walker.update(self, dt)
        ArmedObject.update(self, dt)

    def alterHealth(self,
                    dHealth,
                    incomingImpulse,
                    flinchValue,
                    overcharge=False):
        GameObject.alterHealth(self, dHealth, incomingImpulse, flinchValue,
                               overcharge)

        self.updateHealthUI()

        #self.hurtSound.play()

    def updateHealthUI(self):
        perc = self.health / self.maxHealth
        self.healthBar.setSx(perc)
        self.healthBar.setColorScale(1.0 - (perc - 0.5) / 0.5,
                                     min(1, perc / 0.5), 0, 1)
        #self.healthCounter.setText("{0:-.0f}".format(self.health))
        #self.healthCounter.setColorScale(1.0 - (perc - 0.5)/0.5, min(1, perc/0.5), 0, 1)

    def scrollWeapons(self, direction):
        newIndex = (self.currentWeaponIndex + direction) % len(self.weapons)
        self.setCurrentWeapon(newIndex)

    def interact(self):
        self.interactionSegmentTraverser.traverse(render)

        if self.interactionSegmentQueue.getNumEntries() > 0:
            #print ("Hit something:")
            self.interactionSegmentQueue.sortEntries()
            rayHit = self.interactionSegmentQueue.getEntry(0)
            intoNP = rayHit.getIntoNodePath()
            if intoNP.hasPythonTag(TAG_OWNER):
                intoObj = intoNP.getPythonTag(TAG_OWNER)
                if intoObj is not None and hasattr(intoObj, "interact"):
                    intoObj.interact(self)

    def addUpdatingEffect(self, effect):
        self.updatingEffects.append(effect)
        effect.start(self)

    def cleanup(self):
        if self.uiRoot is not None:
            self.uiRoot.removeNode()
            self.uiRoot = None
        self.healthBar = None
        self.weaponUIRoot = None

        if self.lightNP is not None:
            render.clearLight(self.lightNP)
            self.lightNP.removeNode()
            self.lightNP = None

        for effect in self.updatingEffects:
            effect.cleanup()
        self.updatingEffects = []

        ArmedObject.cleanup(self)
        Walker.cleanup(self)
        GameObject.cleanup(self)
예제 #43
0
class ChessboardDemo(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)

        # This code puts the standard title and instruction text on screen
        self.title = OnscreenText(text="Panda3D: Tutorial - Mouse Picking",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  shadow=(0, 0, 0, 1),
                                  pos=(0.8, -0.95),
                                  scale=.07)
        self.escapeEvent = OnscreenText(text="ESC: Quit",
                                        parent=base.a2dTopLeft,
                                        style=1,
                                        fg=(1, 1, 1, 1),
                                        pos=(0.06, -0.1),
                                        align=TextNode.ALeft,
                                        scale=.05)
        self.mouse1Event = OnscreenText(
            text="Left-click and drag: Pick up and drag piece",
            parent=base.a2dTopLeft,
            align=TextNode.ALeft,
            style=1,
            fg=(1, 1, 1, 1),
            pos=(0.06, -0.16),
            scale=.05)

        self.accept('escape', sys.exit)  # Escape quits
        self.disableMouse()  # Disble mouse camera control
        camera.setPosHpr(0, -12, 8, 0, -35, 0)  # Set the camera
        self.setupLights()  # Setup default lighting

        # Since we are using collision detection to do picking, we set it up like
        # any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  # Make a traverser
        self.pq = CollisionHandlerQueue()  # Make a handler
        # Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        # Attach that node to the camera since the ray will need to be positioned
        # relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        # Everything to be picked will use bit 1. This way if we were doing other
        # collision we could separate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  # Make our ray
        # Add it to the collision node
        self.pickerNode.addSolid(self.pickerRay)
        # Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        # self.picker.showCollisions(render)

        # Now we create the chess board and its pieces

        # We will attach all of the squares to their own root. This way we can do the
        # collision pass just on the squares and save the time of checking the rest
        # of the scene
        self.squareRoot = render.attachNewNode("squareRoot")

        # For each square
        self.squares = [None for i in range(64)]
        self.pieces = [None for i in range(64)]
        for i in range(64):
            # Load, parent, color, and position the model (a single square
            # polygon)
            self.squares[i] = loader.loadModel("models/square")
            self.squares[i].reparentTo(self.squareRoot)
            self.squares[i].setPos(SquarePos(i))
            self.squares[i].setColor(SquareColor(i))
            # Set the model itself to be collideable with the ray. If this model was
            # any more complex than a single polygon, you should set up a collision
            # sphere around it instead. But for single polygons this works
            # fine.
            self.squares[i].find("**/polygon").node().setIntoCollideMask(
                BitMask32.bit(1))
            # Set a tag on the square's node so we can look up what square this is
            # later during the collision pass
            self.squares[i].find("**/polygon").node().setTag('square', str(i))

            # We will use this variable as a pointer to whatever piece is currently
            # in this square

        # The order of pieces on a chessboard from white's perspective. This list
        # contains the constructor functions for the piece classes defined
        # below
        pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook)

        for i in range(8, 16):
            # Load the white pawns
            self.pieces[i] = Pawn(i, WHITE)
        for i in range(48, 56):
            # load the black pawns
            self.pieces[i] = Pawn(i, PIECEBLACK)
        for i in range(8):
            # Load the special pieces for the front row and color them white
            self.pieces[i] = pieceOrder[i](i, WHITE)
            # Load the special pieces for the back row and color them black
            self.pieces[i + 56] = pieceOrder[i](i + 56, PIECEBLACK)

        # This will represent the index of the currently highlited square
        self.hiSq = False
        # This wil represent the index of the square where currently dragged piece
        # was grabbed from
        self.dragging = False

        # Start the task that handles the picking
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        self.accept("mouse1", self.grabPiece)  # left-click grabs a piece
        self.accept("mouse1-up", self.releasePiece)  # releasing places it

    # This function swaps the positions of two pieces
    def swapPieces(self, fr, to):
        temp = self.pieces[fr]
        self.pieces[fr] = self.pieces[to]
        self.pieces[to] = temp
        if self.pieces[fr]:
            self.pieces[fr].square = fr
            self.pieces[fr].obj.setPos(SquarePos(fr))
        if self.pieces[to]:
            self.pieces[to].square = to
            self.pieces[to].obj.setPos(SquarePos(to))

    def mouseTask(self, task):
        # This task deals with the highlighting and dragging based on the mouse

        # First, clear the current highlight
        if self.hiSq is not False:
            self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
            self.hiSq = False

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

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

            # If we are dragging something, set the position of the object
            # to be at the appropriate point over the plane of the board
            if self.dragging is not False:
                # Gets the point described by pickerRay.getOrigin(), which is relative to
                # camera, relative instead to render
                nearPoint = render.getRelativePoint(camera,
                                                    self.pickerRay.getOrigin())
                # Same thing with the direction of the ray
                nearVec = render.getRelativeVector(
                    camera, self.pickerRay.getDirection())
                self.pieces[self.dragging].obj.setPos(
                    PointAtZ(.5, nearPoint, nearVec))

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

        return Task.cont

    def grabPiece(self):
        # If a square is highlighted and it has a piece, set it to dragging
        # mode
        if self.hiSq is not False and self.pieces[self.hiSq]:
            self.dragging = self.hiSq
            self.hiSq = False

    def releasePiece(self):
        # Letting go of a piece. If we are not on a square, return it to its original
        # position. Otherwise, swap it with the piece in the new square
        # Make sure we really are dragging something
        if self.dragging is not False:
            # We have let go of the piece, but we are not on a square
            if self.hiSq is False:
                self.pieces[self.dragging].obj.setPos(SquarePos(self.dragging))
            else:
                # Otherwise, swap the pieces
                self.swapPieces(self.dragging, self.hiSq)

        # We are no longer dragging anything
        self.dragging = False

    def setupLights(self):  # This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 45, -45))
        directionalLight.setColor((0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
예제 #44
0
class Viewfinder(DirectFrame):
    notify = directNotify.newCategory("Viewfinder")

    Ratio = 0.91
    GoodRows = 13
    BadRows = 4
    RaySpreadX = 0.08
    RaySpreadY = 0.06
    ViewSizeX = (GoodRows - BadRows) * RaySpreadX
    ViewSizeY = (GoodRows - BadRows) * RaySpreadY

    def __init__(self, size):
        DirectFrame.__init__(self,
                             parent=aspect2d,
                             pos=(0, -1.0, 0),
                             relief=None)
        image = loader.loadModel(
            "phase_4/models/minigames/photo_game_viewfinder.bam")
        self['image'] = image
        self['image_scale'] = (size, 1.0, size)

        self.screenSizeMult = size * Viewfinder.Ratio

        self.setTransparency(True)
        self.setDepthWrite(1)
        self.setDepthTest(1)

        self.initialiseoptions(Viewfinder)

        self.captureCam = NodePath(Camera("CaptureCamera"))
        self.captureCam.reparentTo(base.camera)
        self.captureLens = PerspectiveLens()
        self.captureCam.node().setLens(self.captureLens)

        self.focusTrav = CollisionTraverser('focusTrav')
        ray = CollisionRay()
        rayNode = CollisionNode('rayNode')
        rayNode.addSolid(ray)
        rayNode.setCollideMask(BitMask32(0))
        rayNode.setFromCollideMask(CIGlobals.WallBitmask)
        self.focusRay = ray
        self.focusRayNode = self.captureCam.attachNewNode(rayNode)
        self.focusHandler = CollisionHandlerQueue()
        self.focusTrav.addCollider(self.focusRayNode, self.focusHandler)

        self.textureBuffer = base.win.makeTextureBuffer(
            "ViewFinderCapture", int(128 * 1.33), 128)
        self.displayRegion = self.textureBuffer.makeDisplayRegion()
        self.displayRegion.setCamera(self.captureCam)

        self.__updateRegions()

        taskMgr.add(self.__update, "viewfinderUpdate")

    def takePicture(self):
        return self.displayRegion.getScreenshot()

    def takePictureRaw(self):
        img = PNMImage()
        tex = self.takePicture()
        tex.store(img)

        ss = StringStream()
        img.write(ss, 'jpg')

        if 1:
            # Test it
            img2 = PNMImage()
            img2.read(ss)
            img2.write(Filename("test_viewfinder.jpg"))

        return ss.getData()

    def isInView(self, nodePath):
        """
        Returns True if the `nodePath` is both in the bounds of the
        camera lens and not occluded by anything.
        """

        if not nodePath or not isinstance(nodePath, RemoteCameraShyAvatar):
            return False

        nodePath = nodePath.avatar

        lensBounds = self.captureCam.node().getLens().makeBounds()
        bounds = nodePath.getBounds()
        bounds.xform(nodePath.getParent().getMat(self.captureCam))
        inView = lensBounds.contains(bounds)

        if inView:
            # We have another step, make sure they're not occluded by another object.
            self.focusRayNode.lookAt(nodePath)
            self.focusTrav.traverse(render)
            if self.focusHandler.getNumEntries() > 0:

                self.focusHandler.sortEntries()

                collNP = self.focusHandler.getEntry(0).getIntoNodePath()
                parentNP = collNP.getParent().getPythonTag('player')
                # Make sure this is the same NodePath that was passed in.
                if parentNP == nodePath:
                    return True

        return False

    def __updateRegions(self):
        self.screenSizeX = (base.a2dRight - base.a2dLeft) * self.screenSizeMult
        self.screenSizeY = (base.a2dTop - base.a2dBottom) * self.screenSizeMult
        self.captureFOV = (
            Viewfinder.ViewSizeX / self.screenSizeX *
            CIGlobals.getSettingsMgr().getSetting("fpmgfov").getValue() * 0.5)
        self.captureLens.setFov(self.captureFOV)
        self.captureLens.setAspectRatio(1.33)

    def __update(self, task):
        self.__updateRegions()
        return task.cont

    def cleanup(self):
        taskMgr.remove("viewfinderUpdate")
        self.captureCam.removeNode()
        del self.captureCam
        del self.screenSizeX
        del self.screenSizeY
        del self.captureLens
        del self.captureFOV
        del self.screenSizeMult
        self.focusRayNode.removeNode()
        del self.focusRayNode
        del self.focusRay
        del self.focusTrav
        del self.focusHandler
        self.destroy()
예제 #45
0
파일: mode_head.py 프로젝트: noPounch/golog
class mode_head():
    def __init__(self,base,Golog, folder_path = None, parent = None):
        # Set up basic attributes
        self.base = base
        self.golog = Golog
        self.bools = {'textboxes':True}
        self.buttons = dict()
        self.window_tasks = dict()
        self.bt = None
        self.mw = None
        self.listener = DirectObject()
        self.folder_path = folder_path #absolute path of golog folder '/path/to/golog/folder'
        if self.folder_path:
            self.file_path = os.path.abspath(self.folder_path + '/' + self.golog.label+ '.golog')
            autosave = True
        self.has_window = False
        self.parent = parent #for autosaving up to original golog
        self.reset = self.basic_reset
        self.garbage = [] #list of deleted math_data/graphics_data etc.


        #create a 2d rende
        self.render2d = NodePath('2d render')
        self.camera2D = self.render2d.attachNewNode(Camera('2d Camera'))
        self.camera2D.setDepthTest(False)
        self.camera2D.setDepthWrite(False)
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setNearFar(-1000, 1000)
        self.camera2D.node().setLens(lens)


        # make a dictionary of mode_heads in the underlying golog
        if hasattr(self.golog,'mode_heads'):
            m = 0
            while m in self.golog.mode_heads.keys(): m+=1 #get smallest unused mode_head index
            self.index = m
            self.label = self.golog.label+"_mode_head_"+str(self.index)
            self.golog.mode_heads[self.index] = self

        else:
            self.golog.mode_heads = dict()
            self.index = 0
            self.label = self.golog.label+"_mode_head_"+ str(self.index)
            self.golog.mode_heads[self.index] = self
        ##########

        ### set up collision handling ###
        self.queue = CollisionHandlerQueue()

        ### set up selection tools
        self.create_list = [[],[]] #select nodes and add to create_list in order to create higher simplecies
        self.bools = {'selecter':False,'textboxes':True,'shift_clicked':False} #some bools that will be usefull
        self.dict = {'shift_pt':[None,None]}


        # set up mouse picker
        self.pickerNode = CollisionNode('mouseRay')
        self.pickerNP = self.golog.camera.attachNewNode(self.pickerNode) #attach collision node to camera
        self.pickerRay = CollisionRay()
        self.pickerNode.addSolid(self.pickerRay)
        self.pickerNode.set_into_collide_mask(0) #so that collision rays don't collide into each other if there are two mode_heads
        self.golog.cTrav.addCollider(self.pickerNP,self.queue) #send collisions to self.queue
        # set up plane for picking
        self.planeNode = self.golog.render.attachNewNode("plane")
        self.planeNode.setTag("mode_head",self.label) # tag to say it belongs to this mode_head
        self.planeNode.setTag("mode_node", 'plane')
        self.planeFromObject = self.planeNode.attachNewNode(CollisionNode("planeColNode"))
        self.planeFromObject.node().addSolid(CollisionPlane(Plane(Vec3(0,-1,0),Point3(0,0,0))))
        self.plane = self.planeFromObject.node().getSolid(0)
        ###
        # set up preview text
        self.textNP = self.render2d.attachNewNode(TextNode('text node'))
        self.textNP.setScale(.2)
        self.textNP.setPos(-1,0,0)
        self.textNP.show()
        #set up dragging info
        self.grabbed_dict = dict()
        self.drag_dict = dict() #a mapping from selected nodes to their original positions for dragging
        self.mouse_down_loc = (0,0,0)
        self.lowest_level = 3

    def open_math_data(self,math_data):
        if math_data.type == 'golog':
            golog_dict = math_data() #calls the mathdata (which is a golog_dict)
            subgolog = golog_dict['golog']
            subfolder_path = golog_dict['folder_path']

            #### just to be safe, but probably not needed
            subgolog_folder_path = os.path.join(self.folder_path,'subgologs')
            if not os.path.exists(subgolog_folder_path): os.mkdir(subgolog_folder_path)
            ####
            folder_path = os.path.join(self.folder_path, *golog_dict['folder_path'])
            print(folder_path)
            controllable_golog = mode_head(self.base, subgolog, folder_path = folder_path, parent = self)
            window_manager.modeHeadToWindow(self.base, controllable_golog)

        if math_data.type == 'file':
            file_name, file_extension = os.path.splitext(math_data()[-1])
            # if file_extension == '.txt':
            #     tk_funcs.edit_txt(os.path.join(self.folder_path,*math_data()))
            # else:
                #prompt user to select a program
            tk_funcs.run_program('',os.path.join(self.folder_path,*math_data()))
        if math_data.type == 'latex':
            file_dict = math_data()
            tex_folder = os.path.join(os.path.abspath(self.folder_path),*file_dict['folder'])
            tex_file = os.path.join(os.path.abspath(self.folder_path),*file_dict['tex'])




            if 'pdf' in file_dict.keys():
                pdf_file = os.path.join(self.folder_path, *file_dict['pdf'])
            elif os.path.exists(tex_file.split('.tex')[0]+'.pdf'): #if there is a pdf in the folder with the same name
                file_dict['pdf'] = file_dict['tex']
                file_dict['pdf'][-1] = file_dict['pdf'][-1].split('.tex')[0]+'.pdf' #change extension to .pdf
                pdf_file = os.path.join(self.folder_path, *file_dict['pdf'])
            else: pdf_file = None


            tk_funcs.pdf_or_tex(pdf_file, tex_file)

        if math_data.type == 'weblink':
            open_new_tab(math_data())

    def update_math_data(self,simplex, math_data_type, **kwargs):


        if autosave == True: self.save()

        if 'label' in kwargs: simplex.label = kwargs['label']
        self.golog.Simplex_to_Graphics[simplex].textNP.node().setText(simplex.label)
        self.golog.text_preview_set(self.bools['textboxes'])

        if simplex.math_data.type != 'None':
            answer = tk_funcs.are_you_sure('are you sure you want to delete the current math_data?')
            if answer == 'yes':
                self.delete_math_data(simplex)
            else: return
        if math_data_type == 'None':
            simplex.math_data = hcat.Math_Data(type = 'None')

        if math_data_type == 'golog':

            #create a path for all subgologs, if it doesn't already exist
            subgolog_folder_path = os.path.join(self.folder_path,'subgologs')
            if not os.path.exists(subgolog_folder_path): os.mkdir(subgolog_folder_path)




            new_golog = golog.golog(self.base, label = kwargs['label']) #create a new golog

            #create a unique folder path list in subgolog_folder_path
            unique_path = tk_funcs.unique_path(subgolog_folder_path,[kwargs['label']])
            new_folder_path = ['subgologs', *unique_path]
            os.mkdir(os.path.join(self.folder_path , *new_folder_path)) #make the directory as above
            #create a new golog save at new_folder_path/label.golog
            new_save_location = os.path.join(self.folder_path, *new_folder_path, kwargs['label']+'.golog')

            #new_save_location should be a subfolder of subgologs
            gexport(new_golog, new_save_location)

            #math data is a dictionary of the physical golog and it's relative save path list
            golog_dict = {'golog':new_golog, 'folder_path':new_folder_path}
            simplex.math_data = hcat.Math_Data(math_data = golog_dict, type = 'golog')

        if math_data_type == 'file':
            if not os.path.exists(os.path.join(self.folder_path,'files')): os.mkdir(os.path.join(self.folder_path,'files'))
            file_folder_path = ['files']

            file_location = tk_funcs.ask_file_location()
            if not file_location: return #if user cancels
            file_name = os.path.split(file_location)[1] #file name with extension
            file_path = tk_funcs.unique_path(os.path.join(self.folder_path),[*file_folder_path, file_name]) #get a unique file path starting from the file_folder
            copyfile(file_location, os.path.join(self.folder_path,*file_path))
            simplex.math_data = hcat.Math_Data(math_data = file_path, type = 'file')
            #? add handler for if user exits text editor
            #? make asynchronous

        if math_data_type == 'latex':
            #ensure latex folder exists
            if not os.path.exists(os.path.join(self.folder_path,'latex')): os.mkdir(os.path.join(self.folder_path,'latex'))

            # create a uniquely named folder in self.folder_path/latex/ based on simplex.label
            tex_folder_path = tk_funcs.unique_path(root = self.folder_path, path = ['latex',simplex.label])
            os.mkdir(os.path.join(self.folder_path, *tex_folder_path))
            #create a tex file in tex folder
            tex_file_path = [*tex_folder_path, simplex.label+'.tex']
            # ask if want new or to load one
            location = tk_funcs.load_tex(self.folder_path)
            # if new, returns True and copies template tex file
            # if load, returns a path and copies the path into tex_file_path
            true_path = os.path.join(self.folder_path,*tex_file_path)
            if location == True: copyfile(os.path.abspath('./misc_data/config_files/template.tex'), true_path)

                #
                # open(   true_path  , 'w').close()
            if isinstance(location, str): copyfile(location, true_path)

            # make a file dictionary with just tex file in it
            file_dict = {'tex':tex_file_path, 'folder':tex_folder_path}
            simplex.math_data = hcat.Math_Data(math_data = file_dict, type = 'latex')

        if math_data_type == 'weblink':
            weblink = tk_funcs.ask_weblink()
            simplex.math_data = hcat.Math_Data(math_data = weblink, type = 'weblink')


        if math_data_type == 'text':
            #create a text file
            if not os.path.exists(os.path.join(self.folder_path,'files')): os.mkdir(os.path.join(self.folder_path,'files'))
            file_folder_path = ['files']
            file_path = tk_funcs.unique_path(root = self.folder_path, path = ['files',simplex.label+'.txt' ])
            with open(os.path.join(self.folder_path, *file_path),'w') as file: pass
            #create a math_data for it
            simplex.math_data = hcat.Math_Data(math_data = file_path, type = 'file')



        #save golog
        if autosave == True: self.save()
        return simplex.math_data

    def delete_math_data(self,simplex,**kwargs):
        simplex.math_data.delete(self.folder_path)
        simplex.math_data = hcat.Math_Data(type = 'None')

    def setup_window(self, windict):
        self.windict = windict
        for button in self.buttons.keys():
            self.listener.accept(self.windict['bt'].prefix+button, self.buttons[button], extraArgs = [self.windict['mw']])
        for window_task in self.window_tasks.keys():
            base.taskMgr.add(self.window_tasks[window_task], window_task, extraArgs = [self.windict['mw']], appendTask = True)
        self.has_window = True

    def save(self, *ask):
        #if has a parent, save the parent. If not, save itself
        if not self.parent: #if doesn't have a parent mode_head, save parent
        #if we pass something to ask it will ask (this includes mousewatchers)
            if ask:
                save_location = tk_funcs.ask_file_location(initial_dir = self.folder_path)
                if not save_location: return #if user cancels
                print('saving to:\n'+save_location)
                gexport(self.golog,  self.folder_path)
            else:
                gexport(self.golog,  self.file_path)

        else: self.parent.save()# if parent has no mode_head, save itself

    #basic reset function which shuts off the listener and removes button bindings. Should only be called if no "reset" function exists
    def basic_reset(self,*args):
        self.buttons = dict()
        self.window_tasks = dict()
        self.listener.ignoreAll()

    #function to call before deleting the mode_head, for example when closing a window
    def clean(self):
        self.reset()

        #close window
        if self.has_window == True:
            if hasattr(mode_head,'windict'):
                if 'win' in mode_head.windict.keys():
                    self.base.closeWindow(mode_head.windict['win'], keepCamera = True, removeWindow = True)
            self.has_window = False
        del self.golog.mode_heads[self.index]
        del self.reset

    # function to return the only the relevant collision data from the mouseRay
    def get_relevant_entries(self, mw):
        # get list of entries by distance
        if not mw.node().hasMouse(): return
        mpos = mw.node().getMouse()
        self.pickerRay.setFromLens(self.golog.camNode,mpos.getX(),mpos.getY()) #mouse ray goes from camera through the 'lens plane' at position of mouse
        self.golog.cTrav.traverse(self.golog.render)
        self.queue.sortEntries()

        # get the first relevant node traversed by mouseRay
        #### ignore everything with a mode_head tag that is not defined by this mode_head
        for e in self.queue.getEntries():
            if e.getIntoNodePath().getParent().hasTag("mode_head"):
                if e.getIntoNodePath().getParent().getTag("mode_head") == self.label:
                    return (e.getIntoNodePath().getParent(), e.getIntoNodePath().getParent().getTag("mode_node"),e.getSurfacePoint(e.getIntoNodePath()))
                    break
            else:
                entry = e
                break

        #return node create_list in the golog
        entryNP = entry.getIntoNodePath().getParent()
        if entryNP.hasTag('level'): return (entryNP, entryNP.getTag('level'),entryNP.getPos())

    #function to 'pick up' a node by adding it to the dragged dictionary
    def pickup(self, mw):
        if not mw.node().hasMouse(): return
        (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)
        


        ### get position on plane for mouseloc
        mpos = mw.node().getMouse()
        self.pickerRay.setFromLens(self.golog.camNode,mpos.getX(),mpos.getY()) #mouse ray goes from camera through the 'lens plane' at position of mouse
        self.golog.cTrav.traverse(self.golog.render)
        self.queue.sortEntries()
        for e in self.queue.getEntries():
            if e.getIntoNodePath().getParent().hasTag("mode_head"):
                if e.getIntoNodePath().getParent().getTag("mode_head") == self.label:
                    if e.getIntoNodePath().getParent().getTag("mode_node") == 'plane':
                        self.mouse_down_loc = e.getSurfacePoint(e.getIntoNodePath())
                        break


        #if selected node is in the drag_dict, use it to set a mouse location
        # if entryNP in self.drag_dict.keys(): self.mouse_down_loc = entryNP.getPos()

        if node_type in ['0','1']:
            self.grabbed_dict = {'graphics': self.golog.NP_to_Graphics[entryNP],'dragged':False,
                                                        'orig_pos': entryNP.getPos()}
        if node_type == 'plane':
            for node in self.create_list[0]: node.setColorScale(1,1,1,1) #turn white
            self.create_list = [[],[]]
            for node in self.drag_dict.keys():  node.setColorScale(1,1,1,1)
            self.drag_dict = dict() #drag dict is used for multi-dragging
            a = self.plane.distToPlane(self.golog.camera.getPos())/(2*self.golog.camera.node().getLens().getNear())# ratio for camera movement
            self.grabbed_dict = {'graphics':self.golog.camera, 'dragged':False, 'orig_pos': self.golog.camera.getPos(), 'mpos': LPoint3f(a*mpos.getX(),a*0,a*mpos.getY())}
            self.lowest_level = 3



    #function to 'put down' a node, returns true if it's dragged something
    def putdown(self, mw):
        for node in self.drag_dict.keys():
            self.drag_dict[node] = self.golog.NP_to_Graphics[node].graphics_kwargs['pos']
            self.lowest_level = min(self.lowest_level, int(node.getTag('level')))

        if 'dragged' in self.grabbed_dict.keys():
            if self.grabbed_dict['dragged'] == True:
                self.grabbed_dict = dict()
                return True
            self.grabbed_dict = dict()
    #function to select a node and add a 1-simplex between 2 create_list 0-simplecies
    def select_for_creation(self, mw):
        if not mw.node().hasMouse(): return
        #remove selected
        for node in self.drag_dict.keys():
            node.setColorScale(1,1,1,1)
        self.drag_dict = dict()
        self.lowest_level = 3

        ### selection ###
        (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)
        if node_type == '0':# and set(create_list[1:]) = {[]}:
            if entryNP not in self.create_list[0]:
                #?  don't just append, re-sort
                self.create_list[0].append(entryNP)
            entryNP.setColorScale(1,0,0,0) #turn red

        if len(self.create_list[0]) == 2:
            # NP -> graphics -> simplex
            faces = tuple([self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[faceNP]] for faceNP in self.create_list[0][-1:-3:-1]])
            asked_list = tk_funcs.ask_math_data('1-Simplex')
            if not asked_list: #[label, math_data_type,]
                return
            simplex = self.golog.add(faces, label = asked_list[0]) #reversed create_list objects and creates a 1 - simplex from them
            self.update_math_data(simplex, asked_list[1], label = asked_list[0])
            for node in self.create_list[0]: node.setColorScale(1,1,1,1)
            self.create_list[0] = [] #reset create_list

    #open math_data of simplex under mouse
    def mouse_open(self, mw):
        (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)

        # if spaced on a 0 simplex, open it's math data, or create it
        if node_type in ['0','1']:
            simplex = self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]]
            if not simplex.math_data():
                asked_list = tk_funcs.ask_math_data(simplex.label)
                if not asked_list:
                    return
                self.update_math_data(simplex, math_data_type = asked_list[1], label = asked_list[0])
                #? make asynchronous


            else:
                self.open_math_data(simplex.math_data)

    # delete a simplex, prompt to delete the math_data and (recursively) it's supported simplecies
    def delete(self,mw):
        (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)
        if node_type in ['0','1']:
            #warning about deleting supported simplecies

            graphics = self.golog.NP_to_Graphics[entryNP]
            simplex = self.golog.Graphics_to_Simplex[graphics]

            if simplex.supports:
                answer = tk_funcs.are_you_sure(simplex.label+' still supports other simplecies. Are you sure you wish to delete?')
                if answer != 'yes': return

            self.delete_math_data(simplex)
            graphics._remove()

    #update the math_data of a simplex under the mouse
    def mouse_update(self, mw):
        (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)
        if node_type in ['0','1']:
            simplex = self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]]
            asked_list = tk_funcs.ask_math_data(simplex.label)
            if not asked_list:
                return
            self.update_math_data(simplex, math_data_type = asked_list[1], label = asked_list[0])

    #create a simplex given a mouse position
    def create(self, mw):
        (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)

        if node_type == 'plane':
            for node in self.create_list[0]: node.setColorScale(1,1,1,1) #turn white
            self.create_list = [[],[]]
            asked_list = tk_funcs.ask_math_data('0-Simplex')
            if not asked_list:
                return #if canceled, do not create a simplex
            simplex = self.golog.add(0, pos = entry_pos, label = asked_list[0]) #create a simplex
            self.update_math_data(simplex, math_data_type = asked_list[1], label = asked_list[0])

    #function which checks the drag dictionary and drags stuff
    def drag(self, mw):
        if self.grabbed_dict:
            #get mouse_loc
            mpos = mw.node().getMouse()
            self.pickerRay.setFromLens(self.golog.camNode,mpos.getX(),mpos.getY()) #mouse ray goes from camera through the 'lens plane' at position of mouse
            self.golog.cTrav.traverse(self.golog.render)
            self.queue.sortEntries()
            mouseloc = None
            for e in self.queue.getEntries():
                if e.getIntoNodePath().getParent().getTag("mode_node") == 'plane':
                    mouseloc = e.getSurfacePoint(e.getIntoNodePath())
                    break
            if not mouseloc:return

            self.bools['dragging'] = True


             # if there is something in the drag dict (for multiselect)
            if self.drag_dict:
                self.grabbed_dict['dragged'] = True
                #only drag lowest dim simplecies
                for node in self.drag_dict.keys():
                    if int(node.getTag('level')) == self.lowest_level: self.golog.NP_to_Graphics[node].update({'pos':self.drag_dict[node]+mouseloc-self.mouse_down_loc})

            #if nothing is selected, drag the thing below you
            elif self.grabbed_dict['graphics'] != self.golog.camera: 
                #radius of drag selection
                offset = mouseloc - self.grabbed_dict['graphics'].parent_pos_convolution()
                delta = offset - self.grabbed_dict['orig_pos']
                norm = delta.getX()**2 +delta.getY()**2 +delta.getZ()**2
                if self.grabbed_dict['dragged'] == True or norm > 1:
                    self.grabbed_dict['dragged'] = True
                #if offset magnitude is greater than 1 or dragged == true, actually drag it
                if self.grabbed_dict['dragged'] == True: self.grabbed_dict['graphics'].update({'pos':offset})

            elif self.grabbed_dict['graphics'] == self.golog.camera: 
                        a = self.plane.distToPlane(self.golog.camera.getPos())/(2*self.golog.camera.node().getLens().getNear())# ratio for camera movement
                        self.golog.camera.setPos(self.grabbed_dict['orig_pos']-(a*mpos.getX(),0,a*mpos.getY())+self.grabbed_dict['mpos'])

           
                    


    #send preview of math_data of simplex under the mouse
    def preview(self, mw):
        (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)

        if node_type == '0':
            simplex =  self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]]
        elif node_type == '1':
            #? again consider what needs to be shown with 1-simplecies
            simplex =  self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]]
        else: return

        # set preview up
        if self.has_window:
            if simplex.math_data.type == 'golog':
                self.windict['preview_dr'].setCamera(simplex.math_data()['golog'].camera)
            else:
                self.windict['preview_dr'].setCamera(self.camera2D)
                self.textNP.node().setText("label:\n" +simplex.label+"\n\n math data type:\n" + simplex.math_data.type)
        return

    def pprint(self,mw):
        (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)

        if node_type == '0':
            simplex =  self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]]
        elif node_type == '1':
            #? again consider what needs to be shown with 1-simplecies
            simplex =  self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]]
        else: return

        simplex.pprint()


    #tool for selecting multiple simplecies
    def multi_select(self,mw):
        if isinstance(mw, NodePath):
            entryNP = mw
            node_type = entryNP.getTag('level')
        else: return

        #reset select and create
        if node_type in ['0','1']:
            if entryNP in self.drag_dict.keys():
                del self.drag_dict[entryNP]
                entryNP.setColorScale(1,1,1,1)
                self.lowest_level = min([*[int(node.getTag('level')) for node in self.drag_dict.keys()],3])
            else:
                self.drag_dict[entryNP] = self.golog.NP_to_Graphics[entryNP].graphics_kwargs['pos']
                entryNP.setColorScale(.5,.5,0,1)
                self.lowest_level = min(self.lowest_level, int(entryNP.getTag('level')))

    def shift_box(self,mw):
        if None in self.dict['shift_pt']:
            self.dict['shift_pt'] = [None,None]
            return
        pt_1 = self.dict['shift_pt'][0]
        pt_2 = self.dict['shift_pt'][1]
        if sum([x**2 for x in list(pt_2-pt_1)]) <= 1:
            (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)
            self.multi_select(entryNP)

        #create vectors
        N = self.planeFromObject.node().getSolid(0).getNormal()
        x = [(pt_2-pt_1).getX(),0,0]
        z = [0,0,(pt_2-pt_1).getZ()]
        campos = list(self.golog.camera.getPos())
        for simplex in self.golog.sSet.rawSimps:
            node = self.golog.Simplex_to_Graphics[simplex].node_list[0]
            P = list(node.getPos())
            if t_int(pt_1,x,z,campos,P): self.multi_select(node)

        self.dict['shift_pt'] = [None,None]


    def consolidate(self, selected = False,sel_simp = None):
        #ask for label, or cancel
        G = self.golog

        # if a collection isn't provided, use the (multi-select) drag dictionary
        if not selected: selected = [G.Graphics_to_Simplex[G.NP_to_Graphics[node]] for node in self.drag_dict.keys()]
        if not selected: return #return if there was nothing passed, and nothing in the drag_dict
        for simp in selected:
            for face in simp.faces:
                if face not in selected: selected.append(face)

        # #? select a simplex to consolidate into
        # sel_simp = None
        # for simp in selected: 
        #     if simp.math_data.type == 'None':
                
        #         sel_simp = simp

        #make a golog from selected
        new_golog = golog.golog(self.base, label ='test')

        def add(simplex):
            for face in simplex.faces:
                add(face)
            new_golog.add(simplex, pos = G.Simplex_to_Graphics[simplex].graphics_kwargs['pos'])
        for simplex in selected: add(simplex)
        

        #consolidate into 1 simplex
        if sel_simp:
            #consolidate into sel_simp
            subgolog_folder_path = os.path.join(self.folder_path,'subgologs')
            unique_path = tk_funcs.unique_path(subgolog_folder_path,[sel_simp.label])
            new_folder_path = ['subgologs', *unique_path]
            
            sel_simp.math_data = hcat.Math_Data(math_data = {'golog':new_golog, 'folder_path':new_folder_path}, type = 'golog')
            
            #? remove simplexes and place at selected simplex location
            return sel_simp


        #create an entirely new simplex to put the golog into
        else:
            #? ask for label / cancel
            label = "test"
            subgolog_folder_path = os.path.join(self.folder_path,'subgologs')
            unique_path = tk_funcs.unique_path(subgolog_folder_path,[label])
            new_folder_path = ['subgologs', *unique_path]

            #create a simplex with average position of things in golog
            avg = LPoint3f(*[sum([G.Simplex_to_Graphics[simplex].graphics_kwargs['pos'][i]/len(new_golog.sSet.simplecies[()])  for simplex in new_golog.sSet.simplecies[()]]) for i in range(3)])
            s = self.golog.add(0, label ='test', math_data = hcat.Math_Data(math_data = {'golog':new_golog, 'folder_path':new_folder_path}, type = 'golog'), pos = LPoint3f(avg))

            return s

    ########## BEGIN DEFINING MODES ##########

    #selection and creation mode
    def selection_and_creation(self, windict):
        def mouse1(mw):
            if not mw: return
            self.bools['shift_clicked'] = False
            self.pickup(mw)

        def shift_mouse1(mw):
            if not mw: return
            #on click, begin a rectagle dragging function
            (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)
            self.dict['shift_pt'][0] = entry_pos
            self.bools['shift_clicked'] = True

        def mouse1_up(mw):
            dropped_bool = self.putdown(mw)
            if self.bools['shift_clicked']:
                (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw)
                self.dict['shift_pt'][1] = entry_pos
                self.shift_box(mw)
                self.bools['shift_clicked'] = False

            elif dropped_bool:
                pass
            else:
                self.select_for_creation(mw)




        def space(mw):
            if not mw: return
            self.mouse_open(mw)

        def u(mw):
            if not mw: return
            #?  do a change not just update
            self.mouse_update(mw)

        def c(mw):
            self.consolidate()
        def p(mw):
            if not mw: return
            self.pprint(mw)

        def mouse3(mw):
            if not mw: return
            self.create(mw)

        def backspace(mw):
            if not mw: return
            self.delete(mw)

        def mouse_watch_task(mw,task):
            if not mw: return task.cont
            if not mw.node().hasMouse(): return task.cont
            self.drag(mw)
            self.preview(mw)
            return task.cont

        def wheel_up(mw):
            if not mw:return
            a = self.plane.distToPlane(self.golog.camera.getPos())/(2*self.golog.camera.node().getLens().getNear())# ratio for camera movement
            self.golog.camera.setPos( self.golog.camera.getPos() + (0,10,0) ) #fix for offset by storing a global camera - plane ratio

        def wheel_down(mw):
            if not mw:return
            self.golog.camera.setPos( self.golog.camera.getPos() - (0,10,0) )

        def reset(*args):
            self.buttons = dict()
            self.window_task = dict()
            self.reset = self.basic_reset
        self.reset = reset

        self.buttons = {'mouse1':mouse1, 'mouse1-up':mouse1_up, 'mouse3':mouse3,'c':c,
        'space':space, 'escape':self.reset, 's':self.save, 'u':u,'backspace':backspace,
        'shift-mouse1':shift_mouse1,'p':p,'wheel_up':wheel_up, "wheel_down":wheel_down}
        self.window_tasks = {'mouse_watch_task':mouse_watch_task}
        self.setup_window(windict)
예제 #46
0
class Mouse(object):
    def __init__(self, base, oid_texture):
        self.base = base
        self.picking_texture = oid_texture
        self.picker = CollisionTraverser()
        self.pq = CollisionHandlerQueue()
        self.pickerNode = CollisionNode('mouseRay')
        self.pickerNP = self.base.cam.attachNewNode(self.pickerNode)
        self.pickerNode.setFromCollideMask(
            CollisionNode.getDefaultCollideMask()
            | GeomNode.getDefaultCollideMask())
        self.pickerRay = CollisionRay()
        self.pickerNode.addSolid(self.pickerRay)
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)
        if settings.mouse_over:
            taskMgr.add(self.mouse_task, 'mouse-task')
        self.over = None

    def find_over_ray(self):
        over = None
        if self.base.mouseWatcherNode.hasMouse():
            mpos = self.base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(self.base.camNode, mpos.getX(),
                                       mpos.getY())
            self.picker.traverse(render)
            if self.pq.getNumEntries() > 0:
                self.pq.sortEntries()
                np = self.pq.getEntry(0).getIntoNodePath().findNetPythonTag(
                    'owner')
                owner = np.getPythonTag('owner')
                over = owner
                np = self.pq.getEntry(0).getIntoNodePath().findNetPythonTag(
                    'patch')
                if np is not None:
                    self.patch = np.getPythonTag('patch')
                else:
                    self.patch = None
        return over

    def find_over_color(self):
        over = None
        if self.base.mouseWatcherNode.hasMouse():
            mpos = self.base.mouseWatcherNode.getMouse()
            self.base.graphicsEngine.extract_texture_data(
                self.picking_texture, self.base.win.gsg)
            texture_peeker = self.picking_texture.peek()
            if texture_peeker is not None:
                x = (mpos.get_x() + 1) / 2
                y = (mpos.get_y() + 1) / 2
                value = LColor()
                texture_peeker.lookup(value, x, y)
                oid = color_to_int(value)
                if oid != 0:
                    over = objectsDB.get_oid(oid)
                    if over is None:
                        print("Unknown oid", oid, value)
        return over

    def find_over(self):
        if settings.color_picking:
            over_color = self.find_over_color()
        else:
            over_color = None
        over_ray = self.find_over_ray()
        over = over_color
        if over_ray is not None:
            if over is None or over.distance_to_obs > over_ray.distance_to_obs:
                over = over_ray
        if hasattr(over, "primary") and over.primary is not None:
            over = over.primary
        return over

    def get_over(self):
        if settings.mouse_over:
            over = self.over
        else:
            over = self.find_over()
        return over

    def mouse_task(self, task):
        if self.base.mouseWatcherNode.hasMouse():
            self.over = self.find_over()
        return Task.cont
예제 #47
0
class GameApp:

    def __init__(self):
        self.gameEventHandler = GameEventHandler(self)
        self.camLimits = ((-5, 5), (-6.5, 5), (1, 10))
        self.gameReady = False
        self.hovered = None
        self.clicked = None
        self.modelToFigure = {}
        self.modelToField = {}
        self.modelToSeaField = {}
        self.modelToBuildingField = {}
        self.modelToBuilding = {}
        # self.highlightableObjects = render.attachNewNode('highlightables')
        self.setupColisionForHighlight()
        self.songMenu = None
        self.buildMenu = None

    def setupColisionForHighlight(self):
        # Since we are using collision detection to do picking, we set it up like
        # any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  # Make a traverser
        self.pq = CollisionHandlerQueue()  # Make a handler
        # Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        # Attach that node to the camera since the ray will need to be positioned
        # relative to it
        self.pickerNP = self.camera.attachNewNode(self.pickerNode)
        # Everything to be picked will use bit 1. This way if we were doing other
        # collision we could seperate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  # Make our ray
        # Add it to the collision node
        self.pickerNode.addSolid(self.pickerRay)
        # Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)

    def getCameraCoords(self):
        return self.camera.getPos()

    def setCameraCoords(self, x, y, z):
        self.camera.setPos(x, y, z)

    def getMouseCoords(self):
        if self.mouseWatcherNode.hasMouse():
            return self.mouseWatcherNode.getMouse()
        return None

    def drawIsland(self, island, suppressRot=False):
        island.model.setPos(island.pos[0], island.pos[1], 0.001)
        island.model.setScale(0.05, 0.05, 0.05)
        island.model.reparentTo(self.render)
        for f in range(0, 6):
            circle = self.loader.loadModel('models/circle')
            pos = (island.fields[f].x, island.fields[f].y, 0.4)
            circle.setPos(pos)
            circle.setScale(0.4)
            circle.reparentTo(island.model)
            circle.setTag('clickable', 'true')
            cs = CollisionSphere(0, 0, 0, 1)
            cnodePath = circle.attachNewNode(CollisionNode('cnode'))
            cnodePath.node().addSolid(cs)
            island.fields[f].model = circle
            self.modelToField[circle.getKey()] = island.fields[f]

        for i in range(0, 3):
            buildingField = island.buildingFields[i]
            circle = self.loader.loadModel('models/circle')
            pos = (buildingField.x, buildingField.y, 0.1)
            circle.setPos(pos)
            circle.setScale(0.6)
            circle.reparentTo(island.model)
            circle.setTag('clickable', 'true')
            cs = CollisionSphere(0, 0, 0, 1)
            cnodePath = circle.attachNewNode(CollisionNode('cnode'))
            cnodePath.node().addSolid(cs)
            buildingField.model = circle
            self.modelToBuildingField[circle.getKey()] = buildingField

        # put the bay field
        circle = self.loader.loadModel('models/circle')
        pos = (island.bay.x, island.bay.y, 0.2)
        circle.setPos(pos)
        circle.setScale(0.6)
        circle.reparentTo(island.model)
        circle.setTag('clickable', 'true')
        cs = CollisionSphere(0, 0, 0, 1)
        cnodePath = circle.attachNewNode(CollisionNode('cnode'))
        cnodePath.node().addSolid(cs)
        island.bay.model = circle
        self.modelToSeaField[circle.getKey()] = island.bay
        degree = angle((0, 1), island.pos) * 180 / math.pi
        if island.pos[0] > 0:
            degree *= -1
        if not suppressRot:
            island.model.setHpr(degree, 0, 0)

    def drawFigures(self):
        for player in self.game.players:
            for figure in player.figures:
                if hasattr(figure, 'model'):
                    continue
                if type(figure) == Ship:
                    field = figure.field
                    figure.model = self.loader.loadModel('models/ship')
                    figure.model.reparentTo(field.model)
                    cs = CollisionSphere(1.5, 0, 1, 1.3)
                    cnodePath = figure.model.attachNewNode(
                        CollisionNode('cnode'))
                    cnodePath.node().addSolid(cs)
                    # cnodePath.show()
                    cs = CollisionSphere(0, 0, 1.4, 1.3)
                    cnodePath = figure.model.attachNewNode(
                        CollisionNode('cnode'))
                    cnodePath.node().addSolid(cs)
                    # cnodePath.show()
                    cs = CollisionSphere(-1.8, 0, 1, 1)
                    cnodePath = figure.model.attachNewNode(
                        CollisionNode('cnode'))
                    cnodePath.node().addSolid(cs)
                    # cnodePath.show()
                    figure.model.setScale(1.4)
                    figure.model.setHpr(90, 0, 0)
                    # figure.model.setTag('highlightable', 'true')
                    figure.model.setTag('clickable', 'true')
                    self.modelToFigure[figure.model.getKey()] = figure
                else:
                    field = figure.field
                    figure.model = self.loader.loadModel('models/warrior100')
                    figure.model.reparentTo(field.model)
                    cs = CollisionSphere(0, -.35, 7, 1)
                    cnodePath = figure.model.attachNewNode(
                        CollisionNode('cnode'))
                    cnodePath.node().addSolid(cs)
                    figure.model.setScale(0.35)
                    figure.model.setTag('highlightable', 'true')
                    figure.model.setTag('clickable', 'true')
                    self.modelToFigure[figure.model.getKey()] = figure

                col = 256 * int(player.color)
                # set figure title
                title = TextNode(str(figure.model.getKey()) + '_title')
                title.setText(type(figure).__name__)
                title.setCardColor(col, col, col, 1)
                title.setCardAsMargin(0.1, 0.1, 0.1, 0.1)
                title.setCardDecal(True)
                titleNode = self.render.attachNewNode(title)
                titleNode.reparentTo(figure.model)
                titleNode.setScale(3)
                titleNode.setPos(0, 3, 10)
                if type(figure) == Ship:
                    titleNode.setScale(1.5)
                    titleNode.setPos(-1.5, 0, 3)
                titleNode.setBillboardPointEye()

    def drawSeaways(self):
        for field in self.game.board.seawayFields:
            circle = self.loader.loadModel('models/circle')
            pos = (field.x, field.y, 0)
            circle.setPos(pos)
            circle.setScale(0.04)
            circle.setHpr(-90, 0, 0)
            circle.reparentTo(self.render)
            circle.setTag('clickable', 'true')
            cs = CollisionSphere(0, 0, 0, 1)
            cnodePath = circle.attachNewNode(CollisionNode('cnode'))
            cnodePath.node().addSolid(cs)
            field.model = circle
            self.modelToSeaField[circle.getKey()] = field

    def drawBuilding(self, building, field):
        model = self.loader.loadModel('models/house')
        # model.setScale(0.05)
        model.reparentTo(field.model)
        building.model = model
        self.modelToBuilding[model.getKey()] = building
        player = self.game.currentPlayer()
        model.setTag('clickable', 'true')
        cs = CollisionSphere(0, 0, 0, 2)
        cnodePath = model.attachNewNode(CollisionNode('cnode'))
        cnodePath.node().addSolid(cs)
        # cnodePath.show()

        col = 256 * int(player.color)
        # set building title
        title = TextNode(str(building.model.getKey()) + '_title')
        title.setText(building.building)
        title.setCardColor(col, col, col, 1)
        title.setCardAsMargin(0.1, 0.1, 0.1, 0.1)
        title.setCardDecal(True)
        titleNode = self.render.attachNewNode(title)
        titleNode.reparentTo(building.model)
        titleNode.setScale(1.5)
        titleNode.setPos(0, 0, 3)
        titleNode.setBillboardPointEye()

    def drawGame(self, game):
        if not self.gameReady:
            self.game = game
            # menu = OnscreenImage(image = 'textures/menu.png', pos = (1.53, 0, 0), scale=(0.35, 1, 1))
            # menu.setTransparency(TransparencyAttrib.MAlpha)

            # setup the background of the board
            self.environ = self.loader.loadModel('models/plane')
            sea = self.loader.loadTexture('textures/sea.png')
            self.environ.setTexture(sea)
            self.environ.setPos(0, 1, 0)
            self.environ.setScale(1.1)
            sea.setWrapU(Texture.WM_repeat)
            sea.setWrapV(Texture.WM_repeat)
            self.environ.reparentTo(self.render)

            # setup camera
            self.camera.setPos(0, 0, 10)
            self.camera.setHpr(0, -70, 0)
            self.camLens.setNear(0.85)

            # setup lighting
            plight = PointLight('plight')
            plight.setColor(VBase4(1, 1, 1, 3))
            plnp = self.render.attachNewNode(plight)
            plnp.setPos(10, 0, 10)
            self.render.setLight(plnp)
            ambientLight = AmbientLight('ambientLight')
            ambientLight.setColor(Vec4(0.25, 0.25, 0.25, .3))
            ambientLightNP = self.render.attachNewNode(ambientLight)
            self.render.setLight(ambientLightNP)

            # place islands
            first = True
            for island in game.board.islands:
                island.drawable = True
                island.model = self.loader.loadModel('models/island2_104')
                self.drawIsland(island, first)
                first = False

            self.drawFigures()
            self.drawSeaways()

            self.turn = OnscreenText(text='Black\'s turn.',
                                     pos=(0.06, -0.1),
                                     align=TextNode.ALeft,
                                     parent=base.a2dTopLeft,
                                     scale=0.06)
            self.resources = OnscreenText(text='Resources: ',
                                          pos=(0.08, -0.2),
                                          align=TextNode.ALeft,
                                          parent=base.a2dTopLeft,
                                          scale=0.06)
            self.gameReady = True

        player = 'Black'
        if game.turn == 1:
            player = 'White'
        self.turn.setText(player + '\'s turn.')
        resourcesText = 'Resources: ' + \
            str(self.game.currentPlayer().resources)
        self.resources.setText(resourcesText)
        if self.game.loosers != None:
            message = OnscreenText(text='End of the game',
                                   align=TextNode.ACenter,
                                   pos=(0, 0),
                                   scale=0.1)
            if self.game.loosers == 'black':
                message.setText('White wins!')
            elif self.game.loosers == 'white':
                message.setText('Black wins!')
            else:
                message.setText('Nobody wins!')

    def destroyGame(self):
        children = self.render.getChildren()
        for child in children:
            child.removeNode()

    def cameraSpeed(self, height, speedRange):
        # Figure out how 'wide' each range is
        leftSpan = self.camLimits[2][1] - self.camLimits[2][0]
        rightSpan = speedRange[1] - speedRange[0]

        # Convert the left range into a 0-1 range (float)
        valueScaled = float(height - self.camLimits[2][0]) / float(leftSpan)

        # Convert the 0-1 range into a value in the right range.
        return speedRange[0] + (valueScaled * rightSpan)

    def moveCamera(self):
        mousePos = self.getMouseCoords()
        if mousePos == None:
            return
        x, y = mousePos
        camX, camY, camZ = self.getCameraCoords()
        transformX, transformY = 0, 0
        speed = self.cameraSpeed(camZ, (0.01, 0.2))
        if x < -0.7 and y < -0.7:
            transformX -= speed
            transformY -= speed
        elif x > 0.7 and y < -0.7:
            transformX += speed
            transformY -= speed
        elif x < -0.7 and y > 0.7:
            transformX -= speed
            transformY += speed
        elif x > 0.7 and y > 0.7:
            transformX += speed
            transformY += speed
        else:
            if x < -0.7:
                transformX -= speed
            elif x > 0.7:
                transformX += speed
            if y < -0.7:
                transformY -= speed
            elif y > 0.7:
                transformY += speed
        newX = camX + transformX
        newY = camY + transformY
        if newX < self.camLimits[0][0] or newX > self.camLimits[0][1]:
            newX = camX
        if newY < self.camLimits[1][0] or newY > self.camLimits[1][1]:
            newY = camY
        self.setCameraCoords(newX, newY, camZ)

    def highlight(self):
        if self.mouseWatcherNode.hasMouse():
            mPos = self.mouseWatcherNode.getMouse()

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

            self.picker.traverse(self.render)
            if self.pq.getNumEntries() > 0:
                # This is so we get the closest object.
                self.pq.sortEntries()
                pickedObj = self.pq.getEntry(0).getIntoNodePath()
                # pick the model and not the cnode
                pickedObj = pickedObj.findNetTag('clickable')
                if not pickedObj.isEmpty():
                    return pickedObj

    @staticmethod
    def boardingTransformations(figure, pos):
        figure.model.setScale(0.2)
        figure.model.setPos(1 + pos, 0, 1)

    @staticmethod
    def unboardingTransformations(figure):
        figure.model.setScale(0.35)
        figure.model.setPos(0, 0, 0)

    def drawSongsMenu(self, songs, field):
        if self.songMenu:
            return
        self.songMenu = [(OnscreenText(text='Choose song:',
                                       pos=(-0.7, -0.1),
                                       align=TextNode.ALeft,
                                       parent=base.a2dTopRight,
                                       scale=0.06), field)]
        i = 1
        for song in songs:
            item = OnscreenText(text=str(i) + ') Song of ' + song,
                                pos=(-0.7, -0.1 - i * 0.1),
                                align=TextNode.ALeft,
                                parent=base.a2dTopRight,
                                scale=0.06)
            i += 1
            self.songMenu.append((item, song))

    def destroySongMenu(self):
        if self.songMenu:
            for item in self.songMenu:
                item[0].destroy()
            self.songMenu = None

    def drawBuildMenu(self, buildings, field):
        self.buildMenu = [(OnscreenText(text='Choose building:',
                                        pos=(-0.7, -0.1),
                                        align=TextNode.ALeft,
                                        parent=base.a2dTopRight,
                                        scale=0.06), field)]
        i = 1
        for building in buildings:
            price = Building.buildingPrice(building)
            text = '{0}) {1} ({2})'.format(str(i), building, price)
            item = OnscreenText(text=text,
                                pos=(-0.7, -0.1 - i * 0.1),
                                align=TextNode.ALeft,
                                parent=base.a2dTopRight,
                                scale=0.06)
            i += 1
            self.buildMenu.append((item, building))

    def destroyBuildMenu(self):
        if self.buildMenu:
            for item in self.buildMenu:
                item[0].destroy()
            self.buildMenu = None

    def clickFigure(self, figure):
        print('figure')
        if type(figure) == Ship:
            ship = figure
            figure = self.clicked
            if isinstance(figure, Figure) and type(figure) != Ship:
                if figure.hasMoved:
                    self.clicked = ship
                    return
                if (figure.field.island == ship.field.island and
                        figure.player == ship.player and
                        None in ship.fields):
                    figure.field.put(None)
                    pos = 0
                    if ship.fields[0] == None:
                        ship.fields[0] = figure
                    else:
                        ship.fields[1] = figure
                        pos = 1
                    figure.field = ship
                    figure.model.reparentTo(ship.model)
                    self.boardingTransformations(figure, pos)
                    figure.hasMoved = True
            if ship.player == self.game.currentPlayer():
                self.clicked = ship
        else:
            if figure.player == self.game.currentPlayer():
                self.clicked = figure

    def initiateBattle(self, blackTroops, whiteTroops):
        self.blackTroops = blackTroops
        self.whiteTroops = whiteTroops
        battle = self.game.newBattle()
        self.push(battle)
        self.gameEventHandler.ignoreAll()

    def clickField(self, field):
        print(self.clicked)
        if type(self.clicked) == Ship:
            return
        if self.clicked and isinstance(self.clicked, Figure):
            figure = self.clicked
            board = self.game.board
            if figure.hasMoved:
                return
            if type(figure.field) == Ship:
                if field in board.possibleMoves(figure.field):
                    figure.field.removeFigure(figure)
                    player = self.game.currentPlayer()
                    battle = field.figure != None and field.figure.player != player
                    whiteTroops = field.figure
                    field.put(figure)
                    figure.model.reparentTo(field.model)
                    self.unboardingTransformations(figure)
                    figure.hasMoved = True
                    self.initiateBattle(figure, whiteTroops)
            if field in board.possibleMoves(self.clicked):
                initiateBattle = field.figure != None
                whiteTroops = field.figure
                figure.field.put(None)
                field.put(figure)
                figure.model.reparentTo(field.model)
                figure.hasMoved = True
                if initiateBattle:
                    self.initiateBattle(figure, whiteTroops)
        if isinstance(self.clicked, Building):
            building = self.clicked
            player = self.game.currentPlayer()
            if not field.figure or field.figure.player != player:
                if field.island != building.field.island:
                    return
                figure = None
                battle = field.figure != None and field.figure.player != player
                whiteTroops = field.figure
                if building.building == 'House':
                    figure = self.game.giveBirthToPeasant(field)
                elif building.building == 'Barracks':
                    figure = self.game.giveBirthToWarrior(field)
                if figure == None:
                    return
                if figure:
                    self.drawFigures()
                if battle:
                    self.initiateBattle(figure, whiteTroops)
                else:
                    print('Not enough resources!')

    def clickSeaField(self, field):
        if type(self.clicked) == Ship:
            figure = self.clicked
            if figure.hasMoved:
                return
            if field.figure != None:
                return
            if field in figure.field.linked:
                figure.field.put(None)
                field.put(figure)
                figure.model.reparentTo(field.model)
                figure.hasMoved = True
        if type(self.clicked) == Building:
            player = self.game.currentPlayer()
            building = self.clicked
            if building.building == 'Harbor':
                if building.field.island.bay != field:
                    return

                player = self.game.currentPlayer()
                if not field.figure or field.figure.player != player:
                    ship = self.game.buildShip(field)
                    if ship:
                        self.drawFigures()
                    else:
                        print('Not enough resources')

    def clickBuildingField(self, field):
        print("Gonna build, huh?")
        player = self.game.currentPlayer()
        print(self.game.possibleBuildings(field.island))
        self.drawSongsMenu(self.game.possibleSongs(field.island), field)

    def handle(self, event, *args):
        print(event)
        if type(self.current()) != Game:
            return
        if event == 'wheel_up':
            x, y, z = self.getCameraCoords()
            if z > self.camLimits[2][0]:
                self.setCameraCoords(x, y, z - 1)
        elif event == 'wheel_down':
            x, y, z = self.getCameraCoords()
            if z < self.camLimits[2][1]:
                self.setCameraCoords(x, y, z + 1)
        elif event == 'enter':
            if self.game.loosers != None:
                self.pop()
            self.game.changeTurn()
        elif event == 'left_click':
            obj = self.highlight()
            if obj != None:
                key = obj.getKey()
                # if it's a figure
                if key in self.modelToFigure:
                    figure = self.modelToFigure[key]
                    self.clickFigure(figure)
                # if it's a figure field
                if key in self.modelToField:
                    field = self.modelToField[key]
                    self.clickField(field)
                # if it's a building field
                if key in self.modelToBuildingField:
                    field = self.modelToBuildingField[key]
                    self.clickBuildingField(field)
                # if it's a sea field
                if key in self.modelToSeaField:
                    field = self.modelToSeaField[key]
                    self.clickSeaField(field)
                # if it's a building
                if key in self.modelToBuilding:
                    self.clicked = self.modelToBuilding[key]
            else:
                self.clicked = None
            if self.songMenu != None:
                if obj == None or obj.getKey() not in self.modelToBuildingField:
                    self.destroySongMenu()
        elif event in [str(i) for i in range(1, 10)]:
            if self.songMenu:
                if self.songMenu[0][1] != self.game.board.islands[0]:
                    song = self.songMenu[int(event)][1]
                    buildings = self.game.buildings[song]
                    self.drawBuildMenu(buildings, self.songMenu[0][1])
                else:
                    print('CHANGE OBJECTIVES!')
                self.destroySongMenu()
                return
            if self.buildMenu:
                building = self.buildMenu[int(event)][1]
                field = self.buildMenu[0][1]
                building = self.game.build(building, field)
                if building:
                    self.drawBuilding(building, field)
                else:
                    print('Not enough resources or field is taken!!>@')
                self.destroyBuildMenu()

    def hoverFigure(self, hovered):
        if self.hovered != None:
            reverseFactor = self.hovered.getScale()[0]
            reverseFactor *= REVERSE_HIGHLIGHT_SCALE
            self.hovered.setScale(reverseFactor)
        self.hovered = None
        if hovered != None:
            figure = self.modelToFigure[hovered.getKey()]
            if figure.player.color != str(self.current().turn):
                return
            self.hovered = hovered
            factor = HIGHLIGHT_SCALE * hovered.getScale()[0]
            hovered.setScale(factor)
예제 #48
0
class InputManager(DirectObject):
    def __init__(self, base, lookatpos, pggen, togglerotcenter=False):
        self.base = base
        self.originallookatpos = lookatpos  # for backup
        self.lookatpos_pdv3 = Vec3(lookatpos[0], lookatpos[1], lookatpos[2])
        self.camdist = (self.base.cam.getPos() - self.lookatpos_pdv3).length()
        self.pggen = pggen
        self.initviewdist = (self.base.cam.getPos() -
                             self.lookatpos_pdv3).length()
        self.wheelscale_distance = 150
        self.lastm1pos = None
        self.lastm2pos = None
        # toggle on the following part to explicitly show the rotation center
        self.togglerotcenter = togglerotcenter
        if self.togglerotcenter:
            self.rotatecenternp = self.base.p3dh.gensphere(
                pos=self.originallookatpos,
                radius=5,
                rgba=np.array([1, 1, 0, 1]))
            self.rotatecenternp.reparentTo(self.base.render)
        # for resetting
        self.original_cam_pdmat4 = Mat4(self.base.cam.getMat())
        self.keymap = {
            "mouse1": False,
            "mouse2": False,
            "mouse3": False,
            "wheel_up": False,
            "wheel_down": False,
            "space": False,
            "w": False,
            "s": False,
            "a": False,
            "d": False,
            "g": False,
            "r": False
        }
        self.accept("mouse1", self.__setkeys, ["mouse1", True])
        self.accept("mouse1-up", self.__setkeys, ["mouse1", False])
        self.accept("mouse2", self.__setkeys, ["mouse2", True])
        self.accept("mouse2-up", self.__setkeys, ["mouse2", False])
        self.accept("mouse3", self.__setkeys, ["mouse3", True])
        self.accept("mouse3-up", self.__setkeys, ["mouse3", False])
        self.accept("wheel_up", self.__setkeys, ["wheel_up", True])
        self.accept("wheel_down", self.__setkeys, ["wheel_down", True])
        self.accept("space", self.__setkeys, ["space", True])
        self.accept("space-up", self.__setkeys, ["space", False])
        self.accept("w", self.__setkeys, ["w", True])
        self.accept("w-up", self.__setkeys, ["w", False])
        self.accept("s", self.__setkeys, ["s", True])
        self.accept("s-up", self.__setkeys, ["s", False])
        self.accept("a", self.__setkeys, ["a", True])
        self.accept("a-up", self.__setkeys, ["a", False])
        self.accept("d", self.__setkeys, ["d", True])
        self.accept("d-up", self.__setkeys, ["d", False])
        self.accept("g", self.__setkeys, ["g", True])
        self.accept("g-up", self.__setkeys, ["g", False])
        self.accept("r", self.__setkeys, ["r", True])
        self.accept("r-up", self.__setkeys, ["r", False])
        self.setup_interactiongeometries()

    def __setkeys(self, key, value):
        self.keymap[key] = value
        return

    def setup_interactiongeometries(self):
        """
        set up collision rays, spheres, and planes for mouse manipulation

        :return: None

        author: weiwei
        date: 20161110
        """

        # create a trackball ray and set its bitmask to 8
        # the trackball ray must be a subnode of cam since we will
        # transform the clicked point (in the view of the cam) to the world coordinate system
        # using the ray
        self.tracker_cn = CollisionNode("tracker")
        self.tracker_ray = CollisionRay()
        self.tracker_cn.addSolid(self.tracker_ray)
        self.tracker_cn.setFromCollideMask(BitMask32.bit(8))
        self.tracker_cn.setIntoCollideMask(BitMask32.allOff())
        self.tracker_np = self.base.cam.attachNewNode(self.tracker_cn)

        # create an inverted collision sphere and puts it into a collision node
        # its bitmask is set to 8, and it will be the only collidable object at bit 8
        self.trackball_cn = CollisionNode("trackball")
        self.trackball_cn.addSolid(
            CollisionSphere(self.lookatpos_pdv3[0], self.lookatpos_pdv3[1],
                            self.lookatpos_pdv3[2], self.camdist))
        self.trackball_cn.setFromCollideMask(BitMask32.allOff())
        self.trackball_cn.setIntoCollideMask(BitMask32.bit(8))
        self.trackball_np = self.base.render.attachNewNode(self.trackball_cn)
        # self.trackball_np.show()

        # This creates a collision plane for mouse track
        self.trackplane_cn = CollisionNode("trackplane")
        # self.aimPlaneCN.addSolid(CollisionPlane(Plane(Vec3(0, 0, 1), self.lookatpos_pdv3)))
        # self.trackplane_cn.addSolid(CollisionBox(Point3(self.lookatpos_pdv3[0], self.lookatpos_pdv3[1], 0.1), 1e6, 1e6, 1e-6))
        self.trackplane_cn.addSolid(
            CollisionPlane(
                Plane(
                    Point3(self.base.cam.getMat().getRow3(2) -
                           self.base.cam.getMat().getRow3(1)),
                    Point3(self.lookatpos_pdv3[0], self.lookatpos_pdv3[1],
                           0.1))))
        self.trackplane_cn.setFromCollideMask(BitMask32.allOff())
        self.trackplane_cn.setIntoCollideMask(BitMask32.bit(8))
        self.trackplane_np = self.base.render.attachNewNode(self.trackplane_cn)
        # self.trackplane_np.show()

        # creates a traverser to do collision testing
        self.ctrav = CollisionTraverser()
        # creates a queue type handler to receive the collision event info
        self.chandler = CollisionHandlerQueue()

        # register the ray as a collider with the traverser,
        # and register the handler queue as the handler to be used for the collisions.
        self.ctrav.addCollider(self.tracker_np, self.chandler)

        # create a pickerray
        self.picker_cn = CollisionNode('picker')
        self.picker_ray = CollisionRay()
        self.picker_cn.addSolid(self.picker_ray)
        self.picker_cn.setFromCollideMask(BitMask32.bit(7))
        self.picker_cn.setIntoCollideMask(BitMask32.allOff())
        self.picker_np = self.base.cam.attachNewNode(self.picker_cn)
        self.ctrav.addCollider(self.picker_np, self.chandler)

    def shift_trackballsphere(self, center=np.array([0, 0, 0])):
        self.camdist = (self.base.cam.getPos() - self.lookatpos_pdv3).length()
        self.trackball_cn.setSolid(
            0, CollisionSphere(center[0], center[1], center[2], self.camdist))

    def shift_trackplane(self):
        self.trackplane_cn.setSolid(
            0,
            CollisionPlane(
                Plane(
                    Point3(self.base.cam.getMat().getRow3(2) -
                           self.base.cam.getMat().getRow3(1)),
                    Point3(self.lookatpos_pdv3[0], self.lookatpos_pdv3[1],
                           0.1))))

    def get_world_mouse1(self):
        """
       给et the position of mouse1 (clicked) using collision detection between a sphere and a ray

        :return: Vec3 or None

        author: weiwei
        date: 20161110
        """
        if self.base.mouseWatcherNode.hasMouse():
            if self.keymap['mouse1']:
                # get the mouse position in the window
                mpos = self.base.mouseWatcherNode.getMouse()
                # sets the ray's origin at the camera and directs it to shoot through the mouse cursor
                self.tracker_ray.setFromLens(self.base.cam.node(), mpos.getX(),
                                             mpos.getY())
                # performs the collision checking pass
                self.ctrav.traverse(self.trackball_np)
                if (self.chandler.getNumEntries() > 0):
                    # Sort the handler entries from nearest to farthest
                    self.chandler.sortEntries()
                    entry = self.chandler.getEntry(0)
                    colPoint = entry.getSurfacePoint(self.base.render)
                    return colPoint
        return None

    def check_mouse1drag(self):
        """
        this function uses a collision sphere to track the rotational mouse motion

        :return:

        author: weiwei
        date: 20200315
        """

        curm1pos = self.get_world_mouse1()
        if curm1pos is None:
            if self.lastm1pos is not None:
                self.lastm1pos = None
            return
        if self.lastm1pos is None:
            # first time click
            self.lastm1pos = curm1pos
            return
        curm1vec = Vec3(curm1pos - self.lookatpos_pdv3)
        lastm1vec = Vec3(self.lastm1pos - self.lookatpos_pdv3)
        curm1vec.normalize()
        lastm1vec.normalize()
        rotatevec = curm1vec.cross(lastm1vec)
        if rotatevec.length() > 1e-10:  # avoid zero length
            rotateangle = curm1vec.signedAngleDeg(lastm1vec, rotatevec)
            rotateangle = rotateangle * self.camdist * 5
            if rotateangle > .02 or rotateangle < -.02:
                rotmat = Mat4(self.base.cam.getMat())
                posvec = Vec3(self.base.cam.getPos())
                rotmat.setRow(3, Vec3(0, 0, 0))
                self.base.cam.setMat(rotmat *
                                     Mat4.rotateMat(rotateangle, rotatevec))
                self.base.cam.setPos(Mat3.rotateMat(rotateangle, rotatevec). \
                                     xform(posvec - self.lookatpos_pdv3) + self.lookatpos_pdv3)
                self.lastm1pos = self.get_world_mouse1()
                self.shift_trackplane()

    def get_world_mouse2(self):
        if self.base.mouseWatcherNode.hasMouse():
            if self.keymap['mouse2']:
                mpos = self.base.mouseWatcherNode.getMouse()
                self.tracker_ray.setFromLens(self.base.cam.node(), mpos.getX(),
                                             mpos.getY())
                self.ctrav.traverse(self.trackplane_np)
                self.chandler.sortEntries()
                if (self.chandler.getNumEntries() > 0):
                    entry = self.chandler.getEntry(0)
                    colPoint = entry.getSurfacePoint(self.base.render)
                    return colPoint
        return None

    def check_mouse2drag(self):
        """

        :return:

        author: weiwei
        date: 20200313
        """

        curm2pos = self.get_world_mouse2()
        if curm2pos is None:
            if self.lastm2pos is not None:
                self.lastm2pos = None
            return
        if self.lastm2pos is None:
            # first time click
            self.lastm2pos = curm2pos
            return
        relm2vec = curm2pos - self.lastm2pos
        if relm2vec.length() > 1:
            self.base.cam.setPos(self.base.cam.getPos() - relm2vec)
            self.lookatpos_pdv3 = Vec3(self.lookatpos_pdv3 - relm2vec)
            newlookatpos = self.base.p3dh.pdv3_to_npv3(self.lookatpos_pdv3)
            if self.togglerotcenter:
                self.rotatecenternp.detachNode()
                self.rotatecenternp = self.base.p3dh.gensphere(
                    pos=newlookatpos, radius=5, rgba=np.array([1, 1, 0, 1]))
                self.rotatecenternp.reparentTo(self.base.render)
            self.shift_trackballsphere(self.lookatpos_pdv3)
            self.last2mpos = curm2pos

    def get_world_mouse3(self):
        """
        picker ray

        :return:

        author: weiwei
        date: 20200316
        """

        if self.base.mouseWatcherNode.hasMouse():
            if self.keymap['mouse3']:
                mpos = self.base.mouseWatcherNode.getMouse()
                self.picker_ray.setFromLens(self.base.cam.node(), mpos.getX(),
                                            mpos.getY())
                self.ctrav.traverse(self.base.render)
                if (self.chandler.getNumEntries() > 0):
                    self.chandler.sortEntries()
                    entry = self.chandler.getEntry(0)
                    colPoint = entry.getSurfacePoint(self.base.render)
                    return colPoint
        return None

    def check_mouse3click(self):
        """

        :return:

        author: weiwei
        date: 20200316
        """

        curm3pos = self.get_world_mouse3()
        if curm3pos is None:
            return
        else:
            print(curm3pos)

    def check_mousewheel(self):
        """
        zoom up or down the 3d view considering mouse action

        author: weiwei
        date: 2016, 20200313
        :return:
        """

        if self.keymap["wheel_up"] is True:
            self.keymap["wheel_up"] = False
            backward = self.base.cam.getPos() - self.lookatpos_pdv3
            backward.normalize()
            newpos = self.base.cam.getPos(
            ) + backward * self.wheelscale_distance
            if newpos.length() < self.initviewdist * 20:
                self.base.cam.setPos(newpos[0], newpos[1], newpos[2])
                self.shift_trackballsphere(
                    self.trackball_cn.getSolid(0).getCenter())
        if self.keymap["wheel_down"] is True:
            self.keymap["wheel_down"] = False
            forward = self.lookatpos_pdv3 - self.base.cam.getPos()
            if forward.length() < self.wheelscale_distance:
                return
            forward.normalize()
            newpos = self.base.cam.getPos(
            ) + forward * self.wheelscale_distance
            if newpos.length() > self.initviewdist * .05:
                self.base.cam.setPos(newpos[0], newpos[1], newpos[2])
                self.shift_trackballsphere(
                    self.trackball_cn.getSolid(0).getCenter())

    def check_mouse1drag_trackball(self):
        """
        This function uses the stereographic projection
        introduced in https://en.wikipedia.org/wiki/Stereographic_projection to track the rotational mouse motion
        Equations:
        [e, f] -> [x, y, z] = [2e/(1+e^2+f^2), 2f/(1+e^2+f^2), (-1+e^2+f^2)/(2+2e^2+2f^2)]

        :return:

        author: weiwei
        date: 20200315
        """
        def cvtvirtualtrackball(screenx, screeny, psec_squared=1 / 4):
            """
            convert a screen point to virtual trackball coordinate
            psec indicates the size of the spherical section to be mapped to
            default radius = 1

            :param screenx:
            :param screeny:
            :param psec_squared:
            :return:

            author: weiwei
            date: 20200315
            """

            screenpoint_squaredsum = screenx**2 + screeny**2
            trackballx = 2 * psec_squared * screenx / (psec_squared +
                                                       screenpoint_squaredsum)
            trackballz = 2 * psec_squared * screeny / (psec_squared +
                                                       screenpoint_squaredsum)
            trackbally = -math.sqrt(1 - trackballx**2 - trackballz**2)
            returnvec = Vec3(trackballx, trackbally, trackballz)
            returnvec.normalize()
            return returnvec

        currentmouse = self.base.mouseWatcherNode.getMouse()
        curm1pos = [currentmouse.getX(), currentmouse.getY()]
        if curm1pos is None:
            if self.lastm1pos is not None:
                self.lastm1pos = None
            return
        if self.lastm1pos is None:
            # first time click
            self.lastm1pos = curm1pos
            return
        curm1vec_pdv3 = cvtvirtualtrackball(curm1pos[0], curm1pos[1])
        lastm1vec_pdv3 = cvtvirtualtrackball(self.lastm1pos[0],
                                             self.lastm1pos[1])
        rotatevec_pdv3 = curm1vec_pdv3.cross(lastm1vec_pdv3)
        rotateangle = curm1vec_pdv3.signedAngleDeg(lastm1vec_pdv3,
                                                   rotatevec_pdv3)
        if rotateangle > .02 or rotateangle < -.02:
            rotateangle = rotateangle * 5
            camrotmat_pd = self.base.cam.getMat().getUpper3()
            calibrated_camrotmat_pd = Mat3.rotateMat(
                rotateangle, camrotmat_pd.xformVec(rotatevec_pdv3))
            posvec_pd = self.base.cam.getPos()
            self.base.cam.setMat(Mat4.identMat())
            self.base.cam.setMat(camrotmat_pd * calibrated_camrotmat_pd)
            self.base.cam.setPos(
                calibrated_camrotmat_pd.xform(posvec_pd -
                                              self.lookatpos_pdv3) +
                self.lookatpos_pdv3)
            self.lastm1pos = curm1pos[:]

    def check_resetcamera(self):
        """
        reset the rendering window to its initial viewpoint

        :return:

        author: weiwei
        date: 20200316
        """

        if self.keymap["r"] is True:
            self.keymap["r"] = False
            self.base.cam.setMat(self.original_cam_pdmat4)
            self.lookatpos_pdv3 = self.base.p3dh.npv3_to_pdv3(
                self.originallookatpos)
            # toggle on the following part to explicitly show the rotation center
            if self.togglerotcenter:
                self.rotatecenternp.detachNode()
                self.rotatecenternp = self.base.p3dh.gensphere(
                    pos=self.originallookatpos,
                    radius=5,
                    rgba=np.array([1, 1, 0, 1]))
                self.rotatecenternp.reparentTo(self.base.render)
예제 #49
0
class Player(GameObject):
    def __init__(self,
                 modelName,
                 model_anims,
                 max_health,
                 speed,
                 collider_name,
                 base,
                 pos,
                 hpr=Vec3(0, 0, 0),
                 scale=1.0):
        GameObject.__init__(self, modelName, model_anims, max_health, speed,
                            collider_name, base, pos, hpr, scale)
        self.player_init()

    def player_init(self):
        self.base.pusher.addCollider(self.collider, self.actor)
        self.base.cTrav.addCollider(self.collider, self.base.pusher)
        self.collider.setPythonTag("player", self)

        self.score = 0
        self.score_string = str(self.score)

        # self.base.camLens.setFov(150) #----------------------------------------------
        # self.base.camLens.setFov(5)

        self.textObject = OnscreenText(text='Score:' + self.score_string,
                                       pos=(-1.15, -0.95),
                                       scale=0.1)

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

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

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

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

        # self.damagePerSecond = -5.0
        self.beamModel = self.base.loader.loadModel("models/frowney")
        self.beamModel.reparentTo(self.actor)
        self.beamModel.setZ(10)

        self.beamModel.setLightOff()
        self.beamModel.hide()

    def move(self, movement_vector):
        anim_controller = self.actor.getAnimControl("walk")
        if not anim_controller.isPlaying():
            self.actor.play("walk")
        self.actor.setPos(self.actor, movement_vector * self.speed)

    def stop(self):
        anim_controller = self.actor.getAnimControl("walk")
        anim_controller.stop()

    def change_health(self, dHealth):
        GameObject.change_health(self, dHealth)
        if self.health == 0:
            #     imageOnject = OnscreenImage(image = "game_over.png")
            self.cleanup()
            sys.exit()

    def update_score(self):
        self.score_string = str(self.score)
        self.textObject.destroy()
        self.textObject = OnscreenText(text='Score:' + self.score_string,
                                       pos=(-1.15, -0.95),
                                       scale=0.1)

    def shoot(self):
        dt = globalClock.getDt()
        # print(self.rayQueue.getNumEntries())
        # print(self.rayQueue)
        if self.rayQueue.getNumEntries() > 0:
            self.rayQueue.sortEntries()
            rayHit = self.rayQueue.getEntry(1)
            hitPos = rayHit.getSurfacePoint(self.base.render)
            # print(hitPos, "hitpos")
            # print(rayHit, "rayhit")
            # beamLength = (hitPos - self.actor.getPos()).length()
            # print("length: ", beamLength)

            hitNodePath = rayHit.getIntoNodePath()
            # print(hitNodePath)
            # print(hitNodePath.getPythonTag)
            # print(hitPos)
            # print(hitNodePath.getTag)
            # print(hitNodePath.hasPythonTag("enemy"))
            # print(rayHit.getFrom())
            if hitNodePath.hasPythonTag("enemy"):
                # print("here")
                hitObject = hitNodePath.getPythonTag("enemy")
                hitObject.change_health(-1)

                # Find out how long the beam is, and scale the
                # beam-model accordingly.
                # print(self.actor.getPos())
                beamLength = (hitPos - (self.actor.getPos())).length()
                self.beamModel.setSy(-beamLength)
                self.score += 1
                self.update_score()
                self.beamModel.show()
            else:
                # If we're not shooting, don't show the beam-model.
                self.beamModel.hide()
예제 #50
0
class WalkingEnemy(Enemy):
    def __init__(self, pos):
        Enemy.__init__(
            self, pos, "Models/Misc/simpleEnemy", {
                "stand": "Models/Misc/simpleEnemy-stand",
                "walk": "Models/Misc/simpleEnemy-walk",
                "attack": "Models/Misc/simpleEnemy-attack",
                "die": "Models/Misc/simpleEnemy-die",
                "spawn": "Models/Misc/simpleEnemy-spawn"
            }, 3.0, 7.0, "walkingEnemy")

        self.attackDistance = 0.75
        self.attackDelay = 0.3
        self.attackDelayTimer = 0
        self.attackWaitTimer = 0
        self.acceleration = 100.0

        mask = BitMask32()
        mask.setBit(2)

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

        self.attackSegment = CollisionSegment(0, 0, 0, 1, 0, 0)

        segmentNode = CollisionNode("enemyAttackSegment")
        segmentNode.addSolid(self.attackSegment)

        mask = BitMask32()
        mask.setBit(1)

        segmentNode.setFromCollideMask(mask)

        mask = BitMask32()

        segmentNode.setIntoCollideMask(mask)

        self.attackSegmentNodePath = render.attachNewNode(segmentNode)
        self.segmentQueue = CollisionHandlerQueue()

        base.cTrav.addCollider(self.attackSegmentNodePath, self.segmentQueue)

        self.attackDamage = -1

        self.deathSound = loader.loadSfx("Sounds/enemyDie.ogg")
        self.attackSound = loader.loadSfx("Sounds/enemyAttack.ogg")

        self.yVector = Vec2(0, 1)

        self.actor.play("spawn")

    def runLogic(self, player, dt):
        spawnControl = self.actor.getAnimControl("spawn")
        if spawnControl is not None and spawnControl.isPlaying():
            return

        vectorToPlayer = player.actor.getPos() - self.actor.getPos()

        vectorToPlayer2D = vectorToPlayer.getXy()
        distanceToPlayer = vectorToPlayer2D.length()

        vectorToPlayer2D.normalize()

        heading = self.yVector.signedAngleDeg(vectorToPlayer2D)

        self.attackSegment.setPointA(self.actor.getPos())
        self.attackSegment.setPointB(self.actor.getPos() +
                                     self.actor.getQuat().getForward() *
                                     self.attackDistance)

        if distanceToPlayer > self.attackDistance * 0.9:
            attackControl = self.actor.getAnimControl("attack")
            if not attackControl.isPlaying():
                self.walking = True
                vectorToPlayer.setZ(0)
                vectorToPlayer.normalize()
                self.velocity += vectorToPlayer * self.acceleration * dt
                self.attackWaitTimer = 0.2
                self.attackDelayTimer = 0
        else:
            self.walking = False
            self.velocity.set(0, 0, 0)

            if self.attackDelayTimer > 0:
                self.attackDelayTimer -= dt
                if self.attackDelayTimer <= 0:
                    if self.segmentQueue.getNumEntries() > 0:
                        self.segmentQueue.sortEntries()
                        segmentHit = self.segmentQueue.getEntry(0)

                        hitNodePath = segmentHit.getIntoNodePath()
                        if hitNodePath.hasPythonTag("owner"):
                            hitObject = hitNodePath.getPythonTag("owner")
                            hitObject.alterHealth(self.attackDamage)
                            self.attackWaitTimer = 1.0
            elif self.attackWaitTimer > 0:
                self.attackWaitTimer -= dt
                if self.attackWaitTimer <= 0:
                    self.attackWaitTimer = random.uniform(0.5, 0.7)
                    self.attackDelayTimer = self.attackDelay
                    self.actor.play("attack")
                    self.attackSound.play()

        self.actor.setH(heading)

    def alterHealth(self, dHealth):
        Enemy.alterHealth(self, dHealth)
        self.updateHealthVisual()

    def updateHealthVisual(self):
        perc = self.health / self.maxHealth
        if perc < 0:
            perc = 0
        self.actor.setColorScale(perc, perc, perc, 1)

    def cleanup(self):
        base.cTrav.removeCollider(self.attackSegmentNodePath)
        self.attackSegmentNodePath.removeNode()

        GameObject.cleanup(self)
예제 #51
0
class Physics:
    def __init__(self):
        self.rayCTrav = CollisionTraverser("collision traverser for ray tests")
        #self.pusher = PhysicsCollisionHandler()
        self.pusher = CollisionHandlerPusher()
        self.pusher.addInPattern('%fn-in-%in')
        self.pusher.addOutPattern('%fn-out-%in')
        self.pusher.addInPattern('%fn-in')
        self.pusher.addOutPattern('%fn-out')

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

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

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

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

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

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

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

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

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

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

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

    def getFirstCollisionInLine(self, pointA, pointB):
        """A simple raycast check which will return the first collision point as
        seen from point A towards pointB"""
        self.raytest_segment.setPointA(pointA)
        self.raytest_segment.setPointB(pointB)
        self.rayCTrav.traverse(render)
        self.raytest_queue.sortEntries()
        pos = None
        if self.raytest_queue.getNumEntries() > 0:
            pos = self.raytest_queue.getEntry(0).getSurfacePoint(render)
        return pos
예제 #52
0
class Player(GameObject):
    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.laserSoundNoHit = loader.loadSfx("Sounds/laserNoHit.ogg")
        self.laserSoundNoHit.setLoop(True)
        self.laserSoundHit = loader.loadSfx("Sounds/laserHit.ogg")
        self.laserSoundHit.setLoop(True)

        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.hurtSound = loader.loadSfx("Sounds/FemaleDmgNoise.ogg")

        self.yVector = Vec2(0, 1)

        self.actor.loop("stand")

    def update(self, keys, dt):
        GameObject.update(self, dt)

        self.walking = False

        if keys["up"]:
            self.walking = True
            self.velocity.addY(self.acceleration * dt)
        if keys["down"]:
            self.walking = True
            self.velocity.addY(-self.acceleration * dt)
        if keys["left"]:
            self.walking = True
            self.velocity.addX(-self.acceleration * dt)
        if keys["right"]:
            self.walking = True
            self.velocity.addX(self.acceleration * dt)

        if self.walking:
            standControl = self.actor.getAnimControl("stand")
            if standControl.isPlaying():
                standControl.stop()

            walkControl = self.actor.getAnimControl("walk")
            if not walkControl.isPlaying():
                self.actor.loop("walk")
        else:
            standControl = self.actor.getAnimControl("stand")
            if not standControl.isPlaying():
                self.actor.stop("walk")
                self.actor.loop("stand")

        mouseWatcher = base.mouseWatcherNode
        if mouseWatcher.hasMouse():
            mousePos = mouseWatcher.getMouse()
        else:
            mousePos = self.lastMousePos

        mousePos3D = Point3()
        nearPoint = Point3()
        farPoint = Point3()

        base.camLens.extrude(mousePos, nearPoint, farPoint)
        self.groundPlane.intersectsLine(
            mousePos3D, render.getRelativePoint(base.camera, nearPoint),
            render.getRelativePoint(base.camera, farPoint))

        firingVector = Vec3(mousePos3D - self.actor.getPos())
        firingVector2D = firingVector.getXy()
        firingVector2D.normalize()
        firingVector.normalize()

        heading = self.yVector.signedAngleDeg(firingVector2D)

        self.actor.setH(heading)

        self.beamHitTimer -= dt
        if self.beamHitTimer <= 0:
            self.beamHitTimer = self.beamHitPulseRate
            self.beamHitModel.setH(random.uniform(0.0, 360.0))
        self.beamHitModel.setScale(
            math.sin(self.beamHitTimer * 3.142 / self.beamHitPulseRate) * 0.4 +
            0.9)

        if keys["shoot"]:
            if self.rayQueue.getNumEntries() > 0:
                scoredHit = False

                self.rayQueue.sortEntries()
                rayHit = self.rayQueue.getEntry(0)
                hitPos = rayHit.getSurfacePoint(render)

                hitNodePath = rayHit.getIntoNodePath()
                if hitNodePath.hasPythonTag("owner"):
                    hitObject = hitNodePath.getPythonTag("owner")
                    if not isinstance(hitObject, TrapEnemy):
                        hitObject.alterHealth(self.damagePerSecond * dt)
                        scoredHit = True

                beamLength = (hitPos - self.actor.getPos()).length()
                self.beamModel.setSy(beamLength)

                self.beamModel.show()

                if scoredHit:
                    if self.laserSoundNoHit.status() == AudioSound.PLAYING:
                        self.laserSoundNoHit.stop()
                    if self.laserSoundHit.status() != AudioSound.PLAYING:
                        self.laserSoundHit.play()

                    self.beamHitModel.show()

                    self.beamHitModel.setPos(hitPos)
                    self.beamHitLightNodePath.setPos(hitPos + Vec3(0, 0, 0.5))

                    if not render.hasLight(self.beamHitLightNodePath):
                        render.setLight(self.beamHitLightNodePath)
                else:
                    if self.laserSoundHit.status() == AudioSound.PLAYING:
                        self.laserSoundHit.stop()
                    if self.laserSoundNoHit.status() != AudioSound.PLAYING:
                        self.laserSoundNoHit.play()

                    if render.hasLight(self.beamHitLightNodePath):
                        render.clearLight(self.beamHitLightNodePath)

                    self.beamHitModel.hide()
        else:
            if render.hasLight(self.beamHitLightNodePath):
                render.clearLight(self.beamHitLightNodePath)

            self.beamModel.hide()
            self.beamHitModel.hide()

            if self.laserSoundNoHit.status() == AudioSound.PLAYING:
                self.laserSoundNoHit.stop()
            if self.laserSoundHit.status() == AudioSound.PLAYING:
                self.laserSoundHit.stop()

        if firingVector.length() > 0.001:
            self.ray.setOrigin(self.actor.getPos())
            self.ray.setDirection(firingVector)

        self.lastMousePos = mousePos

        if self.damageTakenModelTimer > 0:
            self.damageTakenModelTimer -= dt
            self.damageTakenModel.setScale(2.0 - self.damageTakenModelTimer /
                                           self.damageTakenModelDuration)
            if self.damageTakenModelTimer <= 0:
                self.damageTakenModel.hide()

    def updateScore(self):
        self.scoreUI.setText(str(self.score))

    def alterHealth(self, dHealth):
        GameObject.alterHealth(self, dHealth)

        self.updateHealthUI()

        self.damageTakenModel.show()
        self.damageTakenModel.setH(random.uniform(0.0, 360.0))
        self.damageTakenModelTimer = self.damageTakenModelDuration

        self.hurtSound.play()

    def updateHealthUI(self):
        for index, icon in enumerate(self.healthIcons):
            if index < self.health:
                icon.show()
            else:
                icon.hide()

    def cleanup(self):
        self.scoreUI.removeNode()

        for icon in self.healthIcons:
            icon.removeNode()

        self.beamHitModel.removeNode()

        base.cTrav.removeCollider(self.rayNodePath)

        self.laserSoundHit.stop()
        self.laserSoundNoHit.stop()

        render.clearLight(self.beamHitLightNodePath)
        self.beamHitLightNodePath.removeNode()

        GameObject.cleanup(self)
예제 #53
0
class World(DirectObject):
    def __init__(self):
        #This code puts the standard title and instruction text on screen
        self.title = OnscreenText(text="Panda3D: Tutorial - Mouse Picking",
                                  style=1, fg=(1, 1, 1, 1),
                                  pos=(0.8, -0.95), scale=.07)
        self.escapeEvent = OnscreenText(
            text="ESC: Quit",
            style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.95),
            align=TextNode.ALeft, scale=.05)
        self.mouse1Event = OnscreenText(
            text="Left-click and drag: Pick up and drag piece",
            style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.90),
            align=TextNode.ALeft, scale=.05)

        self.accept('escape', sys.exit)  #Escape quits
        base.disableMouse()  #Disble mouse camera control
        camera.setPosHpr(0, -13.75, 6, 0, -25, 0)  #Set the camera
        self.setupLights()  #Setup default lighting

        #Since we are using collision detection to do picking, we set it up like
        #any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  #Make a traverser
        self.pq = CollisionHandlerQueue()  #Make a handler
        #Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        #Attach that node to the camera since the ray will need to be positioned
        #relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        #Everything to be picked will use bit 1. This way if we were doing other
        #collision we could seperate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  #Make our ray
        self.pickerNode.addSolid(self.pickerRay)  #Add it to the collision node
        #Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)

        #Now we create the chess board and its pieces

        #We will attach all of the squares to their own root. This way we can do the
        #collision pass just on the sqaures and save the time of checking the rest
        #of the scene
        self.squareRoot = render.attachNewNode("squareRoot")

        #For each square
        self.squares = [None for i in range(64)]
        self.pieces = dict((i, None) for i in range(64))  #MOD
        for i in range(64):
            #Load, parent, color, and position the model (a single square polygon)
            self.squares[i] = loader.loadModel("models/square")
            self.squares[i].reparentTo(self.squareRoot)
            self.squares[i].setPos(SquarePos(i))
            self.squares[i].setColor(SquareColor(i))
            #Set the model itself to be collideable with the ray. If this model was
            #any more complex than a single polygon, you should set up a collision
            #sphere around it instead. But for single polygons this works fine.
            self.squares[i].find("**/polygon").node().setIntoCollideMask(
                BitMask32.bit(1))
            #Set a tag on the square's node so we can look up what square this is
            #later during the collision pass
            self.squares[i].find("**/polygon").node().setTag('square', str(i))

            #We will use this variable as a pointer to whatever piece is currently
            #in this square

        #The order of pieces on a chessboard from white's perspective. This list
        #contains the constructor functions for the piece classes defined below
        pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook)

        for i in range(8, 16):
            #Load the white pawns
            self.pieces[i] = Pawn(i, WHITE)
        for i in range(48, 56):
            #load the black pawns
            self.pieces[i] = Pawn(i, PIECEBLACK)
        for i in range(8):
            #Load the special pieces for the front row and color them white
            self.pieces[i] = pieceOrder[i](i, WHITE)
            #Load the special pieces for the back row and color them black
            self.pieces[i + 56] = pieceOrder[i](i + 56, PIECEBLACK)

        #This will represent the index of the currently highlited square
        self.hiSq = False
        #This wil represent the index of the square where currently dragged piece
        #was grabbed from
        self.dragging = False

        #Start the task that handles the picking
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        self.accept("mouse1", self.grabPiece)  #left-click grabs a piece
        self.accept("mouse1-up", self.releasePiece)  #releasing places it

    #This function swaps the positions of two pieces
    def swapPieces(self, fr, to):
        temp = self.pieces[fr]
        self.pieces[fr] = self.pieces[to]
        self.pieces[to] = temp
        if self.pieces[fr]:
            self.pieces[fr].square = fr
            self.pieces[fr].obj.setPos(SquarePos(fr))
        if self.pieces[to]:
            self.pieces[to].square = to
            self.pieces[to].obj.setPos(SquarePos(to))

    def mouseTask(self, task):
        #This task deals with the highlighting and dragging based on the mouse

        #First, clear the current highlight
        if self.hiSq is not False:
            self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
            self.hiSq = False

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

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

            #If we are dragging something, set the position of the object
            #to be at the appropriate point over the plane of the board
            if self.dragging is not False:
                #Gets the point described by pickerRay.getOrigin(), which is relative to
                #camera, relative instead to render
                nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin())
                #Same thing with the direction of the ray
                nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection())
                self.pieces[self.dragging].obj.setPos(
                    PointAtZ(.5, nearPoint, nearVec))

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

        return Task.cont

    def grabPiece(self):
        #If a square is highlighted and it has a piece, set it to dragging mode
        if (self.hiSq is not False and
                self.pieces[self.hiSq]):
            self.dragging = self.hiSq
            self.hiSq = False

    def releasePiece(self):
        #Letting go of a piece. If we are not on a square, return it to its original
        #position. Otherwise, swap it with the piece in the new square
        if self.dragging is not False:  #Make sure we really are dragging something
            #We have let go of the piece, but we are not on a square
            if self.hiSq is False:
                self.pieces[self.dragging].obj.setPos(
                    SquarePos(self.dragging))
            else:
                #Otherwise, swap the pieces
                self.swapPieces(self.dragging, self.hiSq)

        #We are no longer dragging anything
        self.dragging = False

    def setupLights(self):  #This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0, 45, -45))
        directionalLight.setColor(Vec4(0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
예제 #54
0
class Player(GameObject):
    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.damagePerSecond = -5.0

        self.yVector = Vec2(0, 1)

        self.actor.loop("stand")

    def update(self, keys, dt):
        GameObject.update(self, dt)

        self.walking = False

        if keys["up"]:
            self.walking = True
            self.velocity.addY(self.acceleration*dt)
        if keys["down"]:
            self.walking = True
            self.velocity.addY(-self.acceleration*dt)
        if keys["left"]:
            self.walking = True
            self.velocity.addX(-self.acceleration*dt)
        if keys["right"]:
            self.walking = True
            self.velocity.addX(self.acceleration*dt)

        if self.walking:
            standControl = self.actor.getAnimControl("stand")
            if standControl.isPlaying():
                standControl.stop()

            walkControl = self.actor.getAnimControl("walk")
            if not walkControl.isPlaying():
                self.actor.loop("walk")
        else:
            standControl = self.actor.getAnimControl("stand")
            if not standControl.isPlaying():
                self.actor.stop("walk")
                self.actor.loop("stand")

        mouseWatcher = base.mouseWatcherNode
        if mouseWatcher.hasMouse():
            mousePos = mouseWatcher.getMouse()
        else:
            mousePos = self.lastMousePos

        mousePos3D = Point3()
        nearPoint = Point3()
        farPoint = Point3()

        base.camLens.extrude(mousePos, nearPoint, farPoint)
        self.groundPlane.intersectsLine(mousePos3D,
                                        render.getRelativePoint(base.camera, nearPoint),
                                        render.getRelativePoint(base.camera, farPoint))

        firingVector = Vec3(mousePos3D - self.actor.getPos())
        firingVector2D = firingVector.getXy()
        firingVector2D.normalize()
        firingVector.normalize()

        heading = self.yVector.signedAngleDeg(firingVector2D)

        self.actor.setH(heading)

        if keys["shoot"]:
            if self.rayQueue.getNumEntries() > 0:
                self.rayQueue.sortEntries()
                rayHit = self.rayQueue.getEntry(0)
                hitPos = rayHit.getSurfacePoint(render)

                hitNodePath = rayHit.getIntoNodePath()
                if hitNodePath.hasPythonTag("owner"):
                    hitObject = hitNodePath.getPythonTag("owner")
                    if not isinstance(hitObject, TrapEnemy):
                        hitObject.alterHealth(self.damagePerSecond*dt)

                beamLength = (hitPos - self.actor.getPos()).length()
                self.beamModel.setSy(beamLength)

                self.beamModel.show()
        else:
            self.beamModel.hide()

        if firingVector.length() > 0.001:
            self.ray.setOrigin(self.actor.getPos())
            self.ray.setDirection(firingVector)

        self.lastMousePos = mousePos

    def cleanup(self):
        base.cTrav.removeCollider(self.rayNodePath)

        GameObject.cleanup(self)
예제 #55
0
class Weapon(DirectObject):
    def __init__(self, _main, _name, _fireRate, _dmg=20,_mountSlot=0, weaponType="Pistol"):
        self.main = _main
        self.name = _name
        self.fireRate = _fireRate
        self.dmg = _dmg
        self.weaponType = weaponType
        self.mountSlot = _mountSlot

        self.muzzleFlash = loader.loadModel("muzzleflash")
        if weaponType == "Pistol":
            self.style = "OneHand"
            self.model = loader.loadModel("Pistol")
            self.muzzleFlash.setZ(0.65)
            self.muzzleFlash.setX(-0.04)
            self.muzzleFlash.setScale(0.25)
            self.muzzleFlash.find('**/+SequenceNode').node().setFrameRate(20)
        else:
            self.style = "TwoHand"
            self.model = loader.loadModel("MG")
            self.muzzleFlash.setZ(0.65)
            self.muzzleFlash.setX(0.08)
            self.muzzleFlash.setScale(0.3)
            self.muzzleFlash.find('**/+SequenceNode').node().setFrameRate(20)
        self.model.setY(2)
        self.muzzleFlash.reparentTo(self.model)
        self.muzzleFlash.find('**/+SequenceNode').node().stop()
        self.muzzleFlash.hide()

        # Load bullet model
        self.bullet = loader.loadModel("Bullet")
        self.bullet.setP(-90)
        self.bullet.setH(180)
        #self.bullet.setPos(0, 0.5, 0)

        # Control
        self.isFiring = False

        # Collision Stuff
        self.wepRay = None
        # Make weapon ray
        self.setupRay()
        self.model.show()

    def setAmmo(self):
        pass

    def setupRay(self):
        self.shootTraverser = CollisionTraverser()
        self.shootingQH = CollisionHandlerQueue()
        #self.shootingEH = CollisionHandlerEvent()
        #self.shootingEH.addInPattern('into-%in')
        # Create a collision Node
        shootNode = CollisionNode('WeaponRay')
        # set the nodes collision bitmask
        shootNode.setFromCollideMask(BitMask32.bit(1))
        # create a collision segment (ray like)
        self.shootRay = CollisionSegment()
        shootNode.addSolid(self.shootRay)
        #self.pickerNP = self.main.player.model.attachNewNode(pickerNode)
        self.shootNP = render.attachNewNode(shootNode)
        #self.shootTraverser.addCollider(self.shootNP, self.shootingEH)
        self.shootTraverser.addCollider(self.shootNP, self.shootingQH)
        #self.shootNP.show()

    def doFire(self, _toPos=(0, 0, 0)):
        self.isFiring = True

        if self.weaponType == "Pistol":
            self.muzzleFlash.find('**/+SequenceNode').node().play(0, 1)
        else:
            self.muzzleFlash.find('**/+SequenceNode').node().loop(True)
        self.muzzleFlash.show()

        # For some reason the mouse ray end up at posZ -1 (which causes a problem when we make the enemy spheres smaller in radius)
        # so here for now.. ill make a quick fix.
        adjustedZ = (_toPos[0], _toPos[1], 0)

        self.shootRay.setPointA(self.main.player.model.getPos())
        self.shootRay.setPointB(adjustedZ)

        fromPos = self.main.player.model.getPos() #self.model.getPos()
        #self.setProjectile(fromPos, adjustedZ)#_toPos)

        self.shootTraverser.traverse(self.main.enemyParent)
        if self.shootingQH.getNumEntries() > 0:
            self.shootingQH.sortEntries()
            enemyCol = self.shootingQH.getEntry(0).getIntoNodePath().node().getName()
            base.messenger.send("into-" + enemyCol, [self.dmg])

    def stopFire(self):
        if self.weaponType == "Pistol" and \
               self.muzzleFlash.find('**/+SequenceNode').node().isPlaying():
            taskMgr.add(self.waitForFrame, "waitForFrame")
            return
        self.muzzleFlash.find('**/+SequenceNode').node().stop()
        self.muzzleFlash.hide()

    def waitForFrame(self, task):
        if self.muzzleFlash.find('**/+SequenceNode').node().isPlaying():
            return task.cont
        self.muzzleFlash.find('**/+SequenceNode').node().stop()
        self.muzzleFlash.hide()

    def reload(self):
        pass

    def setProjectile(self, _from, _to):
        self.bullet.reparentTo(render)#self.model)
        # setup the projectile interval
        #self.bulletProjectile = ProjectileInterval(self.bullet,
        #                                startPos = Point3(_from),
        #                                duration = 1,
        #                                endPos = Point3(_to))
        #self.bulletProjectile = self.bullet.posInterval(1.0, Point3(_to), startPos=Point3(_from))
        #self.bulletProjectile = LerpPosInterval(self.bullet, 2.0, _to, _from)
        print "POSITIONS:"
        print _to
        print _from
        frm = render.getPos(self.main.player.model)
        print frm

        self.bulletProjectile = LerpPosInterval(self.bullet, 1.0, _to, _from)
        self.bulletProjectile.start()
예제 #56
0
class KlobWorld(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        ## wp = WindowProperties(base.win.getProperties())
        ## wp.setSize(1280,720)
        ## base.win.requestProperties(wp)
        base.setBackgroundColor(255,250,250)
               
        self.listAudio3d = []
        self.allSounds()
        
        self.energyTime = 0
        self.collHandQue = CollisionHandlerQueue()
        self.collHandQueEne = CollisionHandlerQueue()
        
        self.SPEED = .5
        self.speedv = 4
        base.cTrav = CollisionTraverser()
        self.bossLvl = False
        self.bossDead = False
        self.isMoving = False
        self.pause = True
        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(render)
        
        self.currentLevel = "start"
        
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0,
                        "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0,
                        "fire-down":0, "p":0}
        
        
        ###Disable the default camera controls###
        base.disableMouse()
        
        self.pusher = CollisionHandlerPusher()
        base.cTrav.setRespectPrevTransform(True)
        
        #Uncomment to show collisions with environment
        #base.cTrav.showCollisions(render)
        
        self.setAcceptKeys()
        self.MainMenu()

        ## List to keep track of all actors added in each level
        ## to make it easier to cleanup level when destroyed
        self.crAct = []
        self.extraElements = []
        self.laserAmo = []
        self.beamC = []
        self.laserAmoCount = 0
        self.enemyTimer = 0
        self.gunAmmoCount = 0
        self.loaded = []
        self.bulletC = []

    def allSounds(self):
    
        self.audio = Audio3DManager(self.sfxManagerList[0])
        
        self.audio.attachListener(base.camera)
        
        self.heartBeat = base.loadMusic("sounds/heartbeat.wav")
        self.cheer = base.loadMusic("sounds/cheer.wav")
        
        
        self.intro = base.loadMusic("sounds/Mario.wav")
        self.bulletSound = base.loadMusic("sounds/gun_shot.wav")
        self.laserSound = base.loadMusic("sounds/gun_shot.wav")
        self.deadSound = base.loadMusic("sounds/pacman_death.wav")
        self.sound = self.audio.loadSfx("sounds/forest.wav")
        self.gust = base.loadMusic("sounds/gust.wav")
        self.siren = base.loadMusic("sounds/siren_2.wav")
        self.waterfallSound = self.audio.loadSfx("sounds/waterfall.wav")
        self.etSound = base.loadMusic("sounds/et-sound.wav")
        self.walking = base.loadMusic("sounds/running.wav")
        self.mainMenuMusic = base.loadMusic("sounds/intro.wav")
        self.rainforestMusic = self.loader.loadSfx("sounds/rainforest.wav")
        self.egyptMusic = self.loader.loadSfx("sounds/egypt.wav")
        self.asiaMusic = self.loader.loadSfx("sounds/asia.wav")
        self.newyorkMusic = self.loader.loadSfx("sounds/newyork.wav")
        
        self.mainMenuMusic.setLoop(True)
        self.rainforestMusic.setLoop(True)
        self.egyptMusic.setLoop(True)
        self.asiaMusic.setLoop(True)
        self.newyorkMusic.setLoop(True)
        
        self.gust.setLoop(True)
        self.sound.setLoop(True)
        self.siren.setLoop(True)
        
        self.walking.setVolume(5)
        self.heartBeat.setVolume(5)
        self.deadSound.setVolume(.5)
        self.laserSound.setVolume(.2)
        self.bulletSound.setVolume(.2)
        self.sound.setVolume(2)
        self.rainforestMusic.setVolume(.6)
        self.egyptMusic.setVolume(2)
        self.siren.setVolume(.3)
    
    def stopAllSounds(self):
        self.audio.detachSound(self.waterfallSound)
        self.audio.detachSound(self.sound)
        self.audio.detachSound(self.rainforestMusic)
        self.audio.detachSound(self.egyptMusic)
        self.audio.detachSound(self.newyorkMusic)
        
        self.intro.stop()
        self.bulletSound.stop()
        self.laserSound.stop()
        self.deadSound.stop()
        self.sound.stop()
        self.gust.stop()
        self.siren.stop()
        self.waterfallSound.stop()
        self.etSound.stop()
        self.walking.stop()
        self.mainMenuMusic.stop()
        self.rainforestMusic.stop()
        self.egyptMusic.stop()
        self.asiaMusic.stop()
        self.newyorkMusic.stop()
        
        
       
    def MainMenuLevels(self):
        if(self.currentLevel != "start"):
            self.destroyLevel()
            self.stopAllSounds()
            
        self.level1Btn = DirectButton(
                                scale = (0.27,0.1,0.1),
                                command = self.loadRainforestLevel,
                                pos = Vec3(0, 0, 0.4),
                                image = 'GUI/southamericabutton.png', 
                                relief = None)
        self.level2Btn = DirectButton(
                                scale = (0.27,0.1,0.1),
                                command = self.loadAfricaLevel,
                                pos = Vec3(0, 0, 0.15),
                                image = 'GUI/africabutton.png', 
                                relief = None)
        self.level3Btn = DirectButton(
                                scale = (0.27,0.1,0.1),
                                command = self.loadAsiaLevel,
                                pos = Vec3(0, 0, -0.1),
                                image = 'GUI/asiabutton.png', 
                                relief = None)
        self.level4Btn = DirectButton(
                                scale = (0.27,0.1,0.1),
                                command = self.loadNewYorkLevel,
                                pos = Vec3(0, 0, -0.35),
                                image = 'GUI/americabutton.png', 
                                relief = None)    
       
        self.level2Btn.setTransparency(TransparencyAttrib.MAlpha)
        self.level3Btn.setTransparency(TransparencyAttrib.MAlpha)
        self.level4Btn.setTransparency(TransparencyAttrib.MAlpha)
        self.level1Btn.setTransparency(TransparencyAttrib.MAlpha)
    

    def destroyMainMenuLevels(self):
        self.level1Btn.destroy()
        self.level2Btn.destroy()
        self.level3Btn.destroy()
        self.level4Btn.destroy()
        self.mainMenuBtn = DirectButton(
                        text="Main Menu",
                        scale = (0.1,0.1,0.1),
                        command = self.MainMenuLevels,
                        pos = Vec3(0.8, 0, -0.9))
        
    def MainMenu(self):
        if(self.currentLevel == "help"):
            self.destroyHelpMenu()
        elif(self.currentLevel != "start"):
            self.destroyLevel()
            self.mainMenuBtn.destroy()
            self.stopAllSounds()
            
        self.currentLevel="start"
        self.mainMenuImage = OnscreenImage("GUI/mainmenu.png",pos = Vec3(0, 0.0,-0.8), scale=(1.8, 0, 1.8))
        self.mainMenuImage.reparentTo(aspect2d)
        self.mainMenuImage.setTransparency(1)
        self.mainMenuMusic.play()
        mapStart = loader.loadModel('GUI/button_maps.egg') 
        self.startBtn = DirectButton(geom =
                        (mapStart.find('**/start_but'),
                         mapStart.find('**/start_but_click'),
                         mapStart.find('**/start_but_roll'),
                         mapStart.find('**/start_but_disabled')),
                         relief = None,
                         command = self.introScreen,
                         scale = (0.7,0.7,0.7),
                         pos = Vec3(0.6, 0, -0.35))
        self.startBtn.setTransparency(TransparencyAttrib.MAlpha)
        mapHelp = loader.loadModel('GUI/helpbutton_maps.egg') 
        self.helpBtn = DirectButton(geom =
                        (mapHelp.find('**/help_but'),
                         mapHelp.find('**/help_but_click'),
                         mapHelp.find('**/help_but_roll'),
                         mapHelp.find('**/help_but_disabled')),
                         relief = None,
                         command = self.HelpMenu,
                         scale = (0.8,0.65,0.65),
                         pos = Vec3(0.6, 0,-0.65))
        self.helpBtn.setTransparency(TransparencyAttrib.MAlpha)
        
    def destroyMainMenu(self):
        self.startBtn.destroy()
        self.helpBtn.destroy()
        self.mainMenuImage.destroy()
        self.stopAllSounds()
        
    def HelpMenu(self):
        self.destroyMainMenu()
        self.currentLevel="help"
        self.helpMenuImage = OnscreenImage("GUI/helpmenu.png",pos = Vec3(0, 0.0,-0.8), scale=(1.8, 0, 1.8))
        self.helpMenuImage.reparentTo(aspect2d)
        self.helpMenuImage.setTransparency(1)
        
        mapHelp = loader.loadModel('GUI/backbutton_maps.egg') 
        self.backBtn = DirectButton(geom =
                        (mapHelp.find('**/backBtn'),
                         mapHelp.find('**/backBtn_click'),
                         mapHelp.find('**/backBtn_roll'),
                         mapHelp.find('**/backBtn_disabled')),
                         relief = None,
                         command = self.MainMenu,
                         scale = (0.7,0.7,0.7),
                         pos = Vec3(-1.4, 0, 0.8))
        self.backBtn.setTransparency(TransparencyAttrib.MAlpha)
      ###......
      #code missing.
     ### ....
        
    ##Records the state of the arrow keys###
    def setKey(self, key, value):
        if(self.pause is False):
            self.keyMap[key] = value
    
            
            if(self.keyMap["fire-down"] != 0 ):
                if( self.energy['value'] != 0 ):
    
                    if(self.bossDead is False):
                        self.beamC.append( self.loadLaser() )
                        self.laserAmo.append( self.laser() )
                    if(self.laserAmo):    
                        self.laserAmo[self.laserAmoCount].start()
                    self.energy['value'] -= 3
                    self.laserAmoCount = self.laserAmoCount + 1
                    
        
            
    def loadEnviron(self, filename, scale):
        
        self.environ = self.loader.loadModel(filename)
        self.environ.setScale(scale)
        self.environ.reparentTo(self.render)
        self.environ.setPos(0, 0, 0)
        self.environ.setTag('wall','1')
        self.environ.setCollideMask(BitMask32(0x01))
        
        alight = AmbientLight('alight')
        alight.setColor(VBase4(0.8, 0.8, 0.8, 1))
        alnp = render.attachNewNode(alight)
        render.setLight(alnp)
    
    
    def loadAlien(self, point):

        ###Load alien actor###
        self.alien = Actor("models/alien/slugrocket-model",
                           {"walk":"models/alien/slugrocket-anim"})
                           
        self.alien.reparentTo(render)
        self.alien.setScale(3)
        self.alien.setPos(point)
        self.alien.setPlayRate(1.2, "walk")
        self.alien.setBlend(frameBlend = True)
        
        self.dlight = DirectionalLight('my dlight')
        self.dlnp = render.attachNewNode(self.dlight)
        self.dlnp.reparentTo(base.camera)
        self.dlnp.lookAt(self.alien)
        self.dlight.setColor(VBase4(0.8, 0.8, 0.5, 1))
        render.setLight(self.dlnp)
        
        base.camera.setPos(0,-10,2)
        base.camera.reparentTo(self.alien)
        

        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(2))
        self.camGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol)
        self.camGroundHandler = CollisionHandlerQueue()
        base.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)
        
        
        csAlien = CollisionSphere(0,0,0.6,0.6)
        cnodeAlienPath = self.alien.attachNewNode(CollisionNode('csAlien'))
        cnodeAlienPath.node().addSolid(csAlien)
        self.pusher.addCollider(cnodeAlienPath, self.alien)
        base.cTrav.addCollider(cnodeAlienPath, self.pusher)
        
        ### Uncomment the following comment to show 
        ### the Collision Sphere on the alien
        ## cnodeAlienPath.show()

        self.health = DirectWaitBar(scale = 0.5,
                            range = 100,
                            value = 100,
                            barColor = (0,1,0,1),
                            pos = Vec3(0.75, 0, 0.9))
                                    
        self.energy = DirectWaitBar(scale = 0.5,
                                    range = 100,
                                    value = 100,
                                    barColor = (1,1,0,1),
                                    pos = Vec3(-0.75, 0, 0.9))
        self.energy.reparentTo(aspect2d)
        self.health.reparentTo(aspect2d)
        self.hud = OnscreenImage("GUI/hud.png",scale = Vec3(1.43, 1.0, 1.03),pos = Vec3(0, 0.0,0.045))
        self.hud.reparentTo(aspect2d)
        self.hud.setTransparency(1)
        self.extraElements.append(self.energy)
        self.extraElements.append(self.health)
        self.extraElements.append(self.hud)

        
        
    def alienDie(self, currLvl):
        self.alien.stop()
        self.pause=True
        temp = NodePath(PandaNode("temp"))
        
        base.camera.reparentTo(self.floater)
        base.camera.setZ(base.camera.getZ()+1)
        base.camera.setY(base.camera.getY()-25)
        self.deadSound.play()
        
        fall = LerpHprInterval(nodePath=self.alien, duration=1.5, hpr=(self.alien.getH(),self.alien.getP(), self.alien.getR()-80))
        fall.start()
        
        
        taskMgr.remove("moveTask")
        taskMgr.remove("laterFc")
        transition = Transitions(loader) 
        transition.setFadeColor(0, 0, 0)
        self.dieImage = OnscreenImage("GUI/died.png",scale = Vec3(0.7, 0, 0.2),pos = Vec3(0, 0,-0.5))
        self.dieImage.reparentTo(aspect2d)
        self.dieImage.setTransparency(1)
        if(self.currentLevel == "rainforest"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadRainforestLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start()
        elif(self.currentLevel == "africa"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadAfricaLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start()
        elif(self.currentLevel == "asia"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadAsiaLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start()
        elif(self.currentLevel == "newyork"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadNewYorkLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start()
        
        
    def collide(self, collEntry):
        collEntry.getFromNodePath().getParent().removeNode()
        
        
        
    def setAcceptKeys(self):
        
        ###Accept the control keys for movement and rotation###
        self.accept("escape", sys.exit)
        self.accept("p", self.setKey, ["p",1])
        
        
        self.accept("arrow_up", self.setKey, ["forward",1])
        self.accept("arrow_up-up", self.setKey, ["forward",0])
        
        self.accept("arrow_down", self.setKey, ["backward", 1])
        self.accept("arrow_down-up", self.setKey, ["backward", 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("a", self.setKey, ["cam-left",1])
        self.accept("a-up", self.setKey, ["cam-left",0])
        
        self.accept("s", self.setKey, ["cam-right",1])    
        self.accept("s-up", self.setKey, ["cam-right",0])
        
        self.accept("z", self.setKey, ["cam-up",1])
        self.accept("z-up", self.setKey, ["cam-up",0])
        
        self.accept("x", self.setKey, ["cam-down", 1])
        self.accept("x-up", self.setKey, ["cam-down", 0])
        
        # Accept f to fire 
        self.accept("f", self.setKey, ["fire-down",1])
        self.accept("f-up", self.setKey, ["fire-down",0])
        self.cTrav.traverse(render)
    
        
    
    
    #gun / laser code ommitted
    
    def getDistance(self, actor):
       self.vecAlien = Vec3(self.alien.getPos())
       self.vecObj = Vec3(actor.getPos())
       disVec = self.vecObj - self.vecAlien

       return disVec.length()    

    def myFunction(self,task):
        
        self.walking.play()
        
        if(self.pause is False):
            for r in range(0, len(self.crAct)):
                self.crAct[r].setTarget(self.alien)     
                self.bulletC.append( self.createBullet(self.crAct[r]) )
                self.loaded.append( self.loadBullet( self.crAct[r]) )                        
                self.loaded[self.gunAmmoCount].start()
                self.gunAmmoCount += 1
                self.bulletSound.play()
            return task.again    
        
        
    def bossLvlTask(self, dec, task):
        self.crAct[0].setAiPursue(self.alien)
                
        if(self.pause is False):
            self.deleteProjectiles()
            
            self.charcMoveKeys()
            startpos = self.alien.getPos()
            
            self.floater.setPos(self.alien.getPos())
            self.floater.setZ(self.alien.getZ() + 2.0)
            base.camera.lookAt(self.floater)
            
            self.collHandQueEne.sortEntries()
            
            if(self.collHandQueEne.getNumEntries() > 0):
                entryb = self.collHandQueEne.getEntry(0)
              
                if( entryb.getIntoNodePath().getName() == "csAlien"):
                    
                    self.health['value'] -=5
                    if(self.bulletC):
                        self.bulletC[self.gunAmmoCount-1].remove()
                        self.bulletC.pop(self.gunAmmoCount-1)
                        self.loaded.pop(self.gunAmmoCount-1)
                        self.gunAmmoCount -= 1
                    if( self.health['value'] < 20 ):
                        self.heartBeat.play()
                    if(self.health['value'] == 0):
                        self.alienDie(self.currentLevel)
                else:
                    self.bulletC[self.gunAmmoCount-1].remove()
                    self.bulletC.pop(self.gunAmmoCount-1)
                    self.loaded.pop(self.gunAmmoCount-1)
                    self.gunAmmoCount -= 1
                    
                    
            self.collHandQue.sortEntries()
            if( self.collHandQue.getNumEntries() > 0 ):
                
                entry = self.collHandQue.getEntry(0)   
                

                if( entry.getIntoNodePath().getName() == self.crAct[0].getCNP()):
                            
                    self.crAct[0].runAround(self.alien)
                            
                    self.crAct[0].setHitCount(1)
                    self.crAct[0].decreaseHealth(dec)
                            
                    if( self.beamC):
                        self.beamC[self.laserAmoCount-1].remove()
                        self.beamC.pop(self.laserAmoCount-1)
                        if(self.laserAmo):
                            self.laserAmo.pop(self.laserAmoCount-1)
                        self.laserAmoCount -= 1

                    if( self.crAct[0].getHealth()%4 == 0):
                        self.crAct[0].jumpAway(self.alien)
                                
                    if( self.crAct[0].getHealth() == 0 ):
                        ## print x.getDeaths()
                        ## if( x.canRespawn() ):
                            ## x.setDeaths(1)
                            ## x.resetHitCount(0)
                
                                    
                            ## x.setX(random.randint(0, 50))
                            ## x.setY(self.alien.getY()+15)
                        ## else:
                        self.crAct[0].cleanup()
                        self.crAct[0].remove()
                        self.crAct.pop(0)
                        self.cutScene()
                           
        if( self.crAct ):
            self.crAct[0].AIworld.update()
                                
        if( self.keyMap["p"]!= 0):
            self.cutScene()
                    
        return task.cont
    
    
    def move(self, task):
        ##ommmitted
        
               
            return task.cont

    
    def deleteProjectiles(self):
        ## if(self.pause is False):
        if(self.laserAmo):
            for i, x in enumerate(self.laserAmo):
                if( not x.isPlaying() ):
                        
                    self.beamC[i].remove()
                    self.beamC.pop(i)
                    self.laserAmo.pop(i)
                    self.laserAmoCount = self.laserAmoCount -1
                        
        if(self.loaded):
            for i, x in enumerate(self.loaded):
                if(not x.isPlaying()):
                    #self.crAct[i].setTarget(self.alien)
                    self.bulletC[i].remove()
                    self.bulletC.pop(i)
                    self.loaded.pop(i)
                    self.gunAmmoCount = self.gunAmmoCount -1
                        
        self.energyTime = self.energyTime + globalClock.getDt()
            
        if(self.energyTime > 2 ):
            if(self.energy['value'] != 100):
                self.energy['value'] +=5
                self.energyTime = 0
                    

    def charcMoveKeys(self):
        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())
                
        if (self.keyMap["cam-up"]!=0):
            base.camera.setY(base.camera, -20 * globalClock.getDt())
                
        if (self.keyMap["cam-down"]!=0):
            base.camera.setY(base.camera, +20 * globalClock.getDt())
                
        if (self.keyMap["forward"]!=0):
            self.alien.setY(self.alien, 10 * globalClock.getDt())
                
                
        if (self.keyMap["backward"]!=0):
            self.alien.setY(self.alien, -10 * globalClock.getDt())
        
                    
        if (self.keyMap["left"]!=0):
                self.alien.setH(self.alien.getH() + 40 * globalClock.getDt())

                
        if (self.keyMap["right"]!=0):
                self.alien.setH(self.alien.getH() - 40 * globalClock.getDt())

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

    def loadingScreen(self):
        self.intro.play()
        transition = Transitions(loader) 
        transition.setFadeColor(0, 0, 0)
        text = TextNode('node name')
        dummy = NodePath(PandaNode("dummy"))
        black = OnscreenImage(image="GUI/black.png",pos=(0,0,0), scale=100)
        black.reparentTo(dummy)
        textNodePath = aspect2d.attachNewNode(text)
        textNodePath.reparentTo(aspect2d, 2)
        textNodePath.setScale(0.07)
        text.setTextColor(1, 1, 1, 1)
        
        if(self.currentLevel=="newyork"):
            Sequence(Func(transition.fadeOut),Func(black.reparentTo, aspect2d),Func(transition.fadeIn),Func(textNodePath.reparentTo,aspect2d, 10),Func(text.setText, "loading"),Wait(1.0),Func(text.setText, "loading."), 
                    Wait(1.0),Func(text.setText, "loading.."), Wait(1.0), Func(text.setText, "loading..."), Func(self.loadNextLevel),Wait(3.0),Func(transition.fadeIn),Func(textNodePath.remove), Func(black.destroy)).start()
        elif(self.currentLevel=="asia"):
            Sequence(Func(transition.fadeOut),Func(black.reparentTo, aspect2d),Func(transition.fadeIn),Func(textNodePath.reparentTo,aspect2d, 10),Func(text.setText, "loading"),Wait(1.0),Func(text.setText, "loading."), 
                    Wait(1.0),Func(text.setText, "loading.."), Wait(1.0), Func(text.setText, "loading..."), Func(self.loadNextLevel),Wait(3.0),Func(transition.fadeIn),Func(textNodePath.remove), Func(black.destroy)).start()
        else:
            Sequence(Func(transition.fadeOut),Func(black.reparentTo, aspect2d),Func(transition.fadeIn),Func(textNodePath.reparentTo,aspect2d, 10),Func(text.setText, "loading"),Wait(0.5),Func(text.setText, "loading."), 
                    Wait(0.5),Func(text.setText, "loading.."), Wait(0.5), Func(text.setText, "loading..."), Func(self.loadNextLevel),Wait(1.5),Func(transition.fadeIn),Func(textNodePath.remove), Func(black.destroy)).start()
        
        
    def cutScene(self):
        self.destroyLevel()
        self.stopAllSounds()
        
        self.cut = OnscreenImage("GUI/bossKilled.png",scale = Vec3(1.6, 0, 1.0),pos = Vec3(0, 0,0))
        self.cut.reparentTo(aspect2d)
        self.cut.setTransparency(1)
        transition = Transitions(loader) 
        transition.setFadeColor(0, 0, 0)
        self.cheer.play()
        if(self.currentLevel=="rainforest"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/map_11.png"),
                     Wait(1.5),Func(self.cut.setImage, "GUI/map_12.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_13.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_14.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_15.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_16.png"),Wait(3.5),Func(self.cut.destroy), Func(transition.fadeOut), Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start()
        elif(self.currentLevel=="africa"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/map_21.png"),
                     Wait(1.5),Func(self.cut.setImage, "GUI/map_22.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_23.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_24.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_25.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_26.png"), Wait(3.5),Func(self.cut.destroy), Func(transition.fadeOut),Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start()
        elif(self.currentLevel=="asia"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/map_31.png"),
                     Wait(1.5),Func(self.cut.setImage, "GUI/map_32.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_33.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_34.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_35.png"),
                     Wait(0.5),Func(self.cut.setImage,"GUI/map_36.png"),Wait(3.5),Func(self.cut.destroy), Func(transition.fadeOut),Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start()
        elif(self.currentLevel=="newyork"):
            Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/win.png"),
                     Wait(6.5),Func(self.cut.destroy), Func(transition.fadeOut),Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start()
            
     
    def loadNextLevel(self):
        if(self.currentLevel=="start"):
            self.loadRainforestLevel()
        elif(self.currentLevel=="rainforest"):
            self.loadAfricaLevel()
        elif(self.currentLevel=="africa"):
            self.loadAsiaLevel()
        elif(self.currentLevel=="asia"):
            self.loadNewYorkLevel()
        else:
            self.MainMenu()
  
    def destroyLevel(self):
        self.mainMenuBtn.destroy()
        taskMgr.remove("moveTask")
        taskMgr.remove("bossTask")
        taskMgr.remove("myFunction")
        self.alien.cleanup()
        for enemy in self.crAct:
            enemy.cleanup()
            enemy.remove()
        self.alien.cleanup()
        self.alien.remove()    
        for element in self.extraElements:
            element.removeNode()
        for beam in self.beamC:
            beam.removeNode()
        self.render.clearFog    
        self.laserBeam2.removeNode()
        
        self.environ.removeNode()
        self.crAct[:] = []
        self.extraElements[:] = []

        self.laserAmo[:] =[]
        self.laserAmoCount = 0

        
    def loadBossActor(self):
        self.bossLvl = True
        ###Load Ralph Boss actor###
        difficult = 10
        taskMgr.remove("moveTask")
        taskMgr.remove("myFunction")
        self.health['value'] = 100
        self.energy['value'] = 100
        
        if(self.bossDead is False):
            self.bossImage = OnscreenImage("GUI/bossLoad.png",scale = Vec3(1.6, 0, 1.0),pos = Vec3(0, 0,0))
            self.bossImage.reparentTo(aspect2d)
            self.bossImage.setTransparency(1)
            self.ralphBoss = EnemyActor(1,difficult,True)
            self.ralphBoss.enemy.setScale(2.0)
            self.crAct.append(self.ralphBoss)
            Sequence(Wait(3.0), Func(self.bossImage.destroy), Func(self.crAct[0].showHealthBar)).start()
            
            self.extraElements.append(self.crAct[0].bossHud)
            self.extraElements.append(self.crAct[0].health)
            self.crAct[0].setAiPursue(self.alien)
            self.pusher.addCollider(self.crAct[0].getFromObj(), self.crAct[0].enemy)
            base.cTrav.addCollider(self.crAct[0].getFromObj(), self.pusher)
            gunTex = loader.loadTexture('models/gun_tex.png')
            if(self.currentLevel == "rainforest"):
                dec = 5
                self.ralphBoss.enemy.setPos(0,90,0)
                ralphTex = loader.loadTexture('models/ralph2rainforest.png')
                self.ralphBoss.enemy.setTexture(ralphTex, 1)
                self.ralphBoss.gunPos.setTexture(gunTex, 1)
            elif(self.currentLevel == "africa"):
                dec = 4
                self.ralphBoss.enemy.setPos(-100,-90,0)
                ralphTex = loader.loadTexture('models/ralph2egypt.png')
                self.ralphBoss.enemy.setTexture(ralphTex, 1)
                self.ralphBoss.gunPos.setTexture(gunTex, 1)
            elif(self.currentLevel == "asia"):
                dec = 3
                self.ralphBoss.enemy.setPos(0,0,0)
                ralphTex = loader.loadTexture('models/ralph2asia.png')
                self.ralphBoss.enemy.setTexture(ralphTex, 1)
                self.ralphBoss.gunPos.setTexture(gunTex, 1)
            elif(self.currentLevel == "newyork"):
                dec = 2
                self.ralphBoss.enemy.setPos(120,10,0)
         
        taskMgr.add(self.bossLvlTask,"bossTask", extraArgs = [dec], appendTask=True)
        taskMgr.doMethodLater(1,self.myFunction,"myFunction")
            
    
    
    def loadRainforestLevel(self):
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0,
                        "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0,
                        "fire-down":0,  "p":0}
        self.pause = False
        self.currentLevel = "rainforest"
        self.destroyIntro()
        difficulty = 2
        self.bossLvl = False
        self.bossDead = False
        ###Load alien###
        startPos = Point3(0,0,0)
        self.loadAlien(startPos)
        self.rainforestMusic.play()
        ###Load the enemies###
        ralphTex = loader.loadTexture('models/ralph2rainforest.png')
        gunTex = loader.loadTexture('models/gun_tex.png')
        for i in range(0,2):
            enemy = EnemyActor(i, difficulty, False)
            enemy.enemy.setTexture(ralphTex, 1)
            enemy.gunPos.setTexture(gunTex, 1)
            
            enemy.setX(random.randint(-50,50))
            enemy.setY(random.randint(-50,50))
            enemy.setZ(0)
            
            self.crAct.append(enemy)
            self.crAct[i].setAiPursue(self.alien)
            
            self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy)
            base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher)
        
            
        taskMgr.add(self.move,"moveTask")
        taskMgr.doMethodLater(3,self.myFunction,"myFunction")
        self.loadLaser2()
        self.loadLaser()
        
        ###Load the environment###
        self.loadEnviron("models/south_america/rainforest", 5)
        self.plants = self.loader.loadModel("models/south_america/rainforest-nocollision")
        self.plants.reparentTo(self.render)
        self.plants.setScale(4)
        self.plants.setTwoSided(True)
        self.extraElements.append(self.plants)
        
        self.myFog = Fog("FOG")
        self.myFog.setColor(0.5,0.6,0.5)
        self.myFog.setExpDensity(0.005)
        render.setFog(self.myFog)
        self.audio.attachSoundToObject(self.sound, self.environ)
        self.audio.setSoundVelocityAuto(self.sound)
        self.audio.setListenerVelocityAuto()
        
        self.sound.play()
        
    
    def loadAfricaLevel(self):
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0,
                        "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0,
                        "fire-down":0, "p":0}
        self.pause = False
        self.currentLevel="africa"
        
        difficulty = 3
        self.bossLvl = False
        self.bossDead = False
        ###Load alien###
        startPos = Point3(-130,-130,0)
        self.loadAlien(startPos)
        self.alien.setH(-40)
        
        ###Load the enemies###
        ralphTex = loader.loadTexture('models/ralph2egypt.png')
        gunTex = loader.loadTexture('models/gun_tex.png')
        for i in range(0,3):
            enemy = EnemyActor(i, difficulty, False)
            enemy.enemy.setTexture(ralphTex, 1)
            enemy.gunPos.setTexture(gunTex, 1)
            enemy.setX(random.randint(-170,-50))
            enemy.setY(random.randint(-170,-50))
            enemy.setZ(0)
        
            self.crAct.append(enemy)
            
            self.crAct[i].setAiPursue(self.alien)
            
            self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy)
            base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher)

        taskMgr.add(self.move,"moveTask")
        taskMgr.doMethodLater(3,self.myFunction,"myFunction")
        
        self.loadLaser2()
        self.loadLaser()
       
        ###Load environment###
        self.loadEnviron("models/africa/egypt", 7)
        self.egypt_nc = self.loader.loadModel("models/africa/egypt-nocollision")
        self.egypt_nc.reparentTo(self.render)
        self.egypt_nc.setPos(0,0,0)
        self.egypt_nc.setScale(7)
        self.extraElements.append(self.egypt_nc)
        self.sphinx = self.loader.loadModel("models/africa/sphinx")
        self.sphinx.setPos(0,80,0)
        self.sphinx.setH(180)
        self.sphinx.setScale(0.12)
        self.sphinx.reparentTo(self.render)
        self.extraElements.append(self.sphinx)
        
        cs = CollisionSphere(0,0,0,200)
        nodePath = self.sphinx.attachNewNode(CollisionNode('nodePath'))
        nodePath.node().addSolid(cs)
        self.gust.play()
        self.audio.attachSoundToObject(self.egyptMusic, self.environ)
        self.audio.setSoundVelocityAuto(self.egyptMusic)
        self.audio.setListenerVelocityAuto()
        self.egyptMusic.play()
        
        
    def loadAsiaLevel(self):
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0,
                        "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0,
                        "fire-down":0, "p":0}
        self.pause = False
        self.currentLevel = "asia"

        difficulty = 4
        self.bossLvl = False
        self.bossDead = False
        ###Load alien###
        startPos = Point3(190,-140,0)
        self.loadAlien(startPos)
        ###Load the enemies###
        ralphTex = loader.loadTexture('models/ralph2asia.png')
        gunTex = loader.loadTexture('models/gun_tex.png')
        for i in range(0,4):
            enemy = EnemyActor(i, difficulty, False)
            enemy.enemy.setTexture(ralphTex, 1)
            enemy.gunPos.setTexture(gunTex, 1)
            enemy.setX(random.randint(0,100))
            enemy.setY(random.randint(-150,-50))
            enemy.setZ(0)
      
            self.crAct.append(enemy)
            self.crAct[i].setAiPursue(self.alien)
            
            self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy)
            base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher)
            
        taskMgr.add(self.move,"moveTask")
        taskMgr.doMethodLater(3,self.myFunction,"myFunction")
        
        self.loadLaser2()
        self.loadLaser()
        
        ###Load the environment###
        self.loadEnviron("models/asia/asia2", 5)
        self.asia_nc = self.loader.loadModel("models/asia/asia-nocollision")
        self.asia_nc.reparentTo(self.render)
        self.asia_nc.setPos(0,0,0)
        self.asia_nc.setScale(5)
        self.extraElements.append(self.asia_nc)
        
        self.myFog = Fog("FOG")
        self.myFog.setColor(0.8,0.8,0.8)
        self.myFog.setExpDensity(0.002)
        render.setFog(self.myFog)
        
        self.bonzai = self.loader.loadModel("models/asia/bonzai")
        self.bonzai.reparentTo(self.render)
        self.bonzai.setPos(170,20,0)
        self.bonzai.setScale(0.015)
        self.bonzai.setH(90)
        self.extraElements.append(self.bonzai)
        cs = CollisionSphere(0,0,200,200)
        nodePath = self.bonzai.attachNewNode(CollisionNode('nodePath'))
        nodePath.node().addSolid(cs)
        self.pusher.addCollider(nodePath, self.bonzai)
        
        self.waterfall = self.loader.loadModel("models/asia/waterFall")
        self.waterfall.reparentTo(self.render)
        self.waterfall.setPos(200,80,-.5)
        self.waterfall.setScale(0.25)
        self.waterfall.setH(180)
        self.extraElements.append(self.waterfall)
        cs = CollisionSphere(0,15,-5,130)
        nodePath = self.waterfall.attachNewNode(CollisionNode('nodePath'))
        nodePath.node().addSolid(cs)
        self.pusher.addCollider(nodePath, self.waterfall)
        
        self.waterfallSound.setLoop(True)
        self.audio.attachSoundToObject(self.waterfallSound,self.waterfall)
        self.audio.setSoundVelocityAuto(self.waterfallSound)
        self.audio.setListenerVelocityAuto()
        self.audio.setDistanceFactor(1.5)
        self.waterfallSound.play()
        
        self.tree1 = self.loader.loadModel("models/asia/bamboo")
        self.tree1.reparentTo(self.render)
        self.tree1.setPos(-50,-50,0)
        self.tree1.setScale(0.6,0.6,0.6)
        self.tree1.setBillboardAxis()
        self.extraElements.append(self.tree1)
        
        #Child bamboos scattered around
        placeholder = render.attachNewNode("Bamboo-Placeholder")
        placeholder.setPos(180,-40,0)
        placeholder.setScale(0.8)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
        
        placeholder = render.attachNewNode("Babmboo-Placeholder")
        placeholder.setPos(-20,-120,0)
        placeholder.setScale(1.0)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
                
        placeholder = render.attachNewNode("Bamboo-Placeholder")
        placeholder.setPos(-50,180,0)
        placeholder.setScale(1.0)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
        
        placeholder = render.attachNewNode("Bamboo-Placeholder")
        placeholder.setPos(-60,165,0)
        placeholder.setScale(0.6)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
        
        placeholder = render.attachNewNode("Bamboo-Placeholder")
        placeholder.setPos(-110,70,0)
        placeholder.setScale(1.0)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
        
        placeholder = render.attachNewNode("Bamboo-Placeholder")
        placeholder.setPos(-100,-50,0)
        placeholder.setScale(1.6)
        self.tree1.instanceTo(placeholder)
        self.extraElements.append(placeholder)
        
        self.asiaMusic.play()

    
    def loadNewYorkLevel(self):
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0,
                        "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0,
                        "fire-down":0,"p":0}
        self.pause = False
        self.currentLevel = "newyork"
        #self.destroyMainMenuLevels()
        difficulty = 5
        ###Load alien###
        startPos = Point3(20,10,0)
        self.loadAlien(startPos)
        self.alien.setH(90)
        
        base.camera.setH(90)
        self.bossLvl = False
        self.bossDead = False
        ###Load the enemies###
        for i in range(0,5):
            enemy = EnemyActor(i, difficulty, False)      
            enemy.setX(random.randint(-100,100))
            enemy.setY(random.randint(8,12))
            enemy.setZ(0)
            
            self.crAct.append(enemy)
            self.crAct[i].setAiPursue(self.alien)
            
            self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy)
            base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher)
            
        taskMgr.add(self.move,"moveTask")
        taskMgr.doMethodLater(2,self.myFunction, "myFunction")
     
        self.loadLaser2()
        self.loadLaser()
        
        ###Load the environment###
        self.loadEnviron("models/america/newyork", 4)
        self.ny_nc = self.loader.loadModel("models/america/newyork-nocollision")
        self.ny_nc.reparentTo(self.render)
        self.ny_nc.setScale(4)
        self.extraElements.append(self.ny_nc)
        
        self.statue = self.loader.loadModel("models/america/statue")
        self.statue.reparentTo(self.render)
        self.statue.setPos(270,-100,13)
        self.statue.setScale(1)
        self.statue.setBillboardAxis()
        self.statue.setTwoSided(True)
        self.extraElements.append(self.statue)
        
        self.myFog = Fog("FOG")
        self.myFog.setColor(0.3,0.3,0.3)
        self.myFog.setExpDensity(0.005)
        render.setFog(self.myFog)
        self.siren.play()
        self.newyorkMusic.play()