Ejemplo n.º 1
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
Ejemplo n.º 2
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
Ejemplo n.º 3
0
class Physics:
    def __init__(self):
        self.rayCTrav = CollisionTraverser("collision traverser for ray tests")
        #self.pusher = PhysicsCollisionHandler()
        self.pusher = CollisionHandlerPusher()
        self.pusher.addInPattern('%fn-in-%in')
        self.pusher.addOutPattern('%fn-out-%in')
        self.pusher.addInPattern('%fn-in')
        self.pusher.addOutPattern('%fn-out')

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

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

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

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

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

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

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

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

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

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

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

    def getFirstCollisionInLine(self, pointA, pointB):
        """A simple raycast check which will return the first collision point as
        seen from point A towards pointB"""
        self.raytest_segment.setPointA(pointA)
        self.raytest_segment.setPointB(pointB)
        self.rayCTrav.traverse(render)
        self.raytest_queue.sortEntries()
        pos = None
        if self.raytest_queue.getNumEntries() > 0:
            pos = self.raytest_queue.getEntry(0).getSurfacePoint(render)
        return pos
class MetalSlender(ShowBase):
	
	VERSION=0.1
	
	GRAVITY = 9.81
	
	def __init__(self):
		ShowBase.__init__(self)
		
		self.initVideo()
		self.initGame()
	
	def initVideo(self):
		self.render.setShaderAuto()
		#TODO: Not working
		self.render.setAntialias(AntialiasAttrib.MMultisample)

		self.props = WindowProperties()

# 		self.props.setFullscreen(True)
#  		self.props.setSize(1920, 1080)
 		self.props.setSize(1280, 720)
		self.props.setCursorHidden(False)
		self.props.setMouseMode(self.props.M_absolute)
		
		self.win.requestProperties(self.props)
		self.win.movePointer(0, 100, 100)

	def initGame(self):
		self.paused = False
		self.initTimer = True
		self.time = 0
		self.gameOver = True

# 		self.setFrameRateMeter(True)
		self.taskMgr.add(self.menuDisplay, "menuDisplay")

		self.mainMenu = MainMenu(self)
		
		self.introSound = self.loader.loadSfx('assets/sounds/intro.mp3')
		self.introSound.setLoop(True)
		self.introSound.play()
		
	#TODO: Refactor environment into a class that inherits from nodepath
	def setupEnvironment(self):
		self.setBackgroundColor(0,0,0)
		self.setupLighting()
		self.setupFog()
		self.setupSkydome()
		self.setupPhysics()
		
	def setupFog(self):
		self.fog = Fog("fog")

		self.fog.setColor(FOG_COLOR)
		self.fog.setExpDensity(FOG_EXP_DENSITY)

		self.render.setFog(self.fog)
		
	def setupSkydome(self):
		self.skydome = self.loader.loadModel(EGG_SKYDOME)
		self.skydome.setBin('background', 0)
		self.skydome.setDepthWrite(False)
		self.skydome.reparentTo(self.cam)
		self.skydome.setCompass()
		self.skydome.setLight(self.shadeless)
		self.skydome.setScale(20)
		
	def setupLighting(self):
		alight = AmbientLight("AmbientLight")
		alight.setColor(AMBIENT_LIGHT)
		self.amblight = self.render.attachNewNode(alight)
		self.render.setLight(self.amblight)
		
		alight = AmbientLight("ShadelessLight")
		alight.setColor((1.0, 1.0, 1.0, 1.0))
		self.shadeless = self.render.attachNewNode(alight)
		
	def setupPhysics(self):
		self.cTrav = CollisionTraverser()
		
		plane = self.render.attachNewNode(CollisionNode('WorldBottom'))
		plane.node().addSolid(CollisionPlane(Plane(0, 0, 1, 30)))
		plane.node().setIntoCollideMask(CollisionMask.SCENE)
	#TODO: Set the scenario's into collide mask to a special value		
	def loadScenario(self):
		self.rooms = []
		
		self.rooms.append(Room(self, self.render, "LCG"      , "assets/chicken/lcg"    ))
		self.rooms.append(Room(self, self.render, "Bloco H"  , "assets/chicken/blocoh" ))
		self.rooms.append(Room(self, self.render, "Bloco H2" , "assets/chicken/blocoh2"))
		self.rooms.append(Room(self, self.render, "Collision", "assets/chicken/collision"    ))
		self.rooms[-1].root.setCollideMask(CollisionMask.SCENE)
		
	def addCommands(self):
		self.accept('escape', self.userExit)
		self.accept('g', self.endGame)
		self.accept('i', self.actionKeys, ['i'])
		self.accept('p', self.pauseGame)
		self.accept('z', self.restartGame)
		
		self.cTrav.setRespectPrevTransform(True)
		
	def addTasks(self):
		self.taskMgr.add(self.camctrl.update, "camera/control")
		self.taskMgr.add(self.player.updateAll, "player/update")
		self.taskMgr.add(self.hud.update, 'hud')
		self.taskMgr.add(self.player.flashlight.updatePower, 'player/flashlight/update')
		self.taskMgr.add(self.AIUpdate,"AIUpdate")
		self.taskMgr.add(self.camctrl.update, "camera/control")
		self.taskMgr.add(self.checkGoal, 'CheckGoal')

	def actionKeys(self, key):
		if key == 'i':
			self.player.fear = min(self.player.fear + 0.1, 1.0)

	def AIUpdate(self,task):
		pass
		hasAttacked = []
		for enemy in self.enemies:
			attack = enemy.update()
			hasAttacked.append(attack)
		for i in hasAttacked:
			if (i == True):
				self.player.hurt()#TODO:The enemy itself should hurt the player
				#attack
		self.AIworld.update()
		if (self.player.isDead()):
			for enemy in self.enemies:
				enemy.stop()
			self.endGame()
			return task.done
		return task.cont

	def newGame(self):
		
		self.setupEnvironment()
		
		self.AIworld = AIWorld(self.render)
		
		self.introSound.stop()
		#TODO: Play creepy sound
		initialSound = loader.loadSfx('assets/sounds/enemies/nazgul_scream.mp3')
		initialSound.play()

		self.enemies = []
		self.items = []
		self.keys = []

		#TODO: Many things are only done once the game is started
		# Load the scene.
		self.loadScenario()
		
		self.player  = Player(self, self.render, 'Player', pos=Vec3(6, 1.44, -1.5))
		self.actions = ActionManager(self, self.player, self.rooms)
		
		self.em = EventManager(self, self.player, self.actions, self.rooms)
		self.em.start()

		for enemy in self.enemies:
			enemy.getHooded().addIntruder(self.player)
			enemy.start()

		self.hud      = HUD(self, self.player)
		self.controls = PlayerControls(self.player, self.actions)
		self.camctrl  = CameraControls(self, self.player)

		self.props.setCursorHidden(True)
		self.win.requestProperties(self.props)

		self.mainMenu.hideNewGame()
		
		self.addTasks()
		self.addCommands()
		
# 		self.cTrav = None
	
	def pauseGame(self):
		if (self.paused == True):
			self.props.setCursorHidden(True)
			self.win.requestProperties(self.props)
			self.mainMenu.hidePauseGame()
			self.paused = False
			self.events.start()
			self.taskMgr.add(self.player.updateAll, "player/update")
			self.taskMgr.add(self.hud.update, 'hud')
			self.taskMgr.add(self.player.flashlight.updatePower, 'player/flashlight/update')
			self.taskMgr.add(self.AIUpdate,"AIUpdate")
			self.taskMgr.add(self.camctrl.update, "camera/control")
			self.taskMgr.add(self.checkGoal, 'CheckGoal')
			self.accept('p', self.pauseGame)
		else:
			self.events.stop()
			self.ignore('p')
			self.player.pause()
			self.taskMgr.remove("camera/control")
			self.taskMgr.remove("player/update")
			self.taskMgr.remove('hud')
			self.player.resetLast()
			self.taskMgr.remove('player/flashlight/update')
			self.taskMgr.remove("AIUpdate")
			self.taskMgr.remove('CheckGoal')
			self.props.setCursorHidden(False)
			self.win.requestProperties(self.props)
			self.mainMenu.showPauseGame()
			self.paused = True
		
	def restartGame(self):
		self.events.stop()
		self.taskMgr.remove("camera/control")
		self.taskMgr.remove("player/update")
		self.taskMgr.remove('hud')
		self.taskMgr.remove('player/flashlight/update')
		self.taskMgr.remove("AIUpdate")
		self.taskMgr.remove('CheckGoal')
		self.cleanResources()
		self.props.setCursorHidden(False)
		self.win.requestProperties(self.props)
		self.initGame()
	
	def cleanResources(self):
		self.AIworld = None
		del self.enemies [:]
		del self.rooms [:]
		self.enemies = None
		self.rooms = None
		self.player = None
		self.actions = None
		self.events = None
		self.mainMenu = None
		self.fog = None
		self.skydome.removeNode()
		self.amblight.removeNode()
		self.shadeless.removeNode()
		self.target1.removeNode()
		self.target2.removeNode()
		self.banana.removeNode()
		self.skydome = None
		self.amblight = None
		self.shadeless = None
		self.target1 = None
		self.target2 = None
		self.banana = None
		self.hud = None
		self.camctrl = None
		self.controls = None
		self.cTrav.clearColliders()
		gc.collect()

		self.taskMgr.add(self.player.updateAll, "player/update")
		self.taskMgr.add(self.player.flashlight.updatePower, 'player/flashlight/update')
		self.taskMgr.add(self.AIUpdate,"AIUpdate")
		self.taskMgr.add(self.camctrl.update, "camera/control")
		self.taskMgr.add(self.playerUpdate, "playerUpdate")
		self.taskMgr.add(self.checkGoal, 'CheckGoal')

	def endGame(self):
		self.hud.hide()
		if (self.gameOver):
			self.image = OnscreenImage(image="assets/images/GameOver.png", pos = (0, 0, 0), parent=base.render2d, scale=(1,1,1))
		else:
			self.image = OnscreenImage(image="assets/images/to-be-continued.jpg", pos = (0, 0, 0), parent=base.render2d, scale=(1,1,1))
		self.startTimer(3)

		self.taskMgr.remove("camera/control")

	def menuDisplay(self, task):
		if (self.initTimer == False):
			hasFinished = self.timer()
			if (hasFinished):
				self.resetTimer()
				self.image.hide()
				self.props.setCursorHidden(False)
				self.props.setMouseMode(self.props.M_absolute)
				self.win.requestProperties(self.props)
				self.mainMenu.showNewGame()

		return task.cont

	def timer(self):
		currentTime = time.time()
		diff = currentTime - self.time
		if (diff > self.interval):
			self.resetTimer()
			return True
		else:
			return False

	def resetTimer(self):
		self.initTimer = True

	def startTimer(self, interval):
		if (self.initTimer == True):
			self.interval = interval
			self.initTimer = False
			self.time = time.time()

	def playerUpdate(self, task):
		reached = self.checkGoal()
		if (reached):
# 			self.player.die()
			self.endGame()
			return task.done
		someKey = False
		for key in self.actions.keys:
			if (key.wasPicked()):
				someKey = True
		self.hud.setKey(someKey)

		return task.cont

	def checkGoal(self, task):
		close = not self.goal.isEmpty() and self.player.getNodePath().getDistance(self.goal) < 2
		hasKey = 'goal' in [key.lock for key in self.player.inventory]
		if (close and hasKey):
			self.gameOver = False
			self.endGame()
		return task.cont