class TerrainPhysics():
    def __init__(self, ):
        # World
        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81))


    def setup(self, terrain, player):
        """Bullet has to be started before some things in the program to avoid crashes."""
        self.terrain = terrain
        self.player = player

        # Demo
        spawn = player.attachNewNode("spawnPoint")
        spawn.setPos(0, -5, 7)
        self.demo = TerrainPhysicsDemo2(self.world, spawn)
        taskMgr.add(self.update, 'physics')

    def test(self):
        self.demo.start()

    def update(self, task):
        dt = globalClock.getDt()
        self.world.doPhysics(dt)
        return task.cont
예제 #2
0
파일: physics.py 프로젝트: croxis/itf
class PhysicsSystem(sandbox.EntitySystem):
    """System that interacts with the Bullet physics world"""
    def init(self):
        self.accept("addSpaceship", self.addSpaceship)
        self.world = BulletWorld()

    def begin(self):
        dt = globalClock.getDt()
        self.world.doPhysics(dt)
        #world.doPhysics(dt, 10, 1.0/180.0)

    def process(self, entity):
        pass

    def addSpaceship(self, component, shipName, position, linearVelcocity):
        component.bulletShape = BulletSphereShape(5)
        component.node = BulletRigidBodyNode(shipName)
        component.node.setMass(1.0)
        component.node.addShape(component.bulletShape)
        component.nodePath = universals.solarSystemRoot.attachNewNode(component.node)
        addBody(component.node)
        position = sandbox.get_system(solarSystem.SolarSystemSystem).solarSystemRoot.find("**/Earth").getPos()
        #component.nodePath.setPos(position + Point3(6671, 0, 0))
        component.nodePath.setPos(position)
        #component.node.setLinearVelocity(Vec3(0, 7.72983, 0))
        component.node.setLinearVelocity(linearVelcocity)
예제 #3
0
class PhysicsMgr():
    def __init__(self, _game, _gravity=(0, 0, -9)):

        self.game = _game
        self.physicsWorld = BulletWorld()
        self.physicsWorld.setGravity(Vec3(_gravity))

    def startPhysics(self):
        taskMgr.add(self.updatePhysics, "update-physics")

    def stopPhysics(self):
        taskMgr.remove("update-physics")

    def setPhysicsDebug(self, _bool=False):
        debugNode = BulletDebugNode('Debug')
        self.debugNP = render.attachNewNode(debugNode)

        if _bool:
            debugNode = BulletDebugNode('Debug')
            debugNode.showWireframe(True)
            debugNode.showConstraints(True)
            debugNode.showBoundingBoxes(False)
            debugNode.showNormals(False)
            self.debugNP = render.attachNewNode(debugNode)
            self.physicsWorld.setDebugNode(self.debugNP.node())
            self.debugNP.show()
        else:
            self.debugNP.hide()
            #debugNode = None

    def updatePhysics(self, task):
        dt = globalClock.getDt()
        self.physicsWorld.doPhysics(dt, 5, 1.0 / 240.0)

        return task.cont
예제 #4
0
class gameMechanics(DirectObject):
    def __init__(self, **kwargs):
        super(gameMechanics, self).__init__()

        self.joy = joystick()
        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81))
        self.arena = kwargs['environment']
        self.worldNp = render.attachNewNode('world')
        self.worldNp.setScale(3)
        self.arena.setupPhysics(world=self.worldNp, mask=BitMask32.allOn())
        self.world.setDebugNode(self.arena.debugNP.node())
        self.world.setDebugNode(self.arena.debugNP.node())

        self.listOfPlayers = kwargs['playerslist']
        self.setupCollisions(playerslist=self.listOfPlayers)
        self.world.attachRigidBody(self.arena.mainNp.node())
        for model in self.arena.modelList:
            self.world.attachRigidBody(model.nodePath.node())

        self.numofjoy = 0
        taskMgr.add(self.mech_update, 'mechupdate')

        self.listOfPlayers[1].characterNP.setY(self.listOfPlayers[0], -5)

    # base.disableMouse()
    def setupCollisions(self, **kwargs):

        for player in self.listOfPlayers:
            player.setupPhysics(worldnp=self.worldNp, world=self.world)
            player.getModel()

    def mech_update(self, task):
        for player in self.listOfPlayers:
            player.setup_collision
        dt = globalClock.getDt()
        self.world.doPhysics(dt, 80, 1 / 180)

        self.cameraTask(task)
        self.joy.get_input()

        return task.cont

    def cameraTask(self, task):

        pass
예제 #5
0
class World:
    def __init__(self):
        self.init_bullet()
        self.init_skybox()

    def init_bullet(self):
        self.bullet_world = BulletWorld()

    def update_bullet(self, task):
        dt = ClockObject.getGlobalClock().getDt()
        self.bullet_world.doPhysics(dt)
        return task.cont

    def init_skybox(self):
        # This should probably have its own class..
        self.sky_material = Material()
        self.sky_material.clearAmbient()
        self.sky_material.clearEmission()
        self.sky_material.setAmbient(VBase4(1, 1, 1, 1))

        # This loads "basic_skybox_#" # being 0-6
        # If the skybox was made in spacescape the files must be renamed to
        # work properly, and the 2 and 3 files should be switched.
        self.skybox_texture = loader.loadCubeMap("images/skybox/red_nebula_purple_flares/Red_nebula_#.png")

        # TODO: Figure out a way (if possible) to allow 3d objects to be seen
        # through the skysphere, It already kinda does this, but its weird.

        self.skybox = NodePath(loader.loadModel("models/skybox.x"))
        self.skybox.setLightOff()
        self.skybox.setAttrib(CullFaceAttrib.make(CullFaceAttrib.MCullCounterClockwise))
        # self.skybox.setTwoSided(True) BETTER ^
        self.skybox.setScale(5000)
        self.skybox.clearDepthWrite
        self.skybox.setDepthWrite(False)
        self.skybox.setMaterial(self.sky_material, 1)
        self.skybox.setTexture(self.skybox_texture)
        self.skybox.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
        # This makes it so objects behind the skybox are rendered
        self.skybox.setBin("back_to_front", 40)
        # projects the texture as it looks from render
        self.skybox.setTexProjector(TextureStage.getDefault(), render, self.skybox)
        self.skybox.setCompass()
        self.skybox.reparentTo(base.camera)
예제 #6
0
class GameState(ShowBase):
    def __init__(self):
        loadPrcFile("server-config.prc")
        ShowBase.__init__(self)
        self.__rotations = {}

        # Panda pollutes the global namespace.  Some of the extra globals can be referred to in nicer ways
        # (for example self.render instead of render).  The globalClock object, though, is only a global!  We
        # create a reference to it here, in a way that won't upset PyFlakes.
        self.globalClock = __builtins__["globalClock"]

        # Set up physics: the ground plane and the capsule which represents the player.
        self.world = BulletWorld()

        # The ground first:
        shape = BulletPlaneShape(Vec3(0, 0, 1), 0)
        node = BulletRigidBodyNode("Ground")
        node.addShape(shape)
        np = self.render.attachNewNode(node)
        np.setPos(0, 0, 0)
        self.world.attachRigidBody(node)

        # Create a task to update the scene regularly.
        self.taskMgr.add(self.update, "UpdateTask")

    # Update the scene by turning objects if necessary, and processing physics.
    def update(self, task):
        asyncore.loop(timeout=0.1, use_poll=True, count=1)
        Player.update_all()

        for node, angular_velocity in self.__rotations.iteritems():
            node.setAngularMovement(angular_velocity)

        dt = self.globalClock.getDt()
        self.world.doPhysics(dt)
        return task.cont

    def set_angular_velocity(self, node, angular_velocity):
        if angular_velocity != 0:
            self.__rotations[node] = angular_velocity
        elif node in self.__rotations:
            del self.__rotations[node]
예제 #7
0
class World(DirectObject):
    def __init__(self):
        DirectObject.__init__(self)

        self.node = NodePath('World')
        self.debug_node = self.node.attachNewNode(BulletDebugNode('Debug'))

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

        self.accept('f1', self.debug)

    def update(self, dt):
        self.world.doPhysics(dt)

    def debug(self):
        if self.debug_node.isHidden():
            self.debug_node.show()
            base.setFrameRateMeter(True)
        else:
            self.debug_node.hide()
            base.setFrameRateMeter(False)
예제 #8
0
class PhysicsMgr():

    def __init__(self, _game, _gravity=(0, 0, -9)):

    	self.game = _game
    	self.physicsWorld = BulletWorld()
    	self.physicsWorld.setGravity(Vec3(_gravity))

    def startPhysics(self):
    	taskMgr.add(self.updatePhysics, "update-physics")

    def stopPhysics(self):
    	taskMgr.remove("update-physics")

    def setPhysicsDebug(self, _bool=False):
        debugNode = BulletDebugNode('Debug')
        self.debugNP = render.attachNewNode(debugNode)

        if _bool:
            debugNode = BulletDebugNode('Debug')
            debugNode.showWireframe(True)
            debugNode.showConstraints(True)
            debugNode.showBoundingBoxes(False)
            debugNode.showNormals(False)
            self.debugNP = render.attachNewNode(debugNode)
            self.physicsWorld.setDebugNode(self.debugNP.node())
            self.debugNP.show()
        else:
            self.debugNP.hide()
            #debugNode = None

    def updatePhysics(self, task):
    	dt = globalClock.getDt()
        self.physicsWorld.doPhysics(dt, 5, 1.0/240.0)

        return task.cont
예제 #9
0
class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        #Camera pos
        self.cam.setPos(0, 0, 20)

        self.world_create(1000, 1000)

    def world_create(self, sizex, sizey):
        self.worldNP = self.render.attachNewNode('World')

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

        self.shape = BulletPlaneShape(Vec3(0, 0, 1), 1)

        self.groundNP = self.worldNP.attachNewNode(BulletRigidBodyNode('Floor'))
        self.groundNP.node().addShape(self.shape)

        self.world.attachRigidBody(self.groundNP.node())

        # Load model
        self.ground = self.loader.loadModel("Models/floor_basic.egg")
        self.ground.reparentTo(self.groundNP)

        # Scale and position model
        self.ground.setScale(sizex, sizey, 0)
        self.ground.setPos(0, 0, 0)

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

    def update(self, task):
        dt = globalClock.getDt()
        self.world.doPhysics(dt, 10, 1.0/180.0)
        return Task.cont
예제 #10
0
파일: gameBase.py 프로젝트: arikel/PPARPG
class GameBase(ShowBase):
	def __init__(self, KEY_LIST):
		ShowBase.__init__(self)
		
		#---------------------------------------------------------------
		# clock
		self.globalClock = ClockObject()
		
		#---------------------------------------------------------------
		# KeyHandler
		self.kh = KeyHandler(KEY_LIST)
		
		#---------------------------------------------------------------
		# Bullet
		self.world = BulletWorld()
		self.world.setGravity(Vec3(0, 0, -12.81))
		self.gravityUp = False
		
		self.debugNode = BulletDebugNode('Debug')
		self.debugNode.showWireframe(True)
		self.debugNode.showConstraints(True)
		self.debugNode.showBoundingBoxes(True)
		self.debugNode.showNormals(True)
		self.debugNP = self.render.attachNewNode(self.debugNode)
		#self.debugNP.show()
		self.world.setDebugNode(self.debugNode)
		self._debug = False
		
		#---------------------------------------------------------------
		# Player
		#---------------------------------------------------------------
		# CharacterController
		self.player = CharacterController(self)
		self.player.setActor('models/characters/female', {
				'walk' : 'models/characters/female-walk.egg'
			},
			flip = True,
			pos = (0,0,-1),
			scale = 1.0)
		self.player.setPos(0, -5, 3)
		self.player.playerModel.loop("walk")
		self.playerNp = self.player.np
		
		#---------------------------------------------------------------
		# Camera
		self.camHandler = CamHandler(self)
		
		#---------------------------------------------------------------
		# task
		#self.taskMgr.add(self.update, "update")
	
	#---------------------------------------------------------------
	# FPS
	def toggleFPS(self):
		if self.frameRateMeter:
			self.setFrameRateMeter(False)
		else:
			self.setFrameRateMeter(True)
	
	#---------------------------------------------------------------
	# Mouse cursor
	def hideCursor(self):
		props = WindowProperties()
		props.setCursorHidden(True) 
		self.win.requestProperties(props)
	def showCursor(self):
		props = WindowProperties()
		props.setCursorHidden(False)
		self.win.requestProperties(props)
	
	def getObjectHoverName(self):
		if not self.mouseWatcherNode.hasMouse():
			return None
		pMouse = self.mouseWatcherNode.getMouse()
		pFrom = Point3()
		pTo = Point3()
		self.camLens.extrude(pMouse, pFrom, pTo)
		# Transform to global coordinates
		pFrom = self.render.getRelativePoint(self.cam, pFrom)
		pTo = self.render.getRelativePoint(self.cam, pTo)
		result = self.world.rayTestClosest(pFrom, pTo)
		if result.hasHit():
			pos = result.getHitPos()
			name = result.getNode().getName()
			return name
		else:
			return None
		
	def getObjectCenterScreen(self):
		pFrom = Point3()
		pTo = Point3()
		self.camLens.extrude((0,0), pFrom, pTo)
		# Transform to global coordinates
		pFrom = self.render.getRelativePoint(self.cam, pFrom)
		pTo = self.render.getRelativePoint(self.cam, pTo)
		result = self.world.rayTestClosest(pFrom, pTo)
		if result.hasHit():
			pos = result.getHitPos()
			name = result.getNode().getName()
			return name
		else:
			return None
	
	#---------------------------------------------------------------
	# Fog
	def setFog(self):
		myFog = Fog("Fog")
		myFog.setColor((0,0,0,1))
		myFog.setExpDensity(0.025)
		self.render.setFog(myFog)
		self.fog = True
		
	def clearFog(self):
		self.render.clearFog()
		self.fog = False
		
	def toggleFog(self):
		if self.fog:
			self.clearFog()
		else:
			self.setFog()
	
	
	#---------------------------------------------------------------
	# Camera	
	def setFov(self, x):
		self.camLens.setFov(x)
	
	def getFov(self):
		return self.camLens.getFov()[0]
	
	def setNear(self, n):
		self.camLens.setNear(n)
		
	def setFar(self, n):
		self.camLens.setFar(n)
	
	#---------------------------------------------------------------	
	# Physics
	
	def toggleGravity(self):
		if self.gravityUp:
			self.gravityUp = False
			self.world.setGravity(Vec3(0,0,-9.8))
		else:
			self.gravityUp = True
			self.world.setGravity(Vec3(0,0,9.8))
		
	def toggleDebug(self):
		#print "Toggle debug, extraArgs = %s" % (extraArgs)
		if self._debug:
			self._debug = False
			self.debugNP.hide()
		else:
			self._debug = True
			self.debugNP.show()

	def updatePhysics(self, dt):
		#self.world.doPhysics(dt, 20, 1.0/180)
		self.world.doPhysics(dt)
		#cnt = self.world.contactTest(self.ground.node)
		#for boxName in self.objects:
		#	self.objects[boxName].update(dt)
		'''
			cntTest = self.world.contactTest(self.objects[boxName].node)
			cnt = cntTest.getContacts()
			for c in cnt:
				node0 = c.getNode0().getName()
				node1 = c.getNode1().getName()
				#print node0, " in contact with ", node1
		'''
		
	def update(self, task):
		self.globalClock.tick()
		t = self.globalClock.getFrameTime()
		dt = self.globalClock.getDt()
		self.updatePhysics(dt)
		self.player.update(dt)
		return task.cont
	
	def quit(self):
		self.taskMgr.stop()
	
	def stop(self):
		self.taskMgr.stop()
		
	def start(self):
		self.taskMgr.run()
class TestApplication(ShowBase):

  def __init__(self):

    ShowBase.__init__(self)

    self.setupRendering()
    self.setupControls()
    self.setupPhysics()
    self.clock_ = ClockObject()
    self.controlled_obj_index_ = 0
    self.kinematic_mode_ = False
  
    # Task
    taskMgr.add(self.update, 'updateWorld')


  def setupRendering(self):

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

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

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

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

  def setupControls(self):

    # Input (Events)
    self.accept('escape', self.doExit)
    self.accept('r', self.doReset)
    self.accept('f1', self.toggleWireframe)
    self.accept('f2', self.toggleTexture)
    self.accept('f3', self.toggleDebug)
    self.accept('f5', self.doScreenshot)
    self.accept('n', self.selectNextControlledObject)
    self.accept('k',self.toggleKinematicMode)
    self.accept('p',self.printInfo)
    self.accept('q',self.zoomIn)
    self.accept('a',self.zoomOut)
    self.accept('s',self.toggleRightLeft)

    # Inputs (Polling)
    self.input_state_ = InputState()
    self.input_state_.watchWithModifiers("right","arrow_right")
    self.input_state_.watchWithModifiers('left', 'arrow_left')
    self.input_state_.watchWithModifiers('jump', 'arrow_up')
    self.input_state_.watchWithModifiers('stop', 'arrow_down')
    self.input_state_.watchWithModifiers('roll_right', 'c')
    self.input_state_.watchWithModifiers('roll_left', 'z')
    self.input_state_.watchWithModifiers('roll_stop', 'x')

    self.title = addTitle("Panda3D: Sprite Animation")
    self.inst1 = addInstructions(0.06, "ESC: Quit")
    self.inst2 = addInstructions(0.12, "Up/Down: Jump/Stop")
    self.inst3 = addInstructions(0.18, "Left/Right: Move Left / Move Rigth")
    self.inst4 = addInstructions(0.24, "z/x/c : Rotate Left/ Rotate Stop / Rotate Right")
    self.inst5 = addInstructions(0.30, "n: Select Next Character")
    self.inst6 = addInstructions(0.36, "k: Toggle Kinematic Mode")
    self.inst7 = addInstructions(0.42, "q/a: Zoom in / Zoom out")
    self.inst7 = addInstructions(0.48, "s: Toggle Rigth|Left ")
    self.inst7 = addInstructions(0.54, "p: Print Info")

  def printInfo(self):
    self.sprt_animator_.printInfo()

  def setupPhysics(self):

    # setting up physics world and parent node path 
    self.physics_world_ = BulletWorld()
    self.world_node_ = self.render.attachNewNode('world')
    self.cam.reparentTo(self.world_node_)
    self.physics_world_.setGravity(Vec3(0, 0, -9.81))

    self.debug_node_ = self.world_node_.attachNewNode(BulletDebugNode('Debug'))
    self.debug_node_.show()
    self.debug_node_.node().showWireframe(True)
    self.debug_node_.node().showConstraints(True)
    self.debug_node_.node().showBoundingBoxes(False)
    self.debug_node_.node().showNormals(True)

    # setting up ground
    self.ground_ = self.world_node_.attachNewNode(BulletRigidBodyNode('Ground'))
    self.ground_.node().addShape(BulletPlaneShape(Vec3(0, 0, 1), 0))
    self.ground_.setPos(0,0,0)
    self.ground_.setCollideMask(BitMask32.allOn())
    self.physics_world_.attachRigidBody(self.ground_.node())

    self.object_nodes_ = []
    self.controlled_objects_=[]
    num_boxes = 20
    side_length = 0.2
    size = Vec3(0.5*side_length,0.5*side_length,0.5*side_length)
    start_pos = Vec3(-num_boxes*side_length,0,6)

    """
    # creating boxes
    box_visual = loader.loadModel('models/box.egg')
    box_visual.clearModelNodes()
    box_visual.setTexture(loader.loadTexture('models/wood.png'))
    
    bounds = box_visual.getTightBounds() # start of box model scaling
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = side_length/max([extents.getX(),extents.getY(),extents.getZ()])
    box_visual.setScale((scale_factor,scale_factor ,scale_factor)) # end of box model scaling

    for i in range(0,20):
      self.addBox("name %i"%(i),size,start_pos + Vec3(i*side_length,0,0),box_visual)

    start_pos = Vec3(-num_boxes*side_length,0,8)
    for i in range(0,20):
      self.addBox("name %i"%(i),size,start_pos + Vec3(i*2*side_length,0,0),box_visual)
    """

    # creating sprite animator
    sprt_animator = SpriteAnimator('hiei_run')            
    if not sprt_animator.loadImage(SPRITE_IMAGE_DETAILS[0], # file path
      SPRITE_IMAGE_DETAILS[1], # columns
      SPRITE_IMAGE_DETAILS[2], # rows
      SPRITE_IMAGE_DETAILS[3], # scale x
      SPRITE_IMAGE_DETAILS[4], # scale y
      SPRITE_IMAGE_DETAILS[5]): # frame rate
      print "Error loading image %s"%(SPRITE_IMAGE_DETAILS[0])
      sys.exit(1)
    self.sprt_animator_ = sprt_animator

    # creating Mobile Character Box
    size = Vec3(0.5,0.2,1)
    mbox_visual = loader.loadModel('models/box.egg')
    bounds = mbox_visual.getTightBounds()
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = 1/max([extents.getX(),extents.getY(),extents.getZ()])
    mbox_visual.setScale(size.getX()*scale_factor,size.getY()*scale_factor,size.getZ()*scale_factor)

    mbox = self.world_node_.attachNewNode(BulletRigidBodyNode('CharacterBox'))
    mbox.node().addShape(BulletBoxShape(size/2))
    mbox.node().setMass(1.0)
    mbox.node().setLinearFactor((1,0,1))
    mbox.node().setAngularFactor((0,1,0))
    mbox.setCollideMask(BitMask32.allOn())
    mbox_visual.instanceTo(mbox)
    mbox_visual.hide()
    mbox.setPos(Vec3(1,0,size.getZ()+1))

    bounds = sprt_animator.getTightBounds()
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = size.getZ()/extents.getZ()
    sprt_animator.setScale(scale_factor,1,scale_factor)
    sprt_animator.reparentTo(mbox)
    bounds = sprt_animator.getTightBounds()
    print "Sprite Animator bounds %s , %s"%(str(bounds[1]),str(bounds[0]))
    
    self.physics_world_.attachRigidBody(mbox.node())
    self.object_nodes_.append(mbox)
    self.controlled_objects_.append(mbox)

    # creating sphere
    diameter = 0.4
    sphere_visual = loader.loadModel('models/ball.egg')

    bounds = sphere_visual.getTightBounds() # start of model scaling
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = diameter/max([extents.getX(),extents.getY(),extents.getZ()])
    sphere_visual.clearModelNodes()
    sphere_visual.setScale(scale_factor,scale_factor,scale_factor) # end of model scaling

    sphere_visual.setTexture(loader.loadTexture('models/bowl.jpg'))
    sphere = self.world_node_.attachNewNode(BulletRigidBodyNode('Sphere'))
    sphere.node().addShape(BulletSphereShape(0.5*diameter))
    sphere.node().setMass(1.0)
    sphere.node().setLinearFactor((1,0,1))
    sphere.node().setAngularFactor((0,1,0))
    sphere.setCollideMask(BitMask32.allOn())
    sphere_visual.instanceTo(sphere)
    sphere.setPos(Vec3(0,0,size.getZ()+1))
    
    self.physics_world_.attachRigidBody(sphere.node())
    self.object_nodes_.append(sphere)
    self.controlled_objects_.append(sphere)

    self.setupLevel()


  def addBox(self,name,size,pos,visual):

    # Box (dynamic)
    box = self.world_node_.attachNewNode(BulletRigidBodyNode(name))
    box.node().setMass(1.0)
    box.node().addShape(BulletBoxShape(size))
    box.setPos(pos)
    box.setCollideMask(BitMask32.allOn())
    box.node().setLinearFactor((1,0,1))
    box.node().setAngularFactor((0,1,0))
    visual.instanceTo(box)

    self.physics_world_.attachRigidBody(box.node())
    self.object_nodes_.append(box)

  def setupLevel(self):

    # (left, top, length ,depth(y) ,height)
    platform_details =[ 
      (-20, 4, 20, 4, 1  ),
      (-2, 5, 10, 4, 1  ),
      ( 4 , 2 , 16, 4, 1.4),
      (-4 , 1, 10, 4, 1),
      ( 16, 6, 30, 4, 1)
      ]
    for i in range(0,len(platform_details)):
      p = platform_details[i]
      topleft = (p[0],p[1])
      size = Vec3(p[2],p[3],p[4])
      self.addPlatform(topleft, size,'Platform%i'%(i))


  def addPlatform(self,topleft,size,name):

    # Visual
    visual = loader.loadModel('models/box.egg')
    visual.setTexture(loader.loadTexture('models/iron.jpg'))
    bounds = visual.getTightBounds()
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = 1/max([extents.getX(),extents.getY(),extents.getZ()])
    visual.setScale(size.getX()*scale_factor,size.getY()*scale_factor,size.getZ()*scale_factor)
    
    # Box (static)
    platform = self.world_node_.attachNewNode(BulletRigidBodyNode(name))
    platform.node().setMass(0)
    platform.node().addShape(BulletBoxShape(size/2))
    platform.setPos(Vec3(topleft[0] + 0.5*size.getX(),0,topleft[1]-0.5*size.getZ()))
    platform.setCollideMask(BitMask32.allOn())
    visual.instanceTo(platform)

    self.physics_world_.attachRigidBody(platform.node())
    self.object_nodes_.append(platform)

  def update(self, task):

    self.clock_.tick()
    dt = self.clock_.getDt()
    self.processInput(dt)    
    self.physics_world_.doPhysics(dt, 5, 1.0/180.0)
    self.updateCamera()
  

    

    return task.cont 

  def processInput(self,dt):
  
    activate = False
    obj = self.controlled_objects_[self.controlled_obj_index_]

    if self.kinematic_mode_:
      obj.node().setKinematic(True)
      return
    else:
      obj.node().setKinematic(False)

    vel = obj.node().getLinearVelocity()
    w = obj.node().getAngularVelocity()

  
    if self.input_state_.isSet('right'): 
      vel.setX(2)
      activate = True

    if self.input_state_.isSet('left'): 
      vel.setX(-2)
      activate = True

    if self.input_state_.isSet('jump'): 
      vel.setZ(4)
      activate = True

    if self.input_state_.isSet('stop'): 
      vel.setX(0)

    if self.input_state_.isSet('roll_right'):
      w.setY(ROTATIONAl_SPEED)
      activate = True

    if self.input_state_.isSet('roll_left'):
      w.setY(-ROTATIONAl_SPEED)
      activate = True

    if self.input_state_.isSet('roll_stop'):
      w.setY(0)

    if activate : obj.node().setActive(True,True)
    obj.node().setLinearVelocity(vel)
    obj.node().setAngularVelocity(w)

  def updateCamera(self):

    if len(self.controlled_objects_) > 0:
      obj = self.controlled_objects_[self.controlled_obj_index_]
      self.cam.setPos(obj,0, -CAM_DISTANCE, 0)
      self.cam.lookAt(obj.getPos())

  def cleanup(self):
    
    for i in range(0,len(self.object_nodes_)):
      rb = self.object_nodes_[i]
      self.physics_world_.removeRigidBody(rb.node())

    self.object_nodes_ = []
    self.controlled_objects_ = []
    self.physics_world_.removeRigidBody(self.ground_.node())
    self.ground_ = None
    self.physics_world_ = None
    self.debug_node_ = None
    self.sprt_animator_ = None
    self.cam.reparentTo(self.render)
    self.world_node_.removeNode()
    self.world_node_ = None

  # _____HANDLER_____

  def zoomIn(self):
    global CAM_DISTANCE
    CAM_DISTANCE-=4

  def zoomOut(self):
    global CAM_DISTANCE
    CAM_DISTANCE+=4

  def toggleKinematicMode(self):
    self.kinematic_mode_ = not self.kinematic_mode_

    print "Kinematic Mode %s"%('ON' if self.kinematic_mode_ else 'OFF')

  def toggleRightLeft(self):
    self.sprt_animator_.faceRight(not self.sprt_animator_.facing_right_)

  def selectNextControlledObject(self):
    self.controlled_obj_index_+=1
    if self.controlled_obj_index_ >= len(self.controlled_objects_):
      self.controlled_obj_index_ = 0 #  reset


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

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

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

  def doScreenshot(self):
    self.screenshot('Bullet')
예제 #12
0
class BulletBase(object):
    """ Manages Panda3d Bullet physics resources and convenience methods."""

    # Bitmasks for each object type. By setting ghost and static
    # objects to different masks, we can filter ghost-to-static
    # collisions.
    ghost_bit = BitMask32.bit(1)
    static_bit = BitMask32.bit(2)
    dynamic_bit = ghost_bit | static_bit
    bw_types = (BulletBaseCharacterControllerNode, BulletBodyNode,
                BulletConstraint, BulletVehicle)

    def __init__(self):
        self.world = None
        # Parameters for simulation.
        self.sim_par = {"size": 1. / 100, "n_subs": 10, "size_sub": 1. / 1000}
        # Initialize axis constraint so that there aren't constraints.
        self.axis_constraint_fac = Vec3(1, 1, 1)
        self.axis_constraint_disp = Vec3(nan, nan, nan)
        # Attribute names of destructable objects.
        self._destructables = ()

    def init(self):
        """ Initialize world and resources. """
        # Initialize world.
        self.world = BulletWorld()

    def destroy(self):
        """ Destroy all resources."""
        for key in self._destructables:
            getattr(self, key).destroy()

    def setup_debug(self):
        debug_node = BulletDebugNode('Debug')
        debug_node.showWireframe(True)
        debug_node.showConstraints(True)
        debug_node.showBoundingBoxes(True)
        debug_node.showNormals(True)
        self.world.setDebugNode(debug_node)
        return debug_node

    @property
    def bodies(self):
        """ Return all bodies (rigid, soft, and ghost) in self.world."""
        bodies = (self.world.getRigidBodies() + self.world.getSoftBodies() +
                  self.world.getGhosts())
        return bodies

    def _constrain_axis(self, body):
        """ Apply existing axis constraints to a body."""
        # Set displacements.
        for axis, (f, d) in enumerate(zip(self.axis_constraint_fac,
                                          self.axis_constraint_disp)):
            if not f and not isnan(d):
                nodep = NodePath(body)
                pos = nodep.getPos()
                pos[axis] = d
                nodep.setPos(pos)
        try:
            # Linear and angular factors of 0 mean forces in the
            # corresponding axis are scaled to 0.
            body.setLinearFactor(self.axis_constraint_fac)
            # Angular factors restrict rotation about an axis, so the
            # following logic selects the appropriate axes to
            # constrain.
            s = sum(self.axis_constraint_fac)
            if s == 3.:
                v = self.axis_constraint_fac
            elif s == 2.:
                v = -self.axis_constraint_fac + 1
            else:
                v = Vec3.zero()
            body.setAngularFactor(v)
        except AttributeError:
            # The body was not a rigid body (it didn't have
            # setLinearFactor method).
            pass

    def set_axis_constraint(self, axis, on, disp=None):
        """ Sets an axis constraint, so that bodies can/cannot
        move in that direction."""
        # Create the constraint vector.
        self.axis_constraint_fac[axis] = int(not on)
        self.axis_constraint_disp[axis] = disp if disp is not None else nan
        # Iterate over bodies, applying the constraint.
        for body in self.bodies:
            self._constrain_axis(body)

    def attach(self, objs, suppress_deact_warn=False):
        """ Attach Bullet objects to the world."""
        if not self.world:
            raise BulletBaseError("No BulletWorld initialized.")
        # Make sure they're iterable.
        if not isinstance(objs, Iterable):
            objs = [objs]
        elif isinstance(objs, dict):
            objs = objs.itervalues()
        bw_objs = []
        for obj in objs:
            if isinstance(obj, NodePath):
                obj = obj.node()
            if isinstance(obj, self.bw_types):
                bw_objs.append(obj)
        # Don't attach ones that are already attached.
        bw_objs = set(bw_objs) - set(self.bodies)
        # Attach them.
        for obj in bw_objs:
            # Warn about deactivation being enabled.
            if (not suppress_deact_warn and
                getattr(obj, "isDeactivationEnabled", lambda: True)()):
                msg = "Deactivation is enabled on object: %s" % obj
                warn(msg, DeactivationEnabledWarning)
            # Apply existing axis constraints to the objects.
            self._constrain_axis(obj)
            # Attach the objects to the world.
            try:
                self.world.attach(obj)
            except AttributeError:
                DeprecationWarning("Upgrade to Panda3d 1.9.")
                for attr in ("attachRigidBody", "attachConstraint",
                             "attachGhost"):
                    attach = getattr(self.world, attr)
                    try:
                        attach(obj)
                    except TypeError:
                        pass
                    else:
                        break

    def remove(self, objs):
        """ Remove Bullet objects to the world."""
        if not self.world:
            raise BulletBaseError("No BulletWorld initialized.")
        # Make sure they're iterable.
        if not isinstance(objs, Iterable):
            objs = [objs]
        elif isinstance(objs, dict):
            objs = objs.itervalues()
        bw_objs = []
        for obj in objs:
            if isinstance(obj, NodePath):
                obj = obj.node()
            if isinstance(obj, self.bw_types):
                bw_objs.append(obj)
        # Remove them.
        for obj in bw_objs:
            # Remove the objects from the world.
            try:
                self.world.remove(obj)
            except AttributeError:
                DeprecationWarning("Upgrade to Panda3d 1.9.")
                for attr in ("removeRigidBody", "removeConstraint",
                             "removeGhost"):
                    remove = getattr(self.world, attr)
                    try:
                        remove(obj)
                    except TypeError:
                        pass
                    else:
                        break

    def remove_all(self):
        """ Remove all objects from world."""
        objs = (self.world.getCharacters() + self.world.getConstraints() +
                self.world.getGhosts() + self.world.getRigidBodies() +
                self.world.getSoftBodies() + self.world.getVehicles())
        self.remove(objs)

    @property
    def gravity(self):
        """ Get gravity on self.world. """
        return self.world.getGravity()

    @gravity.setter
    def gravity(self, gravity):
        """ Set gravity on self.world. """
        self.world.setGravity(Vec3(*gravity))

    def step(self, *args, **kwargs):
        """ Wrapper for BulletWorld.doPhysics."""
        # Defaults.
        dt = args[0] if len(args) > 0 else self.sim_par["size"]
        n_subs = args[1] if len(args) > 1 else self.sim_par["n_subs"]
        size_sub = args[2] if len(args) > 2 else self.sim_par["size_sub"]
        force = kwargs.get("force", None)
        if force:
            bodies, vecpos, dur = force
            dt0 = np.clip(dur, 0., dt)
            n_subs0 = int(np.ceil(n_subs * dt0 / dt))
            dt1 = dt - dt0
            n_subs1 = n_subs - n_subs0 + 1
            for body in bodies:
                body.applyForce(Vec3(*vecpos[0]), Point3(*vecpos[1]))
            # With force.
            self.world.doPhysics(dt0, n_subs0, size_sub)
            for body in bodies:
                body.clearForces()
        else:
            dt1 = dt
            n_subs1 = n_subs
        # With no force.
        self.world.doPhysics(dt1, n_subs1, size_sub)

    @staticmethod
    def attenuate_velocities(bodies, linvelfac=0., angvelfac=0.):
        """ Zeros out the bodies' linear and angular velocities."""
        # Iterate through bodies, re-scaling their velocity vectors
        for body in bodies:
            linvel0 = body.getLinearVelocity()
            angvel0 = body.getAngularVelocity()
            # .normalize() returns True if the length is > 0
            if linvel0.normalize():
                linvel = linvel0 * linvelfac
                body.setLinearVelocity(linvel)
            if angvel0.normalize():
                angvel = angvel0 * angvelfac
                body.setAngularVelocity(angvel)

    def repel(self, n_steps=1000, thresh=10, step_size=0.01):
        """ Performs n_steps physical "repel" steps. """

        @contextmanager
        def repel_context(world):
            """ Sets up a repel context. Gets the bodies, turns off
            gravity, rescales the masses, sets up the collision
            notification callback. """

            def change_contact_thresh(bodies, thresh=0.001):
                """ Adjust the contact processing threshold. This is
                used to make the objects not trigger collisions when
                just barely touching."""
                if isinstance(thresh, Iterable):
                    it = izip(bodies, thresh)
                else:
                    it = ((body, thresh) for body in bodies)
                thresh0 = []
                for body, th in it:
                    thresh0.append(body.getContactProcessingThreshold())
                    body.setContactProcessingThreshold(th)
                return thresh0

            def rescale_masses(bodies):
                """ Rescale the masses so they are proportional to the
                volume."""
                masses, inertias = zip(*[(body.getMass(), body.getInertia())
                                         for body in bodies])
                volumefac = 1.
                for body, mass, inertia in zip(bodies, masses, inertias):
                    # Compute the mass-normalized diagonal elements of the
                    # inertia tensor.
                    if mass > 0.:
                        it = inertia / mass * 12
                        # Calculate volume from the mass-normalized
                        # inertia tensor (from wikipedia).
                        h = sqrt((it[0] - it[1] + it[2]) / 2)
                        w = sqrt(it[2] - h ** 2)
                        d = sqrt(it[1] - w ** 2)
                        volume = h * w * d
                        # Change the mass.
                        body.setMass(volume * volumefac)
                return masses

            # Get the bodies.
            bodies = world.getRigidBodies()
            # Turn gravity off.
            gravity = world.getGravity()
            world.setGravity(Vec3.zero())
            # Tighten the contact processing threshold slightly.
            delta = -0.001
            cp_thresh = change_contact_thresh(bodies, thresh=delta)
            # Adjust masses.
            masses = rescale_masses(bodies)
            # Adjust sleep thresholds.
            deactivations = [b.isDeactivationEnabled() for b in bodies]
            for body in bodies:
                body.setDeactivationEnabled(False)
            # Zero out velocities.
            self.attenuate_velocities(bodies)
            # Collisions monitor.
            collisions = CollisionMonitor(world)
            collisions.push_notifiers(bodies)
            ## Finish __enter__.
            yield bodies, collisions
            ## Start __exit__.
            collisions.pop_notifiers()
            # Zero out velocities.
            self.attenuate_velocities(bodies)
            # Restore the contact processing threshold.
            change_contact_thresh(bodies, thresh=cp_thresh)
            # Set masses back.
            for body, mass in zip(bodies, masses):
                body.setMass(mass)
                # Turn gravity back on.
                world.setGravity(gravity)
            for body, d in zip(bodies, deactivations):
                body.setDeactivationEnabled(d)

        # Operate in a context that changes the masses, turns off
        # gravity, adds collision monitoring callback, etc.
        with repel_context(self.world) as (bodies, collisions):
            # Loop through the repel simulation.
            done_count = 0
            for istep in xrange(n_steps):
                # Take one step.
                self.world.doPhysics(step_size, 1, step_size)
                # HACK: The following can be removed once Panda3d 1.9
                # is installed (and the method can be removed from
                # CollisionMonitor).
                collisions.detect18()
                # Increment done_count, only if there are no contacts.
                if collisions:
                    done_count = 0
                else:
                    done_count += 1
                if any(body.getMass() > 0. and not body.isActive()
                       for body in bodies):
                    BP()
                # Stop criterion.
                if done_count >= thresh:
                    break
                # Zero-out/re-scale velocities.
                linvelfac = bool(collisions) * 0.001
                angvelfac = bool(collisions) * 0.001
                self.attenuate_velocities(bodies, linvelfac, angvelfac)
                # Reset collisions.
                collisions.reset()
        return istep

    @classmethod
    def add_collide_mask(cls, func0):
        """ Decorator. Initializes ghost, static, and dynamic nodes
        with the appropriate collide masks."""
        def func(*args, **kwargs):
            # Create node using func0.
            node = func0(*args, **kwargs)
            # Determine collide mask.
            if isinstance(node, BulletGhostNode):
                bit = cls.ghost_bit
            elif node.getMass() == 0.:
                bit = cls.static_bit
            else:
                bit = cls.dynamic_bit
            # Set collide mask.
            node.setCollideMask(bit)
            return node
        return update_wrapper(func0, func)

    @staticmethod
    def add_ghostnode(node):
        """ Adds a child ghostnode to a node as a workaround for the
        ghost-static node collision detection problem."""
        name = "%s-ghost" % node.getName()
        ghost = NodePath(BulletGhostNode(name))
        ghost.reparentTo(node)
        return ghost
예제 #13
0
class BallInMaze(DirectObject):
    def __init__(self):
        base.setBackgroundColor(0.1, 0.1, 0.8, 1)
        base.setFrameRateMeter(True)

        base.cam.setPosHpr(0, 0, 25, 0, -90, 0)
        base.disableMouse()

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

        # Setup scene 1: World
        self.debugNP = render.attachNewNode(BulletDebugNode('Debug'))
        self.debugNP.node().showWireframe(True)
        self.debugNP.node().showConstraints(True)
        self.debugNP.node().showBoundingBoxes(True)
        self.debugNP.node().showNormals(True)
        self.debugNP.show()

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

        # Setup scene 2: Ball
        visNP = loader.loadModel('models/ball.egg')
        visNP.clearModelNodes()

        bodyNPs = BulletHelper.fromCollisionSolids(visNP, True)
        self.ballNP = bodyNPs[0]
        self.ballNP.reparentTo(render)
        self.ballNP.node().setMass(1.0)
        self.ballNP.setPos(4, -4, 1)
        self.ballNP.node().setDeactivationEnabled(False)

        visNP.reparentTo(self.ballNP)

        # Setup scene 3: Maze
        visNP = loader.loadModel('models/maze.egg')
        visNP.clearModelNodes()
        visNP.reparentTo(render)

        self.holes = []
        self.maze = []
        self.mazeNP = visNP

        bodyNPs = BulletHelper.fromCollisionSolids(visNP, True)
        for bodyNP in bodyNPs:
            bodyNP.reparentTo(render)

            if isinstance(bodyNP.node(), BulletRigidBodyNode):
                bodyNP.node().setMass(0.0)
                bodyNP.node().setKinematic(True)
                self.maze.append(bodyNP)

            elif isinstance(bodyNP.node(), BulletGhostNode):
                self.holes.append(bodyNP)

        # Lighting and material for the ball
        ambientLight = AmbientLight('ambientLight')
        ambientLight.setColor(Vec4(0.55, 0.55, 0.55, 1))
        directionalLight = DirectionalLight('directionalLight')
        directionalLight.setDirection(Vec3(0, 0, -1))
        directionalLight.setColor(Vec4(0.375, 0.375, 0.375, 1))
        directionalLight.setSpecularColor(Vec4(1, 1, 1, 1))
        self.ballNP.setLight(render.attachNewNode(ambientLight))
        self.ballNP.setLight(render.attachNewNode(directionalLight))

        m = Material()
        m.setSpecular(Vec4(1, 1, 1, 1))
        m.setShininess(96)
        self.ballNP.setMaterial(m, 1)

        # Startup
        self.startGame()

    def exitGame(self):
        sys.exit()

    def toggleWireframe(self):
        base.toggleWireframe()

    def toggleTexture(self):
        base.toggleTexture()

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

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

    def startGame(self):
        self.ballNP.setPos(4, -4, 1)
        self.ballNP.node().setLinearVelocity(Vec3(0, 0, 0))
        self.ballNP.node().setAngularVelocity(Vec3(0, 0, 0))

        # Mouse
        p = base.win.getProperties()
        base.win.movePointer(0, p.getXSize() / 2, p.getYSize() / 2)

        # Add bodies and ghosts
        self.world.attachRigidBody(self.ballNP.node())
        for bodyNP in self.maze:
            self.world.attachRigidBody(bodyNP.node())
        for ghostNP in self.holes:
            self.world.attachGhost(ghostNP.node())

        # Simulation task
        taskMgr.add(self.updateGame, 'updateGame')

    def stopGame(self):

        # Remove bodies and ghosts
        self.world.removeRigidBody(self.ballNP.node())
        for bodyNP in self.maze:
            self.world.removeRigidBody(bodyNP.node())
        for ghostNP in self.holes:
            self.world.removeGhost(ghostNP.node())

        # Simulation task
        taskMgr.remove('updateGame')

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

        # Get mouse position and tilt maze
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            hpr = Vec3(0, mpos.getY() * -10, mpos.getX() * 10)

            # Maze visual node
            self.mazeNP.setHpr(hpr)

            # Maze body nodes
            for bodyNP in self.maze:
                bodyNP.setHpr(hpr)

        # Update simulation
        self.world.doPhysics(dt)

        # Check if ball is touching a hole
        for holeNP in self.holes:
            if holeNP.node().getNumOverlappingNodes() > 2:
                if (self.ballNP.node() in holeNP.node().getOverlappingNodes()):
                    self.looseGame(holeNP)

        return task.cont

    def looseGame(self, holeNP):
        toPos = holeNP.node().getShapePos(0)
        self.stopGame()

        Sequence(
            Parallel(
                LerpFunc(self.ballNP.setX,
                         fromData=self.ballNP.getX(),
                         toData=toPos.getX(),
                         duration=.1),
                LerpFunc(self.ballNP.setY,
                         fromData=self.ballNP.getY(),
                         toData=toPos.getY(),
                         duration=.1),
                LerpFunc(self.ballNP.setZ,
                         fromData=self.ballNP.getZ(),
                         toData=self.ballNP.getZ() - .9,
                         duration=.2)), Wait(1), Func(self.startGame)).start()
예제 #14
0
class Player(ShowBase):
    def __init__(self, env_name, trial_data, headless=False):
        self.manually_quit = True
        try:
            ShowBase.__init__(self,
                              windowType="none" if headless else "onscreen")
        except:
            self.trial_finished_callback()

        # Allows importing components from project folder
        sys.path.append(".")

        # Initial scene setup
        self.disableMouse()
        self.setBackgroundColor(0.15, 0.15, 0.15, 1)
        EComponent.panda_root_node = self.render.attach_new_node(
            PandaNode("Root"))
        EComponent.base = self

        # Attach a directional light to the camera
        if not headless:
            self.dir_light = DirectionalLight("cam_dir_light")
            dir_light_path = self.camera.attach_new_node(self.dir_light)
            EComponent.panda_root_node.setLight(dir_light_path)

        # Read the project config file
        config_path = Path("project.yaml")
        config = None
        if not config_path.exists():
            sys.stderr.write("Error: Could not find project.yaml.")
            return
        with open("project.yaml", "r") as file:
            config = yaml.load(file, Loader=yaml.FullLoader)

        # Add floor
        if not headless:
            self.floor_node = FloorNode(self)
            floor_path = self.render.attach_new_node(self.floor_node)
            floor_path.setTwoSided(True)
            floor_path.set_shader_input("object_id", 0)

        # Add camera controller
        if not headless:
            self.cam_controller = CameraController(self, self.render,
                                                   self.camera)

        # Set up physics system
        self.physics_world = BulletWorld()
        self.physics_world.setGravity(LVector3f(0, 0, -9.81))
        EComponent.physics_world = self.physics_world
        self.taskMgr.add(self.physics_task, "physics_task")

        # Load environment
        with open(env_name + ".json", "r") as file:
            scene_dict = json.load(file)
            self.root_node = GraphNode.dict_to_scene_graph(scene_dict,
                                                           use_gui=False)

            trial = Trial()
            trial.data = trial_data
            trial.trial_finished_callback = self.trial_finished_callback
            self.setup_node(self.root_node, trial)

        # Set up update task
        self.taskMgr.add(self.update_task, "update_task")

    # Sets up all nodes
    def setup_node(self, node, trial):
        for component in node.data:
            # Register components to event system
            register_component(component)

            # Set trial property of components
            component.trial = trial

        # Start all the components
        node.start_components()

        # Propagate to children
        for child in node.children:
            self.setup_node(child, trial)

    # Updates components every frame
    def update_task(self, task):
        event.send_event("main", "update")
        return Task.cont

    # Updates the physics engine
    def physics_task(self, task):
        dt = globalClock.getDt()
        self.physics_world.doPhysics(dt)
        return Task.cont

    # Called when trial is finished
    def trial_finished_callback(self):
        self.manually_quit = False
        self.taskMgr.remove("update_task")
        self.taskMgr.remove("physics_task")
        event.COMPONENTS.clear()
        GizmoSystem.gizmos = [None for _ in range(256)]
        sys.exit()
class TestApplication(ShowBase):

  def __init__(self):

    ShowBase.__init__(self)

    self.setupRendering()
    self.setupControls()
    self.setupPhysics()
    #self.cam.reparentTo(self.world_node_)
    self.clock_ = ClockObject()
    self.controlled_obj_index_ = 0
    self.kinematic_mode_ = False
  
    # Task
    taskMgr.add(self.update, 'updateWorld')


  def setupRendering(self):

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

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

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

    self.render.clearLight()
    self.render.setLight(alightNP)
    self.render.setLight(dlightNP)
    
    self.setupBackgroundImage()
    
  def setupBackgroundImage(self):
    
    
    image_file = Filename(rospack.RosPack().get_path(BACKGROUND_IMAGE_PACKAGE) + '/resources/backgrounds/' + BACKGROUND_IMAGE_PATH)
    
    # check if image can be loaded
    img_head = PNMImageHeader()
    if not img_head.readHeader(image_file ):
        raise IOError, "PNMImageHeader could not read file %s. Try using absolute filepaths"%(image_file.c_str())
        sys.exit()
        
    # Load the image with a PNMImage
    w = img_head.getXSize()
    h = img_head.getYSize()
    img = PNMImage(w,h)
    #img.alphaFill(0)
    img.read(image_file) 
    
    texture = Texture()        
    texture.setXSize(w)
    texture.setYSize(h)
    texture.setZSize(1)    
    texture.load(img)
    texture.setWrapU(Texture.WM_border_color) # gets rid of odd black edges around image
    texture.setWrapV(Texture.WM_border_color)
    texture.setBorderColor(LColor(0,0,0,0))
    
    # creating CardMaker to hold the texture
    cm = CardMaker('background')
    cm.setFrame(-0.5*w,0.5*w,-0.5*h,0.5*h)  # This configuration places the image's topleft corner at the origin (left, right, bottom, top)
    background_np = NodePath(cm.generate())            
    background_np.setTexture(texture)
    
    background_np.reparentTo(self.render)
    background_np.setPos(BACKGROUND_POSITION)
    background_np.setScale(BACKGROUND_IMAGE_SCALE)
  

  def setupControls(self):

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

    # Inputs (Polling)
    self.input_state_ = InputState()
    self.input_state_.watchWithModifiers("right","arrow_right")
    self.input_state_.watchWithModifiers('left', 'arrow_left')
    self.input_state_.watchWithModifiers('jump', 'arrow_up')
    self.input_state_.watchWithModifiers('stop', 'arrow_down')
    self.input_state_.watchWithModifiers('roll_right', 'c')
    self.input_state_.watchWithModifiers('roll_left', 'z')
    self.input_state_.watchWithModifiers('roll_stop', 'x')


    self.title = addTitle("Panda3D: Kinematic Objects")
    self.inst1 = addInstructions(0.06, "ESC: Quit")
    self.inst2 = addInstructions(0.12, "Up/Down: Jump/Stop")
    self.inst3 = addInstructions(0.18, "Left/Right: Move Left / Move Rigth")
    self.inst4 = addInstructions(0.24, "z/x/c : Rotate Left/ Rotate Stop / Rotate Right")
    self.inst5 = addInstructions(0.30, "n: Select Next Character")
    self.inst6 = addInstructions(0.36, "k: Toggle Kinematic Mode")
    self.inst7 = addInstructions(0.42, "f1: Toggle Wireframe")
    self.inst8 = addInstructions(0.48, "f2: Toggle Texture")
    self.inst9 = addInstructions(0.54, "f3: Toggle BulletDebug")
    self.inst10 = addInstructions(0.60, "f5: Capture Screenshot")



  def setupPhysics(self):

    # setting up physics world and parent node path 
    self.physics_world_ = BulletWorld()
    self.world_node_ = self.render.attachNewNode('world')
    self.cam.reparentTo(self.world_node_)
    self.physics_world_.setGravity(Vec3(0, 0, -9.81))

    self.debug_node_ = self.world_node_.attachNewNode(BulletDebugNode('Debug'))
    self.debug_node_.node().showWireframe(True)
    self.debug_node_.node().showConstraints(True)
    self.debug_node_.node().showBoundingBoxes(True)
    self.debug_node_.node().showNormals(True)
    self.physics_world_.setDebugNode(self.debug_node_.node())
    self.debug_node_.hide()

    # setting up ground
    self.ground_ = self.world_node_.attachNewNode(BulletRigidBodyNode('Ground'))
    self.ground_.node().addShape(BulletPlaneShape(Vec3(0, 0, 1), 0))
    self.ground_.setPos(0,0,0)
    self.ground_.setCollideMask(BitMask32.allOn())
    self.physics_world_.attachRigidBody(self.ground_.node())

    self.object_nodes_ = []
    self.controlled_objects_=[]
    num_boxes = 20
    side_length = 0.2
    size = Vec3(0.5*side_length,0.5*side_length,0.5*side_length)
    start_pos = Vec3(-num_boxes*side_length,0,6)

    # creating boxes
    box_visual = loader.loadModel('models/box.egg')
    box_visual.clearModelNodes()
    box_visual.setTexture(loader.loadTexture('models/wood.png'))
    #box_visual.setRenderModeWireframe()
    bounds = box_visual.getTightBounds() # start of box model scaling
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = side_length/max([extents.getX(),extents.getY(),extents.getZ()])
    box_visual.setScale((scale_factor,scale_factor ,scale_factor)) # end of box model scaling

    for i in range(0,20):
      self.addBox("name %i"%(i),size,start_pos + Vec3(i*side_length,0,0),box_visual)

    start_pos = Vec3(-num_boxes*side_length,0,8)
    for i in range(0,20):
      self.addBox("name %i"%(i),size,start_pos + Vec3(i*2*side_length,0,0),box_visual)


    # creating sphere
    diameter = 0.4
    sphere_visual = loader.loadModel('models/ball.egg')

    bounds = sphere_visual.getTightBounds() # start of model scaling
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = diameter/max([extents.getX(),extents.getY(),extents.getZ()])
    sphere_visual.clearModelNodes()
    sphere_visual.setScale(scale_factor,scale_factor,scale_factor) # end of model scaling

    sphere_visual.setTexture(loader.loadTexture('models/bowl.jpg'))
    sphere = self.world_node_.attachNewNode(BulletRigidBodyNode('Sphere'))
    sphere.node().addShape(BulletSphereShape(0.5*diameter))
    sphere.node().setMass(1.0)
    sphere.node().setLinearFactor((1,0,1))
    sphere.node().setAngularFactor((0,1,0))
    sphere.setCollideMask(BitMask32.allOn())
    sphere_visual.instanceTo(sphere)
    sphere.setPos(Vec3(0,0,size.getZ()+1))
    
    self.physics_world_.attachRigidBody(sphere.node())
    self.object_nodes_.append(sphere)
    self.controlled_objects_.append(sphere)

    # creating mobile box
    size = Vec3(0.2,0.2,0.4)
    mbox_visual = loader.loadModel('models/box.egg')
    bounds = mbox_visual.getTightBounds()
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = 1/max([extents.getX(),extents.getY(),extents.getZ()])
    mbox_visual.setScale(size.getX()*scale_factor,size.getY()*scale_factor,size.getZ()*scale_factor)

    mbox = self.world_node_.attachNewNode(BulletRigidBodyNode('MobileBox'))
    mbox.node().addShape(BulletBoxShape(size/2))
    mbox.node().setMass(1.0)
    mbox.node().setLinearFactor((1,0,1))
    mbox.node().setAngularFactor((0,1,0))
    mbox.setCollideMask(BitMask32.allOn())
    mbox_visual.instanceTo(mbox)
    mbox.setPos(Vec3(1,0,size.getZ()+1))
    
    self.physics_world_.attachRigidBody(mbox.node())
    self.object_nodes_.append(mbox)
    self.controlled_objects_.append(mbox)

    self.setupLevel()
    
    # Nodepath test
    np = NodePath('testnode0')    
    print('Created Nodepath to node %s'%(np.getName()))
    np.clear()    
    
    #np.attachNewNode(PandaNode('testnode1'))
    np.__init__(PandaNode('testnode1'))
    print('Attached new node %s to empty Nodepath'%(np.getName()))


  def addBox(self,name,size,pos,visual):

    # Box (dynamic)
    box = self.world_node_.attachNewNode(BulletRigidBodyNode(name))
    box.node().setMass(1.0)
    box.node().addShape(BulletBoxShape(size))
    box.setPos(pos)
    box.setCollideMask(BitMask32.allOn())
    box.node().setLinearFactor((1,0,1))
    box.node().setAngularFactor((0,1,0))
    visual.instanceTo(box)

    self.physics_world_.attachRigidBody(box.node())
    self.object_nodes_.append(box)

  def setupLevel(self):

    # (left, top, length ,depth(y) ,height)
    platform_details =[ 
      (-20, 4, 20, 4, 1  ),
      (-2, 5, 10, 4, 1  ),
      ( 4 , 2 , 16, 4, 1.4),
      (-4 , 1, 10, 4, 1),
      ( 16, 6, 30, 4, 1)
      ]

    # Platform Visuals
    visual = loader.loadModel('models/box.egg')
    visual.setTexture(loader.loadTexture('models/iron.jpg'))
    
    for i in range(0,len(platform_details)):
      p = platform_details[i]
      topleft = (p[0],p[1])
      size = Vec3(p[2],p[3],p[4])
      self.addPlatform(topleft, size,'Platform%i'%(i),visual)


  def addPlatform(self,topleft,size,name,visual):


    # Box (static)
    platform = self.world_node_.attachNewNode(BulletRigidBodyNode(name))
    platform.node().setMass(0)
    platform.node().addShape(BulletBoxShape(size/2))
    platform.setPos(Vec3(topleft[0] + 0.5*size.getX(),0,topleft[1]-0.5*size.getZ()))
    platform.setCollideMask(BitMask32.allOn())
    local_visual = visual.instanceUnderNode(platform,name + '_visual')

    # Visual scaling
    bounds = local_visual.getTightBounds()
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = 1/max([extents.getX(),extents.getY(),extents.getZ()])
    local_visual.setScale(size.getX()*scale_factor,size.getY()*scale_factor,size.getZ()*scale_factor)
    

    self.physics_world_.attachRigidBody(platform.node())
    self.object_nodes_.append(platform)

  def update(self, task):

    self.clock_.tick()
    dt = self.clock_.getDt()
    self.processInput(dt)    
    self.physics_world_.doPhysics(dt, 5, 1.0/180.0)
    self.updateCamera()

    return task.cont 

  def processInput(self,dt):
  
    activate = False
    obj = self.controlled_objects_[self.controlled_obj_index_]

    if self.kinematic_mode_:
      obj.node().setKinematic(True)
      return
    else:
      obj.node().setKinematic(False)

    vel = obj.node().getLinearVelocity()
    w = obj.node().getAngularVelocity()

  
    if self.input_state_.isSet('right'): 
      vel.setX(2)
      activate = True

    if self.input_state_.isSet('left'): 
      vel.setX(-2)
      activate = True

    if self.input_state_.isSet('jump'): 
      vel.setZ(4)
      activate = True

    if self.input_state_.isSet('stop'): 
      vel.setX(0)

    if self.input_state_.isSet('roll_right'):
      w.setY(ROTATIONAl_SPEED)
      activate = True

    if self.input_state_.isSet('roll_left'):
      w.setY(-ROTATIONAl_SPEED)
      activate = True

    if self.input_state_.isSet('roll_stop'):
      w.setY(0)

    if activate : obj.node().setActive(True,True)
    obj.node().setLinearVelocity(vel)
    obj.node().setAngularVelocity(w)

  def updateCamera(self):

    if len(self.controlled_objects_) > 0:
      obj = self.controlled_objects_[self.controlled_obj_index_]
      self.cam.setPos(obj,0, -CAM_DISTANCE, 0)
      self.cam.lookAt(obj.getPos())

  def cleanup(self):
    
    for i in range(0,len(self.object_nodes_)):
      rb = self.object_nodes_[i]
      self.physics_world_.removeRigidBody(rb.node())

    self.object_nodes_ = []
    self.controlled_objects_ = []
    self.physics_world_.removeRigidBody(self.ground_.node())
    self.ground_ = None
    self.physics_world_ = None
    self.debug_node_ = None
    self.cam.reparentTo(self.render)
    self.world_node_.removeNode()
    self.world_node_ = None

  # _____HANDLER_____

  def toggleKinematicMode(self):
    self.kinematic_mode_ = not self.kinematic_mode_

    print "Kinematic Mode %s"%('ON' if self.kinematic_mode_ else 'OFF')

  def selectNextControlledObject(self):
    self.controlled_obj_index_+=1
    if self.controlled_obj_index_ >= len(self.controlled_objects_):
      self.controlled_obj_index_ = 0 #  reset


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

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

  def toggleDebug(self):

    if self.debug_node_.isHidden():
      self.debug_node_.show()
    else:
      self.debug_node_.hide()

  def doScreenshot(self):
    self.screenshot('Bullet')
예제 #16
0
class GameLogic(ShowBase):
    def __init__(self, pandaBase):
        self.pandaBase = pandaBase
        self.pandaBase.enableParticles()
        self.accept("DemarrerPartie", self.startGame)
        self.accept("DemarrerMenuNiveau", self.startMenu)
        self.accept("DemarrerConnexion", self.startConnexion)
        self.accept("tankElimine", self.gameOver)
        self.accept("DemarrerPageFinPartie", self.pageFinPartie)

    def pageFinPartie(self):
        self.dao = DAO_Oracle()
        # on affiche les résultats de fin de partie seulement si la connexion oracle fonctionne
        if self.dao.getConnexionState():
            self.pageFinPartie = InterfaceFinPartie()

    def gameOver(self, idPerdant):
        # si la connexion oracle fonctionone, on insère les données dans la bd
        dao = DAO_Oracle()
        if dao.getConnexionState():
            #mettre l'état du joueur gagnant à Vrai
            if idPerdant == 0:
                indexGagnant = 1  # joueur 2 a gagné
            elif idPerdant == 1:
                indexGagnant = 0  # joueur 1 a gagné
            DTO.joueurs[indexGagnant].vainqueur = True

            # ajuster les niveaux des deux joueurs
            analyse = AnalyseDTOJoueur()
            # for i in range(2):
            tanks = self.map.listTank

            #ajouter les expériences pour joueur 1
            levelUp1 = DTO.joueurs[0].updateExperience(tanks[0], tanks[1])

            #ajouter les expériences pour joueur 2
            ancienLevel = DTO.joueurs[1].calculerLevel()
            DTO.joueurs[1].updateExperience(tanks[1], tanks[0])
            nouveauLevel = DTO.joueurs[1].calculerLevel()
            if (nouveauLevel > ancienLevel):
                levelUp = True

            #ajouter les statistiques d'armes au DTO
            for i in range(len(self.map.listTank)):
                DTO.joueurs[i].tank = self.map.listTank[i]

            # ajouter la date de fin de partie
            now = datetime.datetime.now()
            DTO.finPartie = datetime.datetime.now()

            self.dao = DAO_Oracle()
            self.dao.envoyerStatistiques()

            # après que tous les nouvelles statistiques sont calculées et/ou envoyées
            # on affiche les résultats de la partie
            messenger.send("DemarrerPageFinPartie")
        # sinon, on ne fait qu'afficher le nom du joueur gagnant
        else:
            pass

    def setup(self):
        self.setupBulletPhysics()

        self.setupCamera()
        self.setupMap()
        self.setupLightAndShadow()

        #Création d'une carte de base
        #self.carte.creerCarteParDefaut()
        if DTO.mapSelectionne == None:
            self.map.construireMapHasard()
        else:
            self.map.construireMapChoisi()

        # le temps de début de partie
        now = datetime.datetime.now()
        DTO.debutPartie = now

        #A besoin des éléments de la map
        self.setupControle()
        self.setupInterface()

        #Fonction d'optimisation
        #DOIVENT ÊTRE APPELÉE APRÈS LA CRÉATION DE LA CARTE
        #Ça va prendre les modèles qui ne bougent pas et en faire un seul gros
        #en faisant un seul gros noeud avec
        self.map.figeObjetImmobile()

        #DEBUG: Décommenter pour affiche la hiérarchie
        #self.pandaBase.startDirect()

        messenger.send("ChargementTermine")

    def startGame(self):
        # self.menu.run()
        self.setup()
        #On démarrer l'effet du compte à rebour.
        #La fonction callBackDebutPartie sera appelée à la fin
        self.interfaceMessage.effectCountDownStart(3, self.callBackDebutPartie)
        self.interfaceMessage.effectMessageGeneral(
            "Appuyer sur F1 pour l'aide", 3)

    def startMenu(self):
        self.menu = InterfaceMenuNiveaux()

    def startConnexion(self):
        self.menuConnexion = InterfaceConnexion()

    def setupBulletPhysics(self):
        debugNode = BulletDebugNode('Debug')
        debugNode.showWireframe(True)
        debugNode.showConstraints(True)
        debugNode.showBoundingBoxes(False)
        debugNode.showNormals(False)
        self.debugNP = render.attachNewNode(debugNode)

        self.mondePhysique = BulletWorld()
        self.mondePhysique.setGravity(Vec3(0, 0, -9.81))
        self.mondePhysique.setDebugNode(self.debugNP.node())
        taskMgr.add(self.updatePhysics, "updatePhysics")

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

    def setupCamera(self):
        #On doit désactiver le contrôle par défaut de la caméra autrement on ne peut pas la positionner et l'orienter
        self.pandaBase.disableMouse()

        #Le flag pour savoir si la souris est activée ou non n'est pas accessible
        #Petit fail de Panda3D
        taskMgr.add(self.updateCamera, "updateCamera")
        self.setupTransformCamera()

    def setupTransformCamera(self):
        #Défini la position et l'orientation de la caméra
        self.positionBaseCamera = Vec3(0, -18, 32)
        camera.setPos(self.positionBaseCamera)
        #On dit à la caméra de regarder l'origine (point 0,0,0)
        camera.lookAt(render)

    def setupMap(self):
        self.map = Map(self.mondePhysique)
        #On construire la carte comme une coquille, de l'extérieur à l'intérieur
        #Décor et ciel
        self.map.construireDecor(camera)
        #Plancher de la carte
        self.map.construirePlancher()
        #Murs et éléments de la map

    def setupLightAndShadow(self):
        #Lumière du skybox
        plight = PointLight('Lumiere ponctuelle')
        plight.setColor(VBase4(1, 1, 1, 1))
        plnp = render.attachNewNode(plight)
        plnp.setPos(0, 0, 0)
        camera.setLight(plnp)

        #Simule le soleil avec un angle
        dlight = DirectionalLight('Lumiere Directionnelle')
        dlight.setColor(VBase4(0.8, 0.8, 0.6, 1))
        dlight.get_lens().set_fov(75)
        dlight.get_lens().set_near_far(0.1, 60)
        dlight.get_lens().set_film_size(30, 30)
        dlnp = render.attachNewNode(dlight)
        dlnp.setPos(Vec3(-2, -2, 7))
        dlnp.lookAt(render)
        render.setLight(dlnp)

        #Lumière ambiante
        alight = AmbientLight('Lumiere ambiante')
        alight.setColor(VBase4(0.25, 0.25, 0.25, 1))
        alnp = render.attachNewNode(alight)
        render.setLight(alnp)

        #Ne pas modifier la valeur 1024 sous peine d'avoir un jeu laid ou qui lag
        dlight.setShadowCaster(True, 1024, 1024)
        #On doit activer l'ombre sur les modèles
        render.setShaderAuto()

    def setupControle(self, ):
        #Créer le contrôle
        #A besoin de la liste de tank pour relayer correctement le contrôle
        self.inputManager = InputManager(self.map.listTank, self.debugNP,
                                         self.pandaBase)
        self.accept("initCam", self.setupTransformCamera)

    def setupInterface(self):
        self.interfaceTank = []
        self.interfaceTank.append(
            InterfaceTank(0, self.map.listTank[0].couleur))
        self.interfaceTank.append(
            InterfaceTank(1, self.map.listTank[1].couleur))

        self.interfaceMessage = InterfaceMessage()

    def callBackDebutPartie(self):
        #Quand le message d'introduction est terminé, on permet aux tanks de bouger
        self.inputManager.debuterControle()

    #Mise à jour du moteur de physique
    def updateCamera(self, task):
        #On ne touche pas à la caméra si on est en mode debug
        if (self.inputManager.mouseEnabled):
            return task.cont

        vecTotal = Vec3(0, 0, 0)
        distanceRatio = 1.0
        if (len(self.map.listTank) != 0):
            for tank in self.map.listTank:
                vecTotal += tank.noeudPhysique.getPos()
            vecTotal = vecTotal / len(self.map.listTank)

        vecTotal.setZ(0)
        camera.setPos(vecTotal + self.positionBaseCamera)
        return task.cont

    #Mise à jour du moteur de physique
    def updatePhysics(self, task):
        dt = globalClock.getDt()
        messenger.send("appliquerForce")
        self.mondePhysique.doPhysics(dt)

        #Analyse de toutes les collisions
        for entrelacement in self.mondePhysique.getManifolds():
            node0 = entrelacement.getNode0()
            node1 = entrelacement.getNode1()

            self.map.traiterCollision(node0, node1)
        return task.cont

    def updateCarte(self, task):
        self.map.update(task.time)
        return task.cont
예제 #17
0
    class __Window(ShowBase):
        def __init__(self):
            if Window.__instance is None:
                Window.__instance = self
                super().__init__()
                self.bind = {}
                self.load_bind()
                self.option = {}
                self.load_option()

                self.properties()
                self.setFrameRateMeter(True)
                self.skybox = Skybox()

                self.accept(self.bind[Bind.EXIT.value], sys.exit)

                self.world = BulletWorld()
                self.world_node = None
                self.debug_node_path = None
                self.setup_world()

        def setup_world(self):
            self.world_node = self.render.attachNewNode('World')
            self.world.setGravity(Vec3(0, 0, -9.81))

            # Landscape
            model = self.loader.loadModel("mesh/models/landscape/landscape")
            model.reparentTo(self.render)
            model.setScale(100)
            model.flatten_light()
            geom_nodes = model.findAllMatches('**/+GeomNode')
            geom_node = geom_nodes.getPath(0).node()
            geom_mesh = geom_node.getGeom(0)
            mesh = BulletTriangleMesh()
            mesh.add_geom(geom_mesh)
            ground_shape = BulletTriangleMeshShape(mesh, dynamic=False)

            ground_node = self.world_node.attachNewNode(
                BulletRigidBodyNode('Ground'))
            ground_node.node().addShape(ground_shape)
            '''
            if self.debug_mode:
                debug_node_path = self.world_node.attachNewNode(BulletDebugNode('Debug'))
                debug_node_path.show()
                debug_node_path.node().showNormals(True)
                self.world.setDebugNode(debug_node_path.node())
            '''
            self.debug_node_path = self.world_node.attachNewNode(
                BulletDebugNode('Debug'))
            self.debug_node_path.hide()
            self.world.setDebugNode(self.debug_node_path.node())

            ground_node.setPos(0, 0, 0)
            ground_node.setCollideMask(BitMask32.allOn())

            self.world.attachRigidBody(ground_node.node())

            # Character
            player = Player()

            # Other models
            path = 'mesh/models/bullet/pyramid'
            self.add_model(path, pos_x=50, pos_y=15, pos_z=370, scale=5)
            self.add_model(path, pos_x=30, pos_y=15, pos_z=370, scale=5)
            self.add_model(path, pos_x=70, pos_y=15, pos_z=390, scale=5)
            self.add_model(path, pos_x=50, pos_y=40, pos_z=360, scale=5)

            path = 'mesh/models/bullet/ball'
            self.add_model(path, pos_x=0, pos_y=15, pos_z=400, scale=8)
            self.add_model(path, pos_x=30, pos_y=40, pos_z=450, scale=8)

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

        def update(self, task):
            dt = globalClock.getDt()
            self.world.doPhysics(dt, 10, 0.008)
            return task.cont

        def toggle_debug(self):
            if self.debug_node_path.isHidden():
                self.debug_node_path.show()
            else:
                self.debug_node_path.hide()

        def add_model(self, path, pos_x, pos_y, pos_z, scale):
            model = self.loader.loadModel(path)
            model.setScale(scale)
            model.flatten_light()

            geom = model.findAllMatches('**/+GeomNode').getPath(
                0).node().getGeom(0)
            mesh = BulletTriangleMesh()
            mesh.addGeom(geom)
            shape = BulletTriangleMeshShape(mesh, dynamic=True)

            body = BulletRigidBodyNode('Bowl')
            body_node_path = self.world_node.attachNewNode(body)
            body_node_path.node().addShape(shape)
            body_node_path.node().setMass(10.0)
            body_node_path.setPos(pos_x, pos_y, pos_z)
            body_node_path.setCollideMask(BitMask32.allOn())
            self.world.attachRigidBody(body_node_path.node())

            model.reparentTo(body_node_path)

        def properties(self):
            if not self.pipe:
                self.makeDefaultPipe()

            props = WindowProperties()

            props.setTitle("Title placeholder")

            if self.option[Options.FULL.value]:
                props.setSize(self.option[Options.RES.value][Options.X.value],
                              self.option[Options.RES.value][Options.Y.value])
                props.setFullscreen(True)
                loadPrcFileData('', 'fullscreen t')
            else:
                props.setSize(self.option[Options.RES.value][Options.X.value],
                              self.option[Options.RES.value][Options.Y.value])

            props.setCursorHidden(True)
            props.setDefault(props)

            self.openMainWindow(props)

        def change_mouse_visibility(self):
            props = WindowProperties().getDefault()
            if props.getCursorHidden():
                props.setCursorHidden(False)
            else:
                props.setCursorHidden(True)
            props.setDefault(props)
            self.win.requestProperties(props)

        def load_bind(self):
            with open('config/bind.json') as f:
                self.bind = json.load(f)

        def load_option(self):
            with open('config/options.json') as f:
                self.option = json.load(f)
예제 #18
0
class Physics(DirectObject):

    """
    Physics Class:
    
    Handles the all Physics
    """

    def __init__(self):

        ## Setup a bullet world.

        # World Node (MAIN)
        self.worldNP = render.attachNewNode("World")

        # World
        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, worldGravity))
        PHYSICS["WORLD"] = self.world

        # Add the simulation method to the taskmgr
        taskMgr.add(self.update, "update bullet world")

        # Setup test World
        self.box = ""
        self.hinge = ""
        self.pickTest = False
        self.sensor = ""

        # test the class test
        self.test = MakeObject(self, "Box1", "b", 20.0)
        self.test.bodyNP.setPos(0, 1, 1)

        pos = 1

        # for x in range(5):
        # x = MakeObject(self, 'box', 'b', 5.0)
        # pos += 1
        # x.bodyNP.setPos(0, 0, pos)

        self.accept("e", self.playerPickup)
        self.accept("f1", self.showDebug)
        self.setup_world()
        # taskMgr.add(self.checkGhost, 'checkGhost')

    def setup_world(self):

        #############################################
        ##
        ##  GROUND FOR TESTING
        #############################################
        pass
        # Ground
        # shape = BulletPlaneShape(Vec3(0, 0, 1), 0)

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

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

        ##############################################
        ##############################################

        ########################
        # FIXED :D  - Still simple atm.
        ########################

    def playerPickup(self):

        # Write a class for pick able objects so that we instance the object in the world and if picked up we change that instance or del it then create new one, then same again when dropped

        bodyA = base.camera

        # Will have to make a pick up mask so that it collides with walls and floors and w/e else.. except with the player
        if self.pickTest == False:
            self.test.bodyNP.wrtReparentTo(PLAYER["CLASS"].picker)
            # self.test.bodyNP.copyTo(bodyA)
            # self.test.worldNP
            # bodyB.setPos(0, 2, 0)
            self.test.bodyNP.node().setMass(1.0)
            # self.test.bodyNP.setScale(1)
            # self.test.bodyNP.setCollideMask(BitMask32.allOn())
            self.pickTest = True

        elif self.pickTest == True:
            self.test.bodyNP.wrtReparentTo(GAMEPLAY_NODES["ITEM"])
            self.test.bodyNP.node().setMass(1.0)
            # self.test.bodyNP.setCollideMask(BitMask32.allOn())
            # bodyB.setPos(bodyPos)
            self.pickTest = False

        # Simulate Physics

    def update(self, task):

        dt = globalClock.getDt()
        self.world.doPhysics(dt, 4, 1.0 / 270.0)

        return task.cont

        # Enable/Disable debug

    def showDebug(self):

        # To enable debug
        self.debugNode = BulletDebugNode("Debug")
        self.debugNode.showBoundingBoxes(True)
        self.debugNode.showNormals(False)
        self.debugNode.showWireframe(True)
        self.debugNode.showConstraints(True)
        self.debugNP = render.attachNewNode(self.debugNode)
        self.debugNP.show()

        # Add the debug node to the physics world
        self.world.setDebugNode(self.debugNP.node())
예제 #19
0
class BallInMaze(DirectObject):

  def __init__(self):
    base.setBackgroundColor(0.1, 0.1, 0.8, 1)
    base.setFrameRateMeter(True)

    base.cam.setPosHpr(0, 0, 25, 0, -90, 0)
    base.disableMouse()

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

    # Setup scene 1: World
    self.debugNP = render.attachNewNode(BulletDebugNode('Debug'))
    self.debugNP.node().showWireframe(True)
    self.debugNP.node().showConstraints(True)
    self.debugNP.node().showBoundingBoxes(True)
    self.debugNP.node().showNormals(True)
    self.debugNP.show()

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

    # Setup scene 2: Ball
    visNP = loader.loadModel('models/ball.egg')
    visNP.clearModelNodes()

    bodyNPs = BulletHelper.fromCollisionSolids(visNP, True)
    self.ballNP = bodyNPs[0]
    self.ballNP.reparentTo(render)
    self.ballNP.node().setMass(1.0)
    self.ballNP.setPos(4, -4, 1)
    self.ballNP.node().setDeactivationEnabled(False)

    visNP.reparentTo(self.ballNP)

    # Setup scene 3: Maze
    visNP = loader.loadModel('models/maze.egg')
    visNP.clearModelNodes()
    visNP.reparentTo(render)

    self.holes = []
    self.maze = []
    self.mazeNP = visNP

    bodyNPs = BulletHelper.fromCollisionSolids(visNP, True);
    for bodyNP in bodyNPs:
      bodyNP.reparentTo(render)

      if isinstance(bodyNP.node(), BulletRigidBodyNode):
        bodyNP.node().setMass(0.0)
        bodyNP.node().setKinematic(True)
        self.maze.append(bodyNP)

      elif isinstance(bodyNP.node(), BulletGhostNode):
        self.holes.append(bodyNP)

    # Lighting and material for the ball
    ambientLight = AmbientLight('ambientLight')
    ambientLight.setColor(Vec4(0.55, 0.55, 0.55, 1))
    directionalLight = DirectionalLight('directionalLight')
    directionalLight.setDirection(Vec3(0, 0, -1))
    directionalLight.setColor(Vec4(0.375, 0.375, 0.375, 1))
    directionalLight.setSpecularColor(Vec4(1, 1, 1, 1))
    self.ballNP.setLight(render.attachNewNode(ambientLight))
    self.ballNP.setLight(render.attachNewNode(directionalLight))

    m = Material()
    m.setSpecular(Vec4(1,1,1,1))
    m.setShininess(96)
    self.ballNP.setMaterial(m, 1)

    # Startup
    self.startGame()

  def exitGame(self):
    sys.exit()

  def toggleWireframe(self):
    base.toggleWireframe()

  def toggleTexture(self):
    base.toggleTexture()

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

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

  def startGame(self):
    self.ballNP.setPos(4, -4, 1)
    self.ballNP.node().setLinearVelocity(Vec3(0, 0, 0))
    self.ballNP.node().setAngularVelocity(Vec3(0, 0, 0))

    # Mouse
    p = base.win.getProperties()
    base.win.movePointer(0, p.getXSize()/2, p.getYSize()/2)

    # Add bodies and ghosts
    self.world.attachRigidBody(self.ballNP.node())
    for bodyNP in self.maze:
      self.world.attachRigidBody(bodyNP.node())
    for ghostNP in self.holes:
      self.world.attachGhost(ghostNP.node())

    # Simulation task
    taskMgr.add(self.updateGame, 'updateGame')

  def stopGame(self):

    # Remove bodies and ghosts
    self.world.removeRigidBody(self.ballNP.node())
    for bodyNP in self.maze:
      self.world.removeRigidBody(bodyNP.node())
    for ghostNP in self.holes:
      self.world.removeGhost(ghostNP.node())

    # Simulation task
    taskMgr.remove('updateGame')

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

    # Get mouse position and tilt maze
    if base.mouseWatcherNode.hasMouse():
      mpos = base.mouseWatcherNode.getMouse()
      hpr = Vec3(0, mpos.getY() * -10, mpos.getX() * 10)

      # Maze visual node
      self.mazeNP.setHpr(hpr)

      # Maze body nodes
      for bodyNP in self.maze:
        bodyNP.setHpr(hpr)

    # Update simulation
    self.world.doPhysics(dt)

    # Check if ball is touching a hole
    for holeNP in self.holes:
      if holeNP.node().getNumOverlappingNodes() > 2:
        if (self.ballNP.node() in holeNP.node().getOverlappingNodes()):
          self.looseGame(holeNP)

    return task.cont

  def looseGame(self, holeNP):
    toPos = holeNP.node().getShapePos(0)
    self.stopGame()

    Sequence(
      Parallel(
      LerpFunc(self.ballNP.setX, fromData = self.ballNP.getX(),
               toData = toPos.getX(), duration = .1),
      LerpFunc(self.ballNP.setY, fromData = self.ballNP.getY(),
               toData = toPos.getY(), duration = .1),
      LerpFunc(self.ballNP.setZ, fromData = self.ballNP.getZ(),
               toData = self.ballNP.getZ() - .9, duration = .2)),
      Wait(1),
      Func(self.startGame)).start()
예제 #20
0
파일: main.py 프로젝트: trinobster/MiniGame
class MyApp(ShowBase) :
    
    def __init__(self) :
        ShowBase.__init__(self)
        
        #--------------------- MUSIC
        mySound = base.loader.loadSfx(musicPath + "mus_reunited.ogg")
        mySound.play()
        
        
        #--------------------- WORLD
        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81))     
        
##         --------------------- DEBUG
#        debugNode = BulletDebugNode('Debug')
#        debugNode.showWireframe(True)
#        debugNode.showConstraints(True)
#        debugNode.showBoundingBoxes(False)
#        debugNode.showNormals(False)
#        debugNP = render.attachNewNode(debugNode)
#        debugNP.show()
#        
#        debugNode.showWireframe(True)
#        self.world.setDebugNode(debugNP.node())
        
        
        #--------------------- GRASS
        shape = BulletPlaneShape(Vec3(0, 0, 1), 0) # creo la forma geometrica (normale, distanza)
        node = BulletRigidBodyNode('Ground') # creo il rigidbody per il terreno
        node.addShape(shape) # link tra il rigidbody e la forma geometrica
        np = render.attachNewNode(node)
        np.setPos(0, 0, -0.5) #-1.5
        
        cm = CardMaker('card') # crea una carta bianca a cui appiccicare la texture
        cm.setFrame(-20, 20, -20, 20)
        grass = self.render.attachNewNode(cm.generate()) # attacca il nodo FLOOR
        pattern = self.loader.loadTexture(imagePath + 'grass3.jpg') # handler per la texture
        ts = TextureStage('ts')
        grass.setP(270)
        grass.setTexScale(ts, 3, 3)
        grass.setTexture(ts, pattern) # appiccica la texture al modello
        grass.reparentTo(np) # collega la texture dell'erba al nodo fisico
        
        self.world.attachRigidBody(node) # solo i nodi attaccati al world vengono considerati nella simulazione

        
        #--------------------- CRASH (MY MODEL)
        self.actor = Actor("models/MyCrash1/MyCrash1.egg", 
                           {"walk":"./models/MyCrash1/CrashWalk.egg","launch":"./models/MyCrash1/CrashLaunch.egg"})
        self.actor.reparentTo(np) # reparent the model to render
        self.actor.setScale(1, 1, 1) # apply scale to model
        self.actor.setPos(3, -10, 0) # apply position to model 
        
        #--------------------- CAMERA
        base.cam.setPos(self.actor.getX(), self.actor.getY() - 18, self.actor.getZ() + 4)
        base.cam.lookAt(self.actor.getX(), self.actor.getY(), self.actor.getZ() + 2)
        
        
        #--------------------- TABLE
        shape = BulletBoxShape(Vec3(4.8, 1.45, 0.15))
        node = BulletRigidBodyNode('Box')
        node.addShape(shape)
        np = render.attachNewNode(node)
        np.setPos(5, 3, 0.8 - 0.5)        
        
        self.table = Object(self, "CafeTableLong/CafeTableLong", 
                            0.01, 0.01, 0.01, 
                            0, 0, 0, 
                            0, 0, -0.15, np)
        
        self.world.attachRigidBody(node) 
                
        
        #--------------------- ARMCHAIR
        shape = BulletBoxShape(Vec3(1.35, 1.5, 2)) #2
        node = BulletRigidBodyNode('Box')
        node.addShape(shape) 
        node.setMass(5)
        np = render.attachNewNode(node)
        np.setPos(12, 3, 1.5)        
        
        self.chair = Object(self, "ArmChair/ArmChair", 
                            0.0013, 0.0013, 0.0013, 
                            100, 0, 0, 
                            0, 0, -1.5, np)
        
        self.world.attachRigidBody(node) 
        
        
        #--------------------- OBJECTS TO HIT
        # cake
        shape = BulletCylinderShape(0.56, 0.5, 2)
        node = BulletRigidBodyNode('Cylinder')
        node.setMass(2)
        node.addShape(shape)
        np = render.attachNewNode(node)
        np.setPos(5, 3, 0.62)
        
        self.cake = Object(self, "Cake/Cake", 
                           0.008, 0.008, 0.009, 
                           0, 0, 0, 
                           0, 0, -0.25, np)

        self.world.attachRigidBody(node)
        
        
        #teapot
        shape = BulletBoxShape(Vec3(0.65, 0.3, 0.8)) # creo la forma geometrica (normale, distanza)
        node = BulletRigidBodyNode('Box') # creo il rigidbody per il terreno
        node.setMass(2)
        node.addShape(shape) # link tra il rigidbody e la forma geometrica
        np = render.attachNewNode(node)
        np.setPos(3, 3, 1.2)   
        
        self.tea = Object(self, "Teapot/Teapot", 
                          1, 1, 1, 
                          90, 0, 0, 
                          0, 0, -0.83, np)

        self.world.attachRigidBody(node)
        
        
        #mug
        shape = BulletCylinderShape(0.2, 0.5, 2)
        node = BulletRigidBodyNode('Cylinder')
        node.setMass(2)
        node.addShape(shape)
        np = render.attachNewNode(node)
        np.setPos(6, 3, 1.2 - 0.54)        
        
        self.mug = Object(self, "cup/cup", 
                          0.02, 0.02, 0.02, 
                          0, 0, 0, 
                          0, 0.2, -0.1, np)

        self.world.attachRigidBody(node)
        
        
        #creamer
        shape = BulletBoxShape(Vec3(0.5, 0.3, 0.5)) 
        node = BulletRigidBodyNode('Box') 
        node.setMass(2)
        node.addShape(shape)
        np = render.attachNewNode(node)
        np.setPos(8, 3.2, 1.1 - 0.2)         
        
        self.creamer = Object(self, "creamer/creamer", 
                              1, 1, 1, 
                              -90, 0, 0, 
                              0.1, 0, -0.5, np)

        self.world.attachRigidBody(node)


        #mint
        shape = BulletCylinderShape(0.25, 0.2, 2)
        node = BulletRigidBodyNode('Cylinder')
        node.setMass(1)
        node.addShape(shape)
        np = render.attachNewNode(node)
        np.setPos(1.8, 3.2, 1.2 - 0.65)         
        
        self.mint = Object(self, "Mint/Mint", 
                           3, 3, 3, 
                           0, 0, 0, 
                           0, 0, 0, np)
        
        self.world.attachRigidBody(node)
        
        
        #--------------------- TASK and FUNCTIONS
        Decoration(self)
        self.lightUp()
        HandleArrows(self, 8, 12, -8, -31)
        Shoot(self)
        HandleCharacter(self, 8, 12, -8, -31)
        taskMgr.add(self.update, 'update')
        
        
    def lightUp(self): # L'oggetto che invoca la funzione viene SEMPRE passato IMPLICITAMENTE!        
       # Metodo che serve per creare e settare una luce ambientale ed una direzionale
        # Directional light
        dlight = DirectionalLight('dlight')
        dlight.setColor(VBase4(0.5, 0.5, 0.5, 1))
        dlnp = render.attachNewNode(dlight)
        dlnp.setHpr(0, -60, 0)
        render.setLight(dlnp)
        # Ambient light
        alight = AmbientLight('alight')
        alight.setColor(VBase4(0.8, 0.8, 0.8, 1))
        alnp = render.attachNewNode(alight)
        render.setLight(alnp)
        
    def update(self, task): 
       # Metodo che serve per attivare ad ogni frame la fisica della libreria Bullet
        dt = globalClock.getDt()
        self.world.doPhysics(dt)
        return task.cont
예제 #21
0
class Game(ShowBase, object):
    """What should be done here:
        Nothing that doesnt have to be.
        If something can have its own class, it should.
        Things that are here that shouldnt be:
            Setting up physics
            Setting up the world
            Menus
            GUI
            World/level things
        Things that are here that should be:
            Setting properties
            Main update loop
            Initalizing things (worlds, physics) Via other classes
        Remember to ask yourself this "Does a X have a Y?"
        So does a game have physics? No, a game has a world,
        and a world has physics.
        An entity is a panda node.

    """

    forceFPS = True
    fsmState = True
    bulletDict = {}
    playerList = {}
    grav_ghost_NP = 0

    def __init__(self):

        #self.gui = loadGui()
        #init_pause_state(self.menu)
        init_pause_state()
        test = World()

        debugNode = BulletDebugNode('Debug')
        debugNode.showWireframe(True)
        debugNode.showConstraints(True)
        debugNode.showBoundingBoxes(False)
        debugNode.showNormals(False)
        debugNP = render.attachNewNode(debugNode)
        debugNP.show()

        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9))

        self.world.setDebugNode(debugNP.node())

        #Add a gravity region
        self.add_gravity_region(
                (100, 100, 100),
                (100, -400, 0),
                (0, 0, 1000))

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

        self.bulletList = self.loadBulletList()

        base.disableMouse()

        self.loadLevel()
        self.initClasses()
        self.setCamera()
        self.addWinProps()

        #TODO: Fix the healthbars
        #self.gui.healthBar("Player1")
        #self.gui.healthBar("AI1")
        #self.gui.healthBar("AI2")
        #self.gui.healthBar("AI3")

        self.loadStation()

        self.addlight()

        self.createControls()

        taskMgr.add(self.updateMenus, 'MenuUpdater')
        print("Instance of game class running.")

        self.simmpoleXP()
        self.flipsXP()

    def update_bullet(self, task):
        dt = globalClock.getDt()
        self.world.doPhysics(dt)
        return task.cont

    def add_gravity_region(self, size, pos, gravity):
        """Makes a bullet ghost, when a object enters
        its gravity is changed to match the arguments passed
        """
        shape = BulletBoxShape(Vec3(size))

        grav_ghost = BulletGhostNode('Ghost')
        grav_ghost.addShape(shape)
        grav_ghost_NP = render.attachNewNode(grav_ghost)
        grav_ghost_NP.setPos(pos)
        grav_ghost_NP.setCollideMask(BitMask32(0x0f))

        self.world.attachGhost(grav_ghost)

        def check_gravity_region(task):
            """Check what bullet nodes are inside
                and apply gravity to them.
            """
            ghost = grav_ghost_NP.node()
            print ghost.getNumOverlappingNodes()
            for node in ghost.getOverlappingNodes():
                print node
                #TODO: Make this only apply when in the region
                #EX: Gravity is set to X  inside, set back to normal when out
                node.setGravity(Vec3(gravity))
            return task.cont
        #Add the region checker task
        taskMgr.add(check_gravity_region, "check_gravity_region")

    def simmpoleXP(self):
        for i in range(101):
            if i < 6:
                xpToLvl = ((i) * ((i * i) / 2) * 256)
            else:
                xpToLvl = (i) * ((i * i) / 2) * 128

            print("SimmPole: Level " + str(i) + ":" + str(xpToLvl))
            #print(str(xpToLvl)+", ")

    def flipsXP(self):
        for i in range(101):
            xpToLvl = (i) * ((i * i) / 2) * 100

            print("Flips: Level " + str(i) + ":" + str(xpToLvl))
            #print(str(xpToLvl)+", ")

    def loadBulletList(self):
        self.bulletDict[0] = ("_normalBullet")
        self.bulletDict[1] = ("_normalMissile")
        return self.bulletDict

    def sortedBulletDictValues(self):
        items = self.bulletDict.items()
        items.sort()
        return [value for key, value in items]

    def initClasses(self):
        '''Makes some instances of some classes'''
        self.playerList["Player1"] = Player(
            self.world,
            "Player1",
            False,
            False,
            None,
            50)  # Makes the main ship, using the base.camera.

        self.playerList["AI1"] = Player(
            self.world,
            "AI1",
            True,
            True,
            self.playerList["Player1"].getShip(),
            10)  # Makes an AI ship, using no camera.

        self.playerList["AI2"] = Player(
            self.world,
            "AI2",
            True,
            True,
            self.playerList["Player1"].getShip(),
            10)

        self.playerList["AI3"] = Player(
            self.world,
            "AI3",
            True,
            True,
            self.playerList["Player1"].getShip(),
            10)

        self.gameSettings = GameSettings()



    def createPlayer(self):
        '''To be implemented.
        Players (and ships) could be in an array,
        and the array could be in a function to assign new players
        (and ships). This would allow direct access to class instances,
         giving more control to the program.
        Example:
        playerArray = []
        def createPlayer(self, playerArray, args, args1):
            player = Player(args, args1)
            playerArray.append(player)
        '''

    def addWinProps(self):
        #Hides the cursor and sets the window title

        self.props = WindowProperties()
        self.props.setCursorHidden(True)
        self.props.setTitle('Space Fighter')
        base.win.requestProperties(self.props)
        base.setFrameRateMeter(True)
        FPS = 60
        self.globalClock = ClockObject.getGlobalClock()
        if self.forceFPS:
            self.globalClock.setMode(ClockObject.MForced)
        else:
            self.globalClock.setMode(ClockObject.MLimited)
        self.globalClock.setFrameRate(FPS)
        self.globalTime = self.globalClock.getRealTime()
        render.setAntialias(AntialiasAttrib.MMultisample)

    def exit(self):
        sys.exit()

    def pause(self):
        '''Runs functions when escape is pressed'''
        PauseState.pause_ssm()



    def debugOn(self):
        self.playerList["Player1"].ship.ForwardSpeed = self.playerList["Player1"].ship.MaxSpeed
        base.acceptOnce("lshift", self.debugOff)  # Leave debug mode "lshift"
        self.playerList["Player1"].score += 1
        print "Debug mode on :)"

    def debugOff(self):
        base.acceptOnce("lshift", self.debugOn)  # Enter debug mode on "lshift"
        print "Debug mode off :("

    def addlight(self):
        sptLight = Spotlight("spot")
        sptLens = PerspectiveLens()
        sptLens.setFar(1000)
        sptLens.setFov(90)
        sptLight.setLens(sptLens)
        sptLight.setColor(Vec4(1.2, 1.2, 1.0, .2))
        sptLight.setShadowCaster(True, 4096, 4096)
        sptNode = render.attachNewNode(sptLight)
        sptNode.setPos(0, 0, 1000)
        sptNode.setHpr(0,-90,0)
        sptNode.lookAt(self.level)
        render.setLight(sptNode)

        dirLight = DirectionalLight("dlight")
        dirLight.setSpecularColor(VBase4(0.249, 0.235, 0.207, 1))
        dirLight.setDirection(Vec3(102, 100, -60))
        dirLight.setShadowCaster(True, 2048, 2048)
        dirLight.getLens().setFilmSize(4096, 4096)
        dirLight.showFrustum()
        dLight = render.attachNewNode(dirLight)
        #render.setLight(dLight)

        alight = AmbientLight('alight')
        alight.setColor(VBase4(.149, .145, .135, 1))
        alnp = render.attachNewNode(alight)
        render.setLight(alnp)

        render.setShaderAuto()

    def loadStation(self):
        #Loads and sets up a station
            self.Station = loader.loadModel('models/station.x')
            self.Station.reparentTo(render)
            self.Station.setPos(0, 0, 0)

        #collisions.pickerCollision(self.Station)

    def loadLevel(self):
        '''Loads and sets up a level'''

        shape = BulletBoxShape(Vec3(200, 200, 200))
        node = BulletRigidBodyNode('Box')
        node.addShape(shape)
        np = render.attachNewNode(node)
        np.setPos(0, 0, -400)
        self.world.attachRigidBody(node)

        lvlmat = Material()
        lvlmat.setDiffuse(VBase4(0.166, 0.151, 0.119, 1))
        self.level = loader.loadModel('models/level.x')
        self.level.reparentTo(np)
        self.level.setPos(0, 0, -00)
        self.level.setScale(200)
        self.level.setMaterial(lvlmat, 1)
        self.level.setColor(0,1,1,1)

        '''
        lvlmat = Material()
        lvlmat.setDiffuse(VBase4(0.166, 0.151, 0.119, 1))
        self.level = loader.loadModel('models/level.x')
        self.level.reparentTo(render)
        self.level.setPos(0, 0, -750)
        self.level.setScale(200)
        self.level.setMaterial(lvlmat, 1)'''


        #self.level.setR(50)
        #self.level.setTwoSided(True)
        #self.level.place()

        #cm = CardMaker("plane")
        #cm.setFrame(-1000, 1000, -1000, 1000)
        #self.level = render.attachNewNode(cm.generate())
        #self.level.setP(270)
        #self.level.setPos(0,0,-10)
        #self.level.setTwoSided(True)

    def setCamera(self):
        '''Loads and sets up cameras'''
        frontCam = Camera("frontCamera")
        frontCamera = render.attachNewNode(frontCam)
        frontCamera.setName("FrontCamera")
        frontCamera.setPos(0, 5, 0)
        frontCamera.setHpr(0, 0, 0)
        #dr = base.camNode.getDisplayRegion(0)
        #dr.setActive(0) # Or leave it (dr.setActive(1))
        #window = dr.getWindow()
        #dr1 = window.makeDisplayRegion(0, 1, 0.5, 1)
        #dr1.setSort(dr.getSort())
        #dr2 = window.makeDisplayRegion(0.5, 1, 0, 1)
        #dr2.setSort(dr.getSort())
        #dr1.setCamera(frontCamera)
        #dr2.setCamera(base.camera)

    def updateMenus(self, task):
        #Updates the menu with recent data.
        #self.menu.updateOptionsMenu()
        return task.cont

    def createControls(self):
        #Sets up the controls

        base.accept("escape", self.pause)  # Exit game on "escape"

        base.acceptOnce("lshift", self.debugOn)  # Enter debug mode on "lshift"
예제 #22
0
class Engine():
    """The engine handles the building and setup of the level, every
    thing parsed from the level.egg.
    """
    def __init__(self, _meotech):

        print "Engine - init >>>"

        # MeoTehc
        self.meotech = _meotech

        # check if we can have good shaders
        if base.win.getGsg().getSupportsShadowFilter():
            # enable pandas auto shader
            render.setShaderAuto()
        # clear all lights from render
        render.clearLight()


        ### Setup Engine Holders ###

        # Create Game Object Holders
        self.GameObjects = {}
        self.GameObjects["player"] = None
        self.GameObjects["level"] = {}
        self.GameObjects["object"] = {}
        self.GameObjects["npc"] = {}
        self.GameObjects["light"] = {}
        self.GameObjects["sensor"] = {}
        self.GameObjects["gameInfo"] = {}

        # Create Render Object Holders for sorting stuff in sceneG.
        # nodepaths
        self.RenderObjects = {}
        self.BulletObjects = {}

        # none visual
        self.BulletObjects["main"] = render.attachNewNode("Bullet_main")
        self.BulletObjects["player"] = self.BulletObjects["main"].attachNewNode("Bullet_player")
        self.BulletObjects["npc"] = self.BulletObjects["main"].attachNewNode("Bullet_npc")
        self.BulletObjects["level"] = self.BulletObjects["main"].attachNewNode("Bullet_level")
        self.BulletObjects["object"] = self.BulletObjects["main"].attachNewNode("Bullet_object")
        self.BulletObjects["sensor"] = self.BulletObjects["main"].attachNewNode("Bullet_sensor")

        # Visuals
        self.RenderObjects["level"] = render.attachNewNode("Render_level")
        self.RenderObjects["npc"] = render.attachNewNode("Render_npc")
        self.RenderObjects["object"] = render.attachNewNode("Render_object")
        self.RenderObjects["light"] = render.attachNewNode("Render_light")

        ### Engine Holders END ###

        # Setup Bullet Physics
        self.bulletWorld = BulletWorld()
        self.bulletWorld.setGravity(Vec3(0, 0, 0))#GRAVITY_X, GRAVITY_Y, GRAVITY_Z))

        # Init Factory
        self.factory = Factory(self)
        self.factory.parseLevelFile("room")

        # Init Input

        # Start Engine Loop
        # Controls Physics and other engine related Things
        taskMgr.add(self.engineLoop, "Engine_Loop")

    def showBulletDebug(self):
        """Show bullet Debug"""
        # Bullet DEBUG
        debugNode = BulletDebugNode('Debug')
        debugNode.showWireframe(True)
        debugNode.showConstraints(True)
        debugNode.showBoundingBoxes(False)
        debugNode.showNormals(False)
        debugNP = render.attachNewNode(debugNode)
        debugNP.show()

        self.bulletWorld.setDebugNode(debugNP.node())


    def engineLoop(self, task):
        """Handle Engine Related Tasks"""
        dt = globalClock.getDt()
        #print dt, "Engine Loop"

        # Handle Physics
        self.bulletWorld.doPhysics(dt)

        # Check collisions

        return task.cont
예제 #23
0
class World(DirectObject):
    gameStateDict = {"Login" : 0,"CreateLobby":4, "EnterGame": 1, "BeginGame": 2, "InitializeGame":3}
    gameState = -1
    # Login , EnterGame , BeginGame
    responseValue = -1
    currentTime = 0
    idleTime = 0
    mySequence = None
    pandaPace = None
    jumpState = False
    isWalk = False
    previousPos = None  # used to store the mainChar pos from one frame to another
    host = ""
    port = 0
    vehiclelist = {}  # Stores the list of all the others players characters
    characters = []
    login = "******"

    def __init__(self):

        self.loading = LoadingScreen()

        base.setFrameRateMeter(True)
        #input states
        inputState.watchWithModifiers('forward', 'w')
        inputState.watchWithModifiers('left', 'a')
        inputState.watchWithModifiers('brake', 's')
        inputState.watchWithModifiers('right', 'd')
        inputState.watchWithModifiers('turnLeft', 'q')
        inputState.watchWithModifiers('turnRight', 'e')

        self.keyMap = {"hello": 0, "left": 0, "right": 0, "forward": 0, "backward": 0, "cam-left": 0, "cam-right": 0,
                       "chat0": 0, "powerup": 0, "reset": 0}
        base.win.setClearColor(Vec4(0, 0, 0, 1))

        # Network Setup
        self.cManager = ConnectionManager(self)
        self.startConnection()
        #self.cManager.sendRequest(Constants.CMSG_LOGIN, ["username", "password"])
        # chat box
        # self.chatbox = Chat(self.cManager, self)


        # Set up the environment
        #
        self.initializeBulletWorld(False)

        #self.createEnvironment()
        Track(self.bulletWorld)

        # Create the main character, Ralph

        self.mainCharRef = Vehicle(self.bulletWorld, (0, 25, 16, 0, 0, 0), self.login)
        #self.mainCharRef = Character(self, self.bulletWorld, 0, "Me")
        self.mainChar = self.mainCharRef.chassisNP
        #self.mainChar.setPos(0, 25, 16)

#         self.characters.append(self.mainCharRef)

#         self.TestChar = Character(self, self.bulletWorld, 0, "test")
#         self.TestChar.actor.setPos(0, 0, 0)

        self.previousPos = self.mainChar.getPos()
        taskMgr.doMethodLater(.1, self.updateMove, 'updateMove')

        # Set Dashboard
        self.dashboard = Dashboard(self.mainCharRef, taskMgr)


        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(render)

        # Accept the control keys for movement and rotation
        self.accept("escape", self.doExit)
        self.accept("a", self.setKey, ["left", 1])
        self.accept("d", self.setKey, ["right", 1])
        self.accept("w", self.setKey, ["forward", 1])
        self.accept("s", self.setKey, ["backward", 1])
        self.accept("arrow_left", self.setKey, ["cam-left", 1])
        self.accept("arrow_right", self.setKey, ["cam-right", 1])
        self.accept("a-up", self.setKey, ["left", 0])
        self.accept("d-up", self.setKey, ["right", 0])
        self.accept("w-up", self.setKey, ["forward", 0])
        self.accept("s-up", self.setKey, ["backward", 0])
        self.accept("arrow_left-up", self.setKey, ["cam-left", 0])
        self.accept("arrow_right-up", self.setKey, ["cam-right", 0])
        self.accept("h", self.setKey, ["hello", 1])
        self.accept("h-up", self.setKey, ["hello", 0])
        self.accept("0", self.setKey, ["chat0", 1])
        self.accept("0-up", self.setKey, ["chat0", 0])
        self.accept("1", self.setKey,["powerup", 1])
        self.accept("1-up", self.setKey,["powerup", 0])
        self.accept("2", self.setKey,["powerup", 2])
        self.accept("2-up", self.setKey,["powerup", 0])
        self.accept("3", self.setKey,["powerup", 3])
        self.accept("3-up", self.setKey,["powerup", 0])
        self.accept("r", self.doReset)
        self.accept("p", self.setTime)

        #self.loading.finish()
        #taskMgr.doMethodLater(5, self.move, "moveTask")

        # Game state variables
        self.isMoving = False

        # Sky Dome
        self.sky = SkyDome()

        # Set up the camera
        self.camera = Camera(self.mainChar, self.bulletWorld)
        #base.disableMouse()
        #base.camera.setPos(self.mainChar.getX(), self.mainChar.getY() + 10, self.mainChar.getZ() + 2)

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

        # Game initialisation
        self.gameState = self.gameStateDict["Login"]
        self.responseValue = -1

        self.cManager.sendRequest(Constants.CMSG_LOGIN,[self.login,"1234"])
        taskMgr.add(self.enterGame,"EnterGame")

    # Create Powerups
        self.createPowerups()
        taskMgr.add(self.powerups.checkPowerPickup, "checkPowerupTask")
        taskMgr.add(self.usePowerup, "usePowerUp")

    def usePowerup(self, task):
        if self.keyMap["powerup"] == 1:
            self.mainCharRef.usePowerup(0)
        elif self.keyMap["powerup"] == 2:
            self.mainCharRef.usePowerup(1)
        elif self.keyMap["powerup"] == 3:
            self.mainCharRef.usePowerup(2)

        return task.cont

    def createPowerups(self):
        self.powerups = PowerupManager(self.cManager, self.characters)


    def use_powerup3(self):
        self.use_powerup(3)

    def setTime(self):
        self.cManager.sendRequest(Constants.CMSG_TIME)

    def use_powerup(self, num):
        if self.mainCharRef.power_ups[num - 1] == 0:
            print "power-up slot empty"
        else:
            print "power-up", num, "used"

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

    def cleanup(self):
        self.cManager.sendRequest(Constants.CMSG_DISCONNECT)
        self.cManager.closeConnection()
        self.world = None
        self.outsideWorldRender.removeNode()

    def doReset(self):
        self.mainCharRef.reset()

    def enterGame(self, task):
        if self.gameState == self.gameStateDict["Login"]:
            #responseValue = 1 indicates that this state has been finished
            if self.responseValue == 1:
                # Authentication succeeded
                self.cManager.sendRequest(Constants.CMSG_CREATE_LOBBY, ["raceroyal","0","1"])
                self.gameState = self.gameStateDict["CreateLobby"]
                self.responseValue = -1
        elif self.gameState == self.gameStateDict["CreateLobby"]:
            if self.responseValue == 1:
                # Lobby Created and we are already in
                self.gameState = self.gameStateDict["EnterGame"]
                self.responseValue = -1
            elif self.responseValue == 0:
                #Game already created, let's join it
                self.cManager.sendRequest(Constants.CMSG_ENTER_GAME_NAME, "raceroyal")
                self.gameState = self.gameStateDict["EnterGame"]
                self.responseValue = -1

        elif self.gameState == self.gameStateDict["EnterGame"]:
            if self.responseValue == 1:
#                 When the positions are sent, an acknowledgment is sent and we begin the InitializeGame
                self.responseValue = -1
                self.gameState = self.gameStateDict["InitializeGame"]
#               Everyone is in the game, we send ReqReady, and the server will send positions when every client did
                self.cManager.sendRequest(Constants.CMSG_READY)


        elif self.gameState == self.gameStateDict["InitializeGame"]:
            if self.responseValue == 1:
                # Set up the camera
                self.camera = Camera(self.mainChar, self.bulletWorld)
                self.gameState = self.gameStateDict["BeginGame"]
                self.cManager.sendRequest(Constants.CMSG_READY)
                self.responseValue = -1

        elif self.gameState == self.gameStateDict["BeginGame"]:
            if self.responseValue == 1:
                self.loading.finish()
                taskMgr.doMethodLater(5, self.move, "moveTask")
                return task.done

        return task.cont

    def createEnvironment(self):
        self.environ = loader.loadModel("models/square")
        self.environ.reparentTo(render)
        self.environ.setPos(0, 0, 0)
        self.environ.setScale(500, 500, 1)
        self.moon_tex = loader.loadTexture("models/moon_1k_tex.jpg")
        self.environ.setTexture(self.moon_tex, 1)

        shape = BulletPlaneShape(Vec3(0, 0, 1), 0)
        node = BulletRigidBodyNode('Ground')
        node.addShape(shape)
        np = render.attachNewNode(node)
        np.setPos(0, 0, 0)

        self.bulletWorld.attachRigidBody(node)

        self.visNP = loader.loadModel('models/track.egg')
        self.tex = loader.loadTexture("models/tex/Main.png")
        self.visNP.setTexture(self.tex)

        geom = self.visNP.findAllMatches('**/+GeomNode').getPath(0).node().getGeom(0)
        mesh = BulletTriangleMesh()
        mesh.addGeom(geom)
        trackShape = BulletTriangleMeshShape(mesh, dynamic=False)

        body = BulletRigidBodyNode('Bowl')
        self.visNP.node().getChild(0).addChild(body)
        bodyNP = render.anyPath(body)
        bodyNP.node().addShape(trackShape)
        bodyNP.node().setMass(0.0)
        bodyNP.setTexture(self.tex)

        self.bulletWorld.attachRigidBody(bodyNP.node())

        self.visNP.reparentTo(render)

        self.bowlNP = bodyNP
        self.visNP.setScale(70)

    def initializeBulletWorld(self, debug=False):
        self.outsideWorldRender = render.attachNewNode('world')

        self.bulletWorld = BulletWorld()
        self.bulletWorld.setGravity(Vec3(0, 0, -9.81))
        if debug:
            self.debugNP = self.outsideWorldRender.attachNewNode(BulletDebugNode('Debug'))
            self.debugNP.show()
            self.debugNP.node().showWireframe(True)
            self.debugNP.node().showConstraints(True)
            self.debugNP.node().showBoundingBoxes(True)
            self.debugNP.node().showNormals(False)
            self.bulletWorld.setDebugNode(self.debugNP.node())

    def makeCollisionNodePath(self, nodepath, solid):
        '''
        Creates a collision node and attaches the collision solid to the
        supplied NodePath. Returns the nodepath of the collision node.
        '''
        # Creates a collision node named after the name of the NodePath.
        collNode = CollisionNode("%s c_node" % nodepath.getName())
        collNode.addSolid(solid)
        collisionNodepath = nodepath.attachNewNode(collNode)

        return collisionNodepath

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

    # Accepts arrow keys to move either the player or the menu cursor,
    # Also deals with grid checking and collision detection
    def getDist(self):
        mainCharX = self.mainChar.getPos().x
        mainCharY = self.mainChar.getPos().y
        pandaX = self.pandaActor2.getPos().x
        pandaY = self.pandaActor2.getPos().y
        dist = math.sqrt(abs(mainCharX - pandaX) ** 2 + abs(mainCharY - pandaY) ** 2)
        return dist

    def move(self, task):
        # If the camera-left key is pressed, move camera left.
        # If the camera-right key is pressed, move camera right.

        #dt = globalClock.getDt()

        #update camera
        self.camera.update(self.mainChar)

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

        # save mainChar's initial position so that we can restore it,
        # in case he falls off the map or runs into something.
        #
        #startpos = self.mainChar.getPos()
        #
        # If a move-key is pressed, move ralph in the specified direction.
        # If a move-key is pressed, move ralph in the specified direction.
        # Steering info
        #steering = 0.0  # degree
        #steeringClamp = 70.0  # degree
        #steeringIncrement = 180.0  # degree per second
        #
        # Process input
        #engineForce = 0.0
        #brakeForce = 0.0
        #if (self.keyMap["forward"] != 0):
        #    # checks for vehicle's max speed
        #    if self.mainCharRef.vehicle.getCurrentSpeedKmHour() <= self.mainCharRef.max_speed:
        #        engineForce = 2000.0
        #        brakeForce = 0.0
        #
        #if (self.keyMap["backward"] != 0):
        #    if self.mainCharRef.vehicle.getCurrentSpeedKmHour() <= 0:
        #        engineForce = -500.0
        #        brakeForce = 0.0
        #    else:
        #        engineForce = 0.0
        #        brakeForce = 100.0
        #
        #if (self.keyMap["left"] != 0):
        #    steering += dt * steeringIncrement
        #    steering = min(steering, steeringClamp)
        #
        #if (self.keyMap["right"] != 0):
        #    steering -= dt * steeringIncrement
        #    steering = max(steering, -steeringClamp)
        #
        # Apply steering to front wheels
        #self.mainCharRef.vehicle.setSteeringValue(steering, 0)
        #self.mainCharRef.vehicle.setSteeringValue(steering, 1)
        #
        # Apply engine and brake to rear wheels
        #self.mainCharRef.vehicle.applyEngineForce(engineForce, 2)
        #self.mainCharRef.vehicle.applyEngineForce(engineForce, 3)
        #self.mainCharRef.vehicle.setBrake(brakeForce, 2)
        #self.mainCharRef.vehicle.setBrake(brakeForce, 3)

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

        dt = globalClock.getDt()

        self.mainCharRef.processInput(inputState, dt)
        self.bulletWorld.doPhysics(dt, 10, 0.02)

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

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

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

        #self.floater.setPos(self.mainChar.getPos())
        #self.floater.setZ(self.mainChar.getZ() + 2.0)
        #base.camera.lookAt(self.floater)

        self.bulletWorld.doPhysics(dt)

        return task.cont

    def startConnection(self):
        """Create a connection to the remote host.

        If a connection cannot be created, it will ask the user to perform
        additional retries.

        """
        if self.cManager.connection == None:
            if not self.cManager.startConnection():
                return False

        return True

    # Chat
    # def message(self, task):
    #     # hide all chatboxes
    #     if self.keyMap["chat0"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(0)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat0"] = 0
    #     if self.keyMap["chat1"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(1)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat1"] = 0
    #     elif self.keyMap["chat2"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(2)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat2"] = 0
    #     elif self.keyMap["chat3"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(3)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat3"] = 0
    #     elif self.keyMap["chat4"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(4)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat4"] = 0
    #     elif self.keyMap["chat5"] != 0:
    #         if self.chatbox.getVisible() is False:
    #             self.chatbox.setVisible(True)
    #             self.chatbox.show(5)
    #         else:
    #             self.chatbox.setVisible(False)
    #             self.chatbox.hide()
    #         self.keyMap["chat5"] = 0
    #     return task.cont

    def listFromInputState(self, inputState):
        # index 0 == forward
        # index 1 == brake
        # index 2 == right
        # index 3 == left
        result = [0, 0, 0, 0]
        if inputState.isSet('forward'):
            result[0] = 1
        if inputState.isSet('brake'):
            result[1] = 1
        if inputState.isSet('right'):
            result[2] = 1
        if inputState.isSet('left'):
            result[3] = 1

        return result

    def updateMove(self, task):
        if self.isMoving == True:
            moving = self.mainChar.getPos() - self.previousPos

            self.cManager.sendRequest(Constants.CMSG_MOVE,
                                      [moving.getX(), moving.getY(), moving.getZ(), self.mainCharRef.actor.getH(),
                                       self.mainCharRef.actor.getP(),
                                       self.mainCharRef.actor.getR(), self.listFromInputState(inputState)])


            # self.cManager.sendRequest(Constants.RAND_FLOAT, 1.0)
            self.previousPos = self.mainChar.getPos()

        return task.again
예제 #24
0
class SMWorld(DirectObject):

	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Constructor
	# (Game state, Map name, Height of death plane)
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def __init__(self, mapID, tObj, aObj):

		self.mapID = mapID
		
		# EX: maps/map-1/map-1.yetimap
		metaFile = open("../maps/map" + str(self.mapID) + "/map" + str(self.mapID) + ".yetimap", 'r')
		metaLines = metaFile.readlines()
		lineCount = len(metaLines)
		self.snowflakeCount = lineCount - 2
		self.snowCount = 0
		
		# First Line: Player's starting position
		# EX: 50,50,50 (NO SPACES)
		playerLine = metaLines[0]
		playerPosList = playerLine.split(",")
		playerInitX = int(playerPosList[0])
		playerInitY = int(playerPosList[1])
		playerInitZ = int(playerPosList[2])
		self.playerStart = Point3(playerInitX, playerInitY, playerInitZ)
		
		# 2nd Line: Deathzone Height
		# ONE INTEGER
		self.deathHeight = int(metaLines[1])
		
		# Get dem snowflakes
		self.snowflakePositions = []
		print("Snowflake Count: " + str(self.snowflakeCount))
		for i in xrange(0, self.snowflakeCount):
			sfline = metaLines[i+2]
			sfList = sfline.split(",")
			sfx = int(sfList[0])
			sfy = int(sfList[1])
			sfz = int(sfList[2])
			self.snowflakePositions.append(Point3(sfx, sfy, sfz))
			print("New snowflake to add: (" + str(sfx) + "," + str(sfy) + "," + str(sfz) + ")")

		#load in controls
		ctrlFl = open("ctrConfig.txt")
		#will skip n lines where [n,]
		#makes a list of controls
		self.keymap = eval(ctrlFl.read())
		#close file
		ctrlFl.close()
		
		# Create new instances of our various objects
		self.mapName = str(mapID)
		self.audioMgr = aObj
		self.worldObj = self.setupWorld()
		self.heightMap = self.setupHeightmap(self.mapName)
		self.deathZone = self.setupDeathzone(self.deathHeight)
		self.debugNode = self.setupDebug()	
		
		# Player Init
		self.playerObj = SMPlayer(self.worldBullet, self.worldObj, self, self.playerStart, self.audioMgr)
		self.playerNP = self.playerObj.getNodePath()
		self.playerNP.setH(180);
		self.canUseShift = True
		self.canAirDash = True
		
		# Snowball Init
		self.ballObj = SMBall(self.worldBullet, self.worldObj, self.playerObj, self.playerNP)
		self.sbCollideFlag = False
		self.ballNP = self.ballObj.getNodePath()
		
		# Key Handler
		self.kh = SMKeyHandler()
		self.lastMousePos = self.kh.getMouse()
		
		# Collision Handler
		self.colObj = self.setupCollisionHandler()
		
		# Lighting
		self.ligObj = SMLighting(Vec4(.4, .4, .4, 1), Vec3(-5, -5, -5), Vec4(2.0, 2.0, 2.0, 1.0))
		
		# Camera
		self.camObj = SMCamera(self.playerObj, self.worldBullet, self.worldObj)
		self.cameraControl = False

		# GUI
		self.GUI = SMGUI()
		self.snowflakeCounter = SMGUICounter("snowflake", self.snowflakeCount) # Replace 3 with # of snowflakes in level.
		self.snowMeter = SMGUIMeter(100)
		self.GUI.addElement("snowflake", self.snowflakeCounter)
		self.GUI.addElement("snowMeter", self.snowMeter)
		
		#Snowy Outside
		# base.enableParticles()
		# self.p = ParticleEffect()
		# self.p.cleanup()
		# self.p = ParticleEffect()
		# self.p.loadConfig('snow.ptf')        
		# self.p.start(self.camObj.getNodePath())
		# self.p.setPos(0.00, 0.500, 0.000)

		# AI
		# self.goat1 = SMAI("../res/models/goat.egg", 75.0, self.worldBullet, self.worldObj, -70, -95, 5)
		# self.goat1.setBehavior("flee", self.playerNP)
		# self.goat2 = SMAI("../res/models/goat.egg", 75.0, self.worldBullet, self.worldObj, -80, -83, 5)
		# self.goat2.setBehavior("flee", self.playerNP)
		# print("AI Initialized")
		
		# Debug Text
		self.textObj = tObj
		self.textObj.addText("yetiPos", "Position: ")
		self.textObj.addText("yetiVel", "Velocity: ")
		self.textObj.addText("yetiFric", "Friction: ")
		self.textObj.addText("onIce", "Ice(%): ")
		self.textObj.addText("onSnow", "Snow(%): ")
		self.textObj.addText("terrHeight", "T Height: ")
		self.textObj.addText("terrSteepness", "Steepness: ")
		
		# Pause screen transition
		self.transition = Transitions(loader)

		# Method-based keybindings
		# self.accept('b', self.spawnBall)
		self.accept('escape', base.userExit)
		self.accept('enter', self.pauseUnpause)
		self.accept('f1', self.toggleDebug)
		
		self.accept('lshift-up', self.enableShiftActions)
		self.accept('mouse1', self.enableCameraControl)
		self.accept('mouse1-up', self.disableCameraControl)
		self.accept('wheel_up', self.camObj.zoomIn)
		self.accept('wheel_down', self.camObj.zoomOut)
		
		self.pauseUnpause()
		
		# Disable the mouse
		base.disableMouse()
		props = WindowProperties()
		props.setCursorHidden(True)
		base.win.requestProperties(props)
		
		# Uncomment this to see everything being rendered.
		self.printSceneGraph()
		
		# Play the BGM
		self.audioMgr.playBGM("snowmanWind")
		
		# Skybox formed
		skybox = loader.loadModel("../res/models/skybox.egg")
		# skybox.set_two_sided(true)
		skybox.setScale(500)
		skybox.setPos(0, 0, -450)
		skybox.reparentTo(render)
		
		mountain = loader.loadModel("../res/models/mountain.egg")
		mountain.reparentTo(render)
		mountain.setPos(650,800,20)
		mountain.setScale(120)
		
		self.colObjects = []
		
		self.caveNew = SMCollide("../res/models/cave_new.egg", self.worldBullet, self.worldObj, Point3(-50, 95, -13), 11, Vec3(0,0,0))
		self.colObjects.append(self.caveNew)
		
		self.planeFront = SMCollide("../res/models/plane_front", self.worldBullet, self.worldObj, Point3(190, -100, -15), 8, Vec3(190,0,30))
		self.colObjects.append(self.planeFront)
		
		self.caveModel = SMCollide("../res/models/cave_tunnel.egg", self.worldBullet, self.worldObj, Point3(233, 68, 32), 4, Vec3(135,180,0))
		self.colObjects.append(self.caveModel)
		
		self.planeTail = SMCollide("../res/models/plane_tail.egg", self.worldBullet, self.worldObj, Point3(-40, -130, -7), 10, Vec3(230,0,0))
		self.colObjects.append(self.planeTail)
		
		self.ropeBridge = SMCollide("../res/models/rope_bridge.egg", self.worldBullet, self.worldObj, Point3(180, 115, 30), 6, Vec3(50,0,0))
		self.colObjects.append(self.ropeBridge)
		
		self.colObjectCount = len(self.colObjects)
		
		print("World initialized.")


	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Enables the camera to be rotated by moving the mouse horizontally.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def enableCameraControl(self):
		self.cameraControl = True
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Disables the camera control.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def disableCameraControl(self):
		self.cameraControl = False
		
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Enables the use of shift actions again.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def enableShiftActions(self):
		self.canUseShift = True
		
	def disableShiftActions(self):
		self.canUseShift = False
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Respawns the yeti's snowball.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
		
	def spawnBall(self):
		if(not(self.playerObj.getAirborneFlag())):
			self.ballObj.respawn()
		
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Toggles the pause screen
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def pauseUnpause(self):
		if taskMgr.hasTaskNamed('UpdateTask'):
			taskMgr.remove('UpdateTask')
			self.transition.fadeScreen(0.5)
		else:
			taskMgr.add(self.update, 'UpdateTask')
			self.transition.noFade()
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Sets up the world and returns a NodePath of the BulletWorld
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def setupWorld(self):
		self.worldBullet = BulletWorld()
		self.worldBullet.setGravity(Vec3(0, 0, -GRAVITY))
		self.terrSteepness = -1
		wNP = render.attachNewNode('WorldNode')
		
		self.audioMgr.loadSFX("snowCrunch01")
		self.audioMgr.loadBGM("snowmanWind")
		
		return wNP
		
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Prints all nodes that are a child of render.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def printSceneGraph(self):
		print(render.ls())
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Initializes and returns a DebugNode NodePath.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def setupDebug(self):
		debug = BulletDebugNode()
		debug.showWireframe(False) # Yeah, don't set this to true unless you want to emulate an 80's computer running Crysis on Ultra settings.
		debug.showConstraints(True)
		debug.showBoundingBoxes(True) # This is the main use I have for it.
		debug.showNormals(True)
		debugNP = render.attachNewNode(debug)
		self.worldBullet.setDebugNode(debugNP.node())
		debugNP.hide()
		return debugNP
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Initializes and returns a BulletRigidBodyNode of the terrain, which loads the map with the specified name.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def setupHeightmap(self, name):
		
		# Automatically generate a heightmap mesh from a monochrome image.
		self.hmHeight = 120
		hmPath = "../maps/map" + name + "/map" + name + "-h.png"
		imPath = "../maps/map" + name + "/map" + name + "-i.png"
		smPath = "../maps/map" + name + "/map" + name + "-s.png"
		scmPath = "../maps/map" + name + "/map" + name + "-sc.png"
		print(hmPath)
		print(imPath)
		print(smPath)
		print(scmPath)
		hmImg = PNMImage(Filename(hmPath))
		hmShape = BulletHeightfieldShape(hmImg, self.hmHeight, ZUp)
		hmNode = BulletRigidBodyNode('Terrain')
		hmNode.addShape(hmShape)
		hmNode.setMass(0)
		self.hmNP = render.attachNewNode(hmNode)
		self.worldBullet.attachRigidBody(hmNode)
		self.hmOffset = hmImg.getXSize() / 2.0 - 0.5
		self.hmTerrain = GeoMipTerrain('gmTerrain')
		self.hmTerrain.setHeightfield(hmImg)
		
		# Optimizations and fixes
		self.hmTerrain.setBruteforce(True) # I don't think this is actually needed. 
		self.hmTerrain.setMinLevel(3) # THIS is what triangulates the terrain.
		self.hmTerrain.setBlockSize(128)  # This does a pretty good job of raising FPS.
		# Level-of-detail (not yet working)
		# self.hmTerrain.setNear(40)
		# self.hmTerrain.setFar(200)
		
		self.hmTerrain.generate()
		
		self.hmTerrainNP = self.hmTerrain.getRoot()
		self.hmTerrainNP.setSz(self.hmHeight)
		self.hmTerrainNP.setPos(-self.hmOffset, -self.hmOffset, -self.hmHeight / 2.0)
		self.hmTerrainNP.flattenStrong() # This only reduces the number of nodes; nothing to do with polys.
		self.hmTerrainNP.analyze()

		# Here begins the scenery mapping
		treeModel = loader.loadModel("../res/models/tree_1.egg")
		rockModel = loader.loadModel("../res/models/rock_1.egg")
		rock2Model = loader.loadModel("../res/models/rock_2.egg")
		rock3Model = loader.loadModel("../res/models/rock_3.egg")
		# caveModel = loader.loadModel("../res/models/cave_new.egg")
		# planeFrontModel = loader.loadModel("../res/models/plane_front.egg")
		# planeWingModel = loader.loadModel("../res/models/plane_wing.egg")
		texpk = loader.loadTexture(scmPath).peek()
		
		# GameObject nodepath for flattening
		self.objNP = render.attachNewNode("gameObjects")
		self.treeNP = self.objNP.attachNewNode("goTrees")
		self.rockNP = self.objNP.attachNewNode("goRocks")
		self.rock2NP = self.objNP.attachNewNode("goRocks2")
		self.rock3NP = self.objNP.attachNewNode("goRocks3")
		# self.caveNP = self.objNP.attachNewNode("goCave")
		# self.planeFrontNP = self.objNP.attachNewNode("goPlaneFront")
		# self.planeWingNP = self.objNP.attachNewNode("goPlaneWing")
		
		for i in range(0, texpk.getXSize()):
			for j in range(0, texpk.getYSize()):
				color = VBase4(0, 0, 0, 0)
				texpk.lookup(color, float(i) / texpk.getXSize(), float(j) / texpk.getYSize())
				if(int(color.getX() * 255.0) == 255.0):
					newTree = self.treeNP.attachNewNode("treeNode")
					treeModel.instanceTo(newTree)
					newTree.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					# newTree.setScale(randint(0,4))
					newTree.setScale(2)
					
				if(int(color.getX() * 255.0) == 128):
					newRock = self.rockNP.attachNewNode("newRock")
					newRock.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					rockModel.instanceTo(newRock)
					
				if(int(color.getX() * 255.0) == 77):
					newRock2 = self.rock2NP.attachNewNode("newRock2")
					newRock2.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					rock2Model.instanceTo(newRock2)
					
				if(int(color.getX() * 255.0) == 102):
					newRock3 = self.rock3NP.attachNewNode("newRock3")
					newRock3.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					rock3Model.instanceTo(newRock3)
					
				# if(int(color.getX() * 255.0) == 64):
					# newCave = self.caveNP.attachNewNode("newCave")
					# newCave.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					# newCave.setScale(5)
					# newCave.setP(180)
					# caveModel.instanceTo(newCave)
				
				# if(int(color.getX() * 255.0) == 191):
					# newPlaneFront = self.planeFrontNP.attachNewNode("newPlaneFront")
					# newPlaneFront.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					# newPlaneFront.setScale(6)
					# planeFrontModel.instanceTo(newPlaneFront)
					
				# if(int(color.getX() * 255.0) == 179):
					# newPlaneWing = self.planeWingNP.attachNewNode("newPlaneWing")
					# newPlaneWing.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
					# newPlaneWing.setScale(6)
					# newPlaneWing.setH(250)
					# newPlaneWing.setR(180)
					# newPlaneWing.setP(135)
					# planeWingModel.instanceTo(newPlaneWing)

		self.snowflakes = []
		
		for i in xrange(0, self.snowflakeCount):
			print("Call " + str(i))
			sf = SMCollect(self.worldBullet, self.worldObj, self.snowflakePositions[i])
			self.snowflakes.append(sf)
					
		# render.flattenStrong()
		self.hmTerrainNP.reparentTo(render)
		
		# Here begins the attribute mapping
		ts = TextureStage("stage-alpha")
		ts.setSort(0)
		ts.setPriority(1)
		ts.setMode(TextureStage.MReplace)
		ts.setSavedResult(True)
		self.hmTerrainNP.setTexture(ts, loader.loadTexture(imPath, smPath))

		ts = TextureStage("stage-stone")
		ts.setSort(1)
		ts.setPriority(1)
		ts.setMode(TextureStage.MReplace)
		self.hmTerrainNP.setTexture(ts, loader.loadTexture("../res/textures/stone_tex.png"))
		self.hmTerrainNP.setTexScale(ts, 32, 32)

		ts = TextureStage("stage-ice")
		ts.setSort(2)
		ts.setPriority(1)
		ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSTexture, TextureStage.COSrcColor,
						 TextureStage.CSPrevious, TextureStage.COSrcColor,
						 TextureStage.CSLastSavedResult, TextureStage.COSrcColor)
		self.hmTerrainNP.setTexture(ts, loader.loadTexture("../res/textures/ice_tex.png"))
		self.hmTerrainNP.setTexScale(ts, 32, 32)

		ts = TextureStage("stage-snow")
		ts.setSort(3)
		ts.setPriority(0)
		ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSTexture, TextureStage.COSrcColor,
						 TextureStage.CSPrevious, TextureStage.COSrcColor,
						 TextureStage.CSLastSavedResult, TextureStage.COSrcAlpha)
		self.hmTerrainNP.setTexture(ts, loader.loadTexture("../res/textures/snow_tex_1.png"))
		self.hmTerrainNP.setTexScale(ts, 32, 32)

		# print(self.snowflakes)
		
		return hmNode
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Sets up and returns the death zone plane (returns its NodePath) with the specified height.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def setupDeathzone(self, height):
		planeShape = BulletPlaneShape(Vec3(0, 0, 1), 1)
		planeNode = BulletRigidBodyNode('DeathZone')
		planeNode.addShape(planeShape)
		planeNP = render.attachNewNode(planeNode)
		planeNP.setPos(0, 0, height)
		self.worldBullet.attachRigidBody(planeNode)
		return planeNP
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Sets up and returns the collision handler.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def setupCollisionHandler(self):
		colHand = SMCollisionHandler(self.worldBullet)
		return colHand
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Toggles showing bounding boxes.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def toggleDebug(self):
		if self.debugNode.isHidden():
			self.debugNode.show()
		else:
			self.debugNode.hide()
	
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Returns the terrain height of the nearest vertical descending raycast from the passed Point3.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def getTerrainHeight(self, pos):
		result = 0
		x = pos.getX()
		y = pos.getY()
		z = pos.getZ()
		rayTerrA = Point3(x, y, z)
		rayTerrB = Point3(x, y, z - 256)
		rayTest = self.worldBullet.rayTestClosest(rayTerrA, rayTerrB)
		
		rayNode = rayTest.getNode()
		if (rayTest.hasHit()):
			rayPos = rayTest.getHitPos()
			result = rayPos.getZ()
		else:
			self.playerObj.respawn()
		return result
		# return self.hmTerrain.get_elevation(x + self.hmOffset, y + self.hmOffset) * self.hmHeight
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Handles player movement
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def playerMove(self):
	
		# Go through the collision and flag tests, and update them
		self.doPlayerTests()
		
		# Rotation and camera movement
		if self.kh.poll(self.keymap['Left']):
			self.playerObj.turn(True)
		elif self.kh.poll(self.keymap['Right']):
			self.playerObj.turn(False)
		elif(self.cameraControl):
			newMousePos = self.kh.getMouse()
			mx = newMousePos.getX()
			self.camObj.rotateCamera(mx)
		
		self.camObj.calculatePosition()
		
		# Movement
		if self.kh.poll(self.keymap['Forward']):
			self.playerObj.move(True)
			self.camObj.rotateTowards(90)
		elif self.kh.poll(self.keymap['Back']):

			self.playerObj.move(False)
		else:
			self.playerObj.stop()

		# Jump
		if(self.kh.poll(self.keymap['Space']) and self.terrSteepness < 0.25): #and not(self.ballObj.isRolling())):
			self.playerObj.jump()
		else:
			self.playerObj.resetJump()
		
		# Air Dash
		if(self.kh.poll(self.keymap['airDash'])): #and self.playerObj.getAirborneFlag() == True and self.canAirDash == True):
			self.canAirDash = False
			self.playerObj.airDash()
		
		# Shift-based actions
		if(self.kh.poll("lshift") and not(self.sbCollideFlag) and not(self.playerObj.getAirborneFlag()) and self.canUseShift):
		
			# If there's another snowball already placed
			if(self.ballObj.exists() and not(self.ballObj.isRolling())):
				self.ballObj.respawn()
				
			# If we're rolling a snowball
			elif(self.ballObj.isRolling()):
			
				# Absorb snowball
				if(self.kh.poll("v")):
					self.canUseShift = False
					snowAmt = self.ballObj.getSnowAmount()
					self.playerObj.addSnow(snowAmt)
					# self.snowMeter.fillBy(snowAmt)
					self.ballObj.destroy()
					
				# Go to iceball throwing mode
				elif(self.kh.poll("b")):
					print("TODO: Ice ball throwing mode.")
					
				# Grow the snowball
				elif(self.kh.poll("w")):
					self.ballObj.grow()
					
			# Spawn a new snowball
			elif(self.ballObj.exists() == False):
				self.ballObj.respawn()
				
		# If the player is not pressing shift
		else:
			if(self.ballObj.isRolling()):
				self.ballObj.dropBall()

		base.win.movePointer(0, 400, 300)
		
		# So updating the stats is VERY expensive.
		if (self.debugNode.isHidden() == False):
			self.updateStats()
	
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Various tests concerning the player flags and collisions.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def doPlayerTests(self):
		
		# Player's position
		plPos = self.playerObj.getPosition()
		px = plPos.getX()
		py = plPos.getY()
		pz = plPos.getZ()
		
		# Raycast directly down for terrain steepness
		rayYetiA = Point3(px, py, pz)
		rayYetiB = Point3(px, py, pz - 300)
		self.downRayTest = self.worldBullet.rayTestClosest(rayYetiA, rayYetiB).getHitNormal()
		rx = self.downRayTest.getX()
		ry = self.downRayTest.getY()
		rz = self.downRayTest.getZ()
		self.terrSteepness = 1.0 - rz

		# Redo collision flags later
		objCollisionFlag = False
		
		# Snow/Ice height adjust
		self.playerObj.updateTerrain()
		
		# Collision: Player x Objects
		for i in xrange(0, self.colObjectCount):
			if(self.colObj.didCollide(self.playerNP.node(), self.colObjects[i].AINode)):
				objCollisionFlag = True
				self.playerObj.setAirborneFlag(False)
				self.canAirDash = True
				self.playerObj.setFactor(1,1,1)
		
		# Collision: Player x Snowball
		if(self.ballObj.exists() and self.colObj.didCollide(self.playerNP.node(), self.ballObj.getRigidbody())):
			self.sbCollideFlag = True
			self.playerObj.setAirborneFlag(False)
			self.playerObj.setFactor(1, 1, 1)
		else:
			self.sbCollideFlag = False
		
		# Collision: Player x Terrain
		if(self.colObj.didCollide(self.playerNP.node(), self.heightMap)):
			if(self.playerObj.getAirborneFlag()):
				self.audioMgr.playSFX("snowCrunch01")
			self.playerObj.setAirborneFlag(False)
			self.canAirDash = True
			self.playerObj.setFactor(1, 1, 1)
			objCollisionFlag = False
			
		# Collision: Player x Death Zone
		# if(pz - 7 <= self.deathHeight or (self.colObj.didCollide(self.playerNP.node(), self.deathZone.node()))):
		if(self.colObj.didCollide(self.playerNP.node(), self.deathZone.node())):
			print("Player confirmed #REKT")
			self.playerObj.respawn()
		
		# Out of bounds checking
		if(abs(px) > 254 or abs(py) > 254):
			print("Player out of bounds!")
			self.playerObj.respawn()
		
		# Snap to terrain if... something. I need to restructure this. Don't read it.
		if(not(self.playerObj.getAirborneFlag()) and not(self.sbCollideFlag) and not(objCollisionFlag)):
			z = self.getTerrainHeight(Point3(px, py, pz))
			self.playerObj.snapToTerrain(z)
			# self.playerObj.snapToTerrain(th, self.hmHeight)
		
		# Collision: Player x Snowflakes
		for i in xrange(0, self.snowflakeCount):
			if(self.snowflakes[i].exists() and self.colObj.didCollide(self.playerNP.node(), self.snowflakes[i].getNode())):
				self.snowflakes[i].destroy()
				self.snowflakeCounter.increment()
				self.snowCount += 1
			
		self.snowMeter.updateSnow(self.playerObj)
		
		#Check if there is a "next" level. If there is, load it. Otherwise display end game screen.
		if(self.snowCount >= self.snowflakeCount):
			file_path="../maps/map" + str(self.mapID+1) + "/map" + str(self.mapID+1) + ".yetimap"
			if  os.path.lexists(file_path):
			
				self.snowCount = 0
				self.snowflakeCount = 0
				self.snowflakeCounter.setValue(0)
				self.snowflakeCounter.setState(2)
				
				#Loading Screen
				self.transition.fadeScreen(0.7)	
				self.loadingText=OnscreenText("Loading...",1,fg=(1,1,1,0),pos=(0,0),align=TextNode.ACenter,scale=.07,mayChange=1)
				base.graphicsEngine.renderFrame() 
				base.graphicsEngine.renderFrame() 
				base.graphicsEngine.renderFrame() 
				base.graphicsEngine.renderFrame()
				self.transition.noFade()
				
				#destroy objects
				self.worldBullet.removeRigidBody(self.heightMap)
				self.hmTerrainNP.removeNode()
				self.objNP.removeNode()
				self.treeNP.removeNode()
				self.rockNP.removeNode()
				self.rock2NP.removeNode()
				self.rock3NP.removeNode()
				# self.caveNP.removeNode()
				# self.planeFrontNP.removeNode()
				# self.planeWingNP.removeNode()
				self.hmNP.removeNode()
				if(int(self.mapID) == 1):
					self.ropeBridge.AIChar.setPos(-200,-300,-200)
					# self.ropeBridge.AIChar.removeNode()
					self.planeFront.AIChar.removeNode()
					self.planeTail.AIChar.setPos(-200,-200,-200)
					# self.planeTail.AIChar.removeNode()
					self.caveNew.AIChar.setPos(-1000,-1000,-1000);
					self.caveModel.AIChar.removeNode()
					#Added More Props here!
					self.boulder = SMCollide("../res/models/rock_3.egg", self.worldBullet, self.worldObj, Point3(117, 123, 17), 15, Vec3(0,0,0))
				elif(int(self.mapID) == 2):
					self.boulder.AIChar.setPos(-222,-222,-222)
					self.caveNew.AIChar.setScale(150)
					self.caveNew.AIChar.setPos(-50, 95, -50)
					# self.skybox.setScale(600)
					# self.caveNew.setH(0)
					# self.boulder.removeNode()
			
				self.mapID += 1
				print self.mapID
				# EX: maps/map-1/map-1.yetimap
				metaFile = open("../maps/map" + str(self.mapID) + "/map" + str(self.mapID) + ".yetimap", 'r')
				metaLines = metaFile.readlines()
				lineCount = len(metaLines)
				self.snowflakeCount = lineCount - 2
			
				# First Line: Player's starting position
				# EX: 50,50,50 (NO SPACES)
				playerLine = metaLines[0]
				playerPosList = playerLine.split(",")
				playerInitX = int(playerPosList[0])
				playerInitY = int(playerPosList[1])
				playerInitZ = int(playerPosList[2])
				self.playerObj.playerNP.setPos(playerInitX, playerInitY, playerInitZ)
				self.playerObj.startX = playerInitX
				self.playerObj.startY = playerInitY
				self.playerObj.startZ = playerInitZ
			
				# 2nd Line: Deathzone Height
				# ONE INTEGER
				self.deathHeight = int(metaLines[1])
			
				
				self.snowflakePositions = []
				print("Snowflake Count: " + str(self.snowflakeCount))
				for i in xrange(0, self.snowflakeCount):
					sfline = metaLines[i+2]
					sfList = sfline.split(",")
					sfx = int(sfList[0])
					sfy = int(sfList[1])
					sfz = int(sfList[2])
					self.snowflakePositions.append(Point3(sfx, sfy, sfz))
					print("New snowflake to add: (" + str(sfx) + "," + str(sfy) + "," + str(sfz) + ")")
				self.snowflakeCounter.setMaxValue(self.snowflakeCount)
				
				#load new map
				self.mapName = str(self.mapID)
				self.heightMap = self.setupHeightmap(self.mapName)
				self.deathZone = self.setupDeathzone(self.deathHeight)
					
				
				self.loadingText.cleanup() 
			else:
				taskMgr.remove('UpdateTask')
				self.endImage=OnscreenImage(image = "../res/icons/endgame1.png", pos = (0.0, 0.0, 0.0), scale = (1.35, 2, 1))
				
		
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Update the debug text.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def updateStats(self):
		pos = self.playerObj.getPosition()
		x = pos.getX()
		y = pos.getY()
		z = pos.getZ()
		vel = self.playerObj.getVelocity()
		vx = str(round(vel.getX(), 1))
		vy = str(round(vel.getY(), 1))
		vz = str(round(vel.getZ(), 1))
		sx = str(round(x, 1))
		sy = str(round(y, 1))
		sz = str(round(z, 1))
		rx = str(round(self.downRayTest.getX(), 2))
		ry = str(round(self.downRayTest.getY(), 2))
		rz = str(round(self.terrSteepness, 2))
		fric = str(round(self.playerObj.getFriction(), 2))
		ip = str(round(self.playerObj.getIceCoefficient(), 2))
		sp = str(round(self.playerObj.getSnowCoefficient(), 2))
		tHeight = str(round(self.getTerrainHeight(Point3(x, y, z)), 1))
		self.textObj.editText("yetiPos", "Position: (" + sx + ", " + sy + ", " + sz + ")")
		self.textObj.editText("yetiVel", "Velocity: (" + vx + ", " + vy + ", " + vz + ")")
		self.textObj.editText("yetiFric", "Friction: " + fric)
		self.textObj.editText("onIce", "Ice(%): " + ip)
		self.textObj.editText("onSnow", "Snow(%): " + sp)
		self.textObj.editText("terrHeight", "T Height: " + tHeight)
		self.textObj.editText("terrSteepness", "Steepness: " + rz)

	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# throw Snowball
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	def throw(self):
		self.throwing = True
		size = self.ballObj.getSize()
		#zoom camera and grab pos you wish to throw
		self.camObj.aimMode()
		taskMgr.add(self.controlCamera, "camera-task")
		rotation = self.camObj.getH()
		pitch =self.camObj.getP()
		self.ballObj.throwBall(size, pitch, rotation)
		#fix camera
		#self.throwing = False
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	# Update the world. Called every frame.
	#------------------------------------------------------------------------------------------------------------------------------------------------------------
	
	def update(self, task):
		dt = globalClock.getDt()
		self.worldBullet.doPhysics(dt)
		# self.goat1.AIUpdate()
		# self.goat2.AIUpdate()
		self.playerMove()
		return task.cont
예제 #25
0
class App(ShowBase):

    def __init__(self, width, height):
        ShowBase.__init__(self)

        globalClock.set_mode(ClockObject.MNonRealTime)
        globalClock.set_dt(0.02) # 20ms per frame

        self.setBackgroundColor(0.9, 0.9, 0.9)
        self.createLighting()
        self.setupCamera(width, height)

        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81 * 10.0))
        self.setupDebug()
        self.createPlane()

        self.animated_rig = ExposedJointRig('walking', { 'walk': 'walking-animation.egg' })
        self.animated_rig.reparentTo(self.render)
        self.animated_rig.setPos(0, 0, -98)
        self.animated_rig.createLines(VBase4(0.5, 0.75, 1.0, 1.0))
        self.animated_rig.pose('walk', 0)

        self.physical_rig = RigidBodyRig()
        self.physical_rig.reparentTo(self.render)
        self.physical_rig.setPos(0, 0, -98)
        self.physical_rig.createColliders(self.animated_rig)
        self.physical_rig.createConstraints()
        self.physical_rig.setCollideMask(BitMask32.bit(1))
        self.physical_rig.attachRigidBodies(self.world)
        self.physical_rig.attachConstraints(self.world)

        self.control_rig = ControlJointRig('walking')
        self.control_rig.reparentTo(self.render)
        self.control_rig.setPos(0, 0, -98)
        self.control_rig.createLines(VBase4(1.0, 0.75, 0.5, 1.0))
        self.control_rig.matchPose(self.animated_rig)

        self.disable_collisions()

        self.is_paused = True

        self.accept('escape', sys.exit)
        self.accept('space', self.toggle_pause)

    def toggle_pause(self):
        if self.is_paused:
            self.is_paused = False
            self.taskMgr.add(self.update, 'update')
        else:
            self.is_paused = True
            self.taskMgr.remove('update')

    def disable_collisions(self):
        for i in range(32):
            self.world.setGroupCollisionFlag(i, i, False)
        self.world.setGroupCollisionFlag(0, 1, True)

    def setupDebug(self):
        node = BulletDebugNode('Debug')
        node.showWireframe(True)

        self.world.setDebugNode(node)

        np = self.render.attachNewNode(node)
        np.show()

    def createLens(self, aspect_ratio, fov=60.0, near=1.0, far=1000.0):
        lens = PerspectiveLens()
        lens.setFov(fov)
        lens.setAspectRatio(aspect_ratio)
        lens.setNearFar(near, far)
        return lens

    def setupCamera(self, width, height):
        self.cam.setPos(-200, -100, 0)
        self.cam.lookAt(0, -100, 0)
        self.cam.node().setLens(self.createLens(width / height))

    def createLighting(self):
        light = DirectionalLight('light')
        light.set_color(VBase4(0.2, 0.2, 0.2, 1))

        np = self.render.attach_new_node(light)
        np.setPos(0, -200, 0)
        np.lookAt(0, 0, 0)

        self.render.set_light(np)

        light = AmbientLight('ambient')
        light.set_color(VBase4(0.4, 0.4, 0.4, 1))

        np = self.render.attachNewNode(light)

        self.render.setLight(np)

    def createPlane(self):
        rb = BulletRigidBodyNode('Ground')
        rb.addShape(BulletPlaneShape(Vec3(0, 0, 1), 1))
        rb.setFriction(1.0)

        np = self.render.attachNewNode(rb)
        np.setPos(Vec3(0, 0, -100))
        np.setCollideMask(BitMask32.bit(0))

        self.world.attachRigidBody(rb)

        return np

    def update(self, task):
        self.animated_rig.pose('walk', globalClock.getFrameCount() * 0.5)
        self.physical_rig.matchPose(self.animated_rig)
        self.control_rig.matchPhysicalPose(self.physical_rig)
        self.world.doPhysics(globalClock.getDt(), 10, 1.0 / 180.0)
        return task.cont
예제 #26
0
class GameLogic(ShowBase):
    def __init__(self, pandaBase):
        #######################AJOUTER #########################################################
        self.pandaBase = pandaBase
        self.accept("DemarrerPartie", self.startGame)
        self.unDTO = DTOBalance()
        self.setupBalance()

        self.attribueurBonus = AttributionBonus()
        self.accept("MortJoueur", self.finDePartie)
        self.accept("AjoutFavori", self.ajoutFavori)
        self.accept("updateArmurie", self.updateArmurie)
        self.accept("escape", exit)

    def finDePartie(self, idPerdant):
        self.tempsFin = time.time()
        tempsPartie = self.tempsFin - self.tempsDebut
        for tank in self.map.listTank:
            if tank.identifiant != idPerdant:
                vieGagnant = tank.pointDeVie
                vieMax = tank.pointDeVieMax
                vieJoueur100 = 100 * vieGagnant / vieMax
                idGagnant = tank.identifiant
        #Ajout des bonus
        if idGagnant == 0:
            idJoueurGagnant = self.leDTOUsers.getIdUser(self.username1)
            idJoueurPerdant = self.leDTOUsers.getIdUser(self.username2)
            messenger.send(
                "AttribuerBonus",
                [idJoueurGagnant, self.username1, vieJoueur100, tempsPartie])
        else:
            idJoueurGagnant = self.leDTOUsers.getIdUser(self.username2)
            idJoueurPerdant = self.leDTOUsers.getIdUser(self.username1)
            messenger.send(
                "AttribuerBonus",
                [idJoueurGagnant, self.username2, vieJoueur100, tempsPartie])
        self.map.DTOStat.definitionGagnant(idJoueurGagnant)
        ####Ajout nb fois jouer
        if self.idNiveau != 000:
            self.unDAOUser = DAOOracleUsers()
            self.unDAOUser.updateNbFoisNivJouer(idJoueurGagnant, self.idNiveau)
            self.unDAOUser.updateNbFoisNivJouer(idJoueurPerdant, self.idNiveau)

        self.DAOStats.ecrireStatsFinPartie()

    def updateArmurie(self, listeInfo):
        print listeInfo
        self.unDAOUser = DAOOracleUsers()
        for info in listeInfo:
            self.unDAOUser.updateNbArmes(info[0], info[1])
            print "un update!"

    def setup(self):
        self.setupBulletPhysics()

        self.setupCamera()
        self.setupMap()
        self.setupLightAndShadow()

        #Création d'une carte de base
        if self.idNiveau == 000:
            self.map.construireMapHasard()
        else:
            self.map.creerCarteParDefaut()

        #A besoin des éléments de la map
        self.setupControle()
        self.setupInterface()

        #Fonction d'optimisation
        #DOIVENT ÊTRE APPELÉE APRÈS LA CRÉATION DE LA CARTE
        #Ça va prendre les modèles qui ne bougent pas et en faire un seul gros
        #en faisant un seul gros noeud avec
        self.map.figeObjetImmobile()

        #DEBUG: Décommenter pour affiche la hiérarchie
        #self.pandaBase.startDirect()

        messenger.send("ChargementTermine")

    def startGame(self, idNiveau, leDTOMap, leDTOUsers, username1, username2,
                  listeArmes):
        self.listeArmes = listeArmes
        self.username1 = username1
        self.username2 = username2
        self.idNiveau = idNiveau
        self.leDTOMap = leDTOMap
        self.leDTOUsers = leDTOUsers

        self.tempsDebut = time.time()

        self.setup()
        self.DAOStats = DAOStatistiques(self.map.DTOStat)
        self.DAOStats.ecrireInfosDebutPartie()
        #On démarrer l'effet du compte à rebour.
        #La fonction callBackDebutPartie sera appelée à la fin
        self.interfaceMessage.effectCountDownStart(
            self.unDTO.getValue("messageCompteRebour"),
            self.callBackDebutPartie)
        self.interfaceMessage.effectMessageGeneral(
            self.unDTO.getValue("messageAccueilContenu"),
            self.unDTO.getValue("messageAccueilDuree"))

    def setupBulletPhysics(self):
        debugNode = BulletDebugNode('Debug')
        debugNode.showWireframe(True)
        debugNode.showConstraints(True)
        debugNode.showBoundingBoxes(False)
        debugNode.showNormals(False)
        self.debugNP = render.attachNewNode(debugNode)

        self.mondePhysique = BulletWorld()
        self.mondePhysique.setGravity(Vec3(0, 0, -9.81))
        self.mondePhysique.setDebugNode(self.debugNP.node())
        taskMgr.add(self.updatePhysics, "updatePhysics")

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

    def setupCamera(self):
        #On doit désactiver le contrôle par défaut de la caméra autrement on ne peut pas la positionner et l'orienter
        self.pandaBase.disableMouse()

        #Le flag pour savoir si la souris est activée ou non n'est pas accessible
        #Petit fail de Panda3D
        taskMgr.add(self.updateCamera, "updateCamera")
        self.setupTransformCamera()

    def setupTransformCamera(self):
        #Défini la position et l'orientation de la caméra
        self.positionBaseCamera = Vec3(0, -18, 32)
        camera.setPos(self.positionBaseCamera)
        #On dit à la caméra de regarder l'origine (point 0,0,0)
        camera.lookAt(render)

    def setupMap(self):
        self.map = Map(self, self.mondePhysique, self.idNiveau, self.leDTOMap,
                       self.leDTOUsers, self.username1, self.username2,
                       self.listeArmes)
        #On construire la carte comme une coquille, de l'extérieur à l'intérieur
        #Décor et ciel
        self.map.construireDecor(camera)
        #Plancher de la carte
        self.map.construirePlancher()
        #Murs et éléments de la map

    def setupLightAndShadow(self):
        #Lumière du skybox
        plight = PointLight('Lumiere ponctuelle')
        plight.setColor(VBase4(1, 1, 1, 1))
        plnp = render.attachNewNode(plight)
        plnp.setPos(0, 0, 0)
        camera.setLight(plnp)

        #Simule le soleil avec un angle
        dlight = DirectionalLight('Lumiere Directionnelle')
        dlight.setColor(VBase4(0.8, 0.8, 0.6, 1))
        dlight.get_lens().set_fov(75)
        dlight.get_lens().set_near_far(0.1, 60)
        dlight.get_lens().set_film_size(30, 30)
        dlnp = render.attachNewNode(dlight)
        dlnp.setPos(Vec3(-2, -2, 7))
        dlnp.lookAt(render)
        render.setLight(dlnp)

        #Lumière ambiante
        alight = AmbientLight('Lumiere ambiante')
        alight.setColor(VBase4(0.25, 0.25, 0.25, 1))
        alnp = render.attachNewNode(alight)
        render.setLight(alnp)

        #Ne pas modifier la valeur 1024 sous peine d'avoir un jeu laid ou qui lag
        dlight.setShadowCaster(True, 1024, 1024)
        #On doit activer l'ombre sur les modèles
        render.setShaderAuto()

    def setupControle(self, ):
        #Créer le contrôle
        #A besoin de la liste de tank pour relayer correctement le contrôle
        self.inputManager = InputManager(self.map.listTank, self.debugNP,
                                         self.pandaBase)
        self.accept("initCam", self.setupTransformCamera)

    def setupInterface(self):
        self.interfaceTank = []
        self.interfaceTank.append(
            InterfaceTank(0, self.map.listTank[0].couleur))
        self.interfaceTank.append(
            InterfaceTank(1, self.map.listTank[1].couleur))

        self.interfaceMessage = InterfaceMessage(self)

    def callBackDebutPartie(self):
        #Quand le message d'introduction est terminé, on permet aux tanks de bouger
        self.inputManager.debuterControle()

    #Mise à jour du moteur de physique
    def updateCamera(self, task):
        #On ne touche pas à la caméra si on est en mode debug
        if (self.inputManager.mouseEnabled):
            return task.cont

        vecTotal = Vec3(0, 0, 0)
        distanceRatio = 1.0
        if (len(self.map.listTank) != 0):
            for tank in self.map.listTank:
                vecTotal += tank.noeudPhysique.getPos()
            vecTotal = vecTotal / len(self.map.listTank)

        vecTotal.setZ(0)
        camera.setPos(vecTotal + self.positionBaseCamera)
        return task.cont

    #Mise à jour du moteur de physique
    def updatePhysics(self, task):
        dt = globalClock.getDt()
        messenger.send("appliquerForce")
        self.mondePhysique.doPhysics(dt)
        #print(len(self.mondePhysique.getManifolds()))

        #Analyse de toutes les collisions
        for entrelacement in self.mondePhysique.getManifolds():
            node0 = entrelacement.getNode0()
            node1 = entrelacement.getNode1()
            self.map.traiterCollision(node0, node1)
        return task.cont

    def updateCarte(self, task):

        self.map.update(task.time)
        return task.cont

    def setupBalance(self):
        unDAO = DAOOracleBalance()
        if Connexion().getCurseur() != None:
            self.unDTO = unDAO.read()

    def ajoutFavori(self, identifiant):
        self.unDAOUser = DAOOracleUsers()
        if identifiant == 0:
            idJoueur = self.leDTOUsers.getIdUser(self.username1)
        else:
            idJoueur = self.leDTOUsers.getIdUser(self.username2)
        self.unDAOUser.ajoutAuFavori(self.idNiveau, idJoueur)

    def exit(self):
        Connexion.seDeconnecter()
        exit()
예제 #27
0
class World(object):
    def __init__(self, base, numberOfPlayers):
        self.base = base
        self.render = base.render
        self.taskMgr = base.taskMgr
        self.loader = base.loader

        self.windowEventSetup()

        # Create separate nodes so that shaders apply to
        # stuff in the worldRender but not the outsideWorldRender
        self.worldRender = render.attachNewNode("world")
        self.outsideWorldRender = render.attachNewNode("world")

        self.base.setFrameRateMeter(True)
        self.globalClock = ClockObject.getGlobalClock()
        self.globalClock.setMode(ClockObject.MLimited)
        self.globalClock.setFrameRate(60)
        self.base.disableMouse()

        if not 0 < numberOfPlayers < 5:
            raise ValueError("Number of players must be from 1 to 4")
        self.numberOfPlayers = numberOfPlayers

        self.createLights()

        self.initialisePhysics(debug=False)

        # Load the default arena
        self.level = Level("01.json", self)

        # disable default cam so that we can have multiplayer
        base.camNode.setActive(False)

        # moved player setup out to its own method
        self.setupPlayers(self.numberOfPlayers)

        # Set up shaders for shadows and cartoon outline
        self.setupShaders()

        # Create an audio manager. This is attached to the camera for
        # player 1, so sounds close to other players might not be very
        # loud
        self.audioManager = Audio3DManager.Audio3DManager(self.base.sfxManagerList[0], self.playerCameras[0])
        # Distance should be in m, not feet
        self.audioManager.setDistanceFactor(3.28084)

        # Now initialise audio for all vehicles that were
        # previously set up. We can't just create the audio manager
        # first because we need the player 1 camera
        for vehicle in self.playerVehicles:
            vehicle.initialiseSound(self.audioManager)

        self.initialiseCollisionInfo()

    def run(self):
        """
        Start running the game loop by adding it
        to the task manager
        """

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

    def setupPlayers(self, numberOfPlayers):
        """
        Method to set up player, camera and skybox
        Sets up two player splitscreen
        TODO: Needs reorganising, removal of hardcoding
        """
        self.playerCameras = []
        self.playerVehicles = []
        self.playerControllers = []
        self.playerInputKeys = range(numberOfPlayers)
        # default camera position bound to each car
        cameraPosition = (0, -8, 3)
        vehiclePositions = self.level.spawnPositions
        if numberOfPlayers > len(vehiclePositions):
            raise ValueError(
                "Number of players (%d) requested is greater "
                "than the number of spawn positions (%d)" % (numberOfPlayers, len(vehiclePositions))
            )

        # single player display setup - default
        displayXStart = 0.0
        displayXEnd = 1.0
        displayYStart = 0.0
        displayYEnd = 1.0

        # I am not proud of myself for this... There has to be a better way using maths
        # But it's nearly 2am and I'll figure it out tomorrow
        for i in xrange(numberOfPlayers):
            vehiclePosition = vehiclePositions[i]
            if numberOfPlayers == 2:
                if i == 0:  # player 1, indexes from 0
                    displayXStart = 0.0  # don't need this but it's safer to have it'
                    displayXEnd = 1.0
                    displayYStart = 0.5
                    displayYEnd = 1.0
                else:
                    displayXStart = 0.0  # don't need this but it's safer to have it'
                    displayXEnd = 1.0
                    displayYStart = 0.0
                    displayYEnd = 0.5
            elif numberOfPlayers == 3:
                if i == 0:  # top of screen
                    displayXStart = 0.0  # don't need this but it's safer to have it'
                    displayXEnd = 1.0
                    displayYStart = 0.5
                    displayYEnd = 1.0
                elif i == 1:  # p2, bottom left
                    displayXStart = 0.0
                    displayXEnd = 0.5
                    displayYStart = 0.0
                    displayYEnd = 0.5
                else:  # bottom right
                    displayXStart = 0.5
                    displayXEnd = 1.0
                    displayYStart = 0.0
                    displayYEnd = 0.5
            elif numberOfPlayers == 4:
                if i == 0:  # p1, top left
                    displayXStart = 0.0  # don't need this but it's safer to have it'
                    displayXEnd = 0.5
                    displayYStart = 0.5
                    displayYEnd = 1.0
                elif i == 1:  # p2, top right
                    displayXStart = 0.5
                    displayXEnd = 1.0
                    displayYStart = 0.5
                    displayYEnd = 1.0
                elif i == 2:  # p3, bottom left
                    displayXStart = 0.0
                    displayXEnd = 0.5
                    displayYStart = 0.0
                    displayYEnd = 0.5
                else:  # else p4, bottom right
                    displayXStart = 0.5
                    displayXEnd = 1.0
                    displayYStart = 0.0
                    displayYEnd = 0.5

            # setup display area for this player's camera
            displayBox = (displayXStart, displayXEnd, displayYStart, displayYEnd)
            # set up camera with display area above and default camera position
            camera = self.createCamera(displayBox, cameraPosition)
            self.playerCameras.append(camera)
            # set up player car
            vehicle = Vehicle(vehiclePosition, self.worldRender, self.world, self.base)
            self.playerVehicles.append(vehicle)
            # Create a 2D display region for showing the player's HUD
            playerRender2d = self.createPlayerDisplay(displayBox)
            # set up player controller with car, camera and keyset
            playerController = PlayerControl(
                self.playerVehicles[i], self.playerCameras[i], self.playerInputKeys[i], playerRender2d
            )
            self.playerControllers.append(playerController)
            # set up skybox for this particular camera set and hide from other cameras
            self.createSkybox(
                self.playerCameras[i], self.playerInputKeys[i]
            )  # can use inputkey code for bitmaskCode as it will be unique

    def createPlayerDisplay(self, displayBox):
        """Create a 2D display region with camera to be used to
        show things like the speedo and points
        """

        displayRegion = self.base.win.makeDisplayRegion(*displayBox)
        displayRegion.setSort(20)

        camera2d = NodePath(Camera("player2dcam"))
        lens = OrthographicLens()
        lens.setFilmSize(2, 2)
        lens.setNearFar(-1000, 1000)
        camera2d.node().setLens(lens)

        render2d = NodePath("render2d")
        render2d.setDepthTest(False)
        render2d.setDepthWrite(False)
        camera2d.reparentTo(render2d)
        displayRegion.setCamera(camera2d)

        return render2d

    def windowEventSetup(self):
        """
        Method to bind window events (resizing etc) to windowEventHandler method
        """
        self.base.accept("window-event", self.windowEventHandler)

    def windowEventHandler(self, window=None):
        """ 
        Called when the panda window is modified to update FOV and aspect ratio
        TODO fix hardcoding for camera names
        """
        if window.isClosed():
            sys.exit()

        wp = window.getProperties()
        windowWidth = wp.getXSize()
        windowHeight = wp.getYSize()
        for i in self.playerCameras:  # added to allow for changing player number
            # since window size has changed we need to update the aspect ratio and FOV
            i.node().getLens().setAspectRatio(windowWidth / (windowHeight / 2))
            i.node().getLens().setFov(60)

    def createCamera(self, dispRegion, pos):
        """
        Method to create a camera. Takes displayRegion and a position tuple.
        Sets aspect ratio based on window properties and also sets FOV
        """
        camera = base.makeCamera(base.win, displayRegion=dispRegion)
        windowWidth = base.win.getXSize()
        windowHeight = base.win.getYSize()
        camera.node().getLens().setAspectRatio(windowWidth / (windowHeight / 2))
        camera.node().getLens().setFov(60)
        camera.setPos(pos)
        return camera

    def initialisePhysics(self, debug=False):
        """
        Create Bullet world for physics objects
        """

        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81))
        if debug:
            self.debugNP = self.outsideWorldRender.attachNewNode(BulletDebugNode("Debug"))
            self.debugNP.show()
            self.debugNP.node().showWireframe(True)
            self.debugNP.node().showConstraints(True)
            self.debugNP.node().showBoundingBoxes(False)
            self.debugNP.node().showNormals(True)
            self.world.setDebugNode(self.debugNP.node())

    def createSkybox(self, currentCamera, bitmaskCode):
        """
        Create a skybox linked to the current camera setup. 
        Skybox will only be shown to camera with this bitmaskCode
        TODO: remove bitmaskCode or make it more modular to reduce coupling
        """

        sky = self.loader.loadModel("data/models/sky/cube.egg")
        diffuse = self.loader.loadTexture(self.level.skyTexture)
        sky.setTexture(diffuse)
        sky.setScale(270)
        # Get it to follow the camera so it feels as if it's infinitely
        # far away, but call setCompass so it rotates with the world
        sky.reparentTo(currentCamera)
        sky.setCompass()
        # hide skybox from other players
        sky.hide(BitMask32.allOn())
        # show only to this player's camera
        currentCamera.node().setCameraMask(BitMask32.bit(bitmaskCode))
        sky.show(BitMask32.bit(bitmaskCode))

    def createLights(self):
        """Create an ambient light and a spotlight for shadows"""

        self.render.clearLight()

        alight = AmbientLight("ambientLight")
        alight.setColor(Vec4(0.7, 0.7, 0.7, 1))
        alightNP = self.worldRender.attachNewNode(alight)
        self.worldRender.setLight(alightNP)

        # Create a directional light for shadows
        dlight = DirectionalLight("dLight")
        dlight.setColor(Vec4(0.6, 0.6, 0.6, 1))
        dlight.setShadowCaster(True, 1024, 1024)
        dlight.getLens().setNearFar(1, 15)
        dlight.getLens().setFilmSize(128, 128)
        dlightNP = self.worldRender.attachNewNode(dlight)
        dlightNP.setPos(0, 0, 10)
        dlightNP.lookAt(0, 0, 0)
        self.worldRender.setLight(dlightNP)

    def setupShaders(self):
        """
        Creates shaders for cartoon outline and enables
        shaders for shadows
        """

        if self.base.win.getGsg().getSupportsBasicShaders() == 0:
            return

        thickness = 1.0
        for camera in self.playerCameras:
            self.filters = CommonFilters(self.base.win, camera)
            filterEnabled = self.filters.setCartoonInk(separation=thickness)
            if filterEnabled == False:
                # Couldn't enable filter, video card probably
                # doesn't support filter
                return

        self.worldRender.setShaderAuto()

    def initialiseCollisionInfo(self):
        """
        Sets up information required to later check for collisions
        """

        self.previousContactForce = defaultdict(float)
        self.collisionDetected = defaultdict(bool)

        # List of node paths that we want to check for collisions on,
        # with information about the collision sounds to play
        self.collisionObjects = dict((v.rigidNode, v.collisionSound) for v in self.playerVehicles)
        self.collisionObjects.update(self.level.collisionObjects)

        # For assigning points etc, keep track of the player that
        # controls each vehicle
        self.vehicleControllers = dict(
            (vehicle.rigidNode, player) for vehicle, player in zip(self.playerVehicles, self.playerControllers)
        )

    def checkCollisions(self, dt):
        """
        Check to see what objects have collided and take actions
        Eg. play sounds, update player points
        """

        # Use the change in the sum of contact force magnitudes to
        # check for collisions.

        # Go though contact points, calculating the total contact
        # force on all nodes of interest
        totalContactForce = defaultdict(float)
        for manifold in self.world.getManifolds():
            nodes = (manifold.getNode0(), manifold.getNode1())
            # Sum all points to get total impulse. Not sure if this is a
            # good idea or we should use individual points, and if we
            # need to use force direction rather than just magnitude
            points = manifold.getManifoldPoints()
            totalImpulse = sum((p.getAppliedImpulse() for p in points))
            # Use force to get a more frame-rate independent measure of
            # collision magnitude
            force = totalImpulse / dt
            for node in nodes:
                if node in self.collisionObjects:
                    totalContactForce[node] += force
            # If both objects are vehicles, then update points
            if all(n in self.vehicleControllers for n in nodes):
                self.calculateCollisionPoints(
                    manifold, self.vehicleControllers[nodes[0]], self.vehicleControllers[nodes[1]]
                )

        for node, force in totalContactForce.iteritems():
            forceChange = force - self.previousContactForce[node]
            if self.collisionDetected[node]:
                # If a collision was recently detected, don't keep checking
                # This avoids sounds repeatedly starting to play
                continue
            soundInfo = self.collisionObjects[node]
            if forceChange > soundInfo.thresholdForce:
                self.playCollisionSound(soundInfo, forceChange)
                # Set collision detected, and then set a time out
                # so that it is later reset to False
                self.collisionDetected[node] = True
                self.taskMgr.doMethodLater(
                    0.2, self.collisionDetected.update, "clearColision", extraArgs=[{node: False}]
                )

        # Want to reset anything not touching to zero, so replace
        # previous contact forces with current ones rather than updating
        self.previousContactForce = totalContactForce

    def playCollisionSound(self, soundInfo, magnitude):
        """Play a sound when an object is impacted

        Selects from a list of sounds depending on the collision
        magnitude, and scales the sound volume by the magnitude
        """

        relativeMagnitude = (magnitude - soundInfo.thresholdForce) / (soundInfo.maxForce - soundInfo.thresholdForce)
        soundIndex = min(int(relativeMagnitude * len(soundInfo.sounds)), len(soundInfo.sounds) - 1)
        collisionSound = self.audioManager.loadSfx(soundInfo.sounds[soundIndex])
        self.audioManager.attachSoundToObject(collisionSound, soundInfo.nodePath)
        collisionSound.setVolume(min(0.2 + magnitude / soundInfo.maxForce, 1.0))
        collisionSound.play()

    def calculateCollisionPoints(self, manifold, player1, player2):
        """Calculate points to give players when vehicles collide
        """

        # Todo: Make this actually assign points based on the vehicle
        # travelling towards the collision location
        manifoldPoints = manifold.getManifoldPoints()
        totalImpulse = sum((p.getAppliedImpulse() for p in manifoldPoints))
        player1.add_points(int(totalImpulse) // 100)
        player2.add_points(int(totalImpulse) // 100)

    def gameLoop(self, task):
        dt = self.globalClock.getDt()
        for i in self.playerControllers:  # added to allow for changing player number
            i.updatePlayer(dt)
        self.checkCollisions(dt)
        self.world.doPhysics(dt)

        return task.cont
예제 #28
0
class PandaPhysicsSystem(DelegateByNetmode, SignalListener):
    subclasses = {}

    def __init__(self):
        self.register_signals()

        self.world = BulletWorld()
        self.world.setGravity((0, 0, -9.81))

        # # Seems that this does not function
        # on_contact_added = PythonCallbackObject(self._on_contact_added)
        # self.world.set_contact_added_callback(on_contact_added)

        # on_filter = PythonCallbackObject(self._filter_collision)
        # self.world.set_filter_callback(on_filter)

        self.listener = DirectObject()
        self.listener.accept('bullet-contact-added', self._on_contact_added)
        self.listener.accept('bullet-contact-destroyed', self._on_contact_removed)

        debug_node = BulletDebugNode('Debug')
        debug_node.showWireframe(True)
        debug_node.showConstraints(True)
        debug_node.showBoundingBoxes(False)
        debug_node.showNormals(False)

        self.debug_nodepath = render.attachNewNode(debug_node)
        self.world.set_debug_node(debug_node)

        self.tracked_contacts = defaultdict(int)
        self.existing_collisions = set()

    def _create_contacts_from_result(self, requesting_node, contact_result):
        """Return collision contacts between two nodes"""
        contacts = []

        for contact in contact_result.get_contacts():
            if contact.get_node0() == requesting_node:
                manifold = contact.get_manifold_point()

                position = manifold.get_position_world_on_a()
                normal = -manifold.get_normal_world_on_b()

            elif contact.get_node1() == requesting_node:
                manifold = contact.get_manifold_point()

                position = manifold.get_position_world_on_b()
                normal = manifold.get_normal_world_on_b()

            impulse = manifold.get_applied_impulse()
            contact_ = CollisionContact(position, normal, impulse)
            contacts.append(contact_)

        return contacts

    def _on_contact_removed(self, node_a, node_b):
        self.tracked_contacts[(node_a, node_b)] -= 1

    def _on_contact_added(self, node_a, node_b):
        self.tracked_contacts[(node_a, node_b)] += 1

    def _filter_collision(self, filter_data):
        filter_data.set_collide(True)

    @RegisterPhysicsNode.on_global
    def register_node(self, node):
        self.world.attachRigidBody(node)
        node.set_python_tag("world", self.world)

    @DeregisterPhysicsNode.on_global
    def deregister_node(self, node):
        self.world.removeRigidBody(node)
        node.clear_python_tag("world")

    def dispatch_collisions(self):
        # Dispatch collisions
        existing_collisions = self.existing_collisions
        for pair, contact_count in self.tracked_contacts.items():
            if contact_count > 0 and pair not in existing_collisions:
                existing_collisions.add(pair)

                # Dispatch collision
                node_a, node_b = pair

                entity_a = entity_from_nodepath(node_a)
                entity_b = entity_from_nodepath(node_b)

                contact_result = None

                if entity_a is not None:
                    def contact_getter():
                        nonlocal contact_result
                        if contact_result is None:
                            contact_result = self.world.contact_test_pair(node_a, node_b)

                        return self._create_contacts_from_result(node_a, contact_result)

                    collision_result = LazyCollisionResult(entity_b, CollisionState.started, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_a)

                if entity_b is not None:
                    def contact_getter():
                        nonlocal contact_result
                        if contact_result is None:
                            contact_result = self.world.contact_test_pair(node_a, node_b)

                        return self._create_contacts_from_result(node_b, contact_result)

                    collision_result = LazyCollisionResult(entity_a, CollisionState.started, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_b)

            elif contact_count == 0 and pair in existing_collisions:
                existing_collisions.remove(pair)

                # Dispatch collision
                node_a, node_b = pair

                entity_a = entity_from_nodepath(node_a)
                entity_b = entity_from_nodepath(node_b)

                # Don't send contacts for ended collisions
                contact_getter = lambda: None

                if entity_a is not None:
                    collision_result = LazyCollisionResult(entity_b, CollisionState.ended, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_a)

                if entity_b is not None:
                    collision_result = LazyCollisionResult(entity_a, CollisionState.ended, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_b)

    def update(self, delta_time):
        self.world.doPhysics(delta_time)
        self.dispatch_collisions()
class SMWorld(DirectObject):

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Constructor
    # (Game state, Map name, Height of death plane)
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def __init__(self, mapID, tObj, aObj):

        self.mapID = mapID

        # EX: maps/map-1/map-1.yetimap
        metaFile = open(
            "../maps/map" + str(self.mapID) + "/map" + str(self.mapID) +
            ".yetimap", 'r')
        metaLines = metaFile.readlines()
        lineCount = len(metaLines)
        self.snowflakeCount = lineCount - 2
        self.snowCount = 0

        # First Line: Player's starting position
        # EX: 50,50,50 (NO SPACES)
        playerLine = metaLines[0]
        playerPosList = playerLine.split(",")
        playerInitX = int(playerPosList[0])
        playerInitY = int(playerPosList[1])
        playerInitZ = int(playerPosList[2])
        self.playerStart = Point3(playerInitX, playerInitY, playerInitZ)

        # 2nd Line: Deathzone Height
        # ONE INTEGER
        self.deathHeight = int(metaLines[1])

        # Get dem snowflakes
        self.snowflakePositions = []
        print("Snowflake Count: " + str(self.snowflakeCount))
        for i in xrange(0, self.snowflakeCount):
            sfline = metaLines[i + 2]
            sfList = sfline.split(",")
            sfx = int(sfList[0])
            sfy = int(sfList[1])
            sfz = int(sfList[2])
            self.snowflakePositions.append(Point3(sfx, sfy, sfz))
            print("New snowflake to add: (" + str(sfx) + "," + str(sfy) + "," +
                  str(sfz) + ")")

        #load in controls
        ctrlFl = open("ctrConfig.txt")
        #will skip n lines where [n,]
        #makes a list of controls
        self.keymap = eval(ctrlFl.read())
        #close file
        ctrlFl.close()

        # Create new instances of our various objects
        self.mapName = str(mapID)
        self.audioMgr = aObj
        self.worldObj = self.setupWorld()
        self.heightMap = self.setupHeightmap(self.mapName)
        self.deathZone = self.setupDeathzone(self.deathHeight)
        self.debugNode = self.setupDebug()

        # Player Init
        self.playerObj = SMPlayer(self.worldBullet, self.worldObj, self,
                                  self.playerStart, self.audioMgr)
        self.playerNP = self.playerObj.getNodePath()
        self.playerNP.setH(180)
        self.canUseShift = True
        self.canAirDash = True

        # Snowball Init
        self.ballObj = SMBall(self.worldBullet, self.worldObj, self.playerObj,
                              self.playerNP)
        self.sbCollideFlag = False
        self.ballNP = self.ballObj.getNodePath()

        # Key Handler
        self.kh = SMKeyHandler()
        self.lastMousePos = self.kh.getMouse()

        # Collision Handler
        self.colObj = self.setupCollisionHandler()

        # Lighting
        self.ligObj = SMLighting(Vec4(.4, .4, .4, 1), Vec3(-5, -5, -5),
                                 Vec4(2.0, 2.0, 2.0, 1.0))

        # Camera
        self.camObj = SMCamera(self.playerObj, self.worldBullet, self.worldObj)
        self.cameraControl = False

        # GUI
        self.GUI = SMGUI()
        self.snowflakeCounter = SMGUICounter(
            "snowflake",
            self.snowflakeCount)  # Replace 3 with # of snowflakes in level.
        self.snowMeter = SMGUIMeter(100)
        self.GUI.addElement("snowflake", self.snowflakeCounter)
        self.GUI.addElement("snowMeter", self.snowMeter)

        #Snowy Outside
        # base.enableParticles()
        # self.p = ParticleEffect()
        # self.p.cleanup()
        # self.p = ParticleEffect()
        # self.p.loadConfig('snow.ptf')
        # self.p.start(self.camObj.getNodePath())
        # self.p.setPos(0.00, 0.500, 0.000)

        # AI
        # self.goat1 = SMAI("../res/models/goat.egg", 75.0, self.worldBullet, self.worldObj, -70, -95, 5)
        # self.goat1.setBehavior("flee", self.playerNP)
        # self.goat2 = SMAI("../res/models/goat.egg", 75.0, self.worldBullet, self.worldObj, -80, -83, 5)
        # self.goat2.setBehavior("flee", self.playerNP)
        # print("AI Initialized")

        # Debug Text
        self.textObj = tObj
        self.textObj.addText("yetiPos", "Position: ")
        self.textObj.addText("yetiVel", "Velocity: ")
        self.textObj.addText("yetiFric", "Friction: ")
        self.textObj.addText("onIce", "Ice(%): ")
        self.textObj.addText("onSnow", "Snow(%): ")
        self.textObj.addText("terrHeight", "T Height: ")
        self.textObj.addText("terrSteepness", "Steepness: ")

        # Pause screen transition
        self.transition = Transitions(loader)

        # Method-based keybindings
        # self.accept('b', self.spawnBall)
        self.accept('escape', base.userExit)
        self.accept('enter', self.pauseUnpause)
        self.accept('f1', self.toggleDebug)

        self.accept('lshift-up', self.enableShiftActions)
        self.accept('mouse1', self.enableCameraControl)
        self.accept('mouse1-up', self.disableCameraControl)
        self.accept('wheel_up', self.camObj.zoomIn)
        self.accept('wheel_down', self.camObj.zoomOut)

        self.pauseUnpause()

        # Disable the mouse
        base.disableMouse()
        props = WindowProperties()
        props.setCursorHidden(True)
        base.win.requestProperties(props)

        # Uncomment this to see everything being rendered.
        self.printSceneGraph()

        # Play the BGM
        self.audioMgr.playBGM("snowmanWind")

        # Skybox formed
        skybox = loader.loadModel("../res/models/skybox.egg")
        # skybox.set_two_sided(true)
        skybox.setScale(500)
        skybox.setPos(0, 0, -450)
        skybox.reparentTo(render)

        mountain = loader.loadModel("../res/models/mountain.egg")
        mountain.reparentTo(render)
        mountain.setPos(650, 800, 20)
        mountain.setScale(120)

        self.colObjects = []

        self.caveNew = SMCollide("../res/models/cave_new.egg",
                                 self.worldBullet, self.worldObj,
                                 Point3(-50, 95, -13), 11, Vec3(0, 0, 0))
        self.colObjects.append(self.caveNew)

        self.planeFront = SMCollide("../res/models/plane_front",
                                    self.worldBullet, self.worldObj,
                                    Point3(190, -100,
                                           -15), 8, Vec3(190, 0, 30))
        self.colObjects.append(self.planeFront)

        self.caveModel = SMCollide("../res/models/cave_tunnel.egg",
                                   self.worldBullet, self.worldObj,
                                   Point3(233, 68, 32), 4, Vec3(135, 180, 0))
        self.colObjects.append(self.caveModel)

        self.planeTail = SMCollide("../res/models/plane_tail.egg",
                                   self.worldBullet, self.worldObj,
                                   Point3(-40, -130, -7), 10, Vec3(230, 0, 0))
        self.colObjects.append(self.planeTail)

        self.ropeBridge = SMCollide("../res/models/rope_bridge.egg",
                                    self.worldBullet, self.worldObj,
                                    Point3(180, 115, 30), 6, Vec3(50, 0, 0))
        self.colObjects.append(self.ropeBridge)

        self.colObjectCount = len(self.colObjects)

        print("World initialized.")

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Enables the camera to be rotated by moving the mouse horizontally.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def enableCameraControl(self):
        self.cameraControl = True

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Disables the camera control.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def disableCameraControl(self):
        self.cameraControl = False

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Enables the use of shift actions again.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def enableShiftActions(self):
        self.canUseShift = True

    def disableShiftActions(self):
        self.canUseShift = False

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Respawns the yeti's snowball.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def spawnBall(self):
        if (not (self.playerObj.getAirborneFlag())):
            self.ballObj.respawn()

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Toggles the pause screen
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def pauseUnpause(self):
        if taskMgr.hasTaskNamed('UpdateTask'):
            taskMgr.remove('UpdateTask')
            self.transition.fadeScreen(0.5)
        else:
            taskMgr.add(self.update, 'UpdateTask')
            self.transition.noFade()

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Sets up the world and returns a NodePath of the BulletWorld
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def setupWorld(self):
        self.worldBullet = BulletWorld()
        self.worldBullet.setGravity(Vec3(0, 0, -GRAVITY))
        self.terrSteepness = -1
        wNP = render.attachNewNode('WorldNode')

        self.audioMgr.loadSFX("snowCrunch01")
        self.audioMgr.loadBGM("snowmanWind")

        return wNP

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Prints all nodes that are a child of render.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def printSceneGraph(self):
        print(render.ls())

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Initializes and returns a DebugNode NodePath.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def setupDebug(self):
        debug = BulletDebugNode()
        debug.showWireframe(
            False
        )  # Yeah, don't set this to true unless you want to emulate an 80's computer running Crysis on Ultra settings.
        debug.showConstraints(True)
        debug.showBoundingBoxes(True)  # This is the main use I have for it.
        debug.showNormals(True)
        debugNP = render.attachNewNode(debug)
        self.worldBullet.setDebugNode(debugNP.node())
        debugNP.hide()
        return debugNP

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Initializes and returns a BulletRigidBodyNode of the terrain, which loads the map with the specified name.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def setupHeightmap(self, name):

        # Automatically generate a heightmap mesh from a monochrome image.
        self.hmHeight = 120
        hmPath = "../maps/map" + name + "/map" + name + "-h.png"
        imPath = "../maps/map" + name + "/map" + name + "-i.png"
        smPath = "../maps/map" + name + "/map" + name + "-s.png"
        scmPath = "../maps/map" + name + "/map" + name + "-sc.png"
        print(hmPath)
        print(imPath)
        print(smPath)
        print(scmPath)
        hmImg = PNMImage(Filename(hmPath))
        hmShape = BulletHeightfieldShape(hmImg, self.hmHeight, ZUp)
        hmNode = BulletRigidBodyNode('Terrain')
        hmNode.addShape(hmShape)
        hmNode.setMass(0)
        self.hmNP = render.attachNewNode(hmNode)
        self.worldBullet.attachRigidBody(hmNode)
        self.hmOffset = hmImg.getXSize() / 2.0 - 0.5
        self.hmTerrain = GeoMipTerrain('gmTerrain')
        self.hmTerrain.setHeightfield(hmImg)

        # Optimizations and fixes
        self.hmTerrain.setBruteforce(
            True)  # I don't think this is actually needed.
        self.hmTerrain.setMinLevel(3)  # THIS is what triangulates the terrain.
        self.hmTerrain.setBlockSize(
            128)  # This does a pretty good job of raising FPS.
        # Level-of-detail (not yet working)
        # self.hmTerrain.setNear(40)
        # self.hmTerrain.setFar(200)

        self.hmTerrain.generate()

        self.hmTerrainNP = self.hmTerrain.getRoot()
        self.hmTerrainNP.setSz(self.hmHeight)
        self.hmTerrainNP.setPos(-self.hmOffset, -self.hmOffset,
                                -self.hmHeight / 2.0)
        self.hmTerrainNP.flattenStrong(
        )  # This only reduces the number of nodes; nothing to do with polys.
        self.hmTerrainNP.analyze()

        # Here begins the scenery mapping
        treeModel = loader.loadModel("../res/models/tree_1.egg")
        rockModel = loader.loadModel("../res/models/rock_1.egg")
        rock2Model = loader.loadModel("../res/models/rock_2.egg")
        rock3Model = loader.loadModel("../res/models/rock_3.egg")
        # caveModel = loader.loadModel("../res/models/cave_new.egg")
        # planeFrontModel = loader.loadModel("../res/models/plane_front.egg")
        # planeWingModel = loader.loadModel("../res/models/plane_wing.egg")
        texpk = loader.loadTexture(scmPath).peek()

        # GameObject nodepath for flattening
        self.objNP = render.attachNewNode("gameObjects")
        self.treeNP = self.objNP.attachNewNode("goTrees")
        self.rockNP = self.objNP.attachNewNode("goRocks")
        self.rock2NP = self.objNP.attachNewNode("goRocks2")
        self.rock3NP = self.objNP.attachNewNode("goRocks3")
        # self.caveNP = self.objNP.attachNewNode("goCave")
        # self.planeFrontNP = self.objNP.attachNewNode("goPlaneFront")
        # self.planeWingNP = self.objNP.attachNewNode("goPlaneWing")

        for i in range(0, texpk.getXSize()):
            for j in range(0, texpk.getYSize()):
                color = VBase4(0, 0, 0, 0)
                texpk.lookup(color,
                             float(i) / texpk.getXSize(),
                             float(j) / texpk.getYSize())
                if (int(color.getX() * 255.0) == 255.0):
                    newTree = self.treeNP.attachNewNode("treeNode")
                    treeModel.instanceTo(newTree)
                    newTree.setPos(
                        i - texpk.getXSize() / 2, j - texpk.getYSize() / 2,
                        self.hmTerrain.get_elevation(i, j) * self.hmHeight -
                        self.hmHeight / 2)
                    # newTree.setScale(randint(0,4))
                    newTree.setScale(2)

                if (int(color.getX() * 255.0) == 128):
                    newRock = self.rockNP.attachNewNode("newRock")
                    newRock.setPos(
                        i - texpk.getXSize() / 2, j - texpk.getYSize() / 2,
                        self.hmTerrain.get_elevation(i, j) * self.hmHeight -
                        self.hmHeight / 2)
                    rockModel.instanceTo(newRock)

                if (int(color.getX() * 255.0) == 77):
                    newRock2 = self.rock2NP.attachNewNode("newRock2")
                    newRock2.setPos(
                        i - texpk.getXSize() / 2, j - texpk.getYSize() / 2,
                        self.hmTerrain.get_elevation(i, j) * self.hmHeight -
                        self.hmHeight / 2)
                    rock2Model.instanceTo(newRock2)

                if (int(color.getX() * 255.0) == 102):
                    newRock3 = self.rock3NP.attachNewNode("newRock3")
                    newRock3.setPos(
                        i - texpk.getXSize() / 2, j - texpk.getYSize() / 2,
                        self.hmTerrain.get_elevation(i, j) * self.hmHeight -
                        self.hmHeight / 2)
                    rock3Model.instanceTo(newRock3)

                # if(int(color.getX() * 255.0) == 64):
                # newCave = self.caveNP.attachNewNode("newCave")
                # newCave.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
                # newCave.setScale(5)
                # newCave.setP(180)
                # caveModel.instanceTo(newCave)

                # if(int(color.getX() * 255.0) == 191):
                # newPlaneFront = self.planeFrontNP.attachNewNode("newPlaneFront")
                # newPlaneFront.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
                # newPlaneFront.setScale(6)
                # planeFrontModel.instanceTo(newPlaneFront)

                # if(int(color.getX() * 255.0) == 179):
                # newPlaneWing = self.planeWingNP.attachNewNode("newPlaneWing")
                # newPlaneWing.setPos(i - texpk.getXSize() / 2, j - texpk.getYSize() / 2, self.hmTerrain.get_elevation(i, j) * self.hmHeight - self.hmHeight / 2)
                # newPlaneWing.setScale(6)
                # newPlaneWing.setH(250)
                # newPlaneWing.setR(180)
                # newPlaneWing.setP(135)
                # planeWingModel.instanceTo(newPlaneWing)

        self.snowflakes = []

        for i in xrange(0, self.snowflakeCount):
            print("Call " + str(i))
            sf = SMCollect(self.worldBullet, self.worldObj,
                           self.snowflakePositions[i])
            self.snowflakes.append(sf)

        # render.flattenStrong()
        self.hmTerrainNP.reparentTo(render)

        # Here begins the attribute mapping
        ts = TextureStage("stage-alpha")
        ts.setSort(0)
        ts.setPriority(1)
        ts.setMode(TextureStage.MReplace)
        ts.setSavedResult(True)
        self.hmTerrainNP.setTexture(ts, loader.loadTexture(imPath, smPath))

        ts = TextureStage("stage-stone")
        ts.setSort(1)
        ts.setPriority(1)
        ts.setMode(TextureStage.MReplace)
        self.hmTerrainNP.setTexture(
            ts, loader.loadTexture("../res/textures/stone_tex.png"))
        self.hmTerrainNP.setTexScale(ts, 32, 32)

        ts = TextureStage("stage-ice")
        ts.setSort(2)
        ts.setPriority(1)
        ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSTexture,
                         TextureStage.COSrcColor, TextureStage.CSPrevious,
                         TextureStage.COSrcColor,
                         TextureStage.CSLastSavedResult,
                         TextureStage.COSrcColor)
        self.hmTerrainNP.setTexture(
            ts, loader.loadTexture("../res/textures/ice_tex.png"))
        self.hmTerrainNP.setTexScale(ts, 32, 32)

        ts = TextureStage("stage-snow")
        ts.setSort(3)
        ts.setPriority(0)
        ts.setCombineRgb(TextureStage.CMInterpolate, TextureStage.CSTexture,
                         TextureStage.COSrcColor, TextureStage.CSPrevious,
                         TextureStage.COSrcColor,
                         TextureStage.CSLastSavedResult,
                         TextureStage.COSrcAlpha)
        self.hmTerrainNP.setTexture(
            ts, loader.loadTexture("../res/textures/snow_tex_1.png"))
        self.hmTerrainNP.setTexScale(ts, 32, 32)

        # print(self.snowflakes)

        return hmNode

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Sets up and returns the death zone plane (returns its NodePath) with the specified height.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def setupDeathzone(self, height):
        planeShape = BulletPlaneShape(Vec3(0, 0, 1), 1)
        planeNode = BulletRigidBodyNode('DeathZone')
        planeNode.addShape(planeShape)
        planeNP = render.attachNewNode(planeNode)
        planeNP.setPos(0, 0, height)
        self.worldBullet.attachRigidBody(planeNode)
        return planeNP

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Sets up and returns the collision handler.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def setupCollisionHandler(self):
        colHand = SMCollisionHandler(self.worldBullet)
        return colHand

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Toggles showing bounding boxes.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

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

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Returns the terrain height of the nearest vertical descending raycast from the passed Point3.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def getTerrainHeight(self, pos):
        result = 0
        x = pos.getX()
        y = pos.getY()
        z = pos.getZ()
        rayTerrA = Point3(x, y, z)
        rayTerrB = Point3(x, y, z - 256)
        rayTest = self.worldBullet.rayTestClosest(rayTerrA, rayTerrB)

        rayNode = rayTest.getNode()
        if (rayTest.hasHit()):
            rayPos = rayTest.getHitPos()
            result = rayPos.getZ()
        else:
            self.playerObj.respawn()
        return result
        # return self.hmTerrain.get_elevation(x + self.hmOffset, y + self.hmOffset) * self.hmHeight

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Handles player movement
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def playerMove(self):

        # Go through the collision and flag tests, and update them
        self.doPlayerTests()

        # Rotation and camera movement
        if self.kh.poll(self.keymap['Left']):
            self.playerObj.turn(True)
        elif self.kh.poll(self.keymap['Right']):
            self.playerObj.turn(False)
        elif (self.cameraControl):
            newMousePos = self.kh.getMouse()
            mx = newMousePos.getX()
            self.camObj.rotateCamera(mx)

        self.camObj.calculatePosition()

        # Movement
        if self.kh.poll(self.keymap['Forward']):
            self.playerObj.move(True)
            self.camObj.rotateTowards(90)
        elif self.kh.poll(self.keymap['Back']):

            self.playerObj.move(False)
        else:
            self.playerObj.stop()

        # Jump
        if (self.kh.poll(self.keymap['Space']) and self.terrSteepness <
                0.25):  #and not(self.ballObj.isRolling())):
            self.playerObj.jump()
        else:
            self.playerObj.resetJump()

        # Air Dash
        if (
                self.kh.poll(self.keymap['airDash'])
        ):  #and self.playerObj.getAirborneFlag() == True and self.canAirDash == True):
            self.canAirDash = False
            self.playerObj.airDash()

        # Shift-based actions
        if (self.kh.poll("lshift") and not (self.sbCollideFlag)
                and not (self.playerObj.getAirborneFlag())
                and self.canUseShift):

            # If there's another snowball already placed
            if (self.ballObj.exists() and not (self.ballObj.isRolling())):
                self.ballObj.respawn()

            # If we're rolling a snowball
            elif (self.ballObj.isRolling()):

                # Absorb snowball
                if (self.kh.poll("v")):
                    self.canUseShift = False
                    snowAmt = self.ballObj.getSnowAmount()
                    self.playerObj.addSnow(snowAmt)
                    # self.snowMeter.fillBy(snowAmt)
                    self.ballObj.destroy()

                # Go to iceball throwing mode
                elif (self.kh.poll("b")):
                    print("TODO: Ice ball throwing mode.")

                # Grow the snowball
                elif (self.kh.poll("w")):
                    self.ballObj.grow()

            # Spawn a new snowball
            elif (self.ballObj.exists() == False):
                self.ballObj.respawn()

        # If the player is not pressing shift
        else:
            if (self.ballObj.isRolling()):
                self.ballObj.dropBall()

        base.win.movePointer(0, 400, 300)

        # So updating the stats is VERY expensive.
        if (self.debugNode.isHidden() == False):
            self.updateStats()

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Various tests concerning the player flags and collisions.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def doPlayerTests(self):

        # Player's position
        plPos = self.playerObj.getPosition()
        px = plPos.getX()
        py = plPos.getY()
        pz = plPos.getZ()

        # Raycast directly down for terrain steepness
        rayYetiA = Point3(px, py, pz)
        rayYetiB = Point3(px, py, pz - 300)
        self.downRayTest = self.worldBullet.rayTestClosest(
            rayYetiA, rayYetiB).getHitNormal()
        rx = self.downRayTest.getX()
        ry = self.downRayTest.getY()
        rz = self.downRayTest.getZ()
        self.terrSteepness = 1.0 - rz

        # Redo collision flags later
        objCollisionFlag = False

        # Snow/Ice height adjust
        self.playerObj.updateTerrain()

        # Collision: Player x Objects
        for i in xrange(0, self.colObjectCount):
            if (self.colObj.didCollide(self.playerNP.node(),
                                       self.colObjects[i].AINode)):
                objCollisionFlag = True
                self.playerObj.setAirborneFlag(False)
                self.canAirDash = True
                self.playerObj.setFactor(1, 1, 1)

        # Collision: Player x Snowball
        if (self.ballObj.exists() and self.colObj.didCollide(
                self.playerNP.node(), self.ballObj.getRigidbody())):
            self.sbCollideFlag = True
            self.playerObj.setAirborneFlag(False)
            self.playerObj.setFactor(1, 1, 1)
        else:
            self.sbCollideFlag = False

        # Collision: Player x Terrain
        if (self.colObj.didCollide(self.playerNP.node(), self.heightMap)):
            if (self.playerObj.getAirborneFlag()):
                self.audioMgr.playSFX("snowCrunch01")
            self.playerObj.setAirborneFlag(False)
            self.canAirDash = True
            self.playerObj.setFactor(1, 1, 1)
            objCollisionFlag = False

        # Collision: Player x Death Zone
        # if(pz - 7 <= self.deathHeight or (self.colObj.didCollide(self.playerNP.node(), self.deathZone.node()))):
        if (self.colObj.didCollide(self.playerNP.node(),
                                   self.deathZone.node())):
            print("Player confirmed #REKT")
            self.playerObj.respawn()

        # Out of bounds checking
        if (abs(px) > 254 or abs(py) > 254):
            print("Player out of bounds!")
            self.playerObj.respawn()

        # Snap to terrain if... something. I need to restructure this. Don't read it.
        if (not (self.playerObj.getAirborneFlag()) and not (self.sbCollideFlag)
                and not (objCollisionFlag)):
            z = self.getTerrainHeight(Point3(px, py, pz))
            self.playerObj.snapToTerrain(z)
            # self.playerObj.snapToTerrain(th, self.hmHeight)

        # Collision: Player x Snowflakes
        for i in xrange(0, self.snowflakeCount):
            if (self.snowflakes[i].exists() and self.colObj.didCollide(
                    self.playerNP.node(), self.snowflakes[i].getNode())):
                self.snowflakes[i].destroy()
                self.snowflakeCounter.increment()
                self.snowCount += 1

        self.snowMeter.updateSnow(self.playerObj)

        #Check if there is a "next" level. If there is, load it. Otherwise display end game screen.
        if (self.snowCount >= self.snowflakeCount):
            file_path = "../maps/map" + str(self.mapID +
                                            1) + "/map" + str(self.mapID +
                                                              1) + ".yetimap"
            if os.path.lexists(file_path):

                self.snowCount = 0
                self.snowflakeCount = 0
                self.snowflakeCounter.setValue(0)
                self.snowflakeCounter.setState(2)

                #Loading Screen
                self.transition.fadeScreen(0.7)
                self.loadingText = OnscreenText("Loading...",
                                                1,
                                                fg=(1, 1, 1, 0),
                                                pos=(0, 0),
                                                align=TextNode.ACenter,
                                                scale=.07,
                                                mayChange=1)
                base.graphicsEngine.renderFrame()
                base.graphicsEngine.renderFrame()
                base.graphicsEngine.renderFrame()
                base.graphicsEngine.renderFrame()
                self.transition.noFade()

                #destroy objects
                self.worldBullet.removeRigidBody(self.heightMap)
                self.hmTerrainNP.removeNode()
                self.objNP.removeNode()
                self.treeNP.removeNode()
                self.rockNP.removeNode()
                self.rock2NP.removeNode()
                self.rock3NP.removeNode()
                # self.caveNP.removeNode()
                # self.planeFrontNP.removeNode()
                # self.planeWingNP.removeNode()
                self.hmNP.removeNode()
                if (int(self.mapID) == 1):
                    self.ropeBridge.AIChar.setPos(-200, -300, -200)
                    # self.ropeBridge.AIChar.removeNode()
                    self.planeFront.AIChar.removeNode()
                    self.planeTail.AIChar.setPos(-200, -200, -200)
                    # self.planeTail.AIChar.removeNode()
                    self.caveNew.AIChar.setPos(-1000, -1000, -1000)
                    self.caveModel.AIChar.removeNode()
                    #Added More Props here!
                    self.boulder = SMCollide("../res/models/rock_3.egg",
                                             self.worldBullet, self.worldObj,
                                             Point3(117, 123, 17), 15,
                                             Vec3(0, 0, 0))
                elif (int(self.mapID) == 2):
                    self.boulder.AIChar.setPos(-222, -222, -222)
                    self.caveNew.AIChar.setScale(150)
                    self.caveNew.AIChar.setPos(-50, 95, -50)
                    # self.skybox.setScale(600)
                    # self.caveNew.setH(0)
                    # self.boulder.removeNode()

                self.mapID += 1
                print self.mapID
                # EX: maps/map-1/map-1.yetimap
                metaFile = open(
                    "../maps/map" + str(self.mapID) + "/map" +
                    str(self.mapID) + ".yetimap", 'r')
                metaLines = metaFile.readlines()
                lineCount = len(metaLines)
                self.snowflakeCount = lineCount - 2

                # First Line: Player's starting position
                # EX: 50,50,50 (NO SPACES)
                playerLine = metaLines[0]
                playerPosList = playerLine.split(",")
                playerInitX = int(playerPosList[0])
                playerInitY = int(playerPosList[1])
                playerInitZ = int(playerPosList[2])
                self.playerObj.playerNP.setPos(playerInitX, playerInitY,
                                               playerInitZ)
                self.playerObj.startX = playerInitX
                self.playerObj.startY = playerInitY
                self.playerObj.startZ = playerInitZ

                # 2nd Line: Deathzone Height
                # ONE INTEGER
                self.deathHeight = int(metaLines[1])

                self.snowflakePositions = []
                print("Snowflake Count: " + str(self.snowflakeCount))
                for i in xrange(0, self.snowflakeCount):
                    sfline = metaLines[i + 2]
                    sfList = sfline.split(",")
                    sfx = int(sfList[0])
                    sfy = int(sfList[1])
                    sfz = int(sfList[2])
                    self.snowflakePositions.append(Point3(sfx, sfy, sfz))
                    print("New snowflake to add: (" + str(sfx) + "," +
                          str(sfy) + "," + str(sfz) + ")")
                self.snowflakeCounter.setMaxValue(self.snowflakeCount)

                #load new map
                self.mapName = str(self.mapID)
                self.heightMap = self.setupHeightmap(self.mapName)
                self.deathZone = self.setupDeathzone(self.deathHeight)

                self.loadingText.cleanup()
            else:
                taskMgr.remove('UpdateTask')
                self.endImage = OnscreenImage(
                    image="../res/icons/endgame1.png",
                    pos=(0.0, 0.0, 0.0),
                    scale=(1.35, 2, 1))

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Update the debug text.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def updateStats(self):
        pos = self.playerObj.getPosition()
        x = pos.getX()
        y = pos.getY()
        z = pos.getZ()
        vel = self.playerObj.getVelocity()
        vx = str(round(vel.getX(), 1))
        vy = str(round(vel.getY(), 1))
        vz = str(round(vel.getZ(), 1))
        sx = str(round(x, 1))
        sy = str(round(y, 1))
        sz = str(round(z, 1))
        rx = str(round(self.downRayTest.getX(), 2))
        ry = str(round(self.downRayTest.getY(), 2))
        rz = str(round(self.terrSteepness, 2))
        fric = str(round(self.playerObj.getFriction(), 2))
        ip = str(round(self.playerObj.getIceCoefficient(), 2))
        sp = str(round(self.playerObj.getSnowCoefficient(), 2))
        tHeight = str(round(self.getTerrainHeight(Point3(x, y, z)), 1))
        self.textObj.editText("yetiPos",
                              "Position: (" + sx + ", " + sy + ", " + sz + ")")
        self.textObj.editText("yetiVel",
                              "Velocity: (" + vx + ", " + vy + ", " + vz + ")")
        self.textObj.editText("yetiFric", "Friction: " + fric)
        self.textObj.editText("onIce", "Ice(%): " + ip)
        self.textObj.editText("onSnow", "Snow(%): " + sp)
        self.textObj.editText("terrHeight", "T Height: " + tHeight)
        self.textObj.editText("terrSteepness", "Steepness: " + rz)

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # throw Snowball
    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    def throw(self):
        self.throwing = True
        size = self.ballObj.getSize()
        #zoom camera and grab pos you wish to throw
        self.camObj.aimMode()
        taskMgr.add(self.controlCamera, "camera-task")
        rotation = self.camObj.getH()
        pitch = self.camObj.getP()
        self.ballObj.throwBall(size, pitch, rotation)
        #fix camera
        #self.throwing = False

    #------------------------------------------------------------------------------------------------------------------------------------------------------------
    # Update the world. Called every frame.
    #------------------------------------------------------------------------------------------------------------------------------------------------------------

    def update(self, task):
        dt = globalClock.getDt()
        self.worldBullet.doPhysics(dt)
        # self.goat1.AIUpdate()
        # self.goat2.AIUpdate()
        self.playerMove()
        return task.cont
예제 #30
0
class PandaUtil:
    def __init__(self,*args,**kw):
        self.solver="bullet"
        if "solver" in kw :
            self.solver = kw["solver"]
        self.rb_func_dic={"bullet":{
            "SingleSphere":self.addSingleSphereRB,
            "SingleCube":self.addSingleCubeRB,
            "MultiSphere":self.addMultiSphereRB,
            "MultiCylinder":self.addMultiCylinderRB,
            "Mesh":self.addMeshRB,
            },
            "ode":{
            "SingleSphere":self.addSingleSphereRBODE,
#            "SingleCube":self.addSingleCubeRBODE,
#            "MultiSphere":self.addMultiSphereRBODE,
#            "MultiCylinder":self.addMultiCylinderRBODE,
#            "Mesh":self.addMeshRBODE,
            },
            }
    def setup(self):
        if self.solver == "bullet":
            self.setupPanda()
        elif self.solver == "ode" :
            self.setupODE()

    def setupODE(self,*args,**kw):
        if self.world is None :
            if panda3d is None :
                return
            from panda3d.core import loadPrcFileData            
            loadPrcFileData("", "window-type none" ) 
            # Make sure we don't need a graphics engine 
            #(Will also prevent X errors / Display errors when starting on linux without X server)
            loadPrcFileData("", "audio-library-name null" ) # Prevent ALSA errors 
#            loadPrcFileData('', 'bullet-enable-contact-events true')
#            loadPrcFileData('', 'bullet-max-objects 50')#10240
            
            import direct.directbase.DirectStart 
#            bullet.bullet-max-objects = 1024 * 10#sum of all predicted n Ingredient ?
#            self.worldNP = render.attachNewNode('World')            
            self.world = OdeWorld()
            self.world.setGravity(Vec3(0, 0, 0))
            self.static=[]
            self.moving = None
            self.rb_panda = []
            return self.world

    def addSingleSphereRBODE()  :
        pass          
    def setupPanda(self,*args,**kw):
        if panda3d is None :
            return
        from panda3d.core import loadPrcFileData
        
        loadPrcFileData("", "window-type none" ) 
        # Make sure we don't need a graphics engine 
        #(Will also prevent X errors / Display errors when starting on linux without X server)
        loadPrcFileData("", "audio-library-name null" ) # Prevent ALSA errors 
        loadPrcFileData('', 'bullet-max-objects 100240')#what number here ?
        import direct.directbase.DirectStart
        self.scale  = 10.0   
        self.worldNP = render.attachNewNode('World')            
        self.world = BulletWorld()
        if "gravity" in kw and kw["gravity"]:
            self.world.setGravity(Vec3(0, -9.81, 0))
        else :
            self.world.setGravity(Vec3(0, 0, 0))
        self.static=[]
        self.moving = None
        self.rb_panda = []

    def delRB(self, node):
        if panda3d is None :
                return
        self.world.removeRigidBody(node)
        if node in self.rb_panda: self.rb_panda.pop(self.rb_panda.index(node))
        if node in self.static: self.static.pop(self.static.index(node))
        if node == self.moving: self.moving = None
        np = NodePath(node)
        np.removeNode()

    def setRB(self,inodenp,**kw):
        if "adamping" in kw :
            inodenp.node().setAngularDamping(kw["adamping"])
        if "ldamping" in kw :
            inodenp.node().setLinearDamping(kw["ldamping"])
        if "mass" in kw :
            inodenp.node().setMass(kw["mass"])
        if "pos" in kw :
            inodenp.setPos(kw["pos"][0],kw["pos"][1],kw["pos"][2])

    def addSinglePlaneRB(self,up,const,**kw):
        pup = Vec3(up[0],up[1],up[2])
        shape = BulletPlaneShape(pup,const)#nomal and constant
        name = "plane"
        if "name" in kw :
            name = kw["name"]
        inodenp = self.worldNP.attachNewNode(BulletRigidBodyNode(name))
#        inodenp.node().setMass(1.0)
#        inodenp.node().addShape(shape)
        inodenp.node().addShape(shape)#rotation ?      ,TransformState.makePos(Point3(0, 0, 0))  
#        spherenp.setPos(-2, 0, 4)
        self.setRB(inodenp,**kw)
        inodenp.setCollideMask(BitMask32.allOn())    
        self.world.attachRigidBody(inodenp.node())
        return inodenp

    def addSingleSphereRB(self,rad,**kw):
        shape = BulletSphereShape(rad)
        name = "sphere"
        if "name" in kw :
            name = kw["name"]
        inodenp = self.worldNP.attachNewNode(BulletRigidBodyNode(name))
        inodenp.node().setMass(1.0)
#        inodenp.node().addShape(shape)
        inodenp.node().addShape(shape,TransformState.makePos(Point3(0, 0, 0)))#rotation ?
#        spherenp.setPos(-2, 0, 4)
        self.setRB(inodenp,**kw)
        inodenp.setCollideMask(BitMask32.allOn())    
        self.world.attachRigidBody(inodenp.node())
        return inodenp
        
    def addMultiSphereRB(self,rads,centT,**kw):
        inodenp = self.worldNP.attachNewNode(BulletRigidBodyNode("Sphere"))
        inodenp.node().setMass(1.0)
        for radc, posc in zip(rads, centT):
            shape = BulletSphereShape(radc)#if radis the same can use the same shape for each node
            inodenp.node().addShape(shape, TransformState.makePos(Point3(posc[0],posc[1],posc[2])))#
        self.setRB(inodenp,**kw)
        inodenp.setCollideMask(BitMask32.allOn())    
        self.world.attachRigidBody(inodenp.node())
        return inodenp

    def addMultiSphereGhost(self,rads,centT,**kw):
        inodenp = self.worldNP.attachNewNode(BulletGhostNode("Sphere"))
        for radc, posc in zip(rads, centT):
            shape = BulletSphereShape(radc)
            inodenp.node().addShape(shape, TransformState.makePos(Point3(posc[0],posc[1],posc[2])))#
        self.setRB(inodenp,**kw)
        inodenp.setCollideMask(BitMask32.allOn())    
        self.world.attachRigidBody(inodenp.node())
        return inodenp     
        
    def addSingleCubeRB(self,halfextents,**kw):
        shape = BulletBoxShape(Vec3(halfextents[0], halfextents[1], halfextents[2]))#halfExtents
        inodenp = self.worldNP.attachNewNode(BulletRigidBodyNode("Box"))
#        inodenp.node().setMass(1.0)
#        inodenp.node().addShape(shape)
        inodenp.node().addShape(shape,TransformState.makePos(Point3(0, 0, 0)))#, pMat)#TransformState.makePos(Point3(jtrans[0],jtrans[1],jtrans[2])))#rotation ?
#        spherenp.setPos(-2, 0, 4)
        self.setRB(inodenp,**kw)
        inodenp.setCollideMask(BitMask32.allOn())    
        self.world.attachRigidBody(inodenp.node())
        return inodenp
        
    def addMultiCylinderRB(self,rads,centT1,centT2,**kw):   
        inodenp = self.worldNP.attachNewNode(BulletRigidBodyNode("Cylinder"))
        inodenp.node().setMass(1.0)
        centT1 = ingr.positions[0]#ingr.transformPoints(jtrans, rotMat, ingr.positions[0])
        centT2 = ingr.positions2[0]#ingr.transformPoints(jtrans, rotMat, ingr.positions2[0])
        for radc, p1, p2 in zip(rads, centT1, centT2):
            length, mat = helper.getTubePropertiesMatrix(p1,p2)
            pMat = self.pandaMatrice(mat)
#            d = numpy.array(p1) - numpy.array(p2)
#            s = numpy.sum(d*d)
            shape = BulletCylinderShape(radc, length,1)#math.sqrt(s), 1)# { XUp = 0, YUp = 1, ZUp = 2 } or LVector3f const half_extents
            inodenp.node().addShape(shape, TransformState.makeMat(pMat))#
        self.setRB(inodenp,**kw)
        inodenp.setCollideMask(BitMask32.allOn())    
        self.world.attachRigidBody(inodenp.node())
        return inodenp
    
    def setGeomFaces(self,tris,face):                
        #have to add vertices one by one since they are not in order
        if len(face) == 2 :
            face = numpy.array([face[0],face[1],face[1],face[1]],dtype='int')
        for i in face :        
            tris.addVertex(i)
        tris.closePrimitive()

    def addMeshRB(self,vertices, faces,ghost=False,**kw):
        #step 1) create GeomVertexData and add vertex information
        format=GeomVertexFormat.getV3()
        vdata=GeomVertexData("vertices", format, Geom.UHStatic)
        
        vertexWriter=GeomVertexWriter(vdata, "vertex")
        [vertexWriter.addData3f(v[0],v[1],v[2]) for v in vertices]
        
        #step 2) make primitives and assign vertices to them
        tris=GeomTriangles(Geom.UHStatic)
        [self.setGeomFaces(tris,face) for face in faces]
        
        #step 3) make a Geom object to hold the primitives
        geom=Geom(vdata)
        geom.addPrimitive(tris)
        
        #step 4) create the bullet mesh and node
        mesh = BulletTriangleMesh()
        mesh.addGeom(geom)

        shape = BulletTriangleMeshShape(mesh, dynamic=not ghost)#BulletConvexHullShape
        if ghost :
            inodenp = self.worldNP.attachNewNode(BulletGhostNode('Mesh'))
        else :
            inodenp = self.worldNP.attachNewNode(BulletRigidBodyNode('Mesh'))
        inodenp.node().addShape(shape)
#        inodenp.setPos(0, 0, 0.1)
        self.setRB(inodenp,**kw)
        inodenp.setCollideMask(BitMask32.allOn())
   
        self.world.attachRigidBody(inodenp.node())
        return inodenp

    def addMeshConvexRB(self,vertices, faces,ghost=False,**kw):
        #step 1) create GeomVertexData and add vertex information
        format=GeomVertexFormat.getV3()
        vdata=GeomVertexData("vertices", format, Geom.UHStatic)
        
        vertexWriter=GeomVertexWriter(vdata, "vertex")
        [vertexWriter.addData3f(v[0],v[1],v[2]) for v in vertices]
        
        #step 2) make primitives and assign vertices to them
        tris=GeomTriangles(Geom.UHStatic)
        [self.setGeomFaces(tris,face) for face in faces]
        
        #step 3) make a Geom object to hold the primitives
        geom=Geom(vdata)
        geom.addPrimitive(tris)
        
        #step 4) create the bullet mesh and node
        mesh = BulletTriangleMesh()
        mesh.addGeom(geom)

        shape = BulletConvexHullShape(mesh, dynamic=not ghost)#
        if ghost :
            inodenp = self.worldNP.attachNewNode(BulletGhostNode('Mesh'))
        else :
            inodenp = self.worldNP.attachNewNode(BulletRigidBodyNode('Mesh'))
        inodenp.node().addShape(shape)
#        inodenp.setPos(0, 0, 0.1)
        self.setRB(inodenp,**kw)
        inodenp.setCollideMask(BitMask32.allOn())
   
        self.world.attachRigidBody(inodenp.node())
        return inodenp
        
    def addTriMeshSB(self,vertices, faces,normals = None,ghost=False,**kw):
        #step 1) create GeomVertexData and add vertex information
        # Soft body world information
        info = self.world.getWorldInfo()
        info.setAirDensity(0.0)
        info.setWaterDensity(0)
        info.setWaterOffset(0)
        info.setWaterNormal(Vec3(0, 0, 0))
        
        format=GeomVertexFormat.getV3n3() #getV3()#http://www.panda3d.org/manual/index.php/Pre-defined_vertex_formats
#        vdata = GeomVertexData('name', format, Geom.UHStatic)
        vdata=GeomVertexData("Mesh", format, Geom.UHStatic)
        
        vertexWriter=GeomVertexWriter(vdata, "vertex")
        [vertexWriter.addData3f(v[0],v[1],v[2]) for v in vertices]

        if normals is not None :
            normalWriter = GeomVertexWriter(vdata, 'normal')
            [normalWriter.addData3f(n[0],n[1],n[2]) for n in normals] 
        else :
            print "we need normals to bind geom to SoftBody"
            return None
        
        #step 2) make primitives and assign vertices to them
        tris=GeomTriangles(Geom.UHStatic)
        [self.setGeomFaces(tris,face) for face in faces]
        
        #step 3) make a Geom object to hold the primitives
        geom=Geom(vdata)
        geom.addPrimitive(tris)
        
        vdata = geom.getVertexData()
#        print (vdata,vdata.hasColumn(InternalName.getVertex()))
        geomNode = GeomNode('')
        geomNode.addGeom(geom)

        #step 4) create the bullet softbody and node
        bodyNode = BulletSoftBodyNode.makeTriMesh(info, geom)
#        bodyNode.linkGeom(geomNode.modifyGeom(0))
        bodyNode.setName('Tri')
        bodyNode.linkGeom(geom)  
        bodyNode.generateBendingConstraints(1)#???
        #bodyNode.getMaterial(0).setLinearStiffness(0.8)
        bodyNode.getCfg().setPositionsSolverIterations(4)
#        bodyNode.getCfg().setCollisionFlag(BulletSoftBodyConfig.CFVertexFaceSoftSoft, True)
        bodyNode.getCfg().setDynamicFrictionCoefficient(1)
        bodyNode.getCfg().setDampingCoefficient(0.001)
        bodyNode.getCfg().setPressureCoefficient(15000*10.0)  
        bodyNode.getCfg().setPoseMatchingCoefficient(0.2)
        bodyNode.setPose(True, True)
#        bodyNode.randomizeConstraints()
        bodyNode.setTotalMass(50000*10, True)
        
        bodyNP = self.worldNP.attachNewNode(bodyNode)
#        fmt = GeomVertexFormat.getV3n3t2()
#        geom = BulletHelper.makeGeomFromFaces(bodyNode, fmt,True)

#        bodyNode.linkGeom(geomNode.modifyGeom(0))
#        geomNode = GeomNode('')
#        geomNode.addGeom(geom)
        
#        world.attachSoftBody(bodyNode)
#        inodenp.setPos(0, 0, 0.1)
#        self.setRB(bodyNP,**kw)#set po
#        inodenp.setCollideMask(BitMask32.allOn())
        self.world.attachSoftBody(bodyNode)
        geomNP = bodyNP.attachNewNode(geomNode)
        return bodyNP,geomNP

    def addTetraMeshSB(self,vertices, faces,normals = None,ghost=False,**kw):
        #step 1) create GeomVertexData and add vertex information
        # Soft body world information
        info = self.world.getWorldInfo()
        info.setAirDensity(1.2)
        info.setWaterDensity(0)
        info.setWaterOffset(0)
        info.setWaterNormal(Vec3(0, 0, 0))
    
        points = [Point3(x,y,z) * 3 for x,y,z in vertices]
        indices = sum([list(x) for x in faces], [])
        #step 4) create the bullet softbody and node
        bodyNode = BulletSoftBodyNode.makeTetMesh(info, points, indices, True)

        bodyNode.setName('Tetra')
        bodyNode.setVolumeMass(150000)
        bodyNode.getShape(0).setMargin(0.01)
        bodyNode.getMaterial(0).setLinearStiffness(0.9)
        bodyNode.getCfg().setPositionsSolverIterations(4)
        bodyNode.getCfg().clearAllCollisionFlags()
        bodyNode.getCfg().setCollisionFlag(BulletSoftBodyConfig.CFClusterSoftSoft, True)
        bodyNode.getCfg().setCollisionFlag(BulletSoftBodyConfig.CFClusterRigidSoft, True)
        bodyNode.generateClusters(12)
        bodyNode.setPose(True, True)
        bodyNP = self.worldNP.attachNewNode(bodyNode)
        
        geom = BulletHelper.makeGeomFromFaces(bodyNode)
        geomNode = GeomNode('vtetra')
        geomNode.addGeom(geom)
        
#        self.setRB(bodyNP,**kw)#set po
#        inodenp.setCollideMask(BitMask32.allOn())
        self.world.attachSoftBody(bodyNode)
        geomNP = bodyNP.attachNewNode(geomNode)
        bodyNode.linkGeom(geom)
        return bodyNP,geomNP

    def getVertices(self,node,gnode):
        geomNode = gnode.node()
        ts = node.getTransform() 
        m = ts.getMat().getUpper3()
        p = ts.getMat().getRow3(3)
        points=[]
        geom = geomNode.getGeoms()[0]
        vdata = geom.getVertexData()
        reader = GeomVertexReader(vdata, 'vertex')
        while not reader.isAtEnd():
            v = reader.getData3f()
            v = m.xform(v) + p
            points.append(Point3(v))
        return numpy.array(points,dtype=numpy.float32)
        
    def pandaMatrice(self,mat):
        mat = mat.transpose().reshape((16,))
#        print mat,len(mat),mat.shape
        pMat = Mat4(mat[0],mat[1],mat[2],mat[3],
                   mat[4],mat[5],mat[6],mat[7],
                   mat[8],mat[9],mat[10],mat[11],
                   mat[12],mat[13],mat[14],mat[15],)
        return pMat
        
#    
#    def addRB(self,rtype,static,**kw):
#        # Sphere
#        if panda3d is None :
#            return None
#        if rotMatis not None and trans is not None:
#            mat = rotMat.copy()
#            mat = mat.transpose().reshape((16,))
#
#            pMat = TransformState.makeMat(Mat4(mat[0],mat[1],mat[2],mat[3],
#                                           mat[4],mat[5],mat[6],mat[7],
#                                           mat[8],mat[9],mat[10],mat[11],
#                                           trans[0],trans[1],trans[2],mat[15],))
#        shape = None
#        inodenp = None
##        print (pMat) 
#        inodenp = self.rb_func_dic[rtype](ingr,pMat,trans,rotMat)

#        inodenp.setCollideMask(BitMask32.allOn())
    
#        self.world.attachRigidBody(inodenp.node())
#        if static :
#            self.static.append(inodenp.node())
#        else :
#            self.moving = inodenp.node()
#        self.rb_panda.append(inodenp.node())
#        return inodenp.node()
    
    def moveRBnode(self,node, trans, rotMat):
        mat = rotMat.copy()
#        mat[:3, 3] = trans
#        mat = mat.transpose()
        mat = mat.transpose().reshape((16,))
#        print mat,len(mat),mat.shape
        pMat = Mat4(mat[0],mat[1],mat[2],mat[3],
                   mat[4],mat[5],mat[6],mat[7],
                   mat[8],mat[9],mat[10],mat[11],
                   trans[0],trans[1],trans[2],mat[15],)
        pTrans = TransformState.makeMat(pMat)
        nodenp = NodePath(node)
        nodenp.setMat(pMat)
#        nodenp.setPos(trans[0],trans[1],trans[2])
#        print nodenp.getPos()

    def applyForce(self,node,F):
        F*=self.scale
        node.node().applyCentralForce(Vec3(F[0],F[1],F[2]))
#        node.node().applyForce(Vec3(F[0],F[1],F[2]),Point3(0, 0, 0))
#        print F
        
    def rayCast(self, startp,endp,closest=False):
        start=Point3(startp[0],startp[1],startp[2])
        end=Point3(endp[0],endp[1],endp[2])
        if closest :
            res = self.world.rayTestClosest(start, end)
        else :
            res = self.world.rayTestAll(start, end)  
        return res

    def sweepRay(self, startp,endp):
        tsFrom = TransformState.makePos(Point3(0, 0, 0))
        tsTo = TransformState.makePos(Point3(10, 0, 0))
        shape = BulletSphereShape(0.5)
        penetration = 0.0
        result = self.world.sweepTestClosest(shape, tsFrom, tsTo, penetration)
        return result 

    def update(self,task,cb=None):
#        print "update"
        dt = globalClock.getDt()
#        print dt
        self.world.doPhysics(dt, 10, 0.008)#,100,1.0/500.0)#world.doPhysics(dt, 10, 1.0/180.0)
        #this may be different for relaxing ?
#        print task.time
        if cb is not None :
            cb()
        if task is not None:
            return task.cont
예제 #31
0
class RollingEve(ShowBase):

	MUSIC_ON = True
	SOUND_EFFECT_ON =True

	def __init__(self):

		ShowBase.__init__(self)
		base.disableMouse()			

		self.camera_views = {'normal' : True, 'top' : False, 'right' : False, 'left' : False, 'first_person' : False}
		self.audio3d = Audio3DManager.Audio3DManager(base.sfxManagerList[0], camera)

		self.levelFinish = False
		self.game_over = False
		self.alreadyPlayed= False
		self.current_level = 'L0'
		self.user = None
		self.tasks=[]

		self.accept('q',self.toggle_music)
		self.accept('x', self.toggle_sfx)


		self.complete = base.loader.loadSfx("sfx/complete.wav")
		self.complete.setLoop(False)
		self.complete.setVolume(.07)

		self.night = base.loader.loadSfx("sfx/night_time.wav")
		self.night.setLoop(True)
		self.night.setVolume(1)

		self.meadow = base.loader.loadSfx("sfx/meadow_land.wav")
		self.meadow.setLoop(True)
		self.meadow.setVolume(.2)

		self.set_world()
		self.set_debug_mode()
			
		self.create_player()
		self.set_interface()	

	def toggle_music(self):
		if RollingEve.MUSIC_ON is True:
			base.enableMusic(False)
			RollingEve.MUSIC_ON = False
		else:
			base.enableMusic(True)
			RollingEve.MUSIC_ON = True

	def toggle_sfx(self):
		if RollingEve.SOUND_EFFECT_ON is True:
			base.enableSoundEffects(False)
			RollingEve.SOUND_EFFECT_ON = False
		else:
			base.enableSoundEffects(True)
			RollingEve.SOUND_EFFECT_ON = True

	def toggle_camera(self):
		if self.camera_views['normal'] is True:
			self.camera_views['normal'] = False
			self.camera_views['top'] = True
		elif self.camera_views['top'] is True:
			self.camera_views['top'] = False
			self.camera_views['right'] = True
		elif self.camera_views['right'] is True:
			self.camera_views['right'] = False
			self.camera_views['left'] = True
		elif self.camera_views['left'] is True:
			self.camera_views['left'] = False
			self.camera_views['first_person'] = True
		elif self.camera_views['first_person'] is True:
			self.camera_views['first_person'] = False
			self.camera_views['normal'] = True

	def set_interface(self,start=True):
		#	ONSCREEN INTERFACE	#
		self.interface = OnScreenInterface(self)
		if start is True:
			self.interface.load_initial_interface()


	def set_world(self):
		#	INSTANTIATE BULLET WORLD	#
		self.world = BulletWorld()
		self.world.setGravity(Vec3(0,0,-9.81))

	def set_debug_mode(self):
		#	Create and attach bullet debug node	#
		self.debugNP = self.render.attachNewNode(BulletDebugNode('Debug'))
		self.world.setDebugNode(self.debugNP.node())

	def create_player(self):
		self.eve = Eve(self,self.render,self.world,self.accept,damage=12.5)

	def clean_and_set(self,level):
		self.camera_views = {'normal' : True, 'top' : False, 'right' : False, 'left' : False, 'first_person' : False}
		self.levelFinish = False
		self.game_over = False
		self.alreadyPlayed= False
		self.user.score = 0

		if self.eve.running.status() == self.eve.running.PLAYING: self.eve.running.stop()
		if self.meadow.status() == self.meadow.PLAYING:
			self.meadow.stop()

		if self.night.status() == self.night.PLAYING:
			self.night.stop()

		print '\n\tCLEANING WORLD...\n'
		#self.interface.stage_select_frame.hide()
		self.interface.main_frame.destroy()
		self.world = None
		self.interface = None
		self.taskMgr.remove('moving')
		self.taskMgr.remove('Ghost-Collision-Detection') 
		self.taskMgr.remove('TokenSpin')
		self.taskMgr.remove('update') 
		self.taskMgr.remove('Timer')
		self.taskMgr.remove('weapon') 
		self.taskMgr.remove('attacks')
		self.taskMgr.remove('attacked')
		self.taskMgr.remove('enemies')
		self.taskMgr.remove('moving')
		self.taskMgr.remove('tokens')
		self.taskMgr.remove('cam_update')

		for node in self.render.getChildren():
			if node != camera:
				node.remove_node()
		self.set_world()
		self.set_debug_mode()
		self.create_player()
		self.set_interface(start = False)
		self.interface.set_timer(level)
		#print self.interface.level_time
		self.interface.load_essentials()
		self.accept('h', self.do_nothing)
		self.accept('f1', self.do_nothing)
		self.setup(level)
		self.taskMgr.add(self.interface.show_title,'Title')
		self.taskMgr.add(self.interface.update_timer,'Timer')

		
	def do_nothing(self):
		pass

	def setup(self,level):
		self.actual_start = globalClock.getRealTime()
		self.current_level = level
		#self.interface.set_timer()
		self.interface.create_stage_title(self.current_level)


		self.e = Environment(self)
		if self.current_level == 'L1':
			self.eve.render_eve((1500,1100,1.5))
			#self.eve.render_eve((0,-5250,-15))
			self.e.loadStage1()
			#self.eve.render_eve((1500,1100,1.5))
		elif self.current_level == 'L2':
			self.eve.render_eve((1500,1100,1005))
			#self.eve.render_eve((1363,982,1335))
			#self.eve.render_eve((1345,1690,1335))
			#self.eve.render_eve((179,1594,1435))
			self.e.loadStage2()
		
		self.accept('c', self.toggle_camera)

        	inputState.watchWithModifiers('camera_up', 'arrow_up')
        	inputState.watchWithModifiers('camera_down', 'arrow_down')																
		
		#	TASK FOR ALL GAME STAGES	#
		self.taskMgr.add(self.update_world,'update')
		self.taskMgr.add(self.update_camera,'cam-update')  
      	
	def update_camera(self,task):
		if self.camera_views['normal'] is True:
			self.normal_view()
		elif self.camera_views['top'] is True:
			self.top_view()
		elif self.camera_views['right'] is True:
			self.right_view()
		elif self.camera_views['left'] is True:
			self.left_view()
		elif self.camera_views['first_person'] is True:
			self.first_person()
			if inputState.isSet('camera_up'):
				if base.camera.getP() < 45:
					base.camera.setP(base.camera.getP() + 1)
			if inputState.isSet('camera_down'):
				if base.camera.getP() > -90:
					base.camera.setP(base.camera.getP() - 1)
		return task.cont
		

	#	WORLD UPDATE TASK	#
	def update_world(self,task):
		check = self.eve.currentControllerNode.isOnGround()				# Task that updates physics world every frame
        	dt = globalClock.getDt()
       		self.eve.updateEveAnim()
		

		# Update info on stats frame		
		self.interface.bar['text'] = str(int(self.eve.health)) + ' / 100'
		self.interface.bar['value'] = int(self.eve.health)
		self.world.doPhysics(dt, 10, 1/180.0)		# Update physics world
		if check == False and self.eve.currentControllerNode.isOnGround() is True:
			self.eve.finishJump()
			self.eve.state['jumping'] = False
		
		if self.current_level == 'L1':
			death = -26
		elif self.current_level == 'L2':
			death = 900


		if self.eve.currentNP.getZ() < death:
			self.eve.health -= 10	# Damage taken for falling off the map
			if self.eve.health > 0:
				self.eve.reset()
				self.eve.currentNP.setH(90)
			else:
				self.interface.hide_game_interface()
				self.interface.game_over()
				self.user.add_to_leaderboard(self.current_level)
				return task.done
		if self.levelFinish is True:
			if self.complete.status() is not self.complete.PLAYING and self.alreadyPlayed is False:
				self.interface.hide_game_interface()
				self.alreadyPlayed = True
				self.complete.play()
			self.interface.level_passed()
			self.user.add_to_leaderboard(self.current_level)
			return task.done

		if self.eve.health <= 0 or self.game_over is True:		
			self.interface.hide_game_interface()
			self.interface.game_over()
			self.user.add_to_leaderboard(self.current_level)
			return task.done
			
		return task.cont
	


	def top_view(self):
		base.camera.setPos(self.eve.currentNP.getX(),self.eve.currentNP.getY(),self.eve.currentNP.getZ()+400)
		base.camera.setHpr(self.eve.currentNP.getH(),-90,0)

	def right_view(self):
		xpos = 200 * cos((180 - self.eve.currentNP.getH()) * (pi / 180.0))
		ypos = -200 * sin((180 - self.eve.currentNP.getH()) * (pi / 180.0))
		base.camera.setPos(self.eve.currentNP.getX() - xpos,self.eve.currentNP.getY() - ypos, self.eve.currentNP.getZ() + 20)
		base.camera.lookAt(self.eve.currentNP)

	def normal_view(self):
		xpos = 200 * cos((270 - self.eve.currentNP.getH()) * (pi / 180.0))
		ypos = -200 * sin((270 - self.eve.currentNP.getH()) * (pi / 180.0))
		base.camera.setPos(self.eve.currentNP.getX() - xpos,self.eve.currentNP.getY() - ypos, self.eve.currentNP.getZ() + 60)
		base.camera.setHpr(self.eve.currentNP.getH(),-15,0)

	def left_view(self):
		xpos = -200 * cos((180 - self.eve.currentNP.getH()) * (pi / 180.0))
		ypos = 200 * sin((180 - self.eve.currentNP.getH()) * (pi / 180.0))
		base.camera.setPos(self.eve.currentNP.getX() - xpos,self.eve.currentNP.getY() - ypos, self.eve.currentNP.getZ() + 20)
		base.camera.lookAt(self.eve.currentNP)

	def first_person(self):
		xpos = 5 * cos((90 - self.eve.currentNP.getH()) * (pi / 180.0))
		ypos = -5 * sin((90 - self.eve.currentNP.getH()) * (pi / 180.0))
		base.camera.setPos(self.eve.currentNP.getX() - xpos,self.eve.currentNP.getY() - ypos, self.eve.currentNP.getZ() + 15)
		base.camera.setH(self.eve.currentNP.getH())


	
	def toggleDebug(self):
		if self.debugNP.isHidden():
			self.taskMgr.add(self.interface.updateCoord, 'updateCoord') 
			self.interface.coord.show()
			self.debugNP.show()
		else:
			self.taskMgr.remove('updateCoord') 
			self.interface.coord.hide()
			self.debugNP.hide()
예제 #32
0
class World(DirectObject):
    gameStateDict = {
        "Login": 0,
        "CreateLobby": 4,
        "EnterGame": 1,
        "BeginGame": 2,
        "InitializeGame": 3
    }
    gameState = -1
    # Login , EnterGame , BeginGame
    responseValue = -1
    currentTime = 0
    idleTime = 0
    mySequence = None
    pandaPace = None
    jumpState = False
    isWalk = False
    previousPos = None  # used to store the mainChar pos from one frame to another
    host = ""
    port = 0
    vehiclelist = {}  # Stores the list of all the others players characters
    characters = []

    def __init__(self):
        self.login = "******"
        base.setFrameRateMeter(True)
        #input states
        inputState.watchWithModifiers('forward', 'w')
        inputState.watchWithModifiers('left', 'a')
        inputState.watchWithModifiers('brake', 's')
        inputState.watchWithModifiers('right', 'd')
        inputState.watchWithModifiers('turnLeft', 'q')
        inputState.watchWithModifiers('turnRight', 'e')

        self.keyMap = {
            "hello": 0,
            "left": 0,
            "right": 0,
            "forward": 0,
            "backward": 0,
            "cam-left": 0,
            "cam-right": 0,
            "chat0": 0,
            "powerup": 0,
            "reset": 0
        }
        base.win.setClearColor(Vec4(0, 0, 0, 1))

        # Network Setup
        self.cManager = ConnectionManager(self)
        self.startConnection()
        #self.cManager.sendRequest(Constants.CMSG_LOGIN, ["username", "password"])
        # chat box
        # self.chatbox = Chat(self.cManager, self)

        # Set up the environment
        #
        self.initializeBulletWorld(False)

        #self.createEnvironment()
        Track(self.bulletWorld)

        # Create the main character, Ralph

        self.mainCharRef = Vehicle(self.bulletWorld, (100, 10, 5, 0, 0, 0),
                                   self.login)
        #self.mainCharRef = Character(self, self.bulletWorld, 0, "Me")
        self.mainChar = self.mainCharRef.chassisNP
        #self.mainChar.setPos(0, 25, 16)

        #         self.characters.append(self.mainCharRef)

        #         self.TestChar = Character(self, self.bulletWorld, 0, "test")
        #         self.TestChar.actor.setPos(0, 0, 0)

        self.previousPos = self.mainChar.getPos()
        taskMgr.doMethodLater(.1, self.updateMove, 'updateMove')

        # Set Dashboard
        self.dashboard = Dashboard(self.mainCharRef, taskMgr)

        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(render)

        # Accept the control keys for movement and rotation
        self.accept("escape", self.doExit)
        self.accept("a", self.setKey, ["left", 1])
        self.accept("d", self.setKey, ["right", 1])
        self.accept("w", self.setKey, ["forward", 1])
        self.accept("s", self.setKey, ["backward", 1])
        self.accept("arrow_left", self.setKey, ["cam-left", 1])
        self.accept("arrow_right", self.setKey, ["cam-right", 1])
        self.accept("a-up", self.setKey, ["left", 0])
        self.accept("d-up", self.setKey, ["right", 0])
        self.accept("w-up", self.setKey, ["forward", 0])
        self.accept("s-up", self.setKey, ["backward", 0])
        self.accept("arrow_left-up", self.setKey, ["cam-left", 0])
        self.accept("arrow_right-up", self.setKey, ["cam-right", 0])
        self.accept("h", self.setKey, ["hello", 1])
        self.accept("h-up", self.setKey, ["hello", 0])
        self.accept("0", self.setKey, ["chat0", 1])
        self.accept("0-up", self.setKey, ["chat0", 0])
        self.accept("1", self.setKey, ["powerup", 1])
        self.accept("1-up", self.setKey, ["powerup", 0])
        self.accept("2", self.setKey, ["powerup", 2])
        self.accept("2-up", self.setKey, ["powerup", 0])
        self.accept("3", self.setKey, ["powerup", 3])
        self.accept("3-up", self.setKey, ["powerup", 0])
        self.accept("r", self.doReset)
        self.accept("p", self.setTime)

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

        # Game state variables
        self.isMoving = False

        # Sky Dome
        self.sky = SkyDome()

        # Set up the camera
        self.camera = Camera(self.mainChar)
        #base.disableMouse()
        #base.camera.setPos(self.mainChar.getX(), self.mainChar.getY() + 10, self.mainChar.getZ() + 2)

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

        # Game initialisation
        self.gameState = self.gameStateDict["Login"]
        self.responseValue = -1

        self.cManager.sendRequest(Constants.CMSG_LOGIN, [self.login, "1234"])
        taskMgr.add(self.enterGame, "EnterGame")

        # Create Powerups
        self.createPowerups()
        taskMgr.add(self.powerups.checkPowerPickup, "checkPowerupTask")
        taskMgr.add(self.usePowerup, "usePowerUp")

    def createOtherVehicles(self, username, carType, carPaint, carTires):
        if username in self.vehiclelist.keys():
            print "Player Already rendered"
        else:
            print "Creating copie other player @ 60"
            char = Vehicle(self.bulletWorld, (100, 10, 5, 0, 0, 0), username)
            self.characters.append(char)
            self.vehiclelist[username] = char

    def usePowerup(self, task):
        if self.keyMap["powerup"] == 1:
            self.mainCharRef.usePowerup(0)
        elif self.keyMap["powerup"] == 2:
            self.mainCharRef.usePowerup(1)
        elif self.keyMap["powerup"] == 3:
            self.mainCharRef.usePowerup(2)

        return task.cont

    def createPowerups(self):
        self.powerups = PowerupManager(self.cManager, self.characters)

    def use_powerup3(self):
        self.use_powerup(3)

    def setTime(self):
        self.cManager.sendRequest(Constants.CMSG_TIME)

    def use_powerup(self, num):
        if self.mainCharRef.power_ups[num - 1] == 0:
            print "power-up slot empty"
        else:
            print "power-up", num, "used"

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

    def cleanup(self):
        self.cManager.sendRequest(Constants.CMSG_DISCONNECT)
        self.cManager.closeConnection()
        self.world = None
        self.outsideWorldRender.removeNode()

    def doReset(self):
        self.mainCharRef.reset()

    def enterGame(self, task):
        self.startGameNow()
        return task.done
        if self.gameState == self.gameStateDict["Login"]:
            #responseValue = 1 indicates that this state has been finished
            if self.responseValue == 1:
                # Authentication succeeded
                #self.cManager.sendRequest(Constants.CMSG_CREATE_LOBBY, ["raceroyal","0","1"])
                self.gameState = self.gameStateDict["CreateLobby"]
                #self.responseValue = -1
        elif self.gameState == self.gameStateDict["CreateLobby"]:
            if self.responseValue == 1:
                print "Lobby Created and we are already in"
                # Lobby Created and we are already in
                self.gameState = self.gameStateDict["EnterGame"]
                self.responseValue = -1
            elif self.responseValue == 0:
                print "Game already created, let's join it"
                #Game already created, let's join it
                self.cManager.sendRequest(Constants.CMSG_ENTER_GAME_NAME,
                                          "raceroyal")
                self.gameState = self.gameStateDict["EnterGame"]
                self.responseValue = -1
                self.startGameNow()
                #self.gameState = self.gameStateDict["InitializeGame"]


#               Everyone is in the game, we send ReqReady, and the server will send positions when every client did
#self.cManager.sendRequest(Constants.CMSG_READY)

        elif self.gameState == self.gameStateDict["EnterGame"]:
            if self.responseValue == 1:
                #                 When the positions are sent, an acknowledgment is sent and we begin the InitializeGame
                self.responseValue = -1
                self.gameState = self.gameStateDict["InitializeGame"]
                #               Everyone is in the game, we send ReqReady, and the server will send positions when every client did
                self.cManager.sendRequest(Constants.CMSG_READY)

        elif self.gameState == self.gameStateDict["InitializeGame"]:
            if self.responseValue == 1:
                # Set up the camera
                self.camera = Camera(self.mainChar)
                self.gameState = self.gameStateDict["BeginGame"]
                self.cManager.sendRequest(Constants.CMSG_READY)
                self.responseValue = -1

        elif self.gameState == self.gameStateDict["BeginGame"]:
            if self.responseValue == 1:
                taskMgr.add(self.move, "moveTask")
                return task.done

        return task.cont
        #return task.done

    def startGameNow(self):
        self.camera = Camera(self.mainChar)
        taskMgr.doMethodLater(.1, self.updateMove, 'updateMove')
        taskMgr.add(self.move, "moveTask")

    def createEnvironment(self):
        self.environ = loader.loadModel("models/square")
        self.environ.reparentTo(render)
        #self.environ.setPos(0, 0, 10)
        self.environ.setScale(500, 500, 1)
        self.moon_tex = loader.loadTexture("models/moon_1k_tex.jpg")
        self.environ.setTexture(self.moon_tex, 1)

        shape = BulletPlaneShape(Vec3(0, 0, 1), 0)
        node = BulletRigidBodyNode('Ground')
        node.addShape(shape)
        np = render.attachNewNode(node)
        #np.setPos(0, 0, 0)

        self.bulletWorld.attachRigidBody(node)

        self.visNP = loader.loadModel('models/track.egg')
        self.tex = loader.loadTexture("models/tex/Main.png")
        self.visNP.setTexture(self.tex)

        geom = self.visNP.findAllMatches('**/+GeomNode').getPath(
            0).node().getGeom(0)
        mesh = BulletTriangleMesh()
        mesh.addGeom(geom)
        trackShape = BulletTriangleMeshShape(mesh, dynamic=False)

        body = BulletRigidBodyNode('Bowl')
        self.visNP.node().getChild(0).addChild(body)
        bodyNP = render.anyPath(body)
        bodyNP.node().addShape(trackShape)
        bodyNP.node().setMass(0.0)
        bodyNP.setTexture(self.tex)

        self.bulletWorld.attachRigidBody(bodyNP.node())

        self.visNP.reparentTo(render)

        self.bowlNP = bodyNP
        self.visNP.setScale(70)

    def initializeBulletWorld(self, debug=False):
        self.outsideWorldRender = render.attachNewNode('world')

        self.bulletWorld = BulletWorld()
        self.bulletWorld.setGravity(Vec3(0, 0, -9.81))
        if debug:
            self.debugNP = self.outsideWorldRender.attachNewNode(
                BulletDebugNode('Debug'))
            self.debugNP.show()
            self.debugNP.node().showWireframe(True)
            self.debugNP.node().showConstraints(True)
            self.debugNP.node().showBoundingBoxes(True)
            self.debugNP.node().showNormals(False)
            self.bulletWorld.setDebugNode(self.debugNP.node())

    def makeCollisionNodePath(self, nodepath, solid):
        '''
        Creates a collision node and attaches the collision solid to the
        supplied NodePath. Returns the nodepath of the collision node.
        '''
        # Creates a collision node named after the name of the NodePath.
        collNode = CollisionNode("%s c_node" % nodepath.getName())
        collNode.addSolid(solid)
        collisionNodepath = nodepath.attachNewNode(collNode)

        return collisionNodepath

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

    # Accepts arrow keys to move either the player or the menu cursor,
    # Also deals with grid checking and collision detection
    def getDist(self):
        mainCharX = self.mainChar.getPos().x
        mainCharY = self.mainChar.getPos().y
        pandaX = self.pandaActor2.getPos().x
        pandaY = self.pandaActor2.getPos().y
        dist = math.sqrt(
            abs(mainCharX - pandaX)**2 + abs(mainCharY - pandaY)**2)
        return dist

    def move(self, task):
        self.camera.update(self.mainChar)
        dt = globalClock.getDt()

        forces = self.mainCharRef.processInput(inputState, dt)
        moving = self.mainCharRef.chassisNP.getPos()
        print "Forces received& sending: ", moving[0], moving[1], moving[2]
        self.cManager.sendRequest(Constants.CMSG_MOVE, [
            forces[0], forces[1], forces[2],
            moving.getX(),
            moving.getY(),
            moving.getZ(),
            self.mainCharRef.chassisNP.getH(),
            self.mainCharRef.chassisNP.getP(),
            self.mainCharRef.chassisNP.getR()
        ])
        self.bulletWorld.doPhysics(dt, 10, 0.02)

        self.bulletWorld.doPhysics(dt)

        return task.cont

    def startConnection(self):
        """Create a connection to the remote host.

        If a connection cannot be created, it will ask the user to perform
        additional retries.

        """
        if self.cManager.connection == None:
            if not self.cManager.startConnection():
                return False

        return True

    def listFromInputState(self, inputState):
        # index 0 == forward
        # index 1 == brake
        # index 2 == right
        # index 3 == left
        result = [0, 0, 0, 0]
        if inputState.isSet('forward'):
            result[0] = 1
        if inputState.isSet('brake'):
            result[1] = 1
        if inputState.isSet('right'):
            result[2] = 1
        if inputState.isSet('left'):
            result[3] = 1

        return result

    def updateMove(self, task):
        if self.isMoving == True:
            moving = self.mainChar.getPos() - self.previousPos

            self.cManager.sendRequest(Constants.CMSG_MOVE, [
                moving.getX(),
                moving.getY(),
                moving.getZ(),
                self.mainCharRef.actor.getH(),
                self.mainCharRef.actor.getP(),
                self.mainCharRef.actor.getR(),
                self.listFromInputState(inputState)
            ])

            # self.cManager.sendRequest(Constants.RAND_FLOAT, 1.0)
            self.previousPos = self.mainChar.getPos()

        return task.again
예제 #33
0
class FriendlyFruit(ShowBase, Scene):
    def __init__(self, server_connection, player_tag):
        ShowBase.__init__(self)
        self.__server_connection = server_connection
        self.__player_tag = player_tag
        self.__rotations = {}

        # Panda pollutes the global namespace.  Some of the extra globals can be referred to in nicer ways
        # (for example self.render instead of render).  The globalClock object, though, is only a global!  We
        # create a reference to it here, in a way that won't upset PyFlakes.
        self.globalClock = __builtins__["globalClock"]

        # Turn off the debugging system which allows the camera to be adjusted directly by the mouse.
        self.disableMouse()

        # Set up physics: the ground plane and the capsule which represents the player.
        self.world = BulletWorld()

        # The ground first:
        shape = BulletPlaneShape(Vec3(0, 0, 1), 0)
        node = BulletRigidBodyNode("Ground")
        node.addShape(shape)
        np = self.render.attachNewNode(node)
        np.setPos(0, 0, 0)
        self.world.attachRigidBody(node)

        # Enable shader generation (for more sophisticated lighting etc.)
        self.render.setShaderAuto()

        # Create lights so we can see the scene.
        dlight = DirectionalLight("dlight")
        dlight.setColor(VBase4(2, 2, 2, 0))
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(0, -60, 0)
        self.render.setLight(dlnp)

        alight = AmbientLight('alight')
        alight.setColor(VBase4(0.75, 0.75, 0.75, 0))
        alnp = self.render.attachNewNode(alight)
        self.render.setLight(alnp)

        # Create a task to update the scene regularly.
        self.taskMgr.add(self.update, "UpdateTask")

    # Update the scene by turning objects if necessary, and processing physics.
    def update(self, task):
        asyncore.loop(timeout=0.01, use_poll=True, count=1)

        for node, angular_velocity in self.__rotations.iteritems():
            node.setAngularMovement(angular_velocity)

        dt = self.globalClock.getDt()
        self.world.doPhysics(dt)
        return task.cont

    def server_created_object(self, tag, height, radius):
        # This shape is used for collision detection, preventing the player falling through the ground for
        # example.
        shape = BulletCapsuleShape(radius, height - 2 * radius, ZUp)

        # A character controller is a physical body which responds instantly to keyboard controls.  (Bodies
        # which respond to forces are difficult to control in a satisfactory way using typical video game
        # controls.  Players expect them to move instantly when a button is pressed, but physics dictates that
        # they should take a short time to accelerate.)
        node = BulletCharacterControllerNode(shape, 0.4, tag)
        node_path = self.render.attachNewNode(node)
        Thing.add(tag, node, node_path)
        self.world.attachCharacter(node)

        # Does this object represent the player who is using this client?
        if tag == self.__player_tag:
            # If yes, attach the camera to the object, so the player's view follows the object.
            self.camera.reparentTo(node_path)
        else:
            # If no, create a new Actor to represent the player or NPC.
            humanoid = Actor("player.bam")
            humanoid.setH(180)
            humanoid.reparentTo(node_path)

            # Scale the Actor so it is the same height as the bounding volume requested by the server.
            point1 = Point3()
            point2 = Point3()
            humanoid.calcTightBounds(point1, point2)
            humanoid.setScale(height / (point2.z - point1.z))

            # If the 3D model has the origin point at floor level, we need to move it down by half the height
            # of the bounding volume.  Otherwise it will hang in mid air, with its feet in the middle of the
            # bounding volume.
            humanoid.setZ(-height / 2)

    def server_removed_object(self, tag):
        thing = Thing.get_thing(tag)
        self.world.removeCharacter(thing.node)
        thing.node_path.removeNode()
        thing.remove()

    def server_moves_thing(self, tag, loc_x, loc_y, loc_z, speed_x, speed_y, speed_z, angle, angular_velocity):
        thing = Thing.get_thing(tag)
        thing.node_path.setPos(loc_x, loc_y, loc_z)
        thing.node.setLinearMovement(Vec3(speed_x, speed_y, speed_z), True)

        # I don't know why deg2Rad is required in the following line; I suspect it is a Panda bug.
        thing.node_path.setH(deg2Rad(angle))

        if angular_velocity != 0:
            self.__rotations[thing.node] = angular_velocity
        elif thing.node in self.__rotations:
            del self.__rotations[thing.node]
예제 #34
0
class App(ShowBase):
    def __init__(self, character_list):
        super().__init__(self)

        self.clock = 0

        for character in character_list:
            character.HP = character.BaseHP
            # displayHP(Character)
        self.characterList = character_list
        self.buttons = []
        self.index = 0

        # Set up the World
        # The World
        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -gravity))

        # Camera
        self.cam.setPos(0, -15, 2)
        self.cam.lookAt(0, 0, 0)

        # The Ground
        np = self.render.attachNewNode(BulletRigidBodyNode('Ground'))
        np.node().addShape(BulletPlaneShape(Vec3(0, 0, 1), 1))
        np.setPos(0, 0, -2)
        self.world.attachRigidBody(np.node())

        # Characters
        character_list[0].insert(self.world, self.render, -1, (-2, 0))
        character_list[1].insert(self.world, self.render, 1, (2, 0))

        # Debug
        debug_node = BulletDebugNode('Debug')
        debug_node.showWireframe(True)
        debug_node.showConstraints(False)
        debug_node.showBoundingBoxes(False)
        debug_node.showNormals(False)
        self.debugNP = self.render.attachNewNode(debug_node)
        self.debugNP.show()
        self.world.setDebugNode(self.debugNP.node())
        debug_object = DirectObject()
        debug_object.accept('f1', self.toggle_debug)

        # Testing Controls
        shoulder_moving_object = ShoulderMovingObject(character_list)
        target_moving_object = TargetMovingObject()
        self.targets = target_moving_object.set_targets(*DefaultTargetPos)
        for i in range(3):
            shoulder_moving_object.move_arms(i, 0)

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

        # Set up GUI
        self.sharedInfo = OnscreenText(text="No information to display yet.",
                                       pos=(0, 0.5),
                                       scale=0.07,
                                       align=TextNode.ACenter,
                                       mayChange=1)
        self.actionBoxes, self.infoBoxes, self.useButtons, self.healthBars = [], [], [], []
        self.selectedAction, self.selection = None, None
        for side in (LEFT, RIGHT):
            action_box = DirectFrame(frameColor=(0, 0, 0, 1),
                                     frameSize=(-frame_width, frame_width,
                                                -frame_height, frame_height),
                                     pos=(side * (window_width - frame_width),
                                          0, -(window_height - frame_height)))
            info_box = OnscreenText(text="No info available",
                                    scale=0.07,
                                    align=TextNode.ACenter,
                                    mayChange=1)
            info_box.reparentTo(action_box)
            info_box.setPos(0, frame_height + 0.25)
            use_button = DirectButton(frameSize=(-button_width, button_width,
                                                 -button_height,
                                                 button_height),
                                      text="N/A",
                                      text_scale=0.1,
                                      borderWidth=(0.025, 0.025),
                                      command=self.use_action,
                                      state=DGG.DISABLED)
            use_button.reparentTo(action_box)
            use_button.setPos(frame_width - button_width, 0, 0)
            hp = self.characterList[0 if side < 0 else side].HP
            bar = DirectWaitBar(text="",
                                range=hp,
                                value=hp,
                                pos=(side * 0.5, 0, 0.75),
                                frameSize=(side * -0.4, side * 0.5, 0, -0.05))
            self.actionBoxes.append(action_box)
            self.infoBoxes.append(info_box)
            self.useButtons.append(use_button)
            self.healthBars.append(bar)

        self.query_action()

    def update(self, task):
        """Update the world using physics."""
        dt = globalClock.getDt()
        self.world.doPhysics(dt)
        self.clock += 1
        if TARGETING[0] and self.clock % 10 == 0:
            for (character,
                 side), target in zip(product(self.characterList, sides),
                                      self.targets):
                character.position_shoulder(side, target)
        return Task.cont

    def toggle_debug(self):
        """Toggle debug display for physical objects."""
        if self.debugNP.isHidden():
            self.debugNP.show()
        else:
            self.debugNP.hide()

    def query_action(self):
        """Set up buttons for a player to choose an action."""
        character, frame = self.characterList[self.index], self.actionBoxes[
            self.index]
        for i, action in enumerate(character.moveList):
            b = DirectButton(frameSize=(-button_width, button_width,
                                        -button_height, button_height),
                             text=action,
                             text_scale=0.1,
                             borderWidth=(0.025, 0.025),
                             command=self.set_action,
                             extraArgs=[character, action])
            b.reparentTo(frame)
            b.setPos(-(frame_width - button_width), 0,
                     frame_height - (2 * i + 1) * button_height)
            self.buttons.append(b)

    def set_action(self, character, name):
        """Set an action to be selected."""
        i = self.index
        self.selectedAction = character.moveList[name]
        self.infoBoxes[i].setText(self.selectedAction.show_stats())
        self.useButtons[i].setText("Use %s" % name)
        self.useButtons[i]["state"] = DGG.NORMAL
        self.selection = name

    def use_action(self):
        """Make the character use the selected action, then move on to the next turn."""
        for button in self.useButtons:
            button["state"] = DGG.DISABLED
            button["text"] = "N/A"
        user = self.characterList[self.index]
        name, move = self.selection, self.selectedAction

        # Result of move
        if move.get_accuracy() > random.randint(0, 99):
            damage = move.get_damage()
            if random.randint(1, 100) <= 2:
                damage *= 1.5
                print("Critical Hit!".format(user.Name, name, damage))
            self.infoBoxes[self.index].setText(
                "{}'s {} hit for {} damage!".format(user.Name, name, damage))
        else:
            damage = 0
            self.infoBoxes[self.index].setText("{}'s {} missed!".format(
                user.Name, name))

        # Move over to other character and apply damage
        self.index = (self.index + 1) % 2
        opponent = self.characterList[self.index]
        damage = min(max(damage - opponent.Defense, 0),
                     opponent.HP)  # TODO: Find and use a better formula
        opponent.HP -= damage
        self.healthBars[self.index]["value"] -= damage
        self.infoBoxes[self.index].setText('{} took {} damage!'.format(
            opponent.Name, damage))

        # Reset GUI
        for button in self.buttons:
            button.destroy()
        self.buttons.clear()

        # Move on to next step (KO or opponent response)
        if opponent.HP <= 0:
            self.sharedInfo.setText('%s wins!' % user.Name)
            # I thought this would make the character fall, but it just glitches out
            self.characterList[self.index].torso.node().setMass(1.0)
            self.characterList[self.index].torso.node().setActive(True, False)
            for button in self.useButtons:
                button.destroy()
        else:
            self.query_action()
예제 #35
0
class World():
    CULLDISTANCE = 10
    def __init__(self, size):
        self.bw = BulletWorld()
        self.bw.setGravity(0,0,0)
        self.size = size
        self.perlin = PerlinNoise2()

        #utilities.app.accept('bullet-contact-added', self.onContactAdded) 
        #utilities.app.accept('bullet-contact-destroyed', self.onContactDestroyed) 

        self.player = Player(self)
        self.player.initialise()

        self.entities = list()
        self.bgs = list()
        self.makeChunk(Point2(0,0), Point2(3.0, 3.0)) 

        self.cmap = buildMap(self.entities, self.player.location)

        self.mps = list()

        self.entities.append(Catcher(Point2(10, 10), self.player, self.cmap, self))

    def update(self, timer):
        dt = globalClock.getDt()
        self.bw.doPhysics(dt, 5, 1.0/180.0)
        
        self.doHits(Flame)

        self.doHits(Catcher)

        for entity in self.entities:
            if entity.remove == True:
                entity.destroy()
                self.entities.remove(entity)

        self.player.update(dt)
        self.cmap = buildMap(self.entities, self.player.location)

        for entity in self.entities:
            entity.update(dt)

    def doHits(self, hit_type):
        for entity in self.entities:
            if isinstance(entity, hit_type):
                ctest = self.bw.contactTest(entity.bnode)
                if ctest.getNumContacts() > 0:
                    entity.removeOnHit()
                    mp =  ctest.getContacts()[0].getManifoldPoint()
                    if isinstance(ctest.getContacts()[0].getNode0().getPythonTag("entity"), hit_type):
                        ctest.getContacts()[0].getNode1().getPythonTag("entity").hitby(hit_type, mp.getIndex0())
                    else:    
                        ctest.getContacts()[0].getNode0().getPythonTag("entity").hitby(hit_type, mp.getIndex0())

    def makeChunk(self, pos, size):
        self.bgs.append(utilities.loadObject("stars", depth=100, scaleX=200, scaleY=200.0, pos=Point2(pos.x*worldsize.x,pos.y*worldsize.y)))
        genFillBox(self, Point2(5,5), 3, 6, 'metalwalls')
        genBox(self, Point2(10,5), 2, 2, 'metalwalls')
        #self.entities[0].bnode.applyTorque(Vec3(0,50,10))

    def addEntity(self, entity):
        self.entities.append(entity)

    def onContactAdded(self, node1, node2):
        e1 = node1.getPythonTag("entity")
        e2 = node2.getPythonTag("entity")

        if isinstance(e1, Flame):
            e1.remove = True
        if isinstance(e2, Flame):
            e2.remove = True

        print "contact"
    
    def onContactDestroyed(self, node1, node2):
        return
예제 #36
0
class CarEnv(DirectObject):
    def __init__(self, params={}):
        self._params = params
        if 'random_seed' in self._params:
            np.random.seed(self._params['random_seed'])
        self._use_vel = self._params.get('use_vel', True)
        self._run_as_task = self._params.get('run_as_task', False)
        self._do_back_up = self._params.get('do_back_up', False)
        self._use_depth = self._params.get('use_depth', False)
        self._use_back_cam = self._params.get('use_back_cam', False)
        self._collision_reward = self._params.get('collision_reward', 0.)
        if not self._params.get('visualize', False):
            loadPrcFileData('', 'window-type offscreen')

        # Defines base, render, loader

        try:
            ShowBase()
        except:
            pass

        base.setBackgroundColor(0.0, 0.0, 0.0, 1)

        # World
        self._worldNP = render.attachNewNode('World')
        self._world = BulletWorld()
        self._world.setGravity(Vec3(0, 0, -9.81))
        self._dt = params.get('dt', 0.25)
        self._step = 0.05

        # Vehicle
        shape = BulletBoxShape(Vec3(0.6, 1.0, 0.25))
        ts = TransformState.makePos(Point3(0., 0., 0.25))
        self._vehicle_node = BulletRigidBodyNode('Vehicle')
        self._vehicle_node.addShape(shape, ts)
        self._mass = self._params.get('mass', 10.)
        self._vehicle_node.setMass(self._mass)
        self._vehicle_node.setDeactivationEnabled(False)
        self._vehicle_node.setCcdSweptSphereRadius(1.0)
        self._vehicle_node.setCcdMotionThreshold(1e-7)
        self._vehicle_pointer = self._worldNP.attachNewNode(self._vehicle_node)

        self._world.attachRigidBody(self._vehicle_node)

        self._vehicle = BulletVehicle(self._world, self._vehicle_node)
        self._vehicle.setCoordinateSystem(ZUp)
        self._world.attachVehicle(self._vehicle)
        self._addWheel(Point3(0.3, 0.5, 0.07), True, 0.07)
        self._addWheel(Point3(-0.3, 0.5, 0.07), True, 0.07)
        self._addWheel(Point3(0.3, -0.5, 0.07), False, 0.07)
        self._addWheel(Point3(-0.3, -0.5, 0.07), False, 0.07)

        # Camera
        size = self._params.get('size', [160, 90])
        hfov = self._params.get('hfov', 60)
        near_far = self._params.get('near_far', [0.1, 100.])
        self._camera_sensor = Panda3dCameraSensor(base,
                                                  color=not self._use_depth,
                                                  depth=self._use_depth,
                                                  size=size,
                                                  hfov=hfov,
                                                  near_far=near_far,
                                                  title='front cam')
        self._camera_node = self._camera_sensor.cam
        self._camera_node.setPos(0.0, 0.5, 0.375)
        self._camera_node.lookAt(0.0, 6.0, 0.0)
        self._camera_node.reparentTo(self._vehicle_pointer)

        if self._use_back_cam:
            self._back_camera_sensor = Panda3dCameraSensor(
                base,
                color=not self._use_depth,
                depth=self._use_depth,
                size=size,
                hfov=hfov,
                near_far=near_far,
                title='back cam')

            self._back_camera_node = self._back_camera_sensor.cam
            self._back_camera_node.setPos(0.0, -0.5, 0.375)
            self._back_camera_node.lookAt(0.0, -6.0, 0.0)
            self._back_camera_node.reparentTo(self._vehicle_pointer)

        # Car Simulator
        self._des_vel = None
        self._setup()

        # Input
        self.accept('escape', self._doExit)
        self.accept('r', self.reset)
        self.accept('f1', self._toggleWireframe)
        self.accept('f2', self._toggleTexture)
        self.accept('f3', self._view_image)
        self.accept('f5', self._doScreenshot)
        self.accept('q', self._forward_0)
        self.accept('w', self._forward_1)
        self.accept('e', self._forward_2)
        self.accept('a', self._left)
        self.accept('s', self._stop)
        self.accept('x', self._backward)
        self.accept('d', self._right)
        self.accept('m', self._mark)

        self._steering = 0.0  # degree
        self._engineForce = 0.0
        self._brakeForce = 0.0
        self._p = self._params.get('p', 1.25)
        self._d = self._params.get('d', 0.0)
        self._last_err = 0.0
        self._curr_time = 0.0
        self._accelClamp = self._params.get('accelClamp', 2.0)
        self._engineClamp = self._accelClamp * self._mass
        self._collision = False
        if self._run_as_task:
            self._mark_d = 0.0
            taskMgr.add(self._update_task, 'updateWorld')
            base.run()

    # _____HANDLER_____

    def _doExit(self):
        sys.exit(1)

    def _toggleWireframe(self):
        base.toggleWireframe()

    def _toggleTexture(self):
        base.toggleTexture()

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

    def _forward_0(self):
        self._des_vel = 1
        self._brakeForce = 0.0

    def _forward_1(self):
        self._des_vel = 2
        self._brakeForce = 0.0

    def _forward_2(self):
        self._des_vel = 4
        self._brakeForce = 0.0

    def _stop(self):
        self._des_vel = 0.0
        self._brakeForce = 0.0

    def _backward(self):
        self._des_vel = -4
        self._brakeForce = 0.0

    def _right(self):
        self._steering = np.min([np.max([-30, self._steering - 5]), 0.0])

    def _left(self):
        self._steering = np.max([np.min([30, self._steering + 5]), 0.0])

    def _view_image(self):
        from matplotlib import pyplot as plt
        image = self._camera_sensor.observe()[0]
        if self._use_depth:
            plt.imshow(image[:, :, 0], cmap='gray')
        else:
            import cv2

            def rgb2gray(rgb):
                return np.dot(rgb[..., :3], [0.299, 0.587, 0.114])

            image = rgb2gray(image)
            im = cv2.resize(image, (64, 36), interpolation=cv2.INTER_AREA
                            )  # TODO how does this deal with aspect ratio
            plt.imshow(im.astype(np.uint8), cmap='Greys_r')
        plt.show()

    def _mark(self):
        self._mark_d = 0.0

    # Setup
    def _setup(self):
        if hasattr(self, '_model_path'):
            # Collidable objects
            visNP = loader.loadModel(self._model_path)
            visNP.clearModelNodes()
            visNP.reparentTo(render)
            pos = (0., 0., 0.)
            visNP.setPos(pos[0], pos[1], pos[2])

            bodyNPs = BulletHelper.fromCollisionSolids(visNP, True)
            for bodyNP in bodyNPs:
                bodyNP.reparentTo(render)
                bodyNP.setPos(pos[0], pos[1], pos[2])

                if isinstance(bodyNP.node(), BulletRigidBodyNode):
                    bodyNP.node().setMass(0.0)
                    bodyNP.node().setKinematic(True)
                    bodyNP.setCollideMask(BitMask32.allOn())
                    self._world.attachRigidBody(bodyNP.node())
        else:
            ground = self._worldNP.attachNewNode(BulletRigidBodyNode('Ground'))
            shape = BulletPlaneShape(Vec3(0, 0, 1), 0)
            ground.node().addShape(shape)
            ground.setCollideMask(BitMask32.allOn())
            self._world.attachRigidBody(ground.node())
        self._place_vehicle()
        self._setup_light()
        self._setup_restart_pos()

    def _setup_restart_pos(self):
        self._restart_pos = []
        self._restart_index = 0
        if self._params.get('position_ranges', None) is not None:
            ranges = self._params['position_ranges']
            num_pos = self._params['num_pos']
            if self._params.get('range_type', 'random') == 'random':
                for _ in range(num_pos):
                    ran = ranges[np.random.randint(len(ranges))]
                    self._restart_pos.append(np.random.uniform(ran[0], ran[1]))
            elif self._params['range_type'] == 'fix_spacing':
                num_ran = len(ranges)
                num_per_ran = num_pos // num_ran
                for i in range(num_ran):
                    ran = ranges[i]
                    low = np.array(ran[0])
                    diff = np.array(ran[1]) - np.array(ran[0])
                    for j in range(num_per_ran):
                        val = diff * ((j + 0.0) / num_per_ran) + low
                        self._restart_pos.append(val)
        elif self._params.get('positions', None) is not None:
            self._restart_pos = self._params['positions']
        else:
            self._restart_pos = self._default_restart_pos()

    def _next_restart_pos_hpr(self):
        num = len(self._restart_pos)
        if num == 0:
            return None, None
        else:
            pos_hpr = self._restart_pos[self._restart_index]
            self._restart_index = (self._restart_index + 1) % num
            return pos_hpr[:3], pos_hpr[3:]

    def _next_random_restart_pos_hpr(self):
        num = len(self._restart_pos)
        if num == 0:
            return None, None
        else:
            index = np.random.randint(num)
            pos_hpr = self._restart_pos[index]
            self._restart_index = (self._restart_index + 1) % num
            return pos_hpr[:3], pos_hpr[3:]

    def _setup_light(self):
        alight = AmbientLight('ambientLight')
        alight.setColor(Vec4(0.5, 0.5, 0.5, 1))
        alightNP = render.attachNewNode(alight)
        render.clearLight()
        render.setLight(alightNP)

    # Vehicle
    def _default_pos(self):
        return (0.0, 0.0, 0.3)

    def _default_hpr(self):
        return (0.0, 0.0, 3.14)

    def _default_restart_pos():
        return [self._default_pos() + self._default_hpr()]

    def _get_speed(self):
        vel = self._vehicle.getCurrentSpeedKmHour() / 3.6
        return vel

    def _update(self, dt=1.0, coll_check=True):
        self._vehicle.setSteeringValue(self._steering, 0)
        self._vehicle.setSteeringValue(self._steering, 1)
        self._vehicle.setBrake(self._brakeForce, 0)
        self._vehicle.setBrake(self._brakeForce, 1)
        self._vehicle.setBrake(self._brakeForce, 2)
        self._vehicle.setBrake(self._brakeForce, 3)

        if dt >= self._step:
            # TODO maybe change number of timesteps
            for i in range(int(dt / self._step)):
                if self._des_vel is not None:
                    vel = self._get_speed()
                    err = self._des_vel - vel
                    d_err = (err - self._last_err) / self._step
                    self._last_err = err
                    self._engineForce = np.clip(
                        self._p * err + self._d * d_err, -self._accelClamp,
                        self._accelClamp) * self._mass
                self._vehicle.applyEngineForce(self._engineForce, 0)
                self._vehicle.applyEngineForce(self._engineForce, 1)
                self._vehicle.applyEngineForce(self._engineForce, 2)
                self._vehicle.applyEngineForce(self._engineForce, 3)
                self._world.doPhysics(self._step, 1, self._step)
            self._collision = self._is_contact()
        elif self._run_as_task:
            self._curr_time += dt
            if self._curr_time > 0.05:
                if self._des_vel is not None:
                    vel = self._get_speed()
                    self._mark_d += vel * self._curr_time
                    print(vel, self._mark_d, self._is_contact())
                    err = self._des_vel - vel
                    d_err = (err - self._last_err) / 0.05
                    self._last_err = err
                    self._engineForce = np.clip(
                        self._p * err + self._d * d_err, -self._accelClamp,
                        self._accelClamp) * self._mass
                self._curr_time = 0.0
                self._vehicle.applyEngineForce(self._engineForce, 0)
                self._vehicle.applyEngineForce(self._engineForce, 1)
                self._vehicle.applyEngineForce(self._engineForce, 2)
                self._vehicle.applyEngineForce(self._engineForce, 3)
            self._world.doPhysics(dt, 1, dt)
            self._collision = self._is_contact()
        else:
            raise ValueError(
                "dt {0} s is too small for velocity control".format(dt))

    def _stop_car(self):
        self._steering = 0.0
        self._engineForce = 0.0
        self._vehicle.setSteeringValue(0.0, 0)
        self._vehicle.setSteeringValue(0.0, 1)
        self._vehicle.applyEngineForce(0.0, 0)
        self._vehicle.applyEngineForce(0.0, 1)
        self._vehicle.applyEngineForce(0.0, 2)
        self._vehicle.applyEngineForce(0.0, 3)

        if self._des_vel is not None:
            self._des_vel = 0

        self._vehicle_node.setLinearVelocity(Vec3(0.0, 0.0, 0.0))
        self._vehicle_node.setAngularVelocity(Vec3(0.0, 0.0, 0.0))
        for i in range(self._vehicle.getNumWheels()):
            wheel = self._vehicle.getWheel(i)
            wheel.setRotation(0.0)
        self._vehicle_node.clearForces()

    def _place_vehicle(self, pos=None, hpr=None):
        if pos is None:
            pos = self._default_pos()
        if hpr is None:
            hpr = self._default_hpr()
        self._vehicle_pointer.setPos(pos[0], pos[1], pos[2])
        self._vehicle_pointer.setHpr(hpr[0], hpr[1], hpr[2])
        self._stop_car()

    def _addWheel(self, pos, front, radius=0.25):
        wheel = self._vehicle.createWheel()
        wheel.setChassisConnectionPointCs(pos)
        wheel.setFrontWheel(front)
        wheel.setWheelDirectionCs(Vec3(0, 0, -1))
        wheel.setWheelAxleCs(Vec3(1, 0, 0))
        wheel.setWheelRadius(radius)
        wheel.setMaxSuspensionTravelCm(40.0)
        wheel.setSuspensionStiffness(40.0)
        wheel.setWheelsDampingRelaxation(2.3)
        wheel.setWheelsDampingCompression(4.4)
        wheel.setFrictionSlip(1e2)
        wheel.setRollInfluence(0.1)

    # Task

    def _update_task(self, task):
        dt = globalClock.getDt()
        self._update(dt=dt)
        self._get_observation()
        return task.cont

    # Helper functions

    def _get_observation(self):
        self._obs = self._camera_sensor.observe()
        observation = []
        observation.append(self._obs[0])
        if self._use_back_cam:
            self._back_obs = self._back_camera_sensor.observe()
            observation.append(self._back_obs[0])
        observation = np.concatenate(observation, axis=2)
        return observation

    def _get_reward(self):
        reward = self._collision_reward if self._collision else self._get_speed(
        )
        return reward

    def _get_done(self):
        return self._collision

    def _get_info(self):
        info = {}
        info['pos'] = np.array(self._vehicle_pointer.getPos())
        info['hpr'] = np.array(self._vehicle_pointer.getHpr())
        info['vel'] = self._get_speed()
        info['coll'] = self._collision
        return info

    def _back_up(self):
        assert (self._use_vel)
        back_up_vel = self._params['back_up'].get('vel', -2.0)
        self._des_vel = back_up_vel
        back_up_steer = self._params['back_up'].get('steer', (-5.0, 5.0))
        # TODO
        self._steering = np.random.uniform(*back_up_steer)
        self._brakeForce = 0.
        duration = self._params['back_up'].get('duration', 1.0)
        self._update(dt=duration)
        self._des_vel = 0.0
        self._steering = 0.0
        self._update(dt=duration)
        self._brakeForce = 0.

    def _is_contact(self):
        result = self._world.contactTest(self._vehicle_node)
        num_contacts = result.getNumContacts()
        return result.getNumContacts() > 0

    # Environment functions

    def reset(self, pos=None, hpr=None, hard_reset=False, random_reset=False):
        if self._do_back_up and not hard_reset and \
                pos is None and hpr is None:
            if self._collision:
                self._back_up()
        else:
            if pos is None and hpr is None:
                if random_reset:
                    pos, hpr = self._next_random_restart_pos_hpr()
                else:
                    pos, hpr = self._next_restart_pos_hpr()
            self._place_vehicle(pos=pos, hpr=hpr)
        self._collision = False
        return self._get_observation()

    def step(self, action):
        self._steering = action[0]
        if action[1] == 0.0:
            self._brakeForce = 1000.
        else:
            self._brakeForce = 0.
        if self._use_vel:
            # Convert from m/s to km/h
            self._des_vel = action[1]
        else:
            self._engineForce = self._engineClamp * \
                ((action[1] - 49.5) / 49.5)

        self._update(dt=self._dt)
        observation = self._get_observation()
        reward = self._get_reward()
        done = self._get_done()
        info = self._get_info()
        return observation, reward, done, info
예제 #37
0
class GameStatePlaying(GState):
    VIDAS = 3
    #LEVEL_TIME = 100
    LEVEL_TIME = 50
    
    def start(self):
        self._playing_node = render.attachNewNode("playing-node")
        self._playing_node2d = aspect2d.attachNewNode("playing2d-node")
        
        self.keyMap = {"left":0, "right":0, "up":0, "down":0}
        
        base.accept( "escape" , sys.exit)

        props = WindowProperties()
        props.setCursorHidden(True)
        base.disableMouse()
        props.setMouseMode(WindowProperties.MRelative)
        base.win.requestProperties(props)
        base.win.movePointer(0, base.win.getXSize() / 2, base.win.getYSize() / 2)
        
        self._modulos = None
        self._paneles = None
        
        self._num_lvl = 1
        self._num_lvls = 2
        
        self.loadLevel()
        self.loadGUI()
        self.loadBkg()
        
        self._last_t = None
        self._last_t_space = 0
        
    def stop(self):
        self._playing_node.removeNode()
        self._playing_node2d.removeNode()
        
    def loadLevel(self):
        self._level_time = self.LEVEL_TIME
        self.initBullet()
        self._player = Player(self.world)
        self.loadMap()
        self.setAI()
        
    def initBullet(self):
        self.world = BulletWorld()
        #self.world.setGravity(Vec3(0, 0, -9.81))
        self.world.setGravity(Vec3(0, 0, -1.62))
        
        groundShape = BulletPlaneShape(Vec3(0, 0, 1), 0)
        groundNode = BulletRigidBodyNode('Ground')
        groundNode.addShape(groundShape)
        self.world.attachRigidBody(groundNode)
 
    def loadBkg(self):
        self.environ1 = loader.loadModel("../data/models/skydome")      
        self.environ1.reparentTo(self._playing_node)
        self.environ1.setPos(0,0,0)
        self.environ1.setScale(1)
        
        self.environ2 = loader.loadModel("../data/models/skydome")      
        self.environ2.reparentTo(self._playing_node)
        self.environ2.setP(180)
        self.environ2.setH(270)
        self.environ2.setScale(1)
        
        self.dirnlight1 = DirectionalLight("dirn_light1")
        self.dirnlight1.setColor(Vec4(1.0,1.0,1.0,1.0))
        self.dirnlightnode1 = self._playing_node.attachNewNode(self.dirnlight1)
        self.dirnlightnode1.setHpr(0,317,0)
        self._playing_node.setLight(self.dirnlightnode1)
        
        self.alight = AmbientLight('alight')
        self.alight.setColor(VBase4(0.05, 0.05, 0.05, 1))
        self.alight_node = self._playing_node.attachNewNode(self.alight)
        self._playing_node.setLight(self.alight_node)
    
        self.environ1 = loader.loadModel("../data/models/ground")      
        self.environ1.reparentTo(self._playing_node)
        self.environ1.setPos(0,0,0)
        self.environ1.setScale(1)
        
        
    def loadGUI(self):
        self.vidas_imgs = list()
        w = 0.24
        for i in range(self.VIDAS):
            image_warning = OnscreenImage(image = '../data/Texture/signal_warning.png', pos=(-1 + i*w, 0, 0.85), parent=self._playing_node2d)
            image_warning.setScale(0.1)
            image_warning.setTransparency(TransparencyAttrib.MAlpha)
            image_warning.hide()
            
            image_ok = OnscreenImage(image = '../data/Texture/signal_ok.png', pos=(-1 + i*w, 0, 0.85), parent=self._playing_node2d)
            image_ok.setScale(0.1)
            image_ok.setTransparency(TransparencyAttrib.MAlpha)
            image_ok.show()
            self.vidas_imgs.append((image_ok, image_warning))
            
        self._level_time_O = OnscreenText(text = '', pos = (0, 0.85), scale = 0.14, fg=(1.0, 1.0, 1.0, 1.0), bg=(0.0, 0.0, 0.0, 1.0), parent=self._playing_node2d)
        
        
    def loadMap(self):
        if (self._modulos is not None):
            for m in self._modulos:
                m.remove()
        if (self._paneles is not None):
            for p in self._paneles:
                p.remove()
                
        self._tp = TiledParser("map"+str(self._num_lvl))
        self._modulos, self._paneles = self._tp.load_models(self.world, self._playing_node)
      
    def setAI(self):
        taskMgr.add(self.update, 'Update')
            
    def update(self, task):
        if (task.frame > 1):
            self.world.doPhysics(globalClock.getDt())
            self._level_time -= globalClock.getDt()
            self._level_time_O.setText(str(int(self._level_time)))
        
        for panel in self._paneles:
            contact = self.world.contactTestPair(self._player.getRBNode(), panel.getRBNode())
            if contact.getNumContacts() > 0:
                panel.manipulate()
                
        brokens = 0
        for panel in self._paneles:
            if panel.isBroken():
                brokens += 1
        #print brokens
        
        for i, vida_imgs in enumerate(self.vidas_imgs):
            if i < len(self.vidas_imgs) - brokens:
                vida_imgs[0].show()
                vida_imgs[1].hide()
            else:
                vida_imgs[0].hide()
                vida_imgs[1].show()
            
        if brokens > self.VIDAS:
            self.gameOver()
            return task.done
            
        if self._level_time <= 0:
            self._num_lvl += 1
            if self._num_lvl <= self._num_lvls:
                self.nextLevel()
            else:
                self.theEnd()
            return task.done
        return task.cont

    def gameOver(self):
        taskMgr.remove('player-task')
        taskMgr.remove('panel-task')
        taskMgr.remove('panel-sound-task')
        self._mission_text_O = OnscreenText(text = 'Game Over', pos = (0, 0), scale = 0.5, fg=(1.0, 1.0, 1.0, 1.0), bg=(0.0, 0.0, 0.0, 1.0))
        taskMgr.add(self.gameOverTransition, 'game-over-transition')
        #self.loadLevel()
        print "Game Over"
        
    def gameOverTransition(self, task):
        base.win.movePointer(0, base.win.getXSize() / 2, base.win.getYSize() / 2)
        if task.time > 3.0:
            self._mission_text_O.hide()
            props = WindowProperties()
            props.setCursorHidden(False)
            base.win.requestProperties(props)
            self._state_context.changeState(gameStateMenu.GameStateMenu(self._state_context))
            print "MENU"
            return task.done

        return task.cont
        
    def nextLevel(self):
        taskMgr.remove('player-task')
        taskMgr.remove('panel-task')
        taskMgr.remove('panel-sound-task')
        self._mission_text_O = OnscreenText(text = 'Mission\nComplete', pos = (0, 0), scale = 0.5, fg=(1.0, 1.0, 1.0, 1.0), bg=(0.0, 0.0, 0.0, 1.0))
        taskMgr.add(self.nextLevelTransition, 'next-Level-transition')
        print "Mission Complete"
        
    def nextLevelTransition(self, task):
        base.win.movePointer(0, base.win.getXSize() / 2, base.win.getYSize() / 2)
        if task.time > 3.0:
            print "Next Level"
            self._mission_text_O.hide()
            self.loadLevel()
            return task.done

        return task.cont
        
    def theEnd(self):
        taskMgr.remove('player-task')
        taskMgr.remove('panel-task')
        taskMgr.remove('panel-sound-task')
        self._mission_text_O = OnscreenText(text = '.       The End       .', pos = (0, 0), scale = 0.5, fg=(1.0, 1.0, 1.0, 1.0), bg=(0.0, 0.0, 0.0, 1.0))
        taskMgr.add(self.theEndTransition, 'theEnd-transition')
        #self.loadLevel()
        print "Mission Complete"
        
    def theEndTransition(self, task):
        base.win.movePointer(0, base.win.getXSize() / 2, base.win.getYSize() / 2)
        if task.time > 3.0:
            self._mission_text_O.hide()
            props = WindowProperties()
            props.setCursorHidden(False)
            base.win.requestProperties(props)
            self._state_context.changeState(gameStateMenu.GameStateMenu(self._state_context))
            print "The End"
            return task.done

        return task.cont
예제 #38
0
class App(ShowBase):
    def __init__(self, args):
        ShowBase.__init__(self)

        headless = args["--headless"]
        width = args["--width"]
        height = args["--height"]

        self.save_path = args["<save_path>"]

        globalClock.setMode(ClockObject.MNonRealTime)
        globalClock.setDt(0.02)  # 20ms per frame

        self.setBackgroundColor(0.9, 0.9, 0.9)
        self.createLighting()

        if not headless:
            self.setupCamera(width, height, Vec3(0, -20, 0), Vec3(0, 0, 0))

        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81))
        self.setupDebug()
        self.createPlane(Vec3(0, 0, -11))

        self.animated_rig = ExposedJointRig("walking", {"walk": "walking-animation.egg"})
        self.animated_rig.reparentTo(self.render)
        self.animated_rig.setPos(0, 0, 0)
        self.animated_rig.setScale(0.1, 0.1, 0.1)
        self.animated_rig.createLines(VBase4(0.5, 0.75, 1.0, 1.0))

        self.physical_rig = RigidBodyRig()
        self.physical_rig.reparentTo(self.render)
        self.physical_rig.setPos(0, 0, 0)
        self.physical_rig.setScale(0.1, 0.1, 0.1)
        self.physical_rig.createColliders(self.animated_rig)
        self.physical_rig.createConstraints(offset_scale=0.1)
        self.physical_rig.setCollideMask(BitMask32.bit(1))
        self.physical_rig.attachRigidBodies(self.world)
        self.physical_rig.attachConstraints(self.world)

        self.disableCollisions()
        # self.setAnimationFrame(0)
        self.physical_rig.matchPose(self.animated_rig)

        self.frame_count = self.animated_rig.getNumFrames("walk")
        self.babble_count = 10

        self.train_count = self.frame_count * self.babble_count * 1000
        self.test_count = self.frame_count * self.babble_count * 100

        widgets = [
            progressbar.SimpleProgress(),
            " ",
            progressbar.Percentage(),
            " ",
            progressbar.Bar(),
            " ",
            progressbar.FileTransferSpeed(format="%(scaled)5.1f/s"),
            " ",
            progressbar.ETA(),
            " ",
            progressbar.Timer(format="Elapsed: %(elapsed)s"),
        ]
        self.progressbar = progressbar.ProgressBar(widgets=widgets, max_value=self.train_count + self.test_count)
        self.progressbar.start()

        self.X_train = []
        self.Y_train = []

        self.X_test = []
        self.Y_test = []

        self.accept("escape", sys.exit)
        self.taskMgr.add(self.update, "update")

    def disableCollisions(self):
        for i in range(32):
            self.world.setGroupCollisionFlag(i, i, False)
        self.world.setGroupCollisionFlag(0, 1, True)

    def setupDebug(self):
        node = BulletDebugNode("Debug")
        node.showWireframe(True)

        self.world.setDebugNode(node)

        np = self.render.attachNewNode(node)
        np.show()

    def createLens(self, aspect_ratio, fov=60.0, near=1.0, far=1000.0):
        lens = PerspectiveLens()
        lens.setFov(fov)
        lens.setAspectRatio(aspect_ratio)
        lens.setNearFar(near, far)
        return lens

    def setupCamera(self, width, height, pos, look):
        self.cam.setPos(pos)
        self.cam.lookAt(look)
        self.cam.node().setLens(self.createLens(width / height))

    def createLighting(self):
        light = DirectionalLight("light")
        light.setColor(VBase4(0.2, 0.2, 0.2, 1))

        np = self.render.attachNewNode(light)
        np.setPos(10, -10, 20)
        np.lookAt(0, 0, 0)

        self.render.setLight(np)

        light = AmbientLight("ambient")
        light.setColor(VBase4(0.4, 0.4, 0.4, 1))

        np = self.render.attachNewNode(light)

        self.render.setLight(np)

    def createPlane(self, pos):
        rb = BulletRigidBodyNode("plane")
        rb.addShape(BulletPlaneShape(Vec3(0, 0, 1), 1))
        rb.setFriction(1.0)
        rb.setAnisotropicFriction(1.0)
        rb.setRestitution(1.0)

        np = self.render.attachNewNode(rb)
        np.setPos(pos)
        np.setCollideMask(BitMask32.bit(0))

        self.world.attachRigidBody(rb)

        return np

    def save(self):
        data = ((self.X_train, self.Y_train), (self.X_test, self.Y_test))

        f = open(self.save_path, "wb")
        pickle.dump(data, f)
        f.close()

        self.progressbar.finish()

    def setAnimationFrame(self, frame):
        self.animated_rig.pose("walk", frame)
        self.physical_rig.matchPose(self.animated_rig)

    def generate(self, count):
        if count % self.babble_count == 0:
            # self.setAnimationFrame(int(count / self.babble_count))
            self.physical_rig.matchPose(self.animated_rig)

        joint_positions = self.physical_rig.getJointPositions()
        joint_rotations = self.physical_rig.getJointRotations()

        linear_velocities = self.physical_rig.getLinearVelocities()
        angular_velocities = self.physical_rig.getAngularVelocities()

        Y = self.physical_rig.babble()
        self.world.doPhysics(globalClock.getDt(), 10, 1.0 / 180.0)

        next_joint_positions = self.physical_rig.getJointPositions()
        next_joint_rotations = self.physical_rig.getJointRotations()

        target_directions = next_joint_positions - joint_positions
        target_rotations = get_angle_vec(next_joint_rotations - joint_rotations)

        X = np.concatenate(
            [
                joint_positions,
                joint_rotations,
                linear_velocities,
                angular_velocities,
                target_directions,
                target_rotations,
            ]
        )

        return X, Y

    def update(self, task):
        # if globalClock.getFrameCount() % self.babble_count == 0:
        #     self.setAnimationFrame(globalClock.getFrameCount() / self.babble_count)
        # self.physical_rig.babble()
        self.world.doPhysics(globalClock.getDt(), 10, 1.0 / 180.0)
        return task.cont

        curr_train_count = len(self.X_train)
        curr_test_count = len(self.X_test)

        train_complete = curr_train_count == self.train_count
        test_complete = curr_test_count == self.test_count

        if not train_complete:  # motor babbling
            X, Y = self.generate(curr_train_count)
            self.X_train.append(X)
            self.Y_train.append(Y)
        elif not test_complete:  # move positions
            X, Y = self.generate(curr_test_count)
            self.X_test.append(X)
            self.Y_test.append(Y)

        if train_complete and test_complete:
            self.save()
            sys.exit()
            return task.done

        self.progressbar.update(curr_train_count + curr_test_count)

        return task.cont
예제 #39
0
class GameLogic(ShowBase):
    def __init__(self,pandaBase):
        self.pandaBase = pandaBase
        self.pandaBase.enableParticles()
        self.accept("DemarrerPartie",self.startGame)
        
        
        #Vérifier si la connexion à la base de donnée est bien établite 
        try: 
            # CREE LE DAO ET LE DTO
            self.leDao = DAO_B_Oracle("e1529743","AAAaaa111","delta/decinfo.edu")
            self.leDto = self.leDao.lire()
            self.leDto.verifier()
            self.leDao.deconnection()
        except:
            self.leDto = DTOdefault()
            ctypes.windll.user32.MessageBoxA(0, "Erreur lors de la connexion a la base de donnee. Les valeurs par defaut sont utilisees !", "Valeurs par defaut", 0)

        
    def setup(self,niveau):
        self.setupBulletPhysics()

        self.setupCamera()
        self.setupMap(niveau)
        self.setupLightAndShadow()

        #Création d'une carte de base
        #self.carte.creerCarteParDefaut()
      

        if (niveau != "quick"):
            print("hasard")
            self.map.construireMapDto() 
        else:
            self.map.construireMapHasard() 
            


        #A besoin des éléments de la map
        self.setupControle()
        self.setupInterface()

        #Fonction d'optimisation
        #DOIVENT ÊTRE APPELÉE APRÈS LA CRÉATION DE LA CARTE
        #Ça va prendre les modèles qui ne bougent pas et en faire un seul gros
        #en faisant un seul gros noeud avec
        self.map.figeObjetImmobile()

        #DEBUG: Décommenter pour affiche la hiérarchie
        #self.pandaBase.startDirect()

        messenger.send("ChargementTermine")

    def startGame(self,niveau):
        self.setup(niveau)
        print (niveau)
        #On démarrer l'effet du compte à rebour.
        #La fonction callBackDebutPartie sera appelée à la fin
        self.interfaceMessage.effectCountDownStart(self.leDto.mess_countdown_time[2],self.callBackDebutPartie)
        #self.row[2], row[3]interfaceMessage.effectMessageGeneral(self.leDto.mess_accueil_content[1],self.leDto.mess_accueil_time[2])

    def setupBulletPhysics(self):
        debugNode = BulletDebugNode('Debug')
        debugNode.showWireframe(True)
        debugNode.showConstraints(True)
        debugNode.showBoundingBoxes(False)
        debugNode.showNormals(False)
        self.debugNP = render.attachNewNode(debugNode)

        self.mondePhysique = BulletWorld()
        self.mondePhysique.setGravity(Vec3(0, 0, -9.81))
        self.mondePhysique.setDebugNode(self.debugNP.node())
        taskMgr.add(self.updatePhysics, "updatePhysics")

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

    def setupCamera(self):
        #On doit désactiver le contrôle par défaut de la caméra autrement on ne peut pas la positionner et l'orienter
        self.pandaBase.disableMouse()

        #Le flag pour savoir si la souris est activée ou non n'est pas accessible
        #Petit fail de Panda3D
        taskMgr.add(self.updateCamera, "updateCamera")
        self.setupTransformCamera()


    def setupTransformCamera(self):
        #Défini la position et l'orientation de la caméra
        self.positionBaseCamera = Vec3(0,-18,32)
        camera.setPos(self.positionBaseCamera)
        #On dit à la caméra de regarder l'origine (point 0,0,0)
        camera.lookAt(render)

    def setupMap(self,niveau):
        self.map = Map(self.mondePhysique, self.leDto, niveau)
    
        #On construire la carte comme une coquille, de l'extérieur à l'intérieur
        #Décor et ciel
        self.map.construireDecor(camera)
        #Plancher de la carte
        self.map.construirePlancher()
        #Murs et éléments de la map

    def setupLightAndShadow(self):
        #Lumière du skybox
        plight = PointLight('Lumiere ponctuelle')
        plight.setColor(VBase4(1,1,1,1))
        plnp = render.attachNewNode(plight)
        plnp.setPos(0,0,0)
        camera.setLight(plnp)

        #Simule le soleil avec un angle
        dlight = DirectionalLight('Lumiere Directionnelle')
        dlight.setColor(VBase4(0.8, 0.8, 0.6, 1))
        dlight.get_lens().set_fov(75)
        dlight.get_lens().set_near_far(0.1, 60)
        dlight.get_lens().set_film_size(30,30)
        dlnp = render.attachNewNode(dlight)
        dlnp.setPos(Vec3(-2,-2,7))
        dlnp.lookAt(render)
        render.setLight(dlnp)

        #Lumière ambiante
        alight = AmbientLight('Lumiere ambiante')
        alight.setColor(VBase4(0.25, 0.25, 0.25, 1))
        alnp  = render.attachNewNode(alight)
        render.setLight(alnp)

        #Ne pas modifier la valeur 1024 sous peine d'avoir un jeu laid ou qui lag
        dlight.setShadowCaster(True, 1024,1024)
        #On doit activer l'ombre sur les modèles
        render.setShaderAuto()

    def setupControle(self,):
        #Créer le contrôle
        #A besoin de la liste de tank pour relayer correctement le contrôle
        self.inputManager = InputManager(self.map.listTank,self.debugNP,self.pandaBase)
        self.accept("initCam",self.setupTransformCamera)

    def setupInterface(self):
        self.interfaceTank = []
        self.interfaceTank.append(InterfaceTank(0,self.map.listTank[0].couleur))
        self.interfaceTank.append(InterfaceTank(1,self.map.listTank[1].couleur))

        self.interfaceMessage = InterfaceMessage(self.leDto)

    def callBackDebutPartie(self):
        #Quand le message d'introduction est terminé, on permet aux tanks de bouger
        self.inputManager.debuterControle()

    #Mise à jour du moteur de physique
    def updateCamera(self,task):
        #On ne touche pas à la caméra si on est en mode debug
        if(self.inputManager.mouseEnabled):
            return task.cont

        vecTotal = Vec3(0,0,0)
        distanceRatio = 1.0
        if (len(self.map.listTank) != 0):
            for tank in self.map.listTank:
                vecTotal += tank.noeudPhysique.getPos()
            vecTotal = vecTotal/len(self.map.listTank)

        vecTotal.setZ(0)
        camera.setPos(vecTotal + self.positionBaseCamera)
        return task.cont

    #Mise à jour du moteur de physique
    def updatePhysics(self,task):
        dt = globalClock.getDt()
        messenger.send("appliquerForce")
        self.mondePhysique.doPhysics(dt)
        #print(len(self.mondePhysique.getManifolds()))

        #Analyse de toutes les collisions
        for entrelacement in self.mondePhysique.getManifolds():
            node0 = entrelacement.getNode0()
            node1 = entrelacement.getNode1()
            self.map.traiterCollision(node0, node1)
        return task.cont

    def updateCarte(self,task):
        #print task.time
        self.map.update(task.time)
        return task.cont
예제 #40
0
파일: conv_env.py 프로젝트: Shirnia/l_sim
class MyApp(ShowBase):
    def __init__(self, screen_size=84, DEBUGGING=False, human_playable=False):
        ShowBase.__init__(self)
        self.forward_button = KeyboardButton.ascii_key(b'w')
        self.backward_button = KeyboardButton.ascii_key(b's')

        self.fps = 20
        self.human_playable = human_playable
        self.actions = 3
        self.last_frame_start_time = time.time()
        self.action_buffer = [1, 1, 1]
        self.last_teleport_time = 0.0
        self.time_to_teleport = False

        if self.human_playable is False:
            winprops = WindowProperties.size(screen_size, screen_size)
            fbprops = FrameBufferProperties()
            fbprops.set_rgba_bits(8, 8, 8, 0)
            fbprops.set_depth_bits(24)
            self.pipe = GraphicsPipeSelection.get_global_ptr().make_module_pipe('pandagl')
            self.imageBuffer = self.graphicsEngine.makeOutput(
                self.pipe,
                "image buffer",
                1,
                fbprops,
                winprops,
                GraphicsPipe.BFRefuseWindow)


            self.camera = Camera('cam')
            self.cam = NodePath(self.camera)
            self.cam.reparentTo(self.render)

            self.dr = self.imageBuffer.makeDisplayRegion()
            self.dr.setCamera(self.cam)

        self.render.setShaderAuto()
        self.cam.setPos(0.5, 0, 6)
        self.cam.lookAt(0.5, 0, 0)

        # Create Ambient Light
        self.ambientLight = AmbientLight('ambientLight')
        self.ambientLight.setColor((0.2, 0.2, 0.2, 1))
        self.ambientLightNP = self.render.attachNewNode(self.ambientLight)
        self.render.setLight(self.ambientLightNP)

        # Spotlight
        self.light = Spotlight('light')
        self.light.setColor((0.9, 0.9, 0.9, 1))
        self.lightNP = self.render.attachNewNode(self.light)
        self.lightNP.setPos(0, 10, 10)
        self.lightNP.lookAt(0, 0, 0)
        self.lightNP.node().getLens().setFov(40)
        self.lightNP.node().getLens().setNearFar(10, 100)
        self.lightNP.node().setShadowCaster(True, 1024, 1024)
        self.render.setLight(self.lightNP)

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

        if DEBUGGING is True:
            debugNode = BulletDebugNode('Debug')
            debugNode.showWireframe(True)
            debugNode.showConstraints(True)
            debugNode.showBoundingBoxes(False)
            debugNode.showNormals(False)
            debugNP = render.attachNewNode(debugNode)
            debugNP.show()
            self.world.setDebugNode(debugNP.node())

        self.finger_speed_mps = 0.0
        self.penalty_applied = False
        self.teleport_cooled_down = True
        self.fps = 20
        self.framecount = 0
        self.reset()


    def reset(self):
        namelist = ['Ground',
                    'Conveyor',
                    'Finger',
                    'Block',
                    'Scrambled Block',
                    'Not Rewardable',
                    'Teleport Me']
        for child in self.render.getChildren():
            for test in namelist:
                if child.node().name == test:
                    self.world.remove(child.node())
                    child.removeNode()
                    break


        # Plane
        self.plane_shape = BulletPlaneShape(Vec3(0, 0, 1), 1)
        self.plane_node = BulletRigidBodyNode('Ground')
        self.plane_node.addShape(self.plane_shape)
        self.plane_np = self.render.attachNewNode(self.plane_node)
        self.plane_np.setPos(0.0, 0.0, -1.0)
        self.world.attachRigidBody(self.plane_node)

        # Conveyor
        self.conv_node = BulletRigidBodyNode('Conveyor')
        self.conv_node.setFriction(1.0)
        self.conv_np = self.render.attachNewNode(self.conv_node)
        self.conv_shape = BulletBoxShape(Vec3(100.0, 1.0, 0.05))
        self.conv_node.setMass(1000.0)
        self.conv_np.setPos(-95.0, 0.0, 0.1)
        self.conv_node.addShape(self.conv_shape)
        self.world.attachRigidBody(self.conv_node)
        self.model = loader.loadModel('assets/conv.egg')
        self.model.flattenLight()
        self.model.reparentTo(self.conv_np)


        # Finger
        self.finger_node = BulletRigidBodyNode('Finger')
        self.finger_node.setFriction(1.0)
        self.finger_np = self.render.attachNewNode(self.finger_node)
        self.finger_shape = BulletCylinderShape(0.1, 0.25, ZUp)
        self.finger_node.setMass(0)
        self.finger_np.setPos(1.8, 0.0, 0.24 + 0.0254*3.5)
        self.finger_node.addShape(self.finger_shape)
        self.world.attachRigidBody(self.finger_node)
        self.model = loader.loadModel('assets/finger.egg')
        self.model.flattenLight()
        self.model.reparentTo(self.finger_np)

        self.blocks = []
        for block_num in range(15):
            new_block = self.spawn_block(Vec3(28, random.uniform(-3, 3), (0.2 * block_num) + 2.0),
                                         2, random.choice([4, 4,
                                                           6]), random.choice([10,
                                                                                     11,
                                                                                     12,
                                                                                     13,
                                                                                     14,
                                                                                     15, 15,
                                                                                     16, 16,
                                                                                     17, 17,
                                                                                     18, 18, 18, 18,
                                                                                     19, 19, 19, 19,
                                                                                     20, 20, 20, 20, 20,
                                                                                     21, 21, 21, 21,
                                                                                     22, 22, 22, 23,
                                                                                     23, 23, 23, 23,
                                                                                     24]))
            # new_block = self.spawn_block(Vec3(18, 0, (0.2 * block_num) + 2.0),
            #                              2, 4, 24)
            self.blocks.append(new_block)

        self.finger_speed_mps = 0.0
        self.penalty_applied = False
        self.teleport_cooled_down = True
        self.fps = 20
        self.framecount = 0
        self.last_teleport_time = 0.0
        self.time_to_teleport = False

        return self.step(1)[0]


    def spawn_block(self, location, z_inches, y_inches, x_inches):
        """
        Spawns a block
        """
        node = BulletRigidBodyNode('Block')
        node.setFriction(1.0)
        block_np = self.render.attachNewNode(node)
        shape = BulletBoxShape(Vec3(0.0254*y_inches, 0.0254*x_inches, 0.0254*z_inches))
        node.setMass(1.0)
        block_np.setPos(location)
        block_np.setHpr(random.uniform(-60, 60), 0.0, 0.0)
        node.addShape(shape)
        self.world.attachRigidBody(node)
        model = loader.loadModel('assets/bullet-samples/models/box.egg')
        model.setH(90)
        model.setSx(0.0254*x_inches*2)
        model.setSy(0.0254*y_inches*2)
        model.setSz(0.0254*z_inches*2)
        model.flattenLight()
        model.reparentTo(block_np)
        block_np.node().setTag('scrambled', 'False')
        return block_np

    def get_camera_image(self, requested_format=None):
        """
        Returns the camera's image, which is of type uint8 and has values
        between 0 and 255.
        The 'requested_format' argument should specify in which order the
        components of the image must be. For example, valid format strings are
        "RGBA" and "BGRA". By default, Panda's internal format "BGRA" is used,
        in which case no data is copied over.
        """
        tex = self.dr.getScreenshot()
        if requested_format is None:
            data = tex.getRamImage()
        else:
            data = tex.getRamImageAs(requested_format)
        image = np.frombuffer(data, np.uint8)  # use data.get_data() instead of data in python 2
        image.shape = (tex.getYSize(), tex.getXSize(), tex.getNumComponents())
        image = np.flipud(image)
        return image[:,:,:3]

    def reset_conv(self):
        conveyor_dist_left = 1 - self.conv_np.getPos()[0]
        if conveyor_dist_left < 10:
            self.conv_np.setX(-95.0)
            self.conv_np.setY(0.0)


    def check_rewards(self):
        reward = 0
        for block in self.blocks:
            block_x, block_y, block_z = block.getPos()
            if block_z > 0.16 and block_x > -1 and block_x < 0:
                block.node().setTag('scrambled', 'True')
            if block_x < 2.3 and block_z < 0.16 and block.node().getTag('scrambled') == 'True':
                block.node().setTag('scrambled', 'False')
                reward = 1

        return reward

    def check_teleportable(self, blocks_per_minute):
        self.time = self.framecount/self.fps

        # if self.time % (1/(blocks_per_minute/60)) < 0.1:
        #     self.time_to_teleport = True
        # else:
        #     self.time_to_teleport = False
        #     self.teleport_cooled_down = True
        teleport_cooled_down = True if self.last_teleport_time + 0.4 < self.time else False
        if random.choice([True,
                          False, False, False]) and teleport_cooled_down:
            self.last_teleport_time = self.time
            self.time_to_teleport = True

        for block in self.blocks:
            block_x = block.getPos()[0]
            if block_x > 5:
                block.node().setTag('scrambled', 'False')
                if self.time_to_teleport is True:
                    self.time_to_teleport = False
                    block.setX(-3)
                    block.setY(0.0)
                    block.setZ(2.0)
                    block.setHpr(random.uniform(-60, 60), 0.0, 0.0)

    def step(self, action):
        dt = 1/self.fps
        self.framecount += 1
        max_dist = 1.1
        # Move finger
        finger_max_speed = 2
        finger_accel = 10.0
        finger_deccel = 10.0
        self.action_buffer.pop(0)
        self.action_buffer.append(action)
        action = self.action_buffer[0]


        if action == 0:
            self.finger_speed_mps += dt * finger_accel
            if self.finger_speed_mps > finger_max_speed:
                self.finger_speed_mps = 2
        if action == 1:
            if self.finger_speed_mps > 0.01:
                self.finger_speed_mps -= finger_deccel * dt
            if self.finger_speed_mps < -0.01:
                self.finger_speed_mps += finger_deccel * dt
        if action == 2:
            self.finger_speed_mps -= dt * finger_accel
            if self.finger_speed_mps < -finger_max_speed:
                self.finger_speed_mps = -finger_max_speed

        real_displacement = self.finger_speed_mps * dt
        self.finger_np.setY(self.finger_np.getY() + real_displacement)

        if self.finger_np.getY() > max_dist:
            self.finger_np.setY(max_dist)
            self.finger_speed_mps = 0
        if self.finger_np.getY() < -max_dist:
            self.finger_np.setY(-max_dist)
            self.finger_speed_mps = 0


        # self.world.doPhysics(dt, 5, 1.0/120.0)
        self.world.doPhysics(dt, 20, 1.0/240.0)
        self.reset_conv()
        self.check_teleportable(blocks_per_minute=59)

        # Keep the conveyor moving
        self.conv_np.node().setLinearVelocity(Vec3(1.0, 0.0, 0.0))

        if self.human_playable is False:
            self.graphicsEngine.renderFrame()
            TransformState.garbageCollect()
            RenderState.garbageCollect()
            image = self.get_camera_image()
        else:
            image = None

        score = 0
        score += self.check_rewards()
        done = False

        return image, score, done

    def update(self, task):
        is_down = self.mouseWatcherNode.is_button_down
        next_act = 1
        if is_down(self.forward_button):
            next_act = 0
        if is_down(self.backward_button):
            next_act = 2
        _, reward, _ = self.step(next_act)
        if reward != 0:
            print(reward)
        last_frame_duration = time.time() - self.last_frame_start_time
        if last_frame_duration < (1/self.fps):
            time.sleep((1/self.fps) - last_frame_duration)
        self.last_frame_start_time = time.time()
        return task.cont
class TestApplication(ShowBase):

  def __init__(self):

    ShowBase.__init__(self)
    
    # game objects   
    self.controlled_obj_index_ = 0
    self.level_sectors_ = []
    self.controlled_objects_ = []
    
    # active objects
    self.active_sector_ = None

    self.setupRendering()
    self.setupControls()
    self.setupPhysics()
    self.clock_ = ClockObject()
    self.kinematic_mode_ = False
    
    # Task
    logging.info("TestSectors demo started")
    taskMgr.add(self.update, 'updateWorld')


  def setupRendering(self):

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

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

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

    self.render.clearLight()
    self.render.setLight(alightNP)
    self.render.setLight(dlightNP)
    
    self.setupBackgroundImage()
    
  def setupBackgroundImage(self):
    
    
    image_file = Filename(rospack.RosPack().get_path(BACKGROUND_IMAGE_PACKAGE) + '/resources/backgrounds/' + BACKGROUND_IMAGE_PATH)
    
    # check if image can be loaded
    img_head = PNMImageHeader()
    if not img_head.readHeader(image_file ):
        raise IOError, "PNMImageHeader could not read file %s. Try using absolute filepaths"%(image_file.c_str())
        sys.exit()
        
    # Load the image with a PNMImage
    w = img_head.getXSize()
    h = img_head.getYSize()
    img = PNMImage(w,h)
    #img.alphaFill(0)
    img.read(image_file) 
    
    texture = Texture()        
    texture.setXSize(w)
    texture.setYSize(h)
    texture.setZSize(1)    
    texture.load(img)
    texture.setWrapU(Texture.WM_border_color) # gets rid of odd black edges around image
    texture.setWrapV(Texture.WM_border_color)
    texture.setBorderColor(LColor(0,0,0,0))
    
    # creating CardMaker to hold the texture
    cm = CardMaker('background')
    cm.setFrame(-0.5*w,0.5*w,-0.5*h,0.5*h)  # This configuration places the image's topleft corner at the origin (left, right, bottom, top)
    background_np = NodePath(cm.generate())            
    background_np.setTexture(texture)
    
    background_np.reparentTo(self.render)
    background_np.setPos(BACKGROUND_POSITION)
    background_np.setScale(BACKGROUND_IMAGE_SCALE)
  

  def setupControls(self):

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

    # Inputs (Polling)
    self.input_state_ = InputState()
    self.input_state_.watchWithModifiers("right","arrow_right")
    self.input_state_.watchWithModifiers('left', 'arrow_left')
    self.input_state_.watchWithModifiers('jump', 'arrow_up')
    self.input_state_.watchWithModifiers('stop', 'arrow_down')
    self.input_state_.watchWithModifiers('roll_right', 'c')
    self.input_state_.watchWithModifiers('roll_left', 'z')
    self.input_state_.watchWithModifiers('roll_stop', 'x')


    self.title = addTitle("Panda3D: Kinematic Objects")
    self.inst1 = addInstructions(0.06, "ESC: Quit")
    self.inst2 = addInstructions(0.12, "Up/Down: Jump/Stop")
    self.inst3 = addInstructions(0.18, "Left/Right: Move Left / Move Rigth")
    self.inst4 = addInstructions(0.24, "z/x/c : Rotate Left/ Rotate Stop / Rotate Right")
    self.inst5 = addInstructions(0.30, "n: Select Next Character")
    self.inst6 = addInstructions(0.36, "k: Toggle Kinematic Mode")
    self.inst7 = addInstructions(0.42, "f1: Toggle Wireframe")
    self.inst8 = addInstructions(0.48, "f2: Toggle Texture")
    self.inst9 = addInstructions(0.54, "f3: Toggle BulletDebug")
    self.inst10 = addInstructions(0.60, "f5: Capture Screenshot")
    
  def processCollisions(self):
    
    contact_manifolds = self.physics_world_.getManifolds()
    for cm in contact_manifolds:      
      node0 = cm.getNode0()
      node1 = cm.getNode1()
      col_mask1 = node0.getIntoCollideMask()
      col_mask2 = node1.getIntoCollideMask()
      
      
      if (col_mask1 == col_mask2) and \
        (col_mask1 == SECTOR_ENTERED_BITMASK) and \
        self.active_sector_.getSectorPlaneNode().getName() != node0.getName():
        
        logging.info('Collision between %s and %s'%(node0.getName(),node1.getName()))
        sector = [s for s in self.level_sectors_ if s.getSectorPlaneNode().getName() == node0.getName()]
        sector = [s for s in self.level_sectors_ if s.getSectorPlaneNode().getName() == node1.getName()] + sector
        
        self.switchToSector(sector[0])
        logging.info("Sector %s entered"%(self.active_sector_.getName()))
        
  def switchToSector(self,sector):       
    
    obj_index = self.controlled_obj_index_
    character_obj = self.controlled_objects_[obj_index]
    
    if self.active_sector_ is not None:
      self.active_sector_.releaseCharacter()
    
    character_obj.setY(sector,0)
    character_obj.setH(sector,0)
    self.active_sector_ = sector
    
    self.active_sector_.constrainCharacter(character_obj)
    
    self.active_sector_.enableDetection(False)
    sectors = [s for s in self.level_sectors_ if s != self.active_sector_]
    for s in sectors:
      s.enableDetection(True)

  def setupPhysics(self):

    # setting up physics world and parent node path 
    self.physics_world_ = BulletWorld()
    self.world_node_ = self.render.attachNewNode('world')
    self.cam.reparentTo(self.world_node_)
    self.physics_world_.setGravity(Vec3(0, 0, -9.81))

    self.debug_node_ = self.world_node_.attachNewNode(BulletDebugNode('Debug'))
    self.debug_node_.node().showWireframe(True)
    self.debug_node_.node().showConstraints(True)
    self.debug_node_.node().showBoundingBoxes(True)
    self.debug_node_.node().showNormals(True)
    self.physics_world_.setDebugNode(self.debug_node_.node())
    self.debug_node_.hide()
    
    # setting up collision groups
    self.physics_world_.setGroupCollisionFlag(GAME_OBJECT_BITMASK.getLowestOnBit(),GAME_OBJECT_BITMASK.getLowestOnBit(),True)
    self.physics_world_.setGroupCollisionFlag(SECTOR_ENTERED_BITMASK.getLowestOnBit(),SECTOR_ENTERED_BITMASK.getLowestOnBit(),True)
    self.physics_world_.setGroupCollisionFlag(GAME_OBJECT_BITMASK.getLowestOnBit(),SECTOR_ENTERED_BITMASK.getLowestOnBit(),False)
    

    # setting up ground
    self.ground_ = self.world_node_.attachNewNode(BulletRigidBodyNode('Ground'))
    self.ground_.node().addShape(BulletPlaneShape(Vec3(0, 0, 1), 0))
    self.ground_.setPos(0,0,0)
    self.ground_.setCollideMask(GAME_OBJECT_BITMASK)
    self.physics_world_.attachRigidBody(self.ground_.node())
    
    # creating level objects    
    self.setupLevelSectors()

    # creating controlled objects
    diameter = 0.4
    sphere_visual = loader.loadModel('models/ball.egg')

    bounds = sphere_visual.getTightBounds() # start of model scaling
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = diameter/max([extents.getX(),extents.getY(),extents.getZ()])
    sphere_visual.clearModelNodes()
    sphere_visual.setScale(scale_factor,scale_factor,scale_factor) # end of model scaling

    sphere_visual.setTexture(loader.loadTexture('models/bowl.jpg'),1)
    sphere = NodePath(BulletRigidBodyNode('Sphere'))
    sphere.node().addShape(BulletSphereShape(0.5*diameter))
    sphere.node().setMass(1.0)
    #sphere.node().setLinearFactor((1,0,1))
    #sphere.node().setAngularFactor((0,1,0))
    sphere.setCollideMask(GAME_OBJECT_BITMASK)
    sphere_visual.instanceTo(sphere)
    
    self.physics_world_.attachRigidBody(sphere.node())
    self.controlled_objects_.append(sphere) 
    sphere.reparentTo(self.world_node_)
    sphere.setPos(self.level_sectors_[0],Vec3(0,0,diameter+10))
    sphere.setHpr(self.level_sectors_[0],Vec3(0,0,0))
    
    # creating bullet ghost for detecting entry into other sectors
    player_ghost = sphere.attachNewNode(BulletGhostNode('player-ghost-node'))
    ghost_box_shape = BulletSphereShape(PLAYER_GHOST_DIAMETER/2)
    ghost_box_shape.setMargin(SECTOR_COLLISION_MARGIN)
    ghost_sphere_shape = BulletSphereShape(PLAYER_GHOST_DIAMETER*0.5)
    ghost_sphere_shape.setMargin(SECTOR_COLLISION_MARGIN)
    player_ghost.node().addShape(ghost_box_shape)
    player_ghost.setPos(sphere,Vec3(0,0,0))
    player_ghost.node().setIntoCollideMask(SECTOR_ENTERED_BITMASK)
    self.physics_world_.attach(player_ghost.node())

    # creating mobile box
    size = Vec3(0.2,0.2,0.4)
    mbox_visual = loader.loadModel('models/box.egg')
    bounds = mbox_visual.getTightBounds()
    extents = Vec3(bounds[1] - bounds[0])
    scale_factor = 1/max([extents.getX(),extents.getY(),extents.getZ()])
    mbox_visual.setScale(size.getX()*scale_factor,size.getY()*scale_factor,size.getZ()*scale_factor)

    mbox = NodePath(BulletRigidBodyNode('MobileBox'))
    mbox.node().addShape(BulletBoxShape(size/2))
    mbox.node().setMass(1.0)
    #mbox.node().setLinearFactor((1,0,1))
    #mbox.node().setAngularFactor((0,1,0))
    mbox.setCollideMask(GAME_OBJECT_BITMASK)
    mbox_visual.instanceTo(mbox)    
    self.physics_world_.attachRigidBody(mbox.node())
    self.controlled_objects_.append(mbox)
    mbox.reparentTo(self.level_sectors_[0])    
    mbox.setPos(Vec3(1,0,size.getZ()+1))
    
    # switching to sector 1
    self.switchToSector(self.level_sectors_[0])


  def setupLevelSectors(self):
    
    start_pos = Vec3(0,-20,0)
    
    for i in range(0,4):
      
      sector = Sector('sector' + str(i),self.physics_world_)
      sector.reparentTo(self.world_node_)
      
      #sector.setHpr(Vec3(60*(i+1),0,0))
      sector.setHpr(Vec3(90*i,0,0))
      sector.setPos(sector,Vec3(0,-20,i*4))
      self.level_sectors_.append(sector)
      sector.setup()      

  def update(self, task):

    self.clock_.tick()
    dt = self.clock_.getDt()
    self.processInput(dt)    
    self.physics_world_.doPhysics(dt, 5, 1.0/180.0)
    self.processCollisions()
    self.updateCamera()

    return task.cont 

  def processInput(self,dt):
  
    activate = False
    obj = self.controlled_objects_[self.controlled_obj_index_]

    if self.kinematic_mode_:
      obj.node().setKinematic(True)
      return
    else:
      obj.node().setKinematic(False)

    vel = self.active_sector_.getRelativeVector(self.world_node_,obj.node().getLinearVelocity())
    w = self.active_sector_.getRelativeVector(self.world_node_, obj.node().getAngularVelocity())
    vel.setY(0)
    #w.setX(0)
    #w.setZ(0)

  
    if self.input_state_.isSet('right'): 
      vel.setX(2)
      activate = True

    if self.input_state_.isSet('left'): 
      vel.setX(-2)
      activate = True

    if self.input_state_.isSet('jump'): 
      vel.setZ(4)
      activate = True

    if self.input_state_.isSet('stop'): 
      vel.setX(0)

    if self.input_state_.isSet('roll_right'):
      w.setY(ROTATIONAl_SPEED)
      activate = True

    if self.input_state_.isSet('roll_left'):
      w.setY(-ROTATIONAl_SPEED)
      activate = True

    if self.input_state_.isSet('roll_stop'):
      w.setY(0)

    if activate : obj.node().setActive(True,True)
    vel = self.world_node_.getRelativeVector(self.active_sector_,vel)
    w = self.world_node_.getRelativeVector(self.active_sector_,w)
    obj.node().setLinearVelocity(vel)
    obj.node().setAngularVelocity(w)
    
    #logging.info("Linear Velocity: %s"%(str(vel)))

  def updateCamera(self):
 
    if len(self.controlled_objects_) > 0:
      obj = self.controlled_objects_[self.controlled_obj_index_]
      self.cam.setPos(self.active_sector_,obj.getPos(self.active_sector_))
      self.cam.setY(self.active_sector_,-CAM_DISTANCE/1)
      self.cam.lookAt(obj.getParent(),obj.getPos())

  def cleanup(self):
    
    for i in range(0,len(self.controlled_objects_)):
      rb = self.controlled_objects_[i]
      self.physics_world_.removeRigidBody(rb.node())
      rb.removeNode()

    self.object_nodes_ = []
    self.controlled_objects_ = []
    self.physics_world_.removeRigidBody(self.ground_.node())
    self.ground_ = None
    self.physics_world_ = None
    self.debug_node_ = None
    self.cam.reparentTo(self.render)
    self.world_node_.removeNode()
    self.world_node_ = None

  # _____HANDLER_____

  def toggleKinematicMode(self):
    self.kinematic_mode_ = not self.kinematic_mode_

    print "Kinematic Mode %s"%('ON' if self.kinematic_mode_ else 'OFF')

  def selectNextControlledObject(self):
    self.controlled_obj_index_+=1
    if self.controlled_obj_index_ >= len(self.controlled_objects_):
      self.controlled_obj_index_ = 0 #  reset


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

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

  def toggleDebug(self):

    if self.debug_node_.isHidden():
      self.debug_node_.show()
    else:
      self.debug_node_.hide()

  def doScreenshot(self):
    self.screenshot('Bullet')
예제 #42
0
파일: dropblt.py 프로젝트: xwavex/pyhiro
class BulletSim(object):
    def __init__(self, base, objpath, bdebug=False):
        self.base = base

        self.smiley = loader.loadModel(objpath)
        self.smileyCount = 0

        self.setupBullet()
        self.addGround()
        # self.addWalls()

        self.partlist = []

        taskMgr.doMethodLater(.1, self.addSmiley, "AddSmiley")
        taskMgr.add(self.updateBlt, "UpdateBlt")

        if bdebug:
            debugNode = BulletDebugNode('Debug')
            debugNode.showWireframe(True)
            debugNode.showConstraints(True)
            debugNode.showBoundingBoxes(False)
            debugNode.showNormals(False)
            bullcldrnp = self.base.render.attachNewNode("bulletcollider")
            debugNP = bullcldrnp.attachNewNode(debugNode)
            debugNP.show()
            self.bltWorld.setDebugNode(debugNP.node())

    def setupBullet(self):
        self.bltWorld = BulletWorld()
        self.bltWorld.setGravity(Vec3(0, 0, -9.81))

    def addGround(self):
        boxx = 500.0
        boxy = 500.0
        boxz = 1.0
        shape = BulletBoxShape(Vec3(boxx, boxy,
                                    boxz))  # the parameters are half extends
        node = BulletRigidBodyNode('Ground')
        node.addShape(shape)
        self.bltWorld.attachRigidBody(node)
        pg.plotBox(self.base.render,
                   pos=[0, 0, -1.0],
                   x=boxx * 2.0,
                   y=boxy * 2.0,
                   z=boxz * 2.0,
                   rgba=None)

        # shape = BulletPlaneShape(Vec3(0, 0, 1), 0.0)
        # node = BulletRigidBodyNode('Ground')
        # node.addShape(shape)
        # np = self.base.render.attachNewNode(node)
        # np.setPos(0, 0, 0)
        # self.bltWorld.attachRigidBody(node)

    def addWalls(self):
        """
        add walls

        :return:
        """

        # x+
        boxx = 2.0
        boxy = 50.0
        boxz = 100.0
        boxpx = 50.0
        boxpy = 0.0
        boxpz = 50.0
        shape = BulletBoxShape(Vec3(boxx, boxy,
                                    boxz))  # the parameters are half extends
        node = BulletRigidBodyNode('Wallx+')
        node.addShape(shape)
        node.setTransform(TransformState.makePos(VBase3(boxpx, boxpy, boxpz)))
        self.bltWorld.attachRigidBody(node)
        pg.plotBox(self.base.render,
                   pos=[boxpx, boxpy, boxpz],
                   x=boxx * 2.0,
                   y=boxy * 2.0,
                   z=boxz * 2.0,
                   rgba=None)
        # x-
        boxx = 2.0
        boxy = 50.0
        boxz = 100.0
        boxpx = -50.0
        boxpy = 0.0
        boxpz = 50.0
        shape = BulletBoxShape(Vec3(boxx, boxy,
                                    boxz))  # the parameters are half extends
        node = BulletRigidBodyNode('Wallx-')
        node.addShape(shape)
        node.setTransform(TransformState.makePos(VBase3(boxpx, boxpy, boxpz)))
        self.bltWorld.attachRigidBody(node)
        pg.plotBox(self.base.render,
                   pos=[boxpx, boxpy, boxpz],
                   x=boxx * 2.0,
                   y=boxy * 2.0,
                   z=boxz * 2.0,
                   rgba=None)
        # y+
        boxx = 50.0
        boxy = 2.0
        boxz = 100.0
        boxpx = 0.0
        boxpy = 50.0
        boxpz = 50.0
        shape = BulletBoxShape(Vec3(boxx, boxy,
                                    boxz))  # the parameters are half extends
        node = BulletRigidBodyNode('Wally+')
        node.addShape(shape)
        node.setTransform(TransformState.makePos(VBase3(boxpx, boxpy, boxpz)))
        self.bltWorld.attachRigidBody(node)
        pg.plotBox(self.base.render,
                   pos=[boxpx, boxpy, boxpz],
                   x=boxx * 2.0,
                   y=boxy * 2.0,
                   z=boxz * 2.0,
                   rgba=None)
        # y-
        boxx = 50.0
        boxy = 2.0
        boxz = 100.0
        boxpx = 0.0
        boxpy = -50.0
        boxpz = 50.0
        shape = BulletBoxShape(Vec3(boxx, boxy,
                                    boxz))  # the parameters are half extends
        node = BulletRigidBodyNode('Wally-')
        node.addShape(shape)
        node.setTransform(TransformState.makePos(VBase3(boxpx, boxpy, boxpz)))
        self.bltWorld.attachRigidBody(node)
        pg.plotBox(self.base.render,
                   pos=[boxpx, boxpy, boxpz],
                   x=boxx * 2.0,
                   y=boxy * 2.0,
                   z=boxz * 2.0,
                   rgba=None)

        # shape = BulletPlaneShape(Vec3(0, 0, 1), 0.0)
        # node = BulletRigidBodyNode('Ground')
        # node.addShape(shape)
        # np = self.base.render.attachNewNode(node)
        # np.setPos(0, 0, 0)
        # self.bltWorld.attachRigidBody(node)
        self.handz = 200.0

    def addSmiley(self, task):
        node = cd.genCollisionMeshNp(self.smiley)
        node.setMass(1.0)
        node.setName("part" + str(self.smileyCount))
        np = base.render.attachNewNode(node)
        np.setPos(random.uniform(-2, 2), random.uniform(-2, 2),
                  15.0 + self.smileyCount * 25.0)
        sm = np.attachNewNode("partrender" + str(self.smileyCount))
        self.smiley.instanceTo(sm)
        self.bltWorld.attachRigidBody(node)

        self.smileyCount += 1

        if self.smileyCount == 20:
            return task.done
        return task.again

    def updateBlt(self, task):
        self.bltWorld.doPhysics(globalClock.getDt())

        # nodep = self.base.render.find("**/part1")
        # if nodep:
        #     print nodep.getPos(), nodep.getHpr()
        # self.handz = self.handz-1
        # self.genHand(self.handz)

        return task.cont

    def genHand(self, handz=100.0):
        # fgr0
        boxx = 5.0
        boxy = 2.0
        boxz = 20.0
        boxpx = 0.0
        boxpy = 10.0
        boxpz = handz
        shape = BulletBoxShape(Vec3(boxx, boxy,
                                    boxz))  # the parameters are half extends
        node = BulletRigidBodyNode('fgr0')
        node.addShape(shape)
        node.setTransform(TransformState.makePos(VBase3(boxpx, boxpy, boxpz)))
        self.bltWorld.attachRigidBody(node)
        pg.plotBox(self.base.render,
                   pos=[boxpx, boxpy, boxpz],
                   x=boxx * 2.0,
                   y=boxy * 2.0,
                   z=boxz * 2.0,
                   rgba=None)
        # fgr1
        boxx = 5.0
        boxy = 2.0
        boxz = 20.0
        boxpx = 0.0
        boxpy = -10.0
        boxpz = handz
        shape = BulletBoxShape(Vec3(boxx, boxy,
                                    boxz))  # the parameters are half extends
        node = BulletRigidBodyNode('fgr1')
        node.addShape(shape)
        node.setTransform(TransformState.makePos(VBase3(boxpx, boxpy, boxpz)))
        self.bltWorld.attachRigidBody(node)
        pg.plotBox(self.base.render,
                   pos=[boxpx, boxpy, boxpz],
                   x=boxx * 2.0,
                   y=boxy * 2.0,
                   z=boxz * 2.0,
                   rgba=None)
예제 #43
0
파일: world.py 프로젝트: hrhryusuke/wrs
class World(ShowBase, object):
    def __init__(self,
                 cam_pos=np.array([2.0, 0.5, 2.0]),
                 lookat_pos=np.array([0, 0, 0.25]),
                 up=np.array([0, 0, 1]),
                 fov=40,
                 w=1920,
                 h=1080,
                 lens_type="perspective",
                 toggle_debug=False,
                 auto_cam_rotate=False):
        """
        :param cam_pos:
        :param lookat_pos:
        :param fov:
        :param w: width of window
        :param h: height of window
        author: weiwei
        date: 2015?, 20201115
        """
        # the taskMgr, loader, render2d, etc. are added to builtin after initializing the showbase parental class
        super().__init__()
        # set up window
        winprops = WindowProperties(base.win.getProperties())
        winprops.setTitle("WRS Robot Planning and Control System")
        base.win.requestProperties(winprops)
        self.disableAllAudio()
        self.setBackgroundColor(1, 1, 1)
        # set up lens
        lens = PerspectiveLens()
        lens.setFov(fov)
        lens.setNearFar(0.001, 5000.0)
        if lens_type == "orthographic":
            lens = OrthographicLens()
            lens.setFilmSize(640, 480)
        # disable the default mouse control
        self.disableMouse()
        self.cam.setPos(cam_pos[0], cam_pos[1], cam_pos[2])
        self.cam.lookAt(Point3(lookat_pos[0], lookat_pos[1], lookat_pos[2]),
                        Vec3(up[0], up[1], up[2]))
        self.cam.node().setLens(lens)
        # set up slight
        ## ambient light
        ablight = AmbientLight("ambientlight")
        ablight.setColor(Vec4(0.2, 0.2, 0.2, 1))
        self.ablightnode = self.cam.attachNewNode(ablight)
        self.render.setLight(self.ablightnode)
        ## point light 1
        ptlight0 = PointLight("pointlight0")
        ptlight0.setColor(Vec4(1, 1, 1, 1))
        self._ptlightnode0 = self.cam.attachNewNode(ptlight0)
        self._ptlightnode0.setPos(0, 0, 0)
        self.render.setLight(self._ptlightnode0)
        ## point light 2
        ptlight1 = PointLight("pointlight1")
        ptlight1.setColor(Vec4(.4, .4, .4, 1))
        self._ptlightnode1 = self.cam.attachNewNode(ptlight1)
        self._ptlightnode1.setPos(self.cam.getPos().length(), 0,
                                  self.cam.getPos().length())
        self.render.setLight(self._ptlightnode1)
        ## point light 3
        ptlight2 = PointLight("pointlight2")
        ptlight2.setColor(Vec4(.3, .3, .3, 1))
        self._ptlightnode2 = self.cam.attachNewNode(ptlight2)
        self._ptlightnode2.setPos(-self.cam.getPos().length(), 0,
                                  self.cam.getPos().length())
        self.render.setLight(self._ptlightnode2)
        # helpers
        self.p3dh = p3dh
        # self.o3dh = o3dh
        self.rbtmath = rm
        # set up inputmanager
        self.lookatpos = lookat_pos
        self.inputmgr = im.InputManager(self, self.lookatpos)
        taskMgr.add(self._interaction_update, "interaction", appendTask=True)
        # set up rotational cam
        if auto_cam_rotate:
            taskMgr.doMethodLater(.1, self._rotatecam_update, "rotate cam")
        # set window size
        props = WindowProperties()
        props.setSize(w, h)
        self.win.requestProperties(props)
        # outline edge shader
        # self.set_outlineshader()
        # set up cartoon effect
        self._separation = 1
        self.filter = flt.Filter(self.win, self.cam)
        self.filter.setCartoonInk(separation=self._separation)
        # self.filter.setViewGlow()
        # set up physics world
        self.physics_scale = 1e3
        self.physicsworld = BulletWorld()
        self.physicsworld.setGravity(Vec3(0, 0, -9.81 * self.physics_scale))
        taskMgr.add(self._physics_update, "physics", appendTask=True)
        globalbprrender = base.render.attachNewNode("globalbpcollider")
        debugNode = BulletDebugNode('Debug')
        debugNode.showWireframe(True)
        debugNode.showConstraints(True)
        debugNode.showBoundingBoxes(False)
        debugNode.showNormals(True)
        self._debugNP = globalbprrender.attachNewNode(debugNode)
        self._debugNP.show()
        self.toggledebug = toggle_debug
        if toggle_debug:
            self.physicsworld.setDebugNode(self._debugNP.node())
        self.physicsbodylist = []
        # set up render update (TODO, only for dynamics?)
        self._internal_update_obj_list = [
        ]  # the nodepath, collision model, or bullet dynamics model to be drawn
        self._internal_update_robot_list = []
        taskMgr.add(self._internal_update, "internal_update", appendTask=True)
        # for remote visualization
        self._external_update_objinfo_list = []  # see anime_info.py
        self._external_update_robotinfo_list = []
        taskMgr.add(self._external_update, "external_update", appendTask=True)
        # for stationary models
        self._noupdate_model_list = []

    def _interaction_update(self, task):
        # reset aspect ratio
        aspectRatio = self.getAspectRatio()
        self.cam.node().getLens().setAspectRatio(aspectRatio)
        self.inputmgr.check_mouse1drag()
        self.inputmgr.check_mouse2drag()
        self.inputmgr.check_mouse3click()
        self.inputmgr.check_mousewheel()
        self.inputmgr.check_resetcamera()
        return task.cont

    def _physics_update(self, task):
        self.physicsworld.doPhysics(globalClock.getDt(), 20, 1 / 1200)
        return task.cont

    def _internal_update(self, task):
        for robot in self._internal_update_robot_list:
            robot.detach()  # TODO gen mesh model?
            robot.attach_to(self)
        for obj in self._internal_update_obj_list:
            obj.detach()
            obj.attach_to(self)
        return task.cont

    def _rotatecam_update(self, task):
        campos = self.cam.getPos()
        camangle = math.atan2(campos[1] - self.lookatpos[1],
                              campos[0] - self.lookatpos[0])
        # print camangle
        if camangle < 0:
            camangle += math.pi * 2
        if camangle >= math.pi * 2:
            camangle = 0
        else:
            camangle += math.pi / 360
        camradius = math.sqrt((campos[0] - self.lookatpos[0])**2 +
                              (campos[1] - self.lookatpos[1])**2)
        camx = camradius * math.cos(camangle)
        camy = camradius * math.sin(camangle)
        self.cam.setPos(self.lookatpos[0] + camx, self.lookatpos[1] + camy,
                        campos[2])
        self.cam.lookAt(self.lookatpos[0], self.lookatpos[1],
                        self.lookatpos[2])
        return task.cont

    def _external_update(self, task):
        for _external_update_robotinfo in self._external_update_robotinfo_list:
            robot_s = _external_update_robotinfo.robot_s
            robot_component_name = _external_update_robotinfo.robot_component_name
            robot_meshmodel = _external_update_robotinfo.robot_meshmodel
            robot_meshmodel_parameter = _external_update_robotinfo.robot_meshmodel_parameters
            robot_path = _external_update_robotinfo.robot_path
            robot_path_counter = _external_update_robotinfo.robot_path_counter
            robot_meshmodel.detach()
            robot_s.fk(component_name=robot_component_name,
                       jnt_values=robot_path[robot_path_counter])
            _external_update_robotinfo.robot_meshmodel = robot_s.gen_meshmodel(
                tcp_jntid=robot_meshmodel_parameter[0],
                tcp_loc_pos=robot_meshmodel_parameter[1],
                tcp_loc_rotmat=robot_meshmodel_parameter[2],
                toggle_tcpcs=robot_meshmodel_parameter[3],
                toggle_jntscs=robot_meshmodel_parameter[4],
                rgba=robot_meshmodel_parameter[5],
                name=robot_meshmodel_parameter[6])
            _external_update_robotinfo.robot_meshmodel.attach_to(self)
            _external_update_robotinfo.robot_path_counter += 1
            if _external_update_robotinfo.robot_path_counter >= len(
                    robot_path):
                _external_update_robotinfo.robot_path_counter = 0
        for _external_update_objinfo in self._external_update_objinfo_list:
            obj = _external_update_objinfo.obj
            obj_parameters = _external_update_objinfo.obj_parameters
            obj_path = _external_update_objinfo.obj_path
            obj_path_counter = _external_update_objinfo.obj_path_counter
            obj.detach()
            obj.set_pos(obj_path[obj_path_counter][0])
            obj.set_rotmat(obj_path[obj_path_counter][1])
            obj.set_rgba(obj_parameters[0])
            obj.attach_to(self)
            _external_update_objinfo.obj_path_counter += 1
            if _external_update_objinfo.obj_path_counter >= len(obj_path):
                _external_update_objinfo.obj_path_counter = 0
        return task.cont

    def change_debugstatus(self, toggledebug):
        if self.toggledebug == toggledebug:
            return
        elif toggledebug:
            self.physicsworld.setDebugNode(self._debugNP.node())
        else:
            self.physicsworld.clearDebugNode()
        self.toggledebug = toggledebug

    def attach_internal_update_obj(self, obj):
        """
        :param obj: CollisionModel or (Static)GeometricModel
        :return:
        """
        self._internal_update_obj_list.append(obj)

    def detach_internal_update_obj(self, obj):
        self._internal_update_obj_list.remove(obj)
        obj.detach()

    def clear_internal_update_obj(self):
        tmp_internal_update_obj_list = self._internal_update_obj_list.copy()
        self._internal_update_obj_list = []
        for obj in tmp_internal_update_obj_list:
            obj.detach()

    def attach_internal_update_robot(
            self, robot_meshmodel):  # TODO robot_meshmodel or robot_s?
        self._internal_update_robot_list.append(robot_meshmodel)

    def detach_internal_update_robot(self, robot_meshmodel):
        tmp_internal_update_robot_list = self._internal_update_robot_list.copy(
        )
        self._internal_update_robot_list = []
        for robot in tmp_internal_update_robot_list:
            robot.detach()

    def clear_internal_update_robot(self):
        for robot in self._internal_update_robot_list:
            self.detach_internal_update_robot(robot)

    def attach_external_update_obj(self, objinfo):
        """
        :param objinfo: anime_info.ObjInfo
        :return:
        """
        self._external_update_objinfo_list.append(objinfo)

    def detach_external_update_obj(self, obj_info):
        self._external_update_objinfo_list.remove(obj_info)
        obj_info.obj.detach()

    def clear_external_update_obj(self):
        for obj in self._external_update_objinfo_list:
            self.detach_external_update_obj(obj)

    def attach_external_update_robot(self, robotinfo):
        """
        :param robotinfo: anime_info.RobotInfo
        :return:
        """
        self._external_update_robotinfo_list.append(robotinfo)

    def detach_external_update_robot(self, robot_info):
        self._external_update_robotinfo_list.remove(robot_info)
        robot_info.robot_meshmodel.detach()

    def clear_external_update_robot(self):
        for robot in self._external_update_robotinfo_list:
            self.detach_external_update_robot(robot)

    def attach_noupdate_model(self, model):
        model.attach_to(self)
        self._noupdate_model_list.append(model)

    def detach_noupdate_model(self, model):
        model.detach()
        self._noupdate_model_list.remove(model)

    def clear_noupdate_model(self):
        for model in self._noupdate_model_list:
            model.detach()
        self._noupdate_model_list = []

    def change_campos(self, campos):
        self.cam.setPos(campos[0], campos[1], campos[2])
        self.inputmgr = im.InputManager(self, self.lookatpos)

    def change_lookatpos(self, lookatpos):
        """
        This function is questionable
        as lookat changes the rotation of the camera
        :param lookatpos:
        :return:
        author: weiwei
        date: 20180606
        """
        self.cam.lookAt(lookatpos[0], lookatpos[1], lookatpos[2])
        self.lookatpos = lookatpos
        self.inputmgr = im.InputManager(self, self.lookatpos)

    def change_campos_and_lookatpos(self, campos, lookatpos):
        self.cam.setPos(campos[0], campos[1], campos[2])
        self.cam.lookAt(lookatpos[0], lookatpos[1], lookatpos[2])
        self.lookatpos = lookatpos
        self.inputmgr = im.InputManager(self, self.lookatpos)

    def set_cartoonshader(self, switchtoon=False):
        """
        set cartoon shader, the following program is a reference
        https://github.com/panda3d/panda3d/blob/master/samples/cartoon-shader/advanced.py
        :return:
        author: weiwei
        date: 20180601
        """
        this_dir, this_filename = os.path.split(__file__)
        if switchtoon:
            lightinggen = Filename.fromOsSpecific(
                os.path.join(this_dir, "shaders", "lighting_gen.sha"))
            tempnode = NodePath("temp")
            tempnode.setShader(loader.loadShader(lightinggen))
            self.cam.node().setInitialState(tempnode.getState())
            # self.render.setShaderInput("light", self.cam)
            self.render.setShaderInput("light", self._ablightnode)
        normalsBuffer = self.win.makeTextureBuffer("normalsBuffer", 0, 0)
        normalsBuffer.setClearColor(Vec4(0.5, 0.5, 0.5, 1))
        normalsCamera = self.makeCamera(normalsBuffer,
                                        lens=self.cam.node().getLens(),
                                        scene=self.render)
        normalsCamera.reparentTo(self.cam)
        normalgen = Filename.fromOsSpecific(
            os.path.join(this_dir, "shaders", "normal_gen.sha"))
        tempnode = NodePath("temp")
        tempnode.setShader(loader.loadShader(normalgen))
        normalsCamera.node().setInitialState(tempnode.getState())
        drawnScene = normalsBuffer.getTextureCard()
        drawnScene.setTransparency(1)
        drawnScene.setColor(1, 1, 1, 0)
        drawnScene.reparentTo(render2d)
        self.drawnScene = drawnScene
        self.separation = 0.001
        self.cutoff = 0.05
        inkGen = Filename.fromOsSpecific(
            os.path.join(this_dir, "shaders", "ink_gen.sha"))
        drawnScene.setShader(loader.loadShader(inkGen))
        drawnScene.setShaderInput("separation", Vec4(0, 0, self.separation, 0))
        drawnScene.setShaderInput("cutoff", Vec4(self.cutoff))

    def set_outlineshader(self):
        """
        document 1: https://qiita.com/nmxi/items/bfd10a3b3f519878e74e
        document 2: https://docs.panda3d.org/1.10/python/programming/shaders/list-of-cg-inputs
        :return:
        author: weiwei
        date: 20180601, 20201210osaka
        """
        depth_sha = """
        void vshader(float4 vtx_position : POSITION,
                     float4 vtx_normal : NORMAL,
                     uniform float4x4 mat_modelproj,
                     uniform float4x4 mat_modelview,
                     out float4 l_position : POSITION,
                     out float4 l_color0: COLOR0) {
            l_position = mul(mat_modelproj, vtx_position);
            float depth = l_position.a*.1;
            //l_color0 = vtx_position + float4(depth, depth, depth, 1);
            l_color0 = float4(depth, depth, depth, 1);
        }
        void fshader(float4 l_color0: COLOR0,
                     uniform sampler2D tex_0 : TEXUNIT0,
                     out float4 o_color : COLOR) {
            o_color = l_color0;
        }"""
        outline_sha = """
        void vshader(float4 vtx_position : POSITION,
             float2 vtx_texcoord0 : TEXCOORD0,
             uniform float4x4 mat_modelproj,
             out float4 l_position : POSITION,
             out float2 l_texcoord0 : TEXCOORD0)
        {
          l_position = mul(mat_modelproj, vtx_position);
          l_texcoord0 = vtx_texcoord0;
        }
        void fshader(float2 l_texcoord0 : TEXCOORD0,
                     uniform sampler2D tex_0 : TEXUNIT0,
                     uniform float2 sys_windowsize,
                     out float4 o_color : COLOR)
        {
          float sepx = 1/sys_windowsize.x;
          float sepy = 1/sys_windowsize.y;
          float4 color0 = tex2D(tex_0, l_texcoord0);
          float2 texcoord1 = l_texcoord0+float2(sepx, 0);
          float4 color1 = tex2D(tex_0, texcoord1);
          float2 texcoord2 = l_texcoord0+float2(0, sepy);
          float4 color2 = tex2D(tex_0, texcoord2);
          float2 texcoord3 = l_texcoord0+float2(-sepx, 0);
          float4 color3 = tex2D(tex_0, texcoord3);
          float2 texcoord4 = l_texcoord0+float2(0, -sepy);
          float4 color4 = tex2D(tex_0, texcoord4);
          float2 texcoord5 = l_texcoord0+float2(sepx, sepy);
          float4 color5 = tex2D(tex_0, texcoord5);
          float2 texcoord6 = l_texcoord0+float2(-sepx, -sepy);
          float4 color6 = tex2D(tex_0, texcoord6);
          float2 texcoord7 = l_texcoord0+float2(-sepx, sepy);
          float4 color7 = tex2D(tex_0, texcoord7);
          float2 texcoord8 = l_texcoord0+float2(sepx, -sepy);
          float4 color8 = tex2D(tex_0, texcoord8);
          float2 texcoord9 = l_texcoord0+float2(2*sepx, 0);
          float4 color9 = tex2D(tex_0, texcoord9);
          float2 texcoord10 = l_texcoord0+float2(-2*sepx, 0);
          float4 color10 = tex2D(tex_0, texcoord10);
          float2 texcoord11 = l_texcoord0+float2(0, 2*sepy);
          float4 color11 = tex2D(tex_0, texcoord11);
          float2 texcoord12 = l_texcoord0+float2(0, -2*sepy);
          float4 color12 = tex2D(tex_0, texcoord12);
          o_color = (color0-color1).x > .005 || (color0-color2).x > .005 || (color0-color3).x > .005 ||
                    (color0-color4).x > .005 || (color0-color5).x > .005 || (color0-color6).x > .005 ||
                    (color0-color7).x > .005 || (color0-color8).x > .005 || (color0-color9).x > .005 ||
                    (color0-color10).x > .005 || (color0-color11).x > .005 || (color0-color12).x > .005 ?
                    float4(0, 0, 0, 1) : float4(0, 0, 0, 0);
        }"""
        depthBuffer = self.win.makeTextureBuffer("depthBuffer", 0, 0)
        depthBuffer.setClearColor(Vec4(1, 1, 1, 1))
        depthCamera = self.makeCamera(depthBuffer,
                                      lens=self.cam.node().getLens(),
                                      scene=self.render)
        depthCamera.reparentTo(self.cam)
        tempnode = NodePath("depth")
        tempnode.setShader(Shader.make(depth_sha, Shader.SL_Cg))
        depthCamera.node().setInitialState(tempnode.getState())
        drawnScene = depthBuffer.getTextureCard()
        drawnScene.reparentTo(render2d)
        drawnScene.setTransparency(1)
        drawnScene.setColor(1, 1, 1, 0)
        drawnScene.setShader(Shader.make(outline_sha, Shader.SL_Cg))
예제 #44
0
class Mecha01Client(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
        self.plight = PointLight('plight')
        self.pnlp = self.camera.attachNewNode(self.plight)
        render.setLight(self.pnlp)


        self.debugNode = BulletDebugNode('Debug')
        self.debugNode.showWireframe(True)
        self.debugNode.showConstraints(True)
        self.debugNode.showBoundingBoxes(False)
        self.debugNode.showNormals(False)
        self.debugNP = render.attachNewNode(self.debugNode)
        self.debugNP.show()

        self.world = BulletWorld()
        self.world.setDebugNode(self.debugNode)

        self.planet = Planet()
        self.planet.perlin_terrain(5, 0.5)
        self.planet.build_node_path(render, self.world)

        shape = BulletCapsuleShape(0.25, 0.5)
        node = BulletRigidBodyNode('Capsule')
        node.addShape(shape)
        np = render.attachNewNode(node)
        np.setPos(Vec3(0, 0.8, 0.8)*self.planet.get_radius())
        new_up_vector = Vec3(
            np.getPos() - self.planet.get_node_path().getPos())
        old_up_vector = Vec3(0, 0, 1)
        q = self.__quatFromTo(old_up_vector, new_up_vector)
        np.setQuat(q)
    
        self.np01 = np
        self.world.attachRigidBody(node)

        #node.applyCentralImpulse(Vec3(0.4, 0.6, 1.0))

        self.taskMgr.add(self.physicsUpdateTask, "PhysicsUpdateTask")

        self.accept('arrow_up', self.test01, ["shalala"])

    def test01(self, x):
        print x

    def gravity(self, position):
        down_vector = Vec3(0, 0, 0) - position
        down_vector.normalize()
        gravity = LVector3f(down_vector*9.81)
        
    def physicsUpdateTask(self, task):
        dt = globalClock.getDt()

        # simulating spherical gravity
        node = self.np01.getNode(0)
        pos = self.np01.getPos()
        gravity = self.gravity(pos)
        #self.np01.setQuat(Quat(0, 1.1, 1.1, 0))

        self.world.doPhysics(dt)

        return Task.cont

    def spinCameraTask(self, task):
        # angleDegrees = task.time * 6.0
        # angleRadians = angleDegrees * (pi / 180.0)
        # self.camera.setPos(
        #     100.0 * sin(angleRadians),
        #     -100.0 * cos(angleRadians), 0.0)
        # self.camera.setHpr(angleDegrees, 0, 0)
        self.camera.setPos(self.np01.getPos()*5.0)
        self.camera.lookAt(self.np01)
        return Task.cont

    def __quatFromTo(self, v0, v1):
        print (v0, v1)
        q = Quat(
            sqrt(v0.length()**2 * v1.length()**2) + v0.dot(v1),
            v0.cross(v1))
        q.normalize()
        return q
예제 #45
0
class App(ShowBase):
    def moveForward(self, catch):
        print('w key pressed')
        self.cy = 3.0
        print(self.current_pos)

    def moveBackward(self, catch):
        print('w key pressed')
        self.cy = -3.0
        print(self.current_pos)

    def moveLeft(self, catch):
        print('w key pressed')
        self.cx = 3.0
        print(self.current_pos)

    def moveRight(self, catch):
        print('w key pressed')
        self.cx = -3.0
        print(self.current_pos)

    def lookLeft(self, catch):
        self.current_omega = 120

    def lookRight(self, catch):
        self.current_omega = -120

    def lookUp(self, catch):
        self.current_hpr = (self.current_hpr[0], self.current_hpr[1] - 1,
                            self.current_hpr[2])

    def moveUp(self, catch):
        self.current_pos = (self.current_pos[0], self.current_pos[1],
                            self.current_pos[2] + 1)

    def lookUp(self, catch):
        self.current_hpr = (self.current_hpr[0], self.current_hpr[1] + 1,
                            self.current_hpr[2])

    def lookDown(self, catch):
        self.current_hpr = (self.current_hpr[0], self.current_hpr[1] - 1,
                            self.current_hpr[2])

    def fire(self, catch):
        print("Fire!")
        if self.pandaPos[0] == self.current_pos[0] and self.pandaPos[
                2] + 0.5 == self.current_pos[2] and not self.pandaPos[
                    1] == self.current_pos[1] and not self.pandaPos[
                        1] - 1 == self.current_pos[1] and not self.current_pos[
                            1] - 1 == self.pandaPos[1] and not self.current_pos[
                                1] > self.pandaPos[1]:
            print('Oof')

    def jump(self, catch):
        self.player.setMaxJumpHeight(5.0)
        self.player.setJumpSpeed(8.0)
        self.player.doJump()

    def __init__(self):
        ShowBase.__init__(self)
        #self.word = BulletWorld()
        self.cx = 0.0
        self.cy = 0.0
        self.current_omega = 0
        s = self.loader.loadSfx('Doom Soundtrack - Level 1 (Extended).mp3')
        s.play()
        self.current_pos = (10, 5, 1)
        self.current_hpr = (0, 0, 0)
        #self.fxboy = self.loader.loadModel("cubearm.egg")
        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -12.0))
        #self.physicsMgr.attachPhysicalNode(self.camera)
        keyboard.on_press_key('w', self.moveForward)
        keyboard.on_press_key('s', self.moveBackward)
        keyboard.on_press_key('j', self.lookLeft)
        keyboard.on_press_key('y', self.lookUp)
        keyboard.on_press_key('h', self.lookDown)
        keyboard.on_press_key('g', self.lookRight)
        keyboard.on_press_key('d', self.moveLeft)
        #self.fxboy.reparentTo(self.render)
        #self.camera.reparentTo(self.render)
        #self.camera.reparentTo(self.fxboy)
        keyboard.on_press_key('a', self.moveRight)
        keyboard.on_press_key('space', self.fire)
        keyboard.on_press_key('2', self.jump)
        #keyboard.on_press_key('y',self.lookUp)
        keyboard.on_press_key('1', self.moveUp)

        self.cam = BulletCapsuleShape(radius, height - 2 * radius, ZUp)
        self.player = BulletCharacterControllerNode(self.cam, 0.4, 'Player')
        self.playernp = self.render.attachNewNode(self.player)
        self.world.attachCharacter(self.playernp.node())
        self.camera.reparentTo(self.playernp)
        self.playernp.setPos(self.current_pos)
        self.playernp.setHpr(self.current_hpr)
        self.playernp.setH(45)
        #self.player.setMass(10.0)
        # self.playernp.setCollideMask(BitMask32.allOn())
        self.disableMouse()

        self.scenes = BulletBoxShape(Vec3(0.25, 0.25, 0.25))
        self.scenenode = BulletRigidBodyNode('Scene')
        self.scenenode.setMass(12.0)
        self.scenenode.addShape(self.scenes)
        self.scenenp = render.attachNewNode(self.scenenode)
        self.scenenp.setPos(-8, 40, 0)
        self.world.attachRigidBody(self.scenenode)
        self.scene = self.loader.loadModel("models/environment.egg.pz")
        self.scene.reparentTo(self.render)
        self.scene.setScale(0.25, 0.25, 0.25)
        self.scene.setPos(-8, 40, 0)
        self.scene.reparentTo(self.scenenp)
        self.scenenode.setGravity(Vec3(0, 0, 0))

        #self.taskMgr.add(self.spinCameraTask,"SpinCameraTask")
        self.taskMgr.add(self.moveChar, "MoveChar")
        self.taskMgr.add(self.moveCBod, "MoveCBod")
        self.pandaActor = Actor("cubearm.egg",
                                {"walk": "cubearm4-ArmatureAction.egg"})
        self.pandaActor.setScale(0.12, 0.12, 0.12)
        self.pandaActor.setPos((10, 10, 0.5))
        self.pandaPos = (10, 10, 0.5)
        self.pandaActor.reparentTo(self.render)
        self.pandaActor.loop('walk')
        '''
        posInterval1 = self.pandaActor.posInterval(13,Point3(0,-10,0),startPos=Point3(0,10,0))
        posInterval2 = self.pandaActor.posInterval(13,Point3(0,10,0),startPos=Point3(0,-10,0))
        hprInterval1 = self.pandaActor.hprInterval(3,Point3(180,0,0),startHpr=Point3(0,0,0))
        hprInterval2 = self.pandaActor.hprInterval(3,Point3(0,0,0),startHpr=Point3(180,0,0))
        self.pandaPace = Sequence(posInterval1,hprInterval1,posInterval2,hprInterval2,name="pandaPace")
        self.pandaPace.loop()
        '''

    def spinCameraTask(self, task):
        print(task.time * 6.0)
        angleDegrees = task.time * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        self.camera.setPos(20 * sin(angleRadians), -20 * cos(angleRadians), 3)
        self.camera.setHpr(angleDegrees, 0, 0)
        return Task.cont

    def moveChar(self, task):
        speed = Vec3(0, 0, 0)
        omega = self.current_omega
        speed.setX(self.cx)
        speed.setY(self.cy)
        #self.scenenp.setPos(-8,40,0)
        print('[Scene]: ' + str(self.scenenp.getPos()))
        print('[Cam]: ' + str(self.playernp.getPos()))
        self.player.setAngularMovement(omega)
        #self.player.setLinearMovement(speed,True)
        #self.playernp.setPos(self.current_pos)
        self.playernp.setHpr(self.current_hpr)

        return task.cont

    def moveCBod(self, task):
        self.world.doPhysics(globalClock.getDt())
        return task.cont
예제 #46
0
class EscapeFromJCMB(object, DirectObject):
    def __init__(self):
        print "Loading..."
        self.init_window()
        self.init_music()
        self.init_bullet()
        self.init_key()
        self.load_world()
        self.init_player()
        self.init_objects()
        render.prepareScene(base.win.getGsg())
        print "Done"
        self.start_physics()

    def init_window(self):
        # Hide the mouse cursor
        props = WindowProperties()
        props.setCursorHidden(True)
        base.win.requestProperties(props)

    def init_music(self):
        music = base.loader.loadSfx("../data/snd/Bent_and_Broken.mp3")
        music.play()
        self.playferscream = base.loader.loadSfx("../data/snd/deadscrm.wav")

    def init_bullet(self):
        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81))

        #    debugNode = BulletDebugNode('Debug')
        #    debugNode.showWireframe(True)
        #    debugNode.showConstraints(True)
        #    debugNode.showBoundingBoxes(False)
        #    debugNode.showNormals(False)
        #    debugNP = render.attachNewNode(debugNode)
        #    debugNP.show()
        #    self.world.setDebugNode(debugNP.node())

        alight = AmbientLight('alight')
        alight.setColor(VBase4(0.05, 0.05, 0.05, 1))
        alnp = render.attachNewNode(alight)
        render.setLight(alnp)

    def init_key(self):

        # Stores the state of the keys, 1 for pressed and 0 for unpressed
        self.key_state = {
            'up': False,
            'right': False,
            'down': False,
            'left': False
        }

        # Assign the key event handler
        self.accept('w', self.set_key_state, ['up', True])
        self.accept('w-up', self.set_key_state, ['up', False])
        self.accept('d', self.set_key_state, ['right', True])
        self.accept('d-up', self.set_key_state, ['right', False])
        self.accept('s', self.set_key_state, ['down', True])
        self.accept('s-up', self.set_key_state, ['down', False])
        self.accept('a', self.set_key_state, ['left', True])
        self.accept('a-up', self.set_key_state, ['left', False])

        # Stores the state of the mouse buttons, 1 for pressed and 0 for unpressed
        self.mouse_state = {'left_click': False, 'right_click': False}

        # Assign the mouse click event handler
        self.accept('mouse1', self.set_mouse_state, ['left_click', True])
        self.accept('mouse1-up', self.set_mouse_state, ['left_click', False])
        self.accept('mouse2', self.set_mouse_state, ['right_click', True])
        self.accept('mouse2-up', self.set_mouse_state, ['right_click', False])

        self.accept('z', self.print_pos)

        # Esc
        self.accept('escape', sys.exit)

    def set_key_state(self, key, state):
        self.key_state[key] = state

    def set_mouse_state(self, button, state):
        self.mouse_state[button] = state

    def print_pos(self):
        print self.playernp.getPos()

    def egg_to_BulletTriangleMeshShape(self, modelnp):
        mesh = BulletTriangleMesh()
        for collisionNP in modelnp.findAllMatches('**/+CollisionNode'):
            collisionNode = collisionNP.node()
            for collisionPolygon in collisionNode.getSolids():
                tri_points = collisionPolygon.getPoints()
                mesh.addTriangle(tri_points[0], tri_points[1], tri_points[2])
        shape = BulletTriangleMeshShape(mesh, dynamic=False)
        return shape

    def load_world(self):
        stairwell = loader.loadModel('../data/mod/jcmbstairs.egg')
        stairwell.reparentTo(render)
        stairwell_shape = self.egg_to_BulletTriangleMeshShape(stairwell)
        stairwellnode = BulletRigidBodyNode('stairwell')
        stairwellnode.addShape(stairwell_shape)
        self.world.attachRigidBody(stairwellnode)

    def init_player(self):
        # Stop the default mouse behaviour
        base.disableMouse()

        # Character has a capsule shape
        shape = BulletCapsuleShape(0.2, 1, ZUp)
        self.player = BulletRigidBodyNode('Player')
        self.player.setMass(80.0)
        self.player.addShape(shape)
        self.playernp = render.attachNewNode(self.player)
        self.playernp.setPos(0, 0, 1)
        self.world.attachRigidBody(self.player)

        self.player.setLinearSleepThreshold(0.0)
        self.player.setAngularFactor(0.0)

        self.player_speed = 3
        self.player_is_grabbing = False

        #    self.head = BulletRigidBodyNode('Player Head')
        #    self.head.addShape(BulletSphereShape(0.2))
        #    self.head.setMass(10)
        #    self.head.setInertia(Vec3(1,1,1))
        #    self.head.setAngularFactor(1.0)
        #    self.head.setLinearFactor(0.0)
        #    self.headnp = self.playernp.attachNewNode(self.head)
        #    self.headnp.setPos(0,0,0)
        #    self.headnp.setCollideMask(BitMask32.allOff())
        #    self.world.attachRigidBody(self.head)

        # Attach the camera to the player's head
        base.camera.reparentTo(self.playernp)
        #    base.camera.setPos(0,0,.5)
        base.camLens.setFov(80)
        base.camLens.setNear(0.01)

        # Make the torch and attach it to our character
        torch = Spotlight('torch')
        torch.setColor(VBase4(1, 1, 1, 1))
        lens = PerspectiveLens()
        lens.setFov(80)
        lens.setNearFar(20, 100)
        torch.setLens(lens)
        self.torchnp = base.camera.attachNewNode(torch)
        self.torchnp.setPos(0, 0, 0)

        # Allow the world to be illuminated by our torch
        render.setLight(self.torchnp)

        self.cs = None

        # Player's "hand" in the world
        hand_model = loader.loadModel('../data/mod/hand.egg')
        hand_model.setScale(1)
        hand_model.setBillboardPointEye()

        self.hand = BulletRigidBodyNode('Hand')
        self.hand.addShape(BulletSphereShape(0.1))
        self.hand.setLinearSleepThreshold(0.0)
        self.hand.setLinearDamping(0.9999999)
        self.hand.setAngularFactor(0.0)
        self.hand.setMass(1.0)
        self.world.attachRigidBody(self.hand)
        self.handnp = render.attachNewNode(self.hand)
        self.handnp.setCollideMask(BitMask32.allOff())
        #    hand_model.reparentTo(self.handnp)

        # Create a text node to display object identification information and attach it to the player's "hand"
        self.hand_text = TextNode('Hand Text')
        self.hand_text.setText("Ch-ch-chek yoself befo yo rek yoself, bro.")
        self.hand_text.setAlign(TextNode.ACenter)
        self.hand_text.setTextColor(1, 1, 1, 1)
        self.hand_text.setShadow(0.05, 0.05)
        self.hand_text.setShadowColor(0, 0, 0, 1)
        self.hand_text_np = render.attachNewNode(self.hand_text)
        self.hand_text_np.setScale(0.03)
        self.hand_text_np.setBillboardPointEye()
        self.hand_text_np.hide()

        # Disable the depth testing for the hand and the text - we always want these things on top, with no clipping
        self.handnp.setDepthTest(False)
        self.hand_text_np.setDepthTest(False)

        # Add the player update task
        taskMgr.add(self.update, 'update_player_task')

    def init_objects(self):

        # Make Playfer Box
        shape = BulletBoxShape(Vec3(0.25, 0.25, 0.25))
        node = BulletRigidBodyNode('Playfer Box')
        node.setMass(110.0)
        node.setFriction(1.0)
        node.addShape(shape)
        node.setAngularDamping(0.0)
        np = render.attachNewNode(node)
        np.setPos(-1.4, 1.7, -1.7)
        self.world.attachRigidBody(node)
        playferboxmodel = loader.loadModel('../data/mod/playferbox.egg')
        playferboxmodel.reparentTo(np)

        # Make Pendlepot
        shape = BulletBoxShape(Vec3(0.2, 0.15, 0.1))
        node = BulletRigidBodyNode('Pendlepot')
        node.setMass(5.0)
        node.setFriction(1.0)
        node.addShape(shape)
        node.setAngularDamping(0.0)
        np = render.attachNewNode(node)
        np.setPos(-1.4, 1.7, -1.5)
        self.world.attachRigidBody(node)
        pendlepotmodel = loader.loadModel('../data/mod/pendlepot.egg')
        pendlepotmodel.reparentTo(np)

    def update(self, task):
        # Update camera orientation
        md = base.win.getPointer(0)
        mouse_x = md.getX()
        mouse_y = md.getY()
        centre_x = base.win.getXSize() / 2
        centre_y = base.win.getYSize() / 2
        if base.win.movePointer(0, centre_x, centre_y):
            new_H = base.camera.getH() + (centre_x - mouse_x)
            new_P = base.camera.getP() + (centre_y - mouse_y)
            if new_P < -90:
                new_P = -90
            elif new_P > 90:
                new_P = 90
            base.camera.setH(new_H)
            base.camera.setP(new_P)

        # Update player position
        speed = 3
        self.player_is_moving = False
        if (self.key_state["up"] == True):
            self.player_is_moving = True
            dir = 0
        if (self.key_state["down"] == True):
            self.player_is_moving = True
            dir = 180
        if (self.key_state["left"] == True):
            self.player_is_moving = True
            dir = 90
        if (self.key_state["right"] == True):
            self.player_is_moving = True
            dir = 270

        self.player.clearForces()
        old_vel = self.player.getLinearVelocity()
        new_vel = Vec3(0, 0, 0)
        if self.player_is_moving == True:
            new_vel.setX(-speed * math.sin(
                (base.camera.getH() + dir) * 3.1415 / 180.0))
            new_vel.setY(speed * math.cos(
                (base.camera.getH() + dir) * 3.1415 / 180.0))

        timescale = 0.001
        linear_force = (new_vel - old_vel) / (timescale)
        linear_force.setZ(0.0)
        self.player.applyCentralForce(linear_force)

        if self.player_is_grabbing == False:
            new_hand_pos = LPoint3f(
                render.getRelativePoint(base.camera, Vec3(0, 0.2, 0)))
            self.handnp.setPos(new_hand_pos)
        else:
            new_hand_pos = LPoint3f(
                render.getRelativePoint(base.camera, Vec3(0, 0.5, 0)))
            diff = new_hand_pos - self.handnp.getPos()
            self.hand.applyCentralForce(diff * 1000 -
                                        self.hand.getLinearVelocity() * 100)
            if diff.length() > .5:
                self.player.setLinearVelocity(Vec3(0, 0, 0))

        # Identify what lies beneath the player's hand (unless player is holding something)
        if self.player_is_grabbing == False:
            ray_from = self.playernp.getPos()
            ray_to = LPoint3f(
                render.getRelativePoint(base.camera, Vec3(0, 1, 0)))
            result = self.world.rayTestClosest(ray_from, ray_to)
            if result.hasHit() == True:
                self.hand_text.setText(result.getNode().getName())
                self.hand_text_np.setPos(result.getHitPos())
                self.hand_text_np.show()

                # If player clicks, grab the object by the nearest point (as chosen by ray)
                if self.mouse_state["left_click"] == True:
                    if result.getNode().getNumChildren() == 1:
                        obj = NodePath(result.getNode().getChild(0))

                        if self.player_is_grabbing == False:
                            self.player_is_grabbing = True

                            # Find the position of contact in terms of the object's local coordinates.
                            # Parent the player's hand to the grabbed object at that position.
                            pos = obj.getRelativePoint(render,
                                                       result.getHitPos())

                            self.grabbed_node = result.getNode()
                            self.grabbed_node.setActive(True)
                            print self.grabbed_node

                            frameA = TransformState.makePosHpr(
                                Vec3(0, 0, 0), Vec3(0, 0, 0))
                            frameB = TransformState.makePosHpr(
                                Vec3(0, 0, 0), Vec3(0, 0, 0))

                            swing1 = 20  # degrees
                            swing2 = 20  # degrees
                            twist = 20  # degrees

                            self.cs = BulletConeTwistConstraint(
                                self.hand, result.getNode(), frameA, frameB)
                            self.cs.setLimit(swing1, swing2, twist)
                            self.world.attachConstraint(self.cs)

                            # Stop the held object swinging all over the place
                            result.getNode().setAngularDamping(0.7)
            else:
                self.hand_text_np.hide()
                self.player_is_grabbing = False

        if self.mouse_state["left_click"] == False:
            self.player_is_grabbing = False
            if self.cs != None:
                self.world.remove_constraint(self.cs)
                self.cs = None
                self.grabbed_node.setAngularDamping(0.0)

        if self.player_is_grabbing == True and self.mouse_state[
                "right_click"] == True:
            self.world.remove_constraint(self.cs)
            self.cs = None
            self.grabbed_node.setAngularDamping(0.0)
            self.grabbed_node.setActive(True)
            self.grabbed_node.applyCentralImpulse(1000, 0, 0)

        if self.player_is_grabbing == True:
            self.hand_text_np.hide()

        return task.cont

    def update_physics(self, task):
        dt = globalClock.getDt()
        self.world.doPhysics(dt)
        return task.cont

    def start_physics(self):
        taskMgr.add(self.update_physics, 'update_physics')
class CIBase(ShowBase):
    notify = directNotify.newCategory("CIBase")

    DebugShaderQualities = False

    def __init__(self):
        self.bspLoader = Py_CL_BSPLoader()
        self.bspLoader.setGlobalPtr(self.bspLoader)

        if metadata.USE_RENDER_PIPELINE:
            from rpcore import RenderPipeline
            self.pipeline = RenderPipeline()
            self.pipeline.create(self)
        else:
            ShowBase.__init__(self)
            self.loader.destroy()
            self.loader = CogInvasionLoader(self)
            __builtin__.loader = self.loader
            self.graphicsEngine.setDefaultLoader(self.loader.loader)

        self.cam.node().getDisplayRegion(0).setClearDepthActive(1)

        from panda3d.core import RenderAttribRegistry
        from panda3d.core import ShaderAttrib, TransparencyAttrib
        from libpandabsp import BSPMaterialAttrib
        attribRegistry = RenderAttribRegistry.getGlobalPtr()
        attribRegistry.setSlotSort(BSPMaterialAttrib.getClassSlot(), 0)
        attribRegistry.setSlotSort(ShaderAttrib.getClassSlot(), 1)
        attribRegistry.setSlotSort(TransparencyAttrib.getClassSlot(), 2)

        gsg = self.win.getGsg()

        # Let's print out the Graphics information.
        self.notify.info(
            'Graphics Information:\n\tVendor: {0}\n\tRenderer: {1}\n\tVersion: {2}\n\tSupports Cube Maps: {3}\n\tSupports 3D Textures: {4}\n\tSupports Compute Shaders: {5}'
            .format(gsg.getDriverVendor(), gsg.getDriverRenderer(),
                    gsg.getDriverVersion(), str(gsg.getSupportsCubeMap()),
                    str(gsg.getSupports3dTexture()),
                    str(gsg.getSupportsComputeShaders())))

        # Enable shader generation on all of the main scenes
        if gsg.getSupportsBasicShaders() and gsg.getSupportsGlsl():
            render.setShaderAuto()
            render2d.setShaderAuto()
            render2dp.setShaderAuto()
        else:
            # I don't know how this could be possible
            self.notify.error("GLSL shaders unsupported by graphics driver.")
            return

        # Let's disable fog on Intel graphics
        if gsg.getDriverVendor() == "Intel":
            metadata.NO_FOG = 1
            self.notify.info('Applied Intel-specific graphical fix.')

        self.win.disableClears()

        self.camNode.setCameraMask(CIGlobals.MainCameraBitmask)

        from direct.distributed.ClockDelta import globalClockDelta
        __builtin__.globalClockDelta = globalClockDelta

        # Any ComputeNodes should be parented to this node, not render.
        # We isolate ComputeNodes to avoid traversing the same ComputeNodes
        # when doing multi-pass rendering.
        self.computeRoot = NodePath('computeRoot')
        self.computeCam = self.makeCamera(base.win)
        self.computeCam.node().setCullBounds(OmniBoundingVolume())
        self.computeCam.node().setFinal(True)
        self.computeCam.reparentTo(self.computeRoot)

        # Initialized in initStuff()
        self.shaderGenerator = None

        render.hide()

        self.camLens.setNearFar(0.5, 10000)

        self.physicsWorld = BulletWorld()
        # Panda units are in feet, so the gravity is 32 feet per second,
        # not 9.8 meters per second.
        self.physicsWorld.setGravity(Vec3(0, 0, -32.1740))

        self.physicsWorld.setGroupCollisionFlag(7, 1, True)
        self.physicsWorld.setGroupCollisionFlag(7, 2, True)
        self.physicsWorld.setGroupCollisionFlag(7, 3, False)
        self.physicsWorld.setGroupCollisionFlag(7, 4, False)
        self.physicsWorld.setGroupCollisionFlag(7, 8, True)

        self.taskMgr.add(self.__physicsUpdate, "physicsUpdate", sort=30)

        debugNode = BulletDebugNode('Debug')
        self.debugNP = render.attachNewNode(debugNode)
        self.physicsWorld.setDebugNode(self.debugNP.node())

        self.physicsDbgFlag = False
        self.setPhysicsDebug(self.config.GetBool('physics-debug', False))

        #self.shadowCaster = ShadowCaster(Vec3(163, -67, 0))
        #self.shadowCaster.enable()

        self.bspLoader.setGamma(2.2)
        self.bspLoader.setWin(self.win)
        self.bspLoader.setCamera(self.camera)
        self.bspLoader.setRender(self.render)
        self.bspLoader.setMaterialsFile("phase_14/etc/materials.txt")
        #self.bspLoader.setTextureContentsFile("phase_14/etc/texturecontents.txt")
        self.bspLoader.setWantVisibility(True)
        self.bspLoader.setVisualizeLeafs(False)
        self.bspLoader.setWantLightmaps(True)
        #self.bspLoader.setShadowCamPos(Point3(-15, 5, 40))
        #self.bspLoader.setShadowResolution(60 * 2, 1024 * 1)
        self.bspLoader.setPhysicsWorld(self.physicsWorld)
        self.bspLevel = None
        self.materialData = {}
        self.skyBox = None
        self.skyBoxUtil = None

        #self.nmMgr = RNNavMeshManager.get_global_ptr()
        #self.nmMgr.set_root_node_path(self.render)
        #self.nmMgr.get_reference_node_path().reparentTo(self.render)
        #self.nmMgr.start_default_update()
        #self.nmMgr.get_reference_node_path_debug().reparentTo(self.render)
        self.navMeshNp = None

        # Setup 3d audio                                 run before igLoop so 3d positioning doesn't lag behind
        base.audio3d = Audio3DManager(base.sfxManagerList[0], camera, render)
        base.audio3d.setDropOffFactor(0.15)
        base.audio3d.setDopplerFactor(0.15)

        # Setup collision handlers
        base.cTrav = CollisionTraverser()
        base.lifter = CollisionHandlerFloor()
        base.pusher = CollisionHandlerPusher()
        base.queue = CollisionHandlerQueue()

        base.lightingCfg = None

        self.cl_attackMgr = None

        #self.accept('/', self.projectShadows)

        # Let's setup the user input storage system
        uis = UserInputStorage()
        self.inputStore = uis
        self.userInputStorage = uis
        __builtin__.inputStore = uis
        __builtin__.userInputStorage = uis

        self.credits2d = self.render2d.attachNewNode(PGTop("credits2d"))
        self.credits2d.setScale(1.0 / self.getAspectRatio(), 1.0, 1.0)

        self.wakeWaterHeight = -30.0

        self.bloomToggle = False
        self.hdrToggle = False
        self.fxaaToggle = CIGlobals.getSettingsMgr().getSetting(
            "aa").getValue() == "FXAA"
        self.aoToggle = False

        self.music = None
        self.currSongName = None

        render.show(CIGlobals.ShadowCameraBitmask)

        self.avatars = []

        wrm = WaterReflectionManager()
        self.waterReflectionMgr = wrm
        __builtin__.waterReflectionMgr = wrm

        # Let's setup our margins
        base.marginManager = MarginManager()
        base.margins = aspect2d.attachNewNode(
            base.marginManager, DirectGuiGlobals.MIDGROUND_SORT_INDEX + 1)
        base.leftCells = [
            base.marginManager.addCell(0.1, -0.6, base.a2dTopLeft),
            base.marginManager.addCell(0.1, -1.0, base.a2dTopLeft),
            base.marginManager.addCell(0.1, -1.4, base.a2dTopLeft)
        ]
        base.bottomCells = [
            base.marginManager.addCell(0.4, 0.1, base.a2dBottomCenter),
            base.marginManager.addCell(-0.4, 0.1, base.a2dBottomCenter),
            base.marginManager.addCell(-1.0, 0.1, base.a2dBottomCenter),
            base.marginManager.addCell(1.0, 0.1, base.a2dBottomCenter)
        ]
        base.rightCells = [
            base.marginManager.addCell(-0.1, -0.6, base.a2dTopRight),
            base.marginManager.addCell(-0.1, -1.0, base.a2dTopRight),
            base.marginManager.addCell(-0.1, -1.4, base.a2dTopRight)
        ]

        base.mouseWatcherNode.setEnterPattern('mouse-enter-%r')
        base.mouseWatcherNode.setLeavePattern('mouse-leave-%r')
        base.mouseWatcherNode.setButtonDownPattern('button-down-%r')
        base.mouseWatcherNode.setButtonUpPattern('button-up-%r')

        cbm = CullBinManager.getGlobalPtr()
        cbm.addBin('ground', CullBinManager.BTUnsorted, 18)
        # The portal uses the shadow bin by default,
        # but we still want to see it with real shadows.
        cbm.addBin('portal', CullBinManager.BTBackToFront, 19)
        if not metadata.USE_REAL_SHADOWS:
            cbm.addBin('shadow', CullBinManager.BTBackToFront, 19)
        else:
            cbm.addBin('shadow', CullBinManager.BTFixed, -100)
        cbm.addBin('gui-popup', CullBinManager.BTUnsorted, 60)
        cbm.addBin('gsg-popup', CullBinManager.BTFixed, 70)
        self.setBackgroundColor(CIGlobals.DefaultBackgroundColor)
        self.disableMouse()
        self.enableParticles()
        base.camLens.setNearFar(CIGlobals.DefaultCameraNear,
                                CIGlobals.DefaultCameraFar)
        base.transitions = CITransitions(loader)
        base.transitions.IrisModelName = "phase_3/models/misc/iris.bam"
        base.transitions.FadeModelName = "phase_3/models/misc/fade.bam"

        self.accept(self.inputStore.TakeScreenshot,
                    ScreenshotHandler.takeScreenshot)

        #self.accept('u', render.setShaderOff)
        #self.accept('i', render.setShaderOff, [1])
        #self.accept('o', render.setShaderOff, [2])

        # Disabled oobe culling
        #self.accept('o', self.oobeCull)
        #self.accept('c', self.reportCam)

        self.taskMgr.add(self.__updateShadersAndPostProcess,
                         'CIBase.updateShadersAndPostProcess', 47)
        self.taskMgr.add(self.__update3DAudio, 'CIBase.update3DAudio', 59)

    def windowEvent(self, win):
        ShowBase.windowEvent(self, win)
        if hasattr(self, 'filters'):
            self.filters.windowEvent()

    def __update3DAudio(self, task):
        self.audio3d.update()
        return task.cont

    def __updateShadersAndPostProcess(self, task):
        if self.shaderGenerator:
            self.shaderGenerator.update()
        if hasattr(self, 'filters'):
            self.filters.update()
        return task.cont

    def hideHood(self):
        base.cr.playGame.hood.loader.geom.hide()

    def reportCam(self):
        print self.camera
        print self.camera.getNetTransform()
        self.camera.setScale(render, 1)
        self.camera.setShear(render, 0)
        """
        print 'TPM START'
        tpMgr = TextPropertiesManager.getGlobalPtr()
        print 'PROPERTIES GET'
        tpRed = TextProperties()
        tpRed.setTextColor(1, 0, 0, 1)
        tpSlant = TextProperties()
        tpSlant.setSlant(0.3)
        print 'RED AND SLANT GENERATED'
        tpMgr.setProperties('red', tpRed)
        print 'RED SET'
        try:
            tpMgr.setProperties('slant', tpSlant)
        except Exception:
            print 'AN EXCEPTION OCCURRED'
        print 'SLANT SET'
        print 'TPM END'
        """

    def convertHammerAngles(self, angles):
        """
        (pitch, yaw + 90, roll) -> (yaw, pitch, roll)
        """
        temp = angles[0]
        angles[0] = angles[1] - 90
        angles[1] = temp
        return angles

    def planPath(self, startPos, endPos):
        """Uses recast/detour to find a path from the generated nav mesh from the BSP file."""

        if not self.navMeshNp:
            return [startPos, endPos]
        result = []
        valueList = self.navMeshNp.node().path_find_follow(startPos, endPos)
        for i in xrange(valueList.get_num_values()):
            result.append(valueList.get_value(i))
        return result

    def getBSPLevelLightEnvironmentData(self):
        #    [has data, angles, color]
        data = [0, Vec3(0), Vec4(0)]

        if not self.bspLoader.hasActiveLevel():
            return data

        for i in xrange(self.bspLoader.getNumEntities()):
            classname = self.bspLoader.getEntityValue(i, "classname")
            if classname == "light_environment":
                data[0] = 1
                data[1] = self.convertHammerAngles(
                    self.bspLoader.getEntityValueVector(i, "angles"))
                data[2] = self.bspLoader.getEntityValueColor(i, "_light")
                break

        return data

    def cleanupSkyBox(self):
        if self.skyBoxUtil:
            self.skyBoxUtil.stopSky()
            self.skyBoxUtil.cleanup()
            self.skyBoxUtil = None
        if self.skyBox:
            self.skyBox.removeNode()
            self.skyBox = None

    def cleanupBSPLevel(self):
        self.cleanupSkyBox()
        #self.cleanupNavMesh()
        if self.bspLevel:
            # Cleanup any physics meshes for the level.
            self.disableAndRemovePhysicsNodes(self.bspLevel)
            self.bspLevel.removeNode()
            self.bspLevel = None
        self.bspLoader.cleanup()
        base.materialData = {}

    #def cleanupNavMesh(self):
    #    if self.navMeshNp:
    #        self.navMeshNp.removeNode()
    #        self.navMeshNp = None

    #def setupNavMesh(self, node):
    #    self.cleanupNavMesh()

    #    nmMgr = RNNavMeshManager.get_global_ptr()
    #    self.navMeshNp = nmMgr.create_nav_mesh()
    #    self.navMeshNp.node().set_owner_node_path(node)
    #    self.navMeshNp.node().setup()

    #    if 0:
    #        self.navMeshNp.node().enable_debug_drawing(self.camera)
    #        self.navMeshNp.node().toggle_debug_drawing(True)

    def setupRender(self):
        """
        Creates the render scene graph, the primary scene graph for
        rendering 3-d geometry.
        """
        ## This is the root of the 3-D scene graph.
        ## Make it a BSPRender node to automatically cull
        ## nodes against the BSP leafs if there is a loaded
        ## BSP level.
        self.render = NodePath(BSPRender('render', BSPLoader.getGlobalPtr()))
        self.render.setAttrib(RescaleNormalAttrib.makeDefault())
        self.render.setTwoSided(0)
        self.backfaceCullingEnabled = 1
        self.textureEnabled = 1
        self.wireframeEnabled = 0

    def loadSkyBox(self, skyType):
        if skyType != OutdoorLightingConfig.STNone:
            self.skyBox = loader.loadModel(
                OutdoorLightingConfig.SkyData[skyType][0])
            self.skyBox.hide(CIGlobals.ShadowCameraBitmask)
            self.skyBox.reparentTo(camera)
            self.skyBox.setCompass()
            self.skyBox.setZ(-350)
            self.skyBoxUtil = SkyUtil()
            self.skyBoxUtil.startSky(self.skyBox)

    def loadBSPLevel(self, mapFile):
        self.cleanupBSPLevel()

        base.bspLoader.read(mapFile)
        base.bspLevel = base.bspLoader.getResult()
        base.bspLoader.doOptimizations()
        for prop in base.bspLevel.findAllMatches("**/+BSPProp"):
            base.createAndEnablePhysicsNodes(prop)
        #base.setupNavMesh(base.bspLevel.find("**/model-0"))

        try:
            skyType = self.cr.playGame.hood.olc.skyType
        except:
            skyType = 1  #self.bspLoader.getEntityValueInt(0, "skytype")

        if skyType != OutdoorLightingConfig.STNone:
            skyCubemap = loader.loadCubeMap(
                OutdoorLightingConfig.SkyData[skyType][2])
            self.shaderGenerator.setIdentityCubemap(skyCubemap)

        CIGlobals.preRenderScene(render)

    def doNextFrame(self, func, extraArgs=[]):
        taskMgr.add(self.__doNextFrameTask,
                    "doNextFrame" + str(id(func)),
                    extraArgs=[func, extraArgs],
                    appendTask=True,
                    sort=100000)

    def __doNextFrameTask(self, func, extraArgs, task):
        func(*extraArgs)
        return task.done

    def loadSfxOnNode(self, sndFile, node):
        """ Loads up a spatialized sound and attaches it to the specified node. """
        snd = self.audio3d.loadSfx(sndFile)
        self.audio3d.attachSoundToObject(snd, node)
        return snd

    def physicsReport(self):
        print "\nThere are {0} total rigid bodies:".format(
            base.physicsWorld.getNumRigidBodies())
        for rb in base.physicsWorld.getRigidBodies():
            print "\t", NodePath(rb)
        print "\n"

    def removeEverything(self):
        for task in self.taskMgr.getTasks():
            if task.getName() not in ['dataLoop', 'igLoop']:
                task.remove()
        camera.reparentTo(render)
        for tex in render.findAllTextures():
            tex.releaseAll()
        for tex in aspect2d.findAllTextures():
            tex.releaseAll()
        for tex in render2d.findAllTextures():
            tex.releaseAll()
        for tex in hidden.findAllTextures():
            tex.releaseAll()
        for node in render.findAllMatches("**;+s"):
            node.removeNode()
        for node in aspect2d.findAllMatches("**;+s"):
            node.removeNode()
        for node in render2d.findAllMatches("**;+s"):
            node.removeNode()
        for node in hidden.findAllMatches("**;+s"):
            node.removeNode()
        TexturePool.garbageCollect()
        ModelPool.garbageCollect()
        RenderState.garbageCollect()
        RenderState.clearCache()
        RenderState.clearMungerCache()

        self.win.getGsg().getPreparedObjects().releaseAll()
        self.graphicsEngine.renderFrame()

    def doMemReport(self):
        MemoryUsage.showCurrentTypes()
        MemoryUsage.showCurrentAges()
        print MemoryUsage.getCurrentCppSize()
        print MemoryUsage.getExternalSize()
        print MemoryUsage.getTotalSize()

    def doPointers(self):
        print "---------------------------------------------------------------------"
        data = {}
        mup = MemoryUsagePointers()
        MemoryUsage.getPointers(mup)
        for i in xrange(mup.getNumPointers()):
            ptr = mup.getPythonPointer(i)
            if ptr.__class__.__name__ in data.keys():
                data[ptr.__class__.__name__] += 1
            else:
                data[ptr.__class__.__name__] = 1

        print "NodeReferenceCount:", data["NodeReferenceCount"]
        print "CopyOnWriteObject:", data["CopyOnWriteObject"]

        print "---------------------------------------------------------------------"

    def hideMouseCursor(self):
        props = WindowProperties()
        props.setCursorHidden(True)
        self.win.requestProperties(props)

    def showMouseCursor(self):
        props = WindowProperties()
        props.setCursorHidden(False)
        self.win.requestProperties(props)

    def doCamShake(self, intensity=1.0, duration=0.5, loop=False):
        shake = ShakeCamera(intensity, duration)
        shake.start(loop)
        return shake

    def renderFrames(self):
        self.graphicsEngine.renderFrame()
        self.graphicsEngine.renderFrame()

    def prepareScene(self):
        render.prepareScene(self.win.getGsg())

    def setPhysicsDebug(self, flag):
        self.physicsDbgFlag = flag
        debugNode = self.debugNP.node()
        if flag:
            debugNode.showWireframe(True)
            debugNode.showConstraints(True)
            debugNode.showBoundingBoxes(True)
            debugNode.showNormals(False)
            self.debugNP.show()
        else:
            debugNode.showWireframe(False)
            debugNode.showConstraints(False)
            debugNode.showBoundingBoxes(False)
            debugNode.showNormals(False)
            self.debugNP.hide()

    def stopMusic(self):
        if self.music:
            self.music.stop()
            self.music = None
        self.currSongName = None

    def playMusic(self, songName, looping=True, volume=1.0):
        if isinstance(songName, list):
            # A list of possible songs were passed in, pick a random one.
            songName = random.choice(songName)

        if songName == self.currSongName:
            # Don't replay the same song.
            return

        self.stopMusic()

        self.currSongName = songName

        song = MusicCache.findSong(songName)
        if not song:
            self.notify.warning(
                "Song `{0}` not found in cache.".format(songName))
            return

        self.music = song
        self.music.setLoop(looping)
        self.music.setVolume(volume)
        self.music.play()

    def fadeOutMusic(self, time=1.0, music=None):
        if not music:
            music = self.music

        if not music:
            return

        self.fadeAudio(time, music, music.getVolume(), 0.0)

    def fadeAudio(self, time, audio, start, end):
        from direct.interval.IntervalGlobal import LerpFunc

        def __changeMusicVolume(vol):
            audio.setVolume(vol)

        LerpFunc(__changeMusicVolume, time, start, end).start()

    def enablePhysicsNodes(self, rootNode):
        PhysicsUtils.attachBulletNodes(rootNode)

    def disablePhysicsNodes(self, rootNode):
        PhysicsUtils.detachBulletNodes(rootNode)

    def createPhysicsNodes(self, rootNode):
        PhysicsUtils.makeBulletCollFromPandaColl(rootNode)

    def createAndEnablePhysicsNodes(self, rootNode):
        self.createPhysicsNodes(rootNode)
        self.enablePhysicsNodes(rootNode)

    def removePhysicsNodes(self, rootNode):
        PhysicsUtils.removeBulletNodes(rootNode)

    def disableAndRemovePhysicsNodes(self, rootNode):
        PhysicsUtils.detachAndRemoveBulletNodes(rootNode)

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

        if dt <= 0.016:
            self.physicsWorld.doPhysics(dt, metadata.PHYS_SUBSTEPS, 0.016)
        elif dt <= 0.033:
            self.physicsWorld.doPhysics(dt, metadata.PHYS_SUBSTEPS, 0.033)
        else:
            self.physicsWorld.doPhysics(dt, 0)

        return task.cont

    def projectShadows(self):
        #self.shadowCaster.projectShadows()
        pass

    def setBloom(self, flag):
        self.bloomToggle = flag

        #if not hasattr(self, 'filters'):
        #    # Sanity check
        #    return

        #if flag:
        #    self.filters.setBloom(desat = 0, intensity = 0.4, mintrigger = 0.85, maxtrigger = 1.0, size = "large")
        #else:
        #    self.filters.delBloom()

    def initStuff(self):
        # Precache water bar shader, prevents crash from running out of GPU registers
        loader.loadShader("phase_14/models/shaders/progress_bar.sha")

        self.bspLoader.setWantShadows(metadata.USE_REAL_SHADOWS)

        self.shaderGenerator = BSPShaderGenerator(self.win, self.win.getGsg(),
                                                  self.camera, self.render)
        self.win.getGsg().setShaderGenerator(self.shaderGenerator)
        self.bspLoader.setShaderGenerator(self.shaderGenerator)
        vlg = VertexLitGenericSpec()  # models
        ulg = UnlitGenericSpec()  # ui elements, particles, etc
        lmg = LightmappedGenericSpec()  # brushes, displacements
        unm = UnlitNoMatSpec()  # when there's no material
        csm = CSMRenderSpec()  # renders the shadow scene for CSM
        skb = SkyBoxSpec()  # renders the skybox onto faces
        dcm = DecalModulateSpec()  # blends decals
        self.shaderGenerator.addShader(vlg)
        self.shaderGenerator.addShader(ulg)
        self.shaderGenerator.addShader(unm)
        self.shaderGenerator.addShader(lmg)
        self.shaderGenerator.addShader(csm)
        self.shaderGenerator.addShader(skb)
        self.shaderGenerator.addShader(dcm)

        self.shaderGenerator.setShaderQuality(
            CIGlobals.getSettingsMgr().getSetting("shaderquality").getValue())

        if metadata.USE_REAL_SHADOWS and self.config.GetBool(
                'pssm-debug-cascades', False):
            from panda3d.core import CardMaker, Shader  #, Camera, Trackball
            cm = CardMaker('cm')
            cm.setFrame(-1, 1, -1, 1)
            np = aspect2d.attachNewNode(cm.generate())
            np.setScale(0.3)
            np.setPos(0, -0.7, -0.7)
            np.setShader(
                Shader.load(Shader.SLGLSL,
                            "phase_14/models/shaders/debug_csm.vert.glsl",
                            "phase_14/models/shaders/debug_csm.frag.glsl"))
            np.setShaderInput("cascadeSampler",
                              self.shaderGenerator.getPssmArrayTexture())
            #cam = Camera('csmDbgCam')
            #tb = Trackball('tb')
            #lens = PerspectiveLens()
            #cam.setLens(lens)
            #cam.reparentTo(render)
            #base.openWindow(useCamera = cam)

        #self.shadowCaster.turnOnShadows()

        self.waterReflectionMgr.load()

        self.filters = CIPostProcess()
        self.filters.startup(self.win)
        self.filters.addCamera(self.cam)
        self.filters.setup()

        self.hdr = HDR()
        self.setHDR(self.hdrToggle)
        self.setBloom(self.bloomToggle)
        self.setFXAA(self.fxaaToggle)
        self.setAmbientOcclusion(self.aoToggle)
        #self.filters.setDepthOfField(distance = 10.0, range = 175.0, near = 1.0, far = 1000.0 / (1000.0 - 1.0))

        #from src.coginvasion.globals import BSPUtility
        #BSPUtility.applyUnlitOverride(render)

        # We define this here (naming it cl_ to avoid trying to use the old base.attackMgr)
        # in order to precache attacks. The ClientRepository will then take our self.cl_attackMgr
        # and use it as base.cr.attackMgr.
        from src.coginvasion.attack.AttackManager import AttackManager
        self.cl_attackMgr = AttackManager()

        if self.DebugShaderQualities:
            from libpandabsp import SHADERQUALITY_HIGH, SHADERQUALITY_MEDIUM, SHADERQUALITY_LOW
            self.accept('1', self.shaderGenerator.setShaderQuality,
                        [SHADERQUALITY_LOW])
            self.accept('2', self.shaderGenerator.setShaderQuality,
                        [SHADERQUALITY_MEDIUM])
            self.accept('3', self.shaderGenerator.setShaderQuality,
                        [SHADERQUALITY_HIGH])

    def makeCamera(self,
                   win,
                   sort=0,
                   scene=None,
                   displayRegion=(0, 1, 0, 1),
                   stereo=None,
                   aspectRatio=None,
                   clearDepth=0,
                   clearColor=None,
                   lens=None,
                   camName='cam',
                   mask=None,
                   useCamera=None):
        """
        Makes a new 3-d camera associated with the indicated window,
        and creates a display region in the indicated subrectangle.

        If stereo is True, then a stereo camera is created, with a
        pair of DisplayRegions.  If stereo is False, then a standard
        camera is created.  If stereo is None or omitted, a stereo
        camera is created if the window says it can render in stereo.

        If useCamera is not None, it is a NodePath to be used as the
        camera to apply to the window, rather than creating a new
        camera.
        """
        # self.camera is the parent node of all cameras: a node that
        # we can move around to move all cameras as a group.
        if self.camera == None:
            # We make it a ModelNode with the PTLocal flag, so that
            # a wayward flatten operations won't attempt to mangle the
            # camera.
            self.camera = self.render.attachNewNode(ModelNode('camera'))
            self.camera.node().setPreserveTransform(ModelNode.PTLocal)
            builtins.camera = self.camera

            self.mouse2cam.node().setNode(self.camera.node())

        if useCamera:
            # Use the existing camera node.
            cam = useCamera
            camNode = useCamera.node()
            assert (isinstance(camNode, Camera))
            lens = camNode.getLens()
            cam.reparentTo(self.camera)

        else:
            # Make a new Camera node.
            camNode = Camera(camName)
            if lens == None:
                lens = PerspectiveLens()

                if aspectRatio == None:
                    aspectRatio = self.getAspectRatio(win)
                lens.setAspectRatio(aspectRatio)

            cam = self.camera.attachNewNode(camNode)

        if lens != None:
            camNode.setLens(lens)

        if scene != None:
            camNode.setScene(scene)

        if mask != None:
            if (isinstance(mask, int)):
                mask = BitMask32(mask)
            camNode.setCameraMask(mask)

        if self.cam == None:
            self.cam = cam
            self.camNode = camNode
            self.camLens = lens

        self.camList.append(cam)

        # Now, make a DisplayRegion for the camera.
        if stereo is not None:
            if stereo:
                dr = win.makeStereoDisplayRegion(*displayRegion)
            else:
                dr = win.makeMonoDisplayRegion(*displayRegion)
        else:
            dr = win.makeDisplayRegion(*displayRegion)

        dr.setSort(sort)

        dr.disableClears()

        # By default, we do not clear 3-d display regions (the entire
        # window will be cleared, which is normally sufficient).  But
        # we will if clearDepth is specified.
        if clearDepth:
            dr.setClearDepthActive(1)

        if clearColor:
            dr.setClearColorActive(1)
            dr.setClearColor(clearColor)

        dr.setCamera(cam)

        return cam

    def makeCamera2d(self,
                     win,
                     sort=10,
                     displayRegion=(0, 1, 0, 1),
                     coords=(-1, 1, -1, 1),
                     lens=None,
                     cameraName=None):
        """
        Makes a new camera2d associated with the indicated window, and
        assigns it to render the indicated subrectangle of render2d.
        """
        dr = win.makeMonoDisplayRegion(*displayRegion)
        dr.setSort(sort)
        dr.disableClears()

        # Make any texture reloads on the gui come up immediately.
        dr.setIncompleteRender(False)

        left, right, bottom, top = coords

        # Now make a new Camera node.
        if (cameraName):
            cam2dNode = Camera('cam2d_' + cameraName)
        else:
            cam2dNode = Camera('cam2d')

        if lens == None:
            lens = OrthographicLens()
            lens.setFilmSize(right - left, top - bottom)
            lens.setFilmOffset((right + left) * 0.5, (top + bottom) * 0.5)
            lens.setNearFar(-1000, 1000)
        cam2dNode.setLens(lens)

        # self.camera2d is the analog of self.camera, although it's
        # not as clear how useful it is.
        if self.camera2d == None:
            self.camera2d = self.render2d.attachNewNode('camera2d')

        camera2d = self.camera2d.attachNewNode(cam2dNode)
        dr.setCamera(camera2d)

        if self.cam2d == None:
            self.cam2d = camera2d

        return camera2d

    def precacheStuff(self):
        from src.coginvasion.toon import ToonGlobals
        ToonGlobals.precacheToons()

        self.cl_attackMgr.precache()

        from src.coginvasion.gags.LocationSeeker import LocationSeeker
        LocationSeeker.precache()

        from src.coginvasion.gags.LocationGag import LocationGag
        LocationGag.precache()

        from src.coginvasion.hood.DistributedBuilding import DistributedBuilding
        DistributedBuilding.precache()

        from src.coginvasion.cog import SuitBank
        SuitBank.precacheSuits()

    def setAmbientOcclusion(self, toggle):
        self.aoToggle = toggle
        #if not hasattr(self, 'filters'):
        #    # Sanity check
        #    return
        #if toggle:
        #    self.filters.setAmbientOcclusion()
        #else:
        #    self.filters.delAmbientOcclusion()

    def setFXAA(self, toggle):
        self.fxaaToggle = toggle

        #if not hasattr(self, 'filters'):
        #    # Sanity check
        #    return

        #if toggle:
        #    self.filters.setFXAA()
        #else:
        #    self.filters.delFXAA()

    def setHDR(self, toggle):
        self.hdrToggle = toggle

        #if not hasattr(self, 'hdr'):
        #    return

        if toggle:
            # Don't clamp lighting calculations with hdr.
            render.setAttrib(LightRampAttrib.makeIdentity())
            #self.hdr.enable()
        else:
            render.setAttrib(LightRampAttrib.makeDefault())
            #self.hdr.disable()

    def setCellsActive(self, cells, active):
        for cell in cells:
            cell.setActive(active)
        self.marginManager.reorganize()

    def setTimeOfDay(self, time):
        if self.metadata.USE_RENDER_PIPELINE:
            self.pipeline.daytime_mgr.time = time

    def doOldToontownRatio(self):
        ShowBase.adjustWindowAspectRatio(self, 4. / 3.)
        self.credits2d.setScale(1.0 / (4. / 3.), 1.0, 1.0)

    def doRegularRatio(self):
        ShowBase.adjustWindowAspectRatio(self, self.getAspectRatio())

    def adjustWindowAspectRatio(self, aspectRatio):
        if (CIGlobals.getSettingsMgr() is None):
            ShowBase.adjustWindowAspectRatio(self, aspectRatio)
            self.credits2d.setScale(1.0 / aspectRatio, 1.0, 1.0)
            return

        if CIGlobals.getSettingsMgr().getSetting("maspr").getValue():
            # Go ahead and maintain the aspect ratio if the user wants us to.
            ShowBase.adjustWindowAspectRatio(self, aspectRatio)
            self.credits2d.setScale(1.0 / aspectRatio, 1.0, 1.0)
        else:
            # The user wants us to keep a 4:3 ratio no matter what (old toontown feels).
            self.doOldToontownRatio()

    def muteMusic(self):
        self.musicManager.setVolume(0.0)

    def unMuteMusic(self):
        self.musicManager.setVolume(
            CIGlobals.SettingsMgr.getSetting("musvol").getValue())

    def muteSfx(self):
        self.sfxManagerList[0].setVolume(0.0)

    def unMuteSfx(self):
        self.sfxManagerList[0].setVolume(
            CIGlobals.SettingsMgr.getSetting("sfxvol").getValue())

    def localAvatarReachable(self):
        # This verifies that the localAvatar hasn't been deleted and isn't none.
        return hasattr(self, 'localAvatar') and self.localAvatar
예제 #48
0
파일: mundo.py 프로젝트: fnadalt/mundo
class EscenaMundo(DirectObject):
    """
    * escena del mundo virtual
    """

    Nombre = "mundo"  # world

    def __init__(self, contexto):
        DirectObject.__init__(self)
        # referencias
        self.contexto = contexto
        # componentes
        self.mundo_fisica = BulletWorld()  # physics world
        self.debug_fisica = None
        self.input = None
        self.terreno = None  # terrain
        self.estaticos = None  # static (model instances)
        self.animados = list()  # animated (model instances, actors)
        self.items = None
        self.atmosfera = None  # atmosphere
        self.cntrlcam = None  # camera controller
        self.texto_info = None  # info text
        self.debug_hud = None
        # parametros
        self.cargar_terreno = True
        self.cargar_atmosfera = True

    def iniciar(self):
        log.info("iniciar")
        self._establecer_parametros()
        #
        b = self.contexto.base
        # física
        self.mundo_fisica.setGravity(Vec3(0, 0, -9.81))
        df = BulletDebugNode("debug_fisica")
        self.mundo_fisica.setDebugNode(df)
        self.debug_fisica = b.render.attachNewNode(df)
        self.debug_fisica.hide()
        self.accept("f11", self._toggle_debug_fisica)
        # input
        self.input = Input(self.contexto)
        if not self.input.iniciar():
            return False
        # terreno
        if self.cargar_terreno:
            self.terreno = Terreno(self.contexto, self.mundo_fisica)
            if not self.terreno.iniciar():
                return False
        # animados (actors)
        self._iniciar_animados()
        # atmosfera
        if self.cargar_atmosfera:
            self.atmosfera = Atmosfera(self.contexto)
            if not self.atmosfera.iniciar():
                return False
        # controlador camara
        self.cntrlcam = ControladorCamara(self.contexto)
        if not self.cntrlcam.iniciar():
            return False
        # info texto
        self.info_texto = OnscreenText(
            text="cámara: f1:libre f2:1ºpers f3:3ºpers\n"
            "debug física: f11")
        # debug hud
        self.debug_hud = OnscreenText(parent=b.a2dTopLeft,
                                      text="Debug?",
                                      pos=(0, -0.1),
                                      scale=0.05,
                                      align=TextNode.ALeft,
                                      bg=(1, 1, 1, 0.3))
        # pelota (ball)
        pelota = b.loader.loadModel("modelos/items/pelota.egg")
        pelota.reparentTo(b.render)
        pelota.setPos(0, 0.5, 15)
        b.messenger.send("establecer_objetivo", [pelota])
        # eventos
        self.accept("escape-up", self._salir)
        # tasks
        b.taskMgr.doMethodLater(0.1, self._update_debug_hud,
                                "Mundo_update_debug_hud")
        b.taskMgr.add(self._update, "Mundo_update")
        #
        return True

    def terminar(self):
        log.info("terminar")
        # tasks
        self.contexto.base.taskMgr.remove("Mundo_update_debug_hud")
        self.contexto.base.taskMgr.remove("Mundo_update")
        # eventos
        self.ignoreAll()
        # camara
        if self.cntrlcam:
            self.cntrlcam.terminar()
            self.cntrlcam = None
        # debug hud
        if self.debug_hud:
            self.debug_hud.destroy()
            self.debug_hud = None
        # info texto
        if self.info_texto:
            self.info_texto.destroy()
            self.info_texto = None
        # atmosfera
        if self.atmosfera:
            self.atmosfera.terminar()
            self.atmosfera = None
        # animados
        for animado in self.animados:
            animado.terminar()
        self.animados = list()
        # terreno
        if self.terreno:
            self.terreno.terminar()
            self.terreno = None
        # input
        if self.input:
            self.input.terminar()
            self.input = None
        # física
        self.mundo_fisica.clearDebugNode()
        self.debug_fisica.removeNode()

    def _establecer_parametros(self):
        log.info("_establecer_parametros")
        try:
            cfg = self.contexto.config["mundo"]
            self.cargar_terreno = cfg.getboolean("terreno")
            self.cargar_atmosfera = cfg.getboolean("atmosfera")
        except ValueError as e:
            log.exception("error en el análisis de la configuración: " +
                          str(e))

    def _iniciar_animados(self):  # init animated (actors)
        log.info("_iniciar_animados")
        actor = Persona(self.contexto, self.input)
        if actor.iniciar():
            self.animados.append(actor)

    def _toggle_texto_info(self):
        pass

    def _toggle_debug_fisica(self):
        if self.debug_fisica.isHidden():
            self.debug_fisica.show()
        else:
            self.debug_fisica.hide()

    def _salir(self):
        self.contexto.base.messenger.send("cambiar_escena", ["inicio"])

    def _update_debug_hud(self, task):
        info = "Debug\n"
        #
        info += self.input.obtener_info() + "\n"
        if self.atmosfera:
            info += self.atmosfera.obtener_info() + "\n"
        #
        self.debug_hud["text"] = info
        return task.again

    def _update(self, task):
        # física
        dt = self.contexto.base.taskMgr.globalClock.getDt()
        self.mundo_fisica.doPhysics(dt, 10, 1.0 / 180.0)
        #
        return task.cont
예제 #49
0
class Simulation(ShowBase):
    scale = 1
    height = 500
    lateralError = 200
    dt = 0.1
    steps = 0
    #Test Controllers
    fuelPID = PID(10, 0.5, 10, 0, 100)
    heightPID = PID(0.08, 0, 0.3, 0.1, 1)
    pitchPID = PID(10, 0, 1000, -10, 10)
    rollPID = PID(10, 0, 1000, -10, 10)
    XPID = PID(0.2, 0, 0.8, -10, 10)
    YPID = PID(0.2, 0, 0.8, -10, 10)
    vulcain = NeuralNetwork()
    tau = 0.5
    Valves=[]

    CONTROL = False

    EMPTY = False
    LANDED = False
    DONE = False

    gimbalX = 0
    gimbalY = 0
    targetAlt = 150

    R = RE(200 * 9.806, 250 * 9.806, 7607000 / 9 * scale, 0.4)
    throttle = 0.0
    fuelMass_full = 417000 * scale
    fuelMass_init = 0.10

    radius = 1.8542 * scale
    length = 47 * scale
    Cd = 1.5


    def __init__(self, VISUALIZE=False):

        self.VISUALIZE = VISUALIZE


        if VISUALIZE is True:
            ShowBase.__init__(self)
            self.setBackgroundColor(0.2, 0.2, 0.2, 1)
            self.setFrameRateMeter(True)
            self.render.setShaderAuto()
            self.cam.setPos(-120 * self.scale, -120 * self.scale, 120 * self.scale)
            self.cam.lookAt(0, 0, 10 * self.scale)
            alight = AmbientLight('ambientLight')
            alight.setColor(Vec4(0.5, 0.5, 0.5, 1))
            alightNP = self.render.attachNewNode(alight)

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

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

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

            inputState.watchWithModifiers('forward', 'w')
            inputState.watchWithModifiers('left', 'a')
            inputState.watchWithModifiers('reverse', 's')
            inputState.watchWithModifiers('right', 'd')
            inputState.watchWithModifiers('turnLeft', 'q')
            inputState.watchWithModifiers('turnRight', 'e')
            self.ostData = OnscreenText(text='ready', pos=(-1.3, 0.9), scale=0.07, fg=Vec4(1, 1, 1, 1),
            align=TextNode.ALeft)

        self.fuelMass = self.fuelMass_full * self.fuelMass_init
        self.vulcain.load_existing_model(path="LandingRockets/",model_name="140k_samples_1024neurons_3layers_l2-0.000001")



        # Physics
        self.setup()

    # _____HANDLER_____

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

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

    def toggleWireframe(self):
        ...#self.toggleWireframe()

    def toggleTexture(self):
        ...#self.toggleTexture()

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

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

    # ____TASK___

    def processInput(self):
        throttleChange = 0.0

        if inputState.isSet('forward'): self.gimbalY = 10
        if inputState.isSet('reverse'): self.gimbalY = -10
        if inputState.isSet('left'):    self.gimbalX = 10
        if inputState.isSet('right'):   self.gimbalX = -10
        if inputState.isSet('turnLeft'):  throttleChange = -1.0
        if inputState.isSet('turnRight'): throttleChange = 1.0

        self.throttle += throttleChange / 100.0
        self.throttle = min(max(self.throttle, 0), 1)

    def processContacts(self):
        result = self.world.contactTestPair(self.rocketNP.node(), self.groundNP.node())
        #print(result.getNumContacts())
        if result.getNumContacts() != 0:
            self.LANDED = True
            #self.DONE = True

    def update(self,task):

        #self.control(0.1,0.1,0.1)
        #self.processInput()
        #self.processContacts()
        # self.terrain.update()
        return task.cont

    def cleanup(self):
        self.world.removeRigidBody(self.groundNP.node())
        self.world.removeRigidBody(self.rocketNP.node())
        self.world = None

        self.debugNP = None
        self.groundNP = None
        self.rocketNP = None

        self.worldNP.removeNode()

        self.LANDED = False
        self.EMPTY = False
        self.DONE = False
        self.steps = 0
        self.fuelMass = self.fuelMass_full*self.fuelMass_init

    def setup(self):

        self.targetAlt = r.randrange(100,300)
        self.Valves = np.array([0.15,0.2,0.15])
        self.EngObs = self.vulcain.predict_data_point(np.array(self.Valves).reshape(1,-1))

        if self.VISUALIZE is True:
            self.worldNP = self.render.attachNewNode('World')

        else:
            self.root = NodePath(PandaNode("world root"))
            self.worldNP = self.root.attachNewNode('World')






        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.80665))

        # World
        self.debugNP = self.worldNP.attachNewNode(BulletDebugNode('Debug'))
        self.debugNP.node().showWireframe(True)
        self.debugNP.node().showConstraints(True)
        self.debugNP.node().showBoundingBoxes(False)
        self.debugNP.node().showNormals(True)
        self.debugNP.show()
        self.world.setDebugNode(self.debugNP.node())

        # self.debugNP.showTightBounds()
        # self.debugNP.showBounds()


        # Ground (static)
        shape = BulletPlaneShape(Vec3(0, 0, 1), 1)

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

        self.world.attachRigidBody(self.groundNP.node())

        # Rocket
        shape = BulletCylinderShape(self.radius, self.length, ZUp)

        self.rocketNP = self.worldNP.attachNewNode(BulletRigidBodyNode('Cylinder'))
        self.rocketNP.node().setMass(27200 * self.scale)
        self.rocketNP.node().addShape(shape)
        #self.rocketNP.setPos(20,20,250)
        self.rocketNP.setPos(20, 20, r.randrange(100, 300)+200)
        #self.rocketNP.setPos(r.randrange(-self.lateralError, self.lateralError, 1), r.randrange(-self.lateralError, self.lateralError, 1), self.height)
        # self.rocketNP.setPos(0, 0, self.length*10)
        self.rocketNP.setCollideMask(BitMask32.allOn())
        # self.rocketNP.node().setCollisionResponse(0)
        self.rocketNP.node().notifyCollisions(True)

        self.world.attachRigidBody(self.rocketNP.node())

        for i in range(4):
            leg = BulletCylinderShape(0.1 * self.radius, 0.5 * self.length, XUp)
            self.rocketNP.node().addShape(leg, TransformState.makePosHpr(
                Vec3(6 * self.radius * math.cos(i * math.pi / 2), 6 * self.radius * math.sin(i * math.pi / 2),
                     -0.6 * self.length), Vec3(i * 90, 0, 30)))

        shape = BulletConeShape(0.75 * self.radius, 0.5 * self.radius, ZUp)
        self.rocketNP.node().addShape(shape, TransformState.makePosHpr(Vec3(0, 0, -1 / 2 * self.length), Vec3(0, 0, 0)))

        # Fuel
        self.fuelRadius = 0.9 * self.radius
        shape = BulletCylinderShape(self.fuelRadius, 0.01 * self.length, ZUp)
        self.fuelNP = self.worldNP.attachNewNode(BulletRigidBodyNode('Cone'))
        self.fuelNP.node().setMass(self.fuelMass_full * self.fuelMass_init)
        self.fuelNP.node().addShape(shape)
        self.fuelNP.setPos(0, 0, self.rocketNP.getPos().getZ() - self.length * 0.5 * (1 - self.fuelMass_init))
        self.fuelNP.setCollideMask(BitMask32.allOn())
        self.fuelNP.node().setCollisionResponse(0)

        self.world.attachRigidBody(self.fuelNP.node())

        frameA = TransformState.makePosHpr(Point3(0, 0, 0), Vec3(0, 0, 90))
        frameB = TransformState.makePosHpr(Point3(0, 0, 0), Vec3(0, 0, 90))

        self.fuelSlider = BulletSliderConstraint(self.rocketNP.node(), self.fuelNP.node(), frameA, frameB, 1)
        self.fuelSlider.setTargetLinearMotorVelocity(0)
        self.fuelSlider.setDebugDrawSize(2.0)
        self.fuelSlider.set_lower_linear_limit(0)
        self.fuelSlider.set_upper_linear_limit(0)
        self.world.attachConstraint(self.fuelSlider)

        self.npThrustForce = LineNodePath(self.rocketNP, 'Thrust', thickness=4, colorVec=Vec4(1, 0.5, 0, 1))
        self.npDragForce = LineNodePath(self.rocketNP, 'Drag', thickness=4, colorVec=Vec4(1, 0, 0, 1))
        self.npLiftForce = LineNodePath(self.rocketNP, 'Lift', thickness=4, colorVec=Vec4(0, 0, 1, 1))
        self.npFuelState = LineNodePath(self.fuelNP, 'Fuel', thickness=20, colorVec=Vec4(0, 1, 0, 1))

        self.rocketCSLon = self.radius ** 2 * math.pi
        self.rocketCSLat = self.length * 2 * self.radius

        if self.VISUALIZE is True:
            self.terrain = loader.loadModel("LZGrid2.egg")
            self.terrain.setScale(10)
            self.terrain.reparentTo(self.render)
            self.terrain.setColor(Vec4(0.1, 0.2, 0.1, 1))
            self.toggleTexture()

        #self.fuelNP.setPos(0, 0, self.rocketNP.getPos().getZ() - self.length * 0.4 * (1 - self.fuelMass_init))

        for i in range(5):
            self.world.doPhysics(self.dt, 5, 1.0 / 180.0)

        self.fuelSlider.set_lower_linear_limit(-self.length * 0.5 * (1 - self.fuelMass_init))
        self.fuelSlider.set_upper_linear_limit(self.length * 0.5 * (1 - self.fuelMass_init))

        for i in range(100):
            self.world.doPhysics(self.dt, 5, 1.0 / 180.0)
            self.rocketNP.node().applyForce(Vec3(0,0,300000), Vec3(0, 0, 0))








    def updateRocket(self, mdot, dt):

        # Fuel Update
        self.fuelMass = self.fuelNP.node().getMass() - dt * mdot
        if self.fuelMass <= 0:
            self.EMPTY is True
        fuel_percent = self.fuelMass / self.fuelMass_full
        self.fuelNP.node().setMass(self.fuelMass)
        fuelHeight = self.length * fuel_percent
        I1 = 1 / 2 * self.fuelMass * self.fuelRadius ** 2
        I2 = 1 / 4 * self.fuelMass * self.fuelRadius ** 2 + 1 / 12 * self.fuelMass * fuelHeight * fuelHeight
        self.fuelNP.node().setInertia(Vec3(I2, I2, I1))

        # Shift fuel along slider constraint
        fuelTargetPos = 0.5 * (self.length - fuelHeight)
        fuelPos = self.fuelSlider.getLinearPos()
        self.fuelSlider.set_upper_linear_limit(fuelTargetPos)
        self.fuelSlider.set_lower_linear_limit(-fuelTargetPos)

        self.npFuelState.reset()
        self.npFuelState.drawArrow2d(Vec3(0, 0, -0.5 * fuelHeight), Vec3(0, 0, 0.5 * fuelHeight), 45, 2)
        self.npFuelState.create()

    def observe(self):
        pos = self.rocketNP.getPos()
        vel = self.rocketNP.node().getLinearVelocity()
        quat = self.rocketNP.getTransform().getQuat()
        Roll, Pitch, Yaw = quat.getHpr()
        rotVel = self.rocketNP.node().getAngularVelocity()
        offset = self.targetAlt-pos.getZ()

        return pos, vel, Roll, Pitch, Yaw, rotVel, self.fuelMass / self.fuelMass_full, self.EMPTY, self.DONE, self.LANDED, offset, self.EngObs[0], self.Valves

    def control(self,ValveCommands):

        self.gimbalX = 0
        self.gimbalY = 0

        self.Valves = ValveCommands-(ValveCommands-self.Valves)*np.exp(-self.dt/self.tau)

        self.EngObs = self.vulcain.predict_data_point(np.array(self.Valves).reshape(1,-1 ))
        #Brennkammerdruck, Gaskammertemp, H2Massenstrom, LOX MAssentrom, Schub
        #Bar,K,Kg/s,Kg/s,kN
        #self.dt = globalClock.getDt()

        pos = self.rocketNP.getPos()
        vel = self.rocketNP.node().getLinearVelocity()
        quat = self.rocketNP.getTransform().getQuat()
        Roll, Pitch, Yaw = quat.getHpr()
        rotVel = self.rocketNP.node().getAngularVelocity()

        # CHECK STATE
        if self.fuelMass <= 0:
            self.EMPTY = True
        #if pos.getZ() <= 36:
        #    self.LANDED = True
        self.LANDED = False
        self.processContacts()

        P, T, rho = air_dens(pos[2])
        rocketZWorld = quat.xform(Vec3(0, 0, 1))

        AoA = math.acos(min(max(dot(norm(vel), norm(-rocketZWorld)), -1), 1))

        dynPress = 0.5 * dot(vel, vel) * rho

        dragArea = self.rocketCSLon + (self.rocketCSLat - self.rocketCSLon) * math.sin(AoA)

        drag = norm(-vel) * dynPress * self.Cd * dragArea

        time = globalClock.getFrameTime()

        liftVec = norm(vel.project(rocketZWorld) - vel)
        if AoA > 0.5 * math.pi:
            liftVec = -liftVec
        lift = liftVec * (math.sin(AoA * 2) * self.rocketCSLat * dynPress)

        if self.CONTROL:
            self.throttle = self.heightPID.control(pos.getZ(), vel.getZ(), 33)

            pitchTgt = self.XPID.control(pos.getX(), vel.getX(), 0)
            self.gimbalX = -self.pitchPID.control(Yaw, rotVel.getY(), pitchTgt)

            rollTgt = self.YPID.control(pos.getY(), vel.getY(), 0)
            self.gimbalY = -self.rollPID.control(Pitch, rotVel.getX(), -rollTgt)



        self.thrust = self.EngObs[0][4]*1000
        #print(self.EngObs)
        quat = self.rocketNP.getTransform().getQuat()
        quatGimbal = TransformState.makeHpr(Vec3(0, self.gimbalY, self.gimbalX)).getQuat()
        thrust = quatGimbal.xform(Vec3(0, 0, self.thrust))
        thrustWorld = quat.xform(thrust)

        #print(thrustWorld)

        self.npDragForce.reset()
        self.npDragForce.drawArrow2d(Vec3(0, 0, 0), quat.conjugate().xform(drag) / 1000, 45, 2)
        self.npDragForce.create()

        self.npLiftForce.reset()
        self.npLiftForce.drawArrow2d(Vec3(0, 0, 0), quat.conjugate().xform(lift) / 1000, 45, 2)
        self.npLiftForce.create()

        self.npThrustForce.reset()
        if self.EMPTY is False & self.LANDED is False:
            self.npThrustForce.drawArrow2d(Vec3(0, 0, -0.5 * self.length),
                                           Vec3(0, 0, -0.5 * self.length) - thrust / 30000, 45, 2)
            self.npThrustForce.create()

        self.rocketNP.node().applyForce(drag, Vec3(0, 0, 0))
        self.rocketNP.node().applyForce(lift, Vec3(0, 0, 0))
        #print(self.EMPTY,self.LANDED)
        if self.EMPTY is False & self.LANDED is False:
            self.rocketNP.node().applyForce(thrustWorld, quat.xform(Vec3(0, 0, -1 / 2 * self.length)))
            self.updateRocket(self.EngObs[0][2]+self.EngObs[0][3], self.dt)
        self.rocketNP.node().setActive(True)
        self.fuelNP.node().setActive(True)

        self.processInput()

        self.world.doPhysics(self.dt)
        self.steps+=1


        if self.steps > 1000:
            self.DONE = True

        telemetry = []

        telemetry.append('Thrust: {}'.format(int(self.EngObs[0][4])))
        telemetry.append('Fuel: {}%'.format(int(self.fuelMass / self.fuelMass_full * 100.0)))
        telemetry.append('Gimbal: {}'.format(int(self.gimbalX)) + ',{}'.format(int(self.gimbalY)))
        telemetry.append('AoA: {}'.format(int(AoA / math.pi * 180.0)))
        telemetry.append('\nPos: {},{}'.format(int(pos.getX()), int(pos.getY())))
        telemetry.append('Height: {}'.format(int(pos.getZ())))
        telemetry.append('RPY: {},{},{}'.format(int(Roll), int(Pitch), int(Yaw)))
        telemetry.append('Speed: {}'.format(int(np.linalg.norm(vel))))
        telemetry.append('Vel: {},{},{}'.format(int(vel.getX()), int(vel.getY()), int(vel.getZ())))
        telemetry.append('Rot: {},{},{}'.format(int(rotVel.getX()), int(rotVel.getY()), int(rotVel.getZ())))
        telemetry.append('LANDED: {}'.format(self.LANDED))
        telemetry.append('Time: {}'.format(self.steps*self.dt))
        telemetry.append('TARGET: {}'.format(self.targetAlt))
        #print(pos)
        if self.VISUALIZE is True:
            self.ostData.setText('\n'.join(telemetry))
            self.cam.setPos(pos[0] - 120 * self.scale, pos[1] - 120 * self.scale, pos[2] + 80 * self.scale)
            self.cam.lookAt(pos[0], pos[1], pos[2])
            self.taskMgr.step()


    """
예제 #50
0
class Mecha01Client(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
        self.plight = PointLight('plight')
        self.pnlp = self.camera.attachNewNode(self.plight)
        render.setLight(self.pnlp)

        self.debugNode = BulletDebugNode('Debug')
        self.debugNode.showWireframe(True)
        self.debugNode.showConstraints(True)
        self.debugNode.showBoundingBoxes(False)
        self.debugNode.showNormals(False)
        self.debugNP = render.attachNewNode(self.debugNode)
        self.debugNP.show()

        self.world = BulletWorld()
        self.world.setDebugNode(self.debugNode)

        self.planet = Planet()
        self.planet.perlin_terrain(5, 0.5)
        self.planet.build_node_path(render, self.world)

        shape = BulletCapsuleShape(0.25, 0.5)
        node = BulletRigidBodyNode('Capsule')
        node.addShape(shape)
        np = render.attachNewNode(node)
        np.setPos(Vec3(0, 0.8, 0.8) * self.planet.get_radius())
        new_up_vector = Vec3(np.getPos() -
                             self.planet.get_node_path().getPos())
        old_up_vector = Vec3(0, 0, 1)
        q = self.__quatFromTo(old_up_vector, new_up_vector)
        np.setQuat(q)

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

        #node.applyCentralImpulse(Vec3(0.4, 0.6, 1.0))

        self.taskMgr.add(self.physicsUpdateTask, "PhysicsUpdateTask")

        self.accept('arrow_up', self.test01, ["shalala"])

    def test01(self, x):
        print(x)

    def gravity(self, position):
        down_vector = Vec3(0, 0, 0) - position
        down_vector.normalize()
        gravity = LVector3f(down_vector * 9.81)

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

        # simulating spherical gravity
        node = self.np01.getNode(0)
        pos = self.np01.getPos()
        gravity = self.gravity(pos)
        #self.np01.setQuat(Quat(0, 1.1, 1.1, 0))

        self.world.doPhysics(dt)

        return Task.cont

    def spinCameraTask(self, task):
        # angleDegrees = task.time * 6.0
        # angleRadians = angleDegrees * (pi / 180.0)
        # self.camera.setPos(
        #     100.0 * sin(angleRadians),
        #     -100.0 * cos(angleRadians), 0.0)
        # self.camera.setHpr(angleDegrees, 0, 0)
        self.camera.setPos(self.np01.getPos() * 5.0)
        self.camera.lookAt(self.np01)
        return Task.cont

    def __quatFromTo(self, v0, v1):
        print(v0, v1)
        q = Quat(
            sqrt(v0.length()**2 * v1.length()**2) + v0.dot(v1), v0.cross(v1))
        q.normalize()
        return q
예제 #51
0
class Panda3dBulletPhysics(World):

    # NOTE: the model ids of objects that correspond to opened doors. They will be ignored for collisions.
    openedDoorModelIds = [
        '122',
        '133',
        '214',
        '246',
        '247',
        '361',
        '73',
        '756',
        '757',
        '758',
        '759',
        '760',
        '761',
        '762',
        '763',
        '764',
        '765',
        '768',
        '769',
        '770',
        '771',
        '778',
        '779',
        '780',
        's__1762',
        's__1763',
        's__1764',
        's__1765',
        's__1766',
        's__1767',
        's__1768',
        's__1769',
        's__1770',
        's__1771',
        's__1772',
        's__1773',
    ]

    # FIXME: is not a complete list of movable objects
    movableObjectCategories = [
        'table', 'dressing_table', 'sofa', 'trash_can', 'chair', 'ottoman',
        'bed'
    ]

    # For more material, see table: http://www.ambrsoft.com/CalcPhysics/Density/Table_2.htm
    defaultDensity = 1000.0  # kg/m^3

    # For more coefficients, see table: https://www.thoughtspike.com/friction-coefficients-for-bullet-physics/
    defaultMaterialFriction = 0.7

    defaultMaterialRestitution = 0.5

    def __init__(self,
                 scene,
                 suncgDatasetRoot=None,
                 debug=False,
                 objectMode='box',
                 agentRadius=0.1,
                 agentHeight=1.6,
                 agentMass=60.0,
                 agentMode='capsule'):

        super(Panda3dBulletPhysics, self).__init__()

        self.__dict__.update(scene=scene,
                             suncgDatasetRoot=suncgDatasetRoot,
                             debug=debug,
                             objectMode=objectMode,
                             agentRadius=agentRadius,
                             agentHeight=agentHeight,
                             agentMass=agentMass,
                             agentMode=agentMode)

        if suncgDatasetRoot is not None:
            self.modelCatMapping = ModelCategoryMapping(
                os.path.join(suncgDatasetRoot, "metadata",
                             "ModelCategoryMapping.csv"))
        else:
            self.modelCatMapping = None

        self.bulletWorld = BulletWorld()
        self.bulletWorld.setGravity(Vec3(0, 0, -9.81))

        if debug:
            debugNode = BulletDebugNode('physic-debug')
            debugNode.showWireframe(True)
            debugNode.showConstraints(False)
            debugNode.showBoundingBoxes(True)
            debugNode.showNormals(False)
            self.debugNodePath = self.scene.scene.attachNewNode(debugNode)
            self.debugNodePath.show()
            self.bulletWorld.setDebugNode(debugNode)
        else:
            self.debugNodePath = None

        self._initLayoutModels()
        self._initAgents()
        self._initObjects()

        self.scene.worlds['physics'] = self

    def destroy(self):
        # Nothing to do
        pass

    def _initLayoutModels(self):

        # Load layout objects as meshes
        for model in self.scene.scene.findAllMatches(
                '**/layouts/object*/model*'):

            shape, transform = getCollisionShapeFromModel(
                model, mode='mesh', defaultCentered=False)

            node = BulletRigidBodyNode('physics')
            node.setMass(0.0)
            node.setFriction(self.defaultMaterialFriction)
            node.setRestitution(self.defaultMaterialRestitution)
            node.setStatic(True)
            node.addShape(shape)
            node.setDeactivationEnabled(True)
            node.setIntoCollideMask(BitMask32.allOn())
            self.bulletWorld.attach(node)

            # Attach the physic-related node to the scene graph
            physicsNp = model.getParent().attachNewNode(node)
            physicsNp.setTransform(transform)

            if node.isStatic():
                model.getParent().setTag('physics-mode', 'static')
            else:
                model.getParent().setTag('physics-mode', 'dynamic')

            # Reparent render and acoustics nodes (if any) below the new physic node
            #XXX: should be less error prone to just reparent all children (except the hidden model)
            renderNp = model.getParent().find('**/render')
            if not renderNp.isEmpty():
                renderNp.reparentTo(physicsNp)
            acousticsNp = model.getParent().find('**/acoustics')
            if not acousticsNp.isEmpty():
                acousticsNp.reparentTo(physicsNp)

            # NOTE: we need this to update the transform state of the internal bullet node
            physicsNp.node().setTransformDirty()

            # Validation
            assert np.allclose(
                mat4ToNumpyArray(physicsNp.getNetTransform().getMat()),
                mat4ToNumpyArray(model.getNetTransform().getMat()),
                atol=1e-6)

    def _initAgents(self):

        # Load agents
        for agent in self.scene.scene.findAllMatches('**/agents/agent*'):

            transform = TransformState.makeIdentity()
            if self.agentMode == 'capsule':
                shape = BulletCapsuleShape(
                    self.agentRadius, self.agentHeight - 2 * self.agentRadius)
            elif self.agentMode == 'sphere':
                shape = BulletCapsuleShape(self.agentRadius,
                                           2 * self.agentRadius)

            # XXX: use BulletCharacterControllerNode class, which already handles local transform?
            node = BulletRigidBodyNode('physics')
            node.setMass(self.agentMass)
            node.setStatic(False)
            node.setFriction(self.defaultMaterialFriction)
            node.setRestitution(self.defaultMaterialRestitution)
            node.addShape(shape)
            self.bulletWorld.attach(node)

            # Constrain the agent to have fixed position on the Z-axis
            node.setLinearFactor(Vec3(1.0, 1.0, 0.0))

            # Constrain the agent not to be affected by rotations
            node.setAngularFactor(Vec3(0.0, 0.0, 0.0))

            node.setIntoCollideMask(BitMask32.allOn())
            node.setDeactivationEnabled(True)

            # Enable continuous collision detection (CCD)
            node.setCcdMotionThreshold(1e-7)
            node.setCcdSweptSphereRadius(0.50)

            if node.isStatic():
                agent.setTag('physics-mode', 'static')
            else:
                agent.setTag('physics-mode', 'dynamic')

            # Attach the physic-related node to the scene graph
            physicsNp = NodePath(node)
            physicsNp.setTransform(transform)

            # Reparent all child nodes below the new physic node
            for child in agent.getChildren():
                child.reparentTo(physicsNp)
            physicsNp.reparentTo(agent)

            # NOTE: we need this to update the transform state of the internal bullet node
            physicsNp.node().setTransformDirty()

            # Validation
            assert np.allclose(
                mat4ToNumpyArray(physicsNp.getNetTransform().getMat()),
                mat4ToNumpyArray(agent.getNetTransform().getMat()),
                atol=1e-6)

    def _initObjects(self):

        # Load objects
        for model in self.scene.scene.findAllMatches(
                '**/objects/object*/model*'):
            modelId = model.getParent().getTag('model-id')

            # XXX: we could create BulletGhostNode instance for non-collidable objects, but we would need to filter out the collisions later on
            if not modelId in self.openedDoorModelIds:

                shape, transform = getCollisionShapeFromModel(
                    model, self.objectMode, defaultCentered=True)

                node = BulletRigidBodyNode('physics')
                node.addShape(shape)
                node.setFriction(self.defaultMaterialFriction)
                node.setRestitution(self.defaultMaterialRestitution)
                node.setIntoCollideMask(BitMask32.allOn())
                node.setDeactivationEnabled(True)

                if self.suncgDatasetRoot is not None:

                    # Check if it is a movable object
                    category = self.modelCatMapping.getCoarseGrainedCategoryForModelId(
                        modelId)
                    if category in self.movableObjectCategories:
                        # Estimate mass of object based on volumetric data and default material density
                        objVoxFilename = os.path.join(self.suncgDatasetRoot,
                                                      'object_vox',
                                                      'object_vox_data',
                                                      modelId,
                                                      modelId + '.binvox')
                        voxelData = ObjectVoxelData.fromFile(objVoxFilename)
                        mass = Panda3dBulletPhysics.defaultDensity * voxelData.getFilledVolume(
                        )
                        node.setMass(mass)
                    else:
                        node.setMass(0.0)
                        node.setStatic(True)
                else:
                    node.setMass(0.0)
                    node.setStatic(True)

                if node.isStatic():
                    model.getParent().setTag('physics-mode', 'static')
                else:
                    model.getParent().setTag('physics-mode', 'dynamic')

                # Attach the physic-related node to the scene graph
                physicsNp = model.getParent().attachNewNode(node)
                physicsNp.setTransform(transform)

                # Reparent render and acoustics nodes (if any) below the new physic node
                #XXX: should be less error prone to just reparent all children (except the hidden model)
                renderNp = model.getParent().find('**/render')
                if not renderNp.isEmpty():
                    renderNp.reparentTo(physicsNp)
                acousticsNp = model.getParent().find('**/acoustics')
                if not acousticsNp.isEmpty():
                    acousticsNp.reparentTo(physicsNp)

                # NOTE: we need this to update the transform state of the internal bullet node
                node.setTransformDirty()

                # NOTE: we need to add the node to the bullet engine only after setting all attributes
                self.bulletWorld.attach(node)

                # Validation
                assert np.allclose(
                    mat4ToNumpyArray(physicsNp.getNetTransform().getMat()),
                    mat4ToNumpyArray(
                        model.getParent().getNetTransform().getMat()),
                    atol=1e-6)

            else:
                logger.debug('Object %s ignored from physics' % (modelId))

    def step(self, dt):
        self.bulletWorld.doPhysics(dt)

    def isCollision(self, root):
        isCollisionDetected = False
        if isinstance(root.node(), BulletRigidBodyNode):
            result = self.bulletWorld.contactTest(root.node())
            if result.getNumContacts() > 0:
                isCollisionDetected = True
        else:
            for nodePath in root.findAllMatches('**/+BulletBodyNode'):
                isCollisionDetected |= self.isCollision(nodePath)
        return isCollisionDetected

    def getCollisionInfo(self, root, dt):

        result = self.bulletWorld.contactTest(root.node())

        force = 0.0
        relativePosition = LVecBase3f(0.0, 0.0, 0.0)
        isCollisionDetected = False
        for _ in result.getContacts():

            # Iterate over all manifolds of the world
            # NOTE: it seems like the contact manifold doesn't hold the information
            #       to calculate contact force. We need the persistent manifolds for that.
            for manifold in self.bulletWorld.getManifolds():

                # Check if the root node is part of that manifold, by checking positions
                # TODO: there is surely a better way to compare the two nodes here
                #if (manifold.getNode0().getTransform().getPos() == root.getNetTransform().getPos()):
                if manifold.getNode0().getTag('model-id') == root.getTag(
                        'model-id'):

                    # Calculate the to
                    totalImpulse = 0.0
                    maxImpulse = 0.0
                    for pt in manifold.getManifoldPoints():
                        impulse = pt.getAppliedImpulse()
                        totalImpulse += impulse

                        if impulse > maxImpulse:
                            maxImpulse = impulse
                            relativePosition = pt.getLocalPointA()

                    force = totalImpulse / dt
                    isCollisionDetected = True

        return force, relativePosition, isCollisionDetected

    def calculate2dNavigationMap(self, agent, z=0.1, precision=0.1, yup=True):

        agentRbNp = agent.find('**/+BulletRigidBodyNode')

        # Calculate the bounding box of the scene
        bounds = []
        for nodePath in self.scene.scene.findAllMatches(
                '**/object*/+BulletRigidBodyNode'):
            node = nodePath.node()

            #NOTE: the bounding sphere doesn't seem to take into account the transform, so apply it manually (translation only)
            bsphere = node.getShapeBounds()
            center = nodePath.getNetTransform().getPos()
            bounds.extend(
                [center + bsphere.getMin(), center + bsphere.getMax()])

        minBounds, maxBounds = np.min(bounds, axis=0), np.max(bounds, axis=0)

        # Using the X and Y dimensions of the bounding box, discretize the 2D plan into a uniform grid with given precision
        X = np.arange(minBounds[0], maxBounds[0], step=precision)
        Y = np.arange(minBounds[1], maxBounds[1], step=precision)
        nbTotalCells = len(X) * len(Y)
        threshold10Perc = int(nbTotalCells / 10)

        # XXX: the simulation needs to be run a little before moving the agent, not sure why
        self.bulletWorld.doPhysics(0.1)

        # Sweep the position of the agent across the grid, checking if collision/contacts occurs with objects or walls in the scene.
        occupancyMap = np.zeros((len(X), len(Y)))
        occupancyMapCoord = np.zeros((len(X), len(Y), 2))
        n = 0
        for i, x in enumerate(X):
            for j, y in enumerate(Y):
                agentRbNp.setPos(LVecBase3f(x, y, z))

                if self.isCollision(agentRbNp):
                    occupancyMap[i, j] = 1.0

                occupancyMapCoord[i, j, 0] = x
                occupancyMapCoord[i, j, 1] = y

                n += 1
                if n % threshold10Perc == 0:
                    logger.debug('Collision test no.%d (out of %d total)' %
                                 (n, nbTotalCells))

        if yup:
            # Convert to image format (y,x)
            occupancyMap = np.flipud(occupancyMap.T)
            occupancyMapCoord = np.flipud(
                np.transpose(occupancyMapCoord, axes=(1, 0, 2)))

        return occupancyMap, occupancyMapCoord
예제 #52
0
class MyApp(ShowBase):
    def __init__(self, screen_size=84, DEBUGGING=False):
        ShowBase.__init__(self)
        self.render_stuff = True
        self.actions = 3

        self.render.setShaderAuto()
        self.cam.setPos(0, 0, 7)
        self.cam.lookAt(0, 0, 0)

        wp = WindowProperties()
        window_size = screen_size
        wp.setSize(window_size, window_size)
        self.win.requestProperties(wp)

        # Create Ambient Light
        self.ambientLight = AmbientLight('ambientLight')
        self.ambientLight.setColor((0.2, 0.2, 0.2, 1))
        self.ambientLightNP = self.render.attachNewNode(self.ambientLight)
        self.render.setLight(self.ambientLightNP)

        # Spotlight
        self.light = Spotlight('light')
        self.light.setColor((0.9, 0.9, 0.9, 1))
        self.lightNP = self.render.attachNewNode(self.light)
        self.lightNP.setPos(0, 10, 10)
        self.lightNP.lookAt(0, 0, 0)
        self.lightNP.node().getLens().setFov(40)
        self.lightNP.node().getLens().setNearFar(10, 100)
        self.lightNP.node().setShadowCaster(True, 1024, 1024)
        self.render.setLight(self.lightNP)

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

        if DEBUGGING is True:
            debugNode = BulletDebugNode('Debug')
            debugNode.showWireframe(True)
            debugNode.showConstraints(True)
            debugNode.showBoundingBoxes(False)
            debugNode.showNormals(False)
            debugNP = render.attachNewNode(debugNode)
            debugNP.show()
            self.world.setDebugNode(debugNP.node())

        # Reward zone
        self.rzone_shape = BulletBoxShape(Vec3(.8, 1, 0.5))
        self.rzone_ghost = BulletGhostNode('Reward Zone')
        self.rzone_ghost.addShape(self.rzone_shape)
        self.rzone_ghostNP = self.render.attachNewNode(self.rzone_ghost)
        self.rzone_ghostNP.setPos(2.2, 0.0, 0.86)
        self.rzone_ghostNP.setCollideMask(BitMask32(0x0f))
        self.world.attachGhost(self.rzone_ghost)

        # Needed for camera image
        self.dr = self.camNode.getDisplayRegion(0)

        # Needed for camera depth image
        winprops = WindowProperties.size(self.win.getXSize(),
                                         self.win.getYSize())
        fbprops = FrameBufferProperties()
        fbprops.setDepthBits(1)
        self.depthBuffer = self.graphicsEngine.makeOutput(
            self.pipe, "depth buffer", -2, fbprops, winprops,
            GraphicsPipe.BFRefuseWindow, self.win.getGsg(), self.win)
        self.depthTex = Texture()
        self.depthTex.setFormat(Texture.FDepthComponent)
        self.depthBuffer.addRenderTexture(self.depthTex,
                                          GraphicsOutput.RTMCopyRam,
                                          GraphicsOutput.RTPDepth)
        lens = self.cam.node().getLens()
        # the near and far clipping distances can be changed if desired
        # lens.setNear(5.0)
        # lens.setFar(500.0)
        self.depthCam = self.makeCamera(self.depthBuffer,
                                        lens=lens,
                                        scene=render)
        self.depthCam.reparentTo(self.cam)

    def reset(self):
        namelist = [
            'Ground', 'Conveyor', 'Finger', 'Block', 'Scrambled Block',
            'Not Rewardable', 'Teleport Me'
        ]
        for child in render.getChildren():
            for test in namelist:
                if child.node().name == test:
                    self.world.remove(child.node())
                    child.removeNode()
                    break

        # Plane
        self.plane_shape = BulletPlaneShape(Vec3(0, 0, 1), 1)
        self.plane_node = BulletRigidBodyNode('Ground')
        self.plane_node.addShape(self.plane_shape)
        self.plane_np = self.render.attachNewNode(self.plane_node)
        self.plane_np.setPos(0.0, 0.0, -1.0)
        self.world.attachRigidBody(self.plane_node)

        # Conveyor
        self.conv_node = BulletRigidBodyNode('Conveyor')
        self.conv_node.setFriction(1.0)
        self.conv_np = self.render.attachNewNode(self.conv_node)
        self.conv_shape = BulletBoxShape(Vec3(100.0, 1.0, 0.05))
        self.conv_node.setMass(1000.0)
        self.conv_np.setPos(-95.0, 0.0, 0.1)
        self.conv_node.addShape(self.conv_shape)
        self.world.attachRigidBody(self.conv_node)
        self.model = loader.loadModel('assets/conv.egg')
        self.model.flattenLight()
        self.model.reparentTo(self.conv_np)

        # Finger
        self.finger_node = BulletRigidBodyNode('Finger')
        self.finger_node.setFriction(1.0)
        self.finger_np = self.render.attachNewNode(self.finger_node)
        self.finger_shape = BulletCylinderShape(0.1, 0.25, ZUp)
        self.finger_node.setMass(0)
        self.finger_np.setPos(1.8, 0.0, 0.24 + 0.0254 * 3.5)
        self.finger_node.addShape(self.finger_shape)
        self.world.attachRigidBody(self.finger_node)
        self.model = loader.loadModel('assets/finger.egg')
        self.model.flattenLight()
        self.model.reparentTo(self.finger_np)

        self.blocks = []
        for block_num in range(15):
            new_block = self.spawn_block(Vec3(18, 0, (0.2 * block_num) + 2.0))
            self.blocks.append(new_block)

        self.have_scramble = False
        self.penalty_applied = False
        self.spawnned = False
        self.score = 10
        self.teleport_cooled_down = True
        self.fps = 20
        self.framecount = 0

        return self.step(1)[0]

    def spawn_block(self, location):
        node = BulletRigidBodyNode('Block')
        node.setFriction(1.0)
        block_np = self.render.attachNewNode(node)
        block_np.setAntialias(AntialiasAttrib.MMultisample)
        shape = BulletBoxShape(Vec3(0.0254 * 4, 0.0254 * 24, 0.0254 * 2))
        node.setMass(1.0)
        #block_np.setPos(-3.7, 0.0, 2.0)
        block_np.setPos(location)
        block_np.setHpr(random.uniform(-60, 60), 0.0, 0.0)
        node.addShape(shape)
        self.world.attachRigidBody(node)
        model = loader.loadModel('assets/bullet-samples/models/box.egg')
        model.setH(90)
        model.setSy(0.0254 * 4 * 2)
        model.setSx(0.0254 * 24 * 2)
        model.setSz(0.0254 * 2 * 2)
        model.flattenLight()
        model.reparentTo(block_np)
        return block_np

    def get_camera_image(self, requested_format=None):
        """
        Returns the camera's image, which is of type uint8 and has values
        between 0 and 255.
        The 'requested_format' argument should specify in which order the
        components of the image must be. For example, valid format strings are
        "RGBA" and "BGRA". By default, Panda's internal format "BGRA" is used,
        in which case no data is copied over.
        """
        tex = self.dr.getScreenshot()
        if requested_format is None:
            data = tex.getRamImage()
        else:
            data = tex.getRamImageAs(requested_format)
        image = np.frombuffer(
            data, np.uint8)  # use data.get_data() instead of data in python 2
        image.shape = (tex.getYSize(), tex.getXSize(), tex.getNumComponents())
        image = np.flipud(image)
        return image[:, :, :3]

    def reset_conv(self):
        conveyor_dist_left = 1 - self.conv_np.getPos()[0]
        if conveyor_dist_left < 10:
            self.conv_np.setX(-95.0)
            self.conv_np.setY(0.0)
        # self.conv_np.setY(0.0)
        # self.conv_np.setHpr(0.0, 0.0, 0.0)

    def check_penalty(self):
        penalty = 0
        self.pzone_ghost = self.pzone_ghostNP.node()
        for node in self.pzone_ghost.getOverlappingNodes():
            if node.name == 'Block':
                penalty = 1
                node.name = 'Scramble'
                self.have_scramble = False
        return penalty

    def check_rewards(self):
        reward = 0
        # Check for reward blocks (recently cleared scrambles)
        rzone_ghost = self.rzone_ghostNP.node()
        scrambled = False
        for node in rzone_ghost.getOverlappingNodes():
            if node.name == 'Block' or node.name == 'Scrambled Block':
                node.name = 'Scrambled Block'
                scrambled = True

        # Rename blocks that are not eligable for reward due to being too late
        for block in self.blocks:
            block_x = block.getPos()[0]
            block_name = block.node().name
            if block_x > 2.4 and block_name == 'Scrambled Block':
                self.have_scramble = False
                scrambled = False
                block.node().name = 'Not Rewardable'

        if scrambled is True:
            self.have_scramble = True
        else:
            if self.have_scramble is True:
                reward = 1
                self.have_scramble = False
        return reward

    def check_teleportable(self, blocks_per_minute):
        self.time = self.framecount / self.fps
        if self.time % (1 / (blocks_per_minute / 60)) < 0.1:
            self.time_to_teleport = True
        else:
            self.time_to_teleport = False
            self.teleport_cooled_down = True
        for block in self.blocks:
            block_x = block.getPos()[0]
            if block_x > 5:
                if block.node().name == 'Scrambled Block':
                    self.have_scramble = False
                block.node().name = 'Teleport Me'
                if self.time_to_teleport is True and self.teleport_cooled_down is True:
                    self.teleport_cooled_down = False
                    block.setX(-4)
                    block.setY(0.0)
                    block.setZ(2.0)
                    block.setHpr(random.uniform(-60, 60), 0.0, 0.0)
                    block.node().name = 'Block'

    def step(self, action):
        dt = 1 / self.fps
        self.framecount += 1
        finger_meters_per_second = 2
        max_dist = 1.1
        real_displacement = finger_meters_per_second * dt
        # Move finger
        if action == 0:
            self.finger_np.setY(self.finger_np.getY() + real_displacement)
            if self.finger_np.getY() > max_dist:
                self.finger_np.setY(max_dist)

        if action == 2:
            self.finger_np.setY(self.finger_np.getY() - real_displacement)
            if self.finger_np.getY() < -max_dist:
                self.finger_np.setY(-max_dist)

        self.world.doPhysics(dt, 5, 1.0 / 120.0)
        self.reset_conv()
        self.check_teleportable(blocks_per_minute=1.1 * 60)

        # Keep the conveyor moving
        self.conv_np.node().setLinearVelocity(Vec3(1.0, 0.0, 0.0))

        if self.render_stuff == True:
            self.graphicsEngine.renderFrame()
        image = self.get_camera_image()
        # image = cv2.resize(image, (84, 84), interpolation=cv2.INTER_CUBIC)

        score = 0
        score += self.check_rewards()
        #score -= self.check_penalty()
        done = False

        return image, score, done
예제 #53
0
class Balls(ShowBase):
  def __init__(self):
    ShowBase.__init__(self)
    self.title = OnscreenText(text="0 balls",
      parent=base.a2dBottomRight, align=TextNode.ARight,
      fg=(1, 1, 1, 1), pos=(-0.1, 0.1), scale=.08,
      shadow=(0, 0, 0, 0.5))
    # exit on esc
    self.accept('escape', sys.exit)
    # disable standart mouse based camera control
    self.disableMouse()
    # set camera position
    self.camera.setPos(0, -30, 25)
    self.camera.lookAt(0, 0, 0)
    #
    self.world = BulletWorld()
    self.world.setGravity(Vec3(0, 0, -9.81))

    self.taskMgr.add(self.updateWorld, 'updateWorld')
    self.setupLight()
    # down
    self.makePlane(0, Vec3(0, 0, 1), (0, 0, 0), (0, 0, 0))
    # up
    self.makePlane(1, Vec3(0, 0, -1), (0, 0, 10), (0, 0, 0))
    # left
    self.makePlane(2, Vec3(1, 0, 0), (-5, 0, 5), (0, 0, 90))
    # right
    self.makePlane(3, Vec3(-1, 0, 0), (5, 0, 5), (0, 0, -90))
    # top
    self.makePlane(4, Vec3(0, 1, 0), (0, -5, 5), (0, 90, 0))
    # buttom
    self.makePlane(5, Vec3(0, -1, 0), (0, 5, 5), (0, -90, 0))

    self.accept('mouse1', self.pickBall)
    self.accept('mouse3', self.releaseBall)
    self.accept('arrow_up', partial(self.rotateCube, hpr = (0, ROTATE_SPEED, 0)))
    self.accept('arrow_down', partial(self.rotateCube, hpr = (0, -ROTATE_SPEED, 0)))
    self.accept('arrow_left', partial(self.rotateCube, hpr = (0, 0, -ROTATE_SPEED)))
    self.accept('arrow_right', partial(self.rotateCube, hpr = (0, 0, ROTATE_SPEED)))
    self.accept('space', self.shakeBalls)
    self.accept('page_up', self.addRandomBall)
    self.accept('page_down', self.rmBall)

    self.ballCnt = 0
    self.ballColors = {}
    for num in xrange(DEFAULT_BALLS):
      self.addRandomBall()
    self.picked = set([])

  def setupLight(self):
    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 updateWorld(self, task):
    dt = globalClock.getDt()
    # bug #1455084, simple doPhysics(dt) does nothing
    # looks like fixed already
    self.world.doPhysics(dt, 1, 1. / 60.)
    return task.cont

  def rayCollision(self):
    if self.mouseWatcherNode.hasMouse():
      mouse = self.mouseWatcherNode.getMouse()
      pointFrom, pointTo = Point3(), Point3()
      self.camLens.extrude(mouse, pointFrom, pointTo)
      pointFrom = render.getRelativePoint(self.cam, pointFrom)
      pointTo = render.getRelativePoint(self.cam, pointTo)
      hits = self.world.rayTestAll(pointFrom, pointTo).getHits()
      return sorted(hits, key = lambda x: (x.getHitPos() - pointFrom).length())
    return []

  def pickBall(self):
      hits = self.rayCollision()
      for hit in hits:
        hit_node = hit.getNode()
        if 'ball' in hit_node.getName():
          self.picked.add(hit_node.getName())
          NodePath(hit_node.getChild(0).getChild(0)).setColor(HIGHLIGHT)

  def releaseBall(self):
    hits = self.rayCollision()
    if hits:
      foundBall = False
      for picked in hits:
        hit_node = picked.getNode()
        if 'ball' in hit_node.getName():
          foundBall = True
          x, y, z = picked.getHitPos()
          bodies = self.world.getRigidBodies()
          for elem in bodies:
            name = elem.getName()
            if name in self.picked:
              # apply some physics
              node = NodePath(elem.getChild(0).getChild(0))
              node_x, node_y, node_z = node.getPos(render)
              ix = (x - node_x)
              iy = (y - node_y)
              dir = atan2(iy, ix)
              dx, dy = SPEED * cos(dir), SPEED * sin(dir)
              elem.applyCentralImpulse(LVector3(dx, dy, z))
              node.setColor(self.ballColors[elem.getName()])
      if foundBall:
        self.picked = set([])

  def rotateCube(self, hpr = (0, 0, 0)):
    # h, p, r = z, x, y
    # FIXME: something completely wrong goes here
    # need some time to figure it out
    planes = render.findAllMatches('**/plane*')
    for plane in planes:
      oldParent = plane.getParent()
      pivot = render.attachNewNode('pivot')
      pivot.setPos(render, 0, 0, 5)
      plane.wrtReparentTo(pivot)
      pivot.setHpr(render, Vec3(hpr))
      if oldParent.getName() != 'render':
        oldParent.removeNode()

  def shakeBalls(self):
    balls = filter(lambda x: 'ball' in x.getName(), self.world.getRigidBodies())
    for ball in balls:
      dx = uniform(-SHAKE_SPEED, SHAKE_SPEED)
      dy = uniform(-SHAKE_SPEED, SHAKE_SPEED)
      dz = uniform(-SHAKE_SPEED, SHAKE_SPEED)
      ball.applyCentralImpulse(LVector3(dx, dy, dz))

  def updateBallsCounter(self, num):
    self.ballCnt += num
    self.title.setText('%d balls' % (self.ballCnt))

  def addRandomBall(self):
    planes = render.findAllMatches('**/plane*')
    x, y, z = zip(*[tuple(plane.getPos()) for plane in planes])
    xPos = uniform(min(x), max(x))
    yPos = uniform(min(y), max(y))
    zPos = uniform(min(z), max(z))
    self.makeBall(self.ballCnt, (xPos, yPos, zPos))
    self.updateBallsCounter(1)

  def rmBall(self):
    if self.ballCnt != 0:
      ball = render.find('**/ball_' + str(self.ballCnt - 1))
      self.ballColors.pop(ball.getName())
      ball.removeNode()
      self.updateBallsCounter(-1)

  def makePlane(self, num, norm, pos, hpr):
    shape = BulletPlaneShape(norm, 0)
    node = BulletRigidBodyNode('plane_' + str(num))
    node.addShape(shape)
    physics = render.attachNewNode(node)
    physics.setPos(*pos)
    self.world.attachRigidBody(node)
    model = loader.loadModel('models/square')
    model.setScale(10, 10, 10)
    model.setHpr(*hpr)
    model.setTransparency(TransparencyAttrib.MAlpha)
    model.setColor(1, 1, 1, 0.25)
    model.reparentTo(physics)

  def makeColor(self):
    return (random(), random(), random(), 1)

  def makeBall(self, num, pos = (0, 0, 0)):
    shape = BulletSphereShape(0.5)
    node = BulletRigidBodyNode('ball_' + str(num))
    node.setMass(1.0)
    node.setRestitution(.9)
    node.setDeactivationEnabled(False)
    node.addShape(shape)
    physics = render.attachNewNode(node)
    physics.setPos(*pos)
    self.world.attachRigidBody(node)
    model = loader.loadModel('models/ball')
    color = self.makeColor()
    model.setColor(color)
    self.ballColors['ball_' + str(num)] = color
    model.reparentTo(physics)
예제 #54
0
class Physics(DirectObject.DirectObject):
    """SPAAAAAAAAAAAAAAAAAAAAAAAACE"""
    def __init__(self, xml):
        globalClock.setMaxDt(0.1)
        #init pre and post callbacks
        self.prePhysics = {}
        self.postPhysics = {}

        #bullet debug node
        debugNode = BulletDebugNode('Debug')
        debugNode.showWireframe(True)
        debugNode.showConstraints(True)
        debugNode.showBoundingBoxes(False)
        debugNode.showNormals(True)
        debugNP = render.attachNewNode(debugNode)
        debugNP.show()

        #create bullet world
        self.bulletworld = BulletWorld()
        self.bulletworld.setDebugNode(debugNP.node())
        self.bulletworld.setGravity(Vec3(0, 0, 0))

        #start doing physics
        self.physicsTask = taskMgr.add(self.simulationTask,
                                       'Physics Loop',
                                       sort=100)

    def reload(self, xml):
        pass

    def start(self):
        pass

    def stop(self):
        pass

    def destroy(self):
        taskMgr.remove(self.physicsTask)
        del self.physicsTask

    def simulationTask(self, task):
        # Call the pre-physics functions
        for ident, func in self.prePhysics.iteritems():
            func()

        self.dt = globalClock.getDt()
        self.bulletworld.doPhysics(self.dt, 10, 1.0 / 180.0)

        # Call the post-physics functions
        for ident, func in self.postPhysics.iteritems():
            func()

        return task.cont

    def getWorld(self):
        return self.bulletworld

    def getDt(self):
        return self.dt

    def registerPreFunc(self, name, func):
        self.prePhysics[name] = func

    def unRegisterPreFunc(self, name):
        if name in self.prePhysics:
            del self.prePhysics[name]

    def registerPostFunc(self, name, func):
        self.postPhysics[name] = func

    def unRegisterPostFunc(self, name):
        if name in self.postPhysics:
            del self.postPhysics[name]
예제 #55
0
class App(ShowBase):
    def __init__(self, args):
        ShowBase.__init__(self)

        headless = args["--headless"]
        width = args["--width"]
        height = args["--height"]

        globalClock.setMode(ClockObject.MNonRealTime)
        globalClock.setDt(0.02)  # 20ms per frame

        self.setBackgroundColor(0.9, 0.9, 0.9)
        self.createLighting()

        if not headless:
            self.setupCamera(width, height, Vec3(200, -200, 0), Vec3(0, 0, 0))

            # self.render.setAntialias(AntialiasAttrib.MAuto)

            # filters = CommonFilters(self.win, self.cam)
            # filters.setAmbientOcclusion(numsamples=16, radius=0.01, amount=1.0, strength=2.0, falloff=0.002)
            # filters.setAmbientOcclusion(radius=0.01, amount=0.5, strength=0.5)

            self.render.setShaderAuto()

        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81 * 100.0))
        # self.world.setGravity(Vec3(0, 0, 0))
        # self.setupDebug()
        self.createPlane(Vec3(0, 0, -100))

        self.animated_rig = ExposedJointRig("walking", {"walk": "walking-animation.egg"})
        self.animated_rig.reparentTo(self.render)
        self.animated_rig.setPos(0, 0, 0)
        # self.animated_rig.createLines(VBase4(0.5, 0.75, 1.0, 1.0))

        self.physical_rig = RigidBodyRig()
        self.physical_rig.reparentTo(self.render)
        self.physical_rig.setPos(0, 0, 0)
        self.physical_rig.createColliders(self.animated_rig)
        self.physical_rig.createConstraints()
        self.physical_rig.setCollideMask(BitMask32.bit(1))
        self.physical_rig.attachRigidBodies(self.world)
        self.physical_rig.attachConstraints(self.world)
        self.physical_rig.attachCubes(self.loader)

        self.target_physical_rig = RigidBodyRig()
        self.target_physical_rig.reparentTo(self.render)
        self.target_physical_rig.setPos(0, 0, 0)
        self.target_physical_rig.createColliders(self.animated_rig)
        self.target_physical_rig.createConstraints()
        self.target_physical_rig.setCollideMask(BitMask32.bit(2))
        self.target_physical_rig.attachRigidBodies(self.world)
        self.target_physical_rig.attachConstraints(self.world)
        self.target_physical_rig.clearMasses()

        self.disableCollisions()

        # self.animated_rig.pose('walk', 0)
        self.physical_rig.matchPose(self.animated_rig)
        self.target_physical_rig.matchPose(self.animated_rig)

        self.world.doPhysics(globalClock.getDt(), 10, 1.0 / 180.0)

        self.physical_rig.clearForces()
        self.target_physical_rig.clearForces()

        self.num_frames = self.animated_rig.getNumFrames("walk")

        self.model = load_model("model.json", "weights.hdf5")
        self.err_sum = 0.0

        self.accept("escape", sys.exit)
        self.taskMgr.add(self.update, "update")

    def disableCollisions(self):
        for i in range(32):
            self.world.setGroupCollisionFlag(i, i, False)
        self.world.setGroupCollisionFlag(0, 1, True)
        self.world.setGroupCollisionFlag(0, 2, True)

    def setupDebug(self):
        node = BulletDebugNode("Debug")
        node.showWireframe(True)

        self.world.setDebugNode(node)

        np = self.render.attachNewNode(node)
        np.show()

    def createLens(self, aspect_ratio, fov=60.0, near=1.0, far=1000.0):
        lens = PerspectiveLens()
        lens.setFov(fov)
        lens.setAspectRatio(aspect_ratio)
        lens.setNearFar(near, far)
        return lens

    def setupCamera(self, width, height, pos, look):
        self.cam.setPos(pos)
        self.cam.lookAt(look)
        self.cam.node().setLens(self.createLens(width / height))

    def createLighting(self):
        light = DirectionalLight("light")
        light.setColor(VBase4(0.4, 0.4, 0.4, 1))
        light.setShadowCaster(True)
        light.getLens().setNearFar(100.0, 400.0)
        light.getLens().setFilmSize(400, 400)
        # light.showFrustum()

        np = self.render.attachNewNode(light)
        np.setPos(100, -100, 200)
        np.lookAt(0, 0, -100)

        self.render.setLight(np)

        light = AmbientLight("ambient")
        light.setColor(VBase4(0.2, 0.2, 0.2, 1))

        np = self.render.attachNewNode(light)

        self.render.setLight(np)

    def createPlane(self, pos):
        rb = BulletRigidBodyNode("GroundPlane")
        rb.addShape(BulletPlaneShape(Vec3(0, 0, 1), 1))
        rb.setFriction(1.0)
        rb.setAnisotropicFriction(1.0)
        rb.setRestitution(1.0)

        np = self.render.attachNewNode(rb)
        np.setPos(pos)
        np.setCollideMask(BitMask32.bit(0))

        plane = self.loader.loadModel("cube")
        plane.setScale(Vec3(100, 100, 1))
        plane.setPos(Vec3(0, 0, -0.5))
        plane.setColor(VBase4(0.8, 0.8, 0.8, 1.0))
        plane.reparentTo(np)

        self.world.attachRigidBody(rb)

        return np

    def update(self, task):
        # self.world.doPhysics(globalClock.getDt(), 10, 1.0 / 180.0)
        # return task.cont

        frame_count = globalClock.getFrameCount()

        joint_positions = self.physical_rig.getJointPositions()
        joint_rotations = self.physical_rig.getJointRotations()

        linear_velocities = self.physical_rig.getLinearVelocities()
        angular_velocities = self.physical_rig.getAngularVelocities()

        # pause_count = 1
        # if frame_count % pause_count == 0:
        #     self.animated_rig.pose('walk', int(frame_count / pause_count) % self.num_frames)
        #     self.target_physical_rig.matchPose(self.animated_rig)

        next_joint_positions = self.target_physical_rig.getJointPositions()
        next_joint_rotations = self.target_physical_rig.getJointRotations()

        target_directions = next_joint_positions - joint_positions
        target_rotations = get_angle_vec(next_joint_rotations - joint_rotations)

        X_max = [
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            123.79363250732422,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            1886.330810546875,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            179.98973083496094,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            33.925838470458984,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
            180.0,
        ]

        Y_max = 200000.0

        X = (
            np.concatenate(
                [
                    joint_positions,
                    joint_rotations,
                    linear_velocities,
                    angular_velocities,
                    target_directions,
                    target_rotations,
                ]
            )
            / X_max
        )

        Y = np.clip(self.model.predict(np.array([X])), -1.0, 1.0) * Y_max

        self.physical_rig.apply_forces(Y[0])

        self.world.doPhysics(globalClock.getDt(), 10, 1.0 / 180.0)

        err = self.target_physical_rig.compareTo(self.physical_rig)
        self.err_sum += math.pow(err, 2.0)

        err_rmse = math.sqrt(self.err_sum / frame_count)
        print err_rmse

        return task.cont
class DroneEnv(gym.Env):
    def __init__(self):

        self.visualize = False

        if self.visualize == False:
            from pandac.PandaModules import loadPrcFileData
            loadPrcFileData("", "window-type none")

        import direct.directbase.DirectStart

        self.ep = 0
        self.ep_rew = 0
        self.t = 0

        self.prevDis = 0

        self.action_space = Box(-1, 1, shape=(3, ))
        self.observation_space = Box(-50, 50, shape=(9, ))

        self.target = 8 * np.random.rand(3)
        self.construct()

        self.percentages = []
        self.percentMean = []
        self.percentStd = []

        taskMgr.add(self.stepTask, 'update')
        taskMgr.add(self.lightTask, 'lights')

        self.rotorForce = np.array([0, 0, 9.81], dtype=np.float)

    def construct(self):

        if self.visualize:

            base.cam.setPos(17, 17, 1)
            base.cam.lookAt(0, 0, 0)

            wp = WindowProperties()
            wp.setSize(1200, 500)
            base.win.requestProperties(wp)

        # World
        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81))

        #skybox
        skybox = loader.loadModel('../models/skybox.gltf')
        skybox.setTexGen(TextureStage.getDefault(),
                         TexGenAttrib.MWorldPosition)
        skybox.setTexProjector(TextureStage.getDefault(), render, skybox)
        skybox.setTexScale(TextureStage.getDefault(), 1)
        skybox.setScale(100)
        skybox.setHpr(0, -90, 0)

        tex = loader.loadCubeMap('../textures/s_#.jpg')
        skybox.setTexture(tex)
        skybox.reparentTo(render)

        render.setTwoSided(True)

        #Light
        plight = PointLight('plight')
        plight.setColor((1.0, 1.0, 1.0, 1))
        plnp = render.attachNewNode(plight)
        plnp.setPos(0, 0, 0)
        render.setLight(plnp)

        # Create Ambient Light
        ambientLight = AmbientLight('ambientLight')
        ambientLight.setColor((0.15, 0.05, 0.05, 1))
        ambientLightNP = render.attachNewNode(ambientLight)
        render.setLight(ambientLightNP)

        # Drone
        shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5))
        self.drone = BulletRigidBodyNode('Box')
        self.drone.setMass(1.0)
        self.drone.addShape(shape)
        self.droneN = render.attachNewNode(self.drone)
        self.droneN.setPos(0, 0, 3)
        self.world.attachRigidBody(self.drone)
        model = loader.loadModel('../models/drone.gltf')
        model.setHpr(0, 90, 0)
        model.flattenLight()
        model.reparentTo(self.droneN)

        blade = loader.loadModel("../models/blade.gltf")
        blade.reparentTo(self.droneN)
        blade.setHpr(0, 90, 0)
        blade.setPos(Vec3(0.3, -3.0, 1.1))
        rotation_interval = blade.hprInterval(0.2, Vec3(180, 90, 0))
        rotation_interval.loop()

        placeholder = self.droneN.attachNewNode("blade-placeholder")
        placeholder.setPos(Vec3(0, 6.1, 0))
        blade.instanceTo(placeholder)

        placeholder = self.droneN.attachNewNode("blade-placeholder")
        placeholder.setPos(Vec3(3.05, 3.0, 0))
        blade.instanceTo(placeholder)

        placeholder = self.droneN.attachNewNode("blade-placeholder")
        placeholder.setPos(Vec3(-3.05, 3.0, 0))
        blade.instanceTo(placeholder)

        #drone ligths
        self.plight2 = PointLight('plight')
        self.plight2.setColor((0.9, 0.1, 0.1, 1))
        plnp = self.droneN.attachNewNode(self.plight2)
        plnp.setPos(0, 0, -1)
        self.droneN.setLight(plnp)

        #over light
        plight3 = PointLight('plight')
        plight3.setColor((0.9, 0.8, 0.8, 1))
        plnp = self.droneN.attachNewNode(plight3)
        plnp.setPos(0, 0, 2)
        self.droneN.setLight(plnp)

        #target object
        self.targetObj = loader.loadModel("../models/target.gltf")
        self.targetObj.reparentTo(render)
        self.targetObj.setPos(
            Vec3(self.target[0], self.target[1], self.target[2]))

    def lightTask(self, task):

        count = globalClock.getFrameCount()

        rest = count % 100
        if rest < 10:
            self.plight2.setColor((0.1, 0.9, 0.1, 1))
        elif rest > 30 and rest < 40:
            self.plight2.setColor((0.9, 0.1, 0.1, 1))
        elif rest > 65 and rest < 70:
            self.plight2.setColor((0.9, 0.9, 0.9, 1))
        elif rest > 75 and rest < 80:
            self.plight2.setColor((0.9, 0.9, 0.9, 1))
        else:
            self.plight2.setColor((0.1, 0.1, 0.1, 1))

        return task.cont

    def getState(self):

        #vel = self.drone.get_linear_velocity()
        po = self.drone.transform.pos
        ang = self.droneN.getHpr()

        #velocity = np.nan_to_num(np.array([vel[0], vel[1], vel[2]]))
        position = np.array([po[0], po[1], po[2]])

        state = np.array([position, self.target]).reshape(6, )
        state = np.around(state, decimals=3)

        return state

    def getReward(self):

        reward = 0

        s = self.getState()
        d = np.linalg.norm(s[0:3] - s[3:6])

        if d < 20:
            reward = 20 - d
            reward = reward / 40  #/4000

        #if d < self.prevDis :
        #    reward *= 1.2

        #self.prevDis = np.copy(d)

        return reward

    def reset(self):

        #log
        self.percentages.append(self.ep_rew)
        me = np.mean(self.percentages[-500:])
        self.percentMean.append(me)
        self.percentStd.append(np.std(self.percentages[-500:]))

        s = self.getState()
        d = np.linalg.norm(np.abs(s[:3] - self.target))
        ds = np.linalg.norm(s[:3] - np.array([0, 0, 4]))

        if self.ep % 50 == 0:
            self.PlotReward()

        print(
            f'{self.ep}   {self.t}    {self.ep_rew:+8.2f}    {me:+6.2f}    {d:6.2f}    {ds:6.2f}    {s}'
        )  #{s[:6]}

        #physics reset
        self.droneN.setPos(0, 0, 4)
        self.droneN.setHpr(0, 0, 0)
        self.drone.set_linear_velocity(Vec3(0, 0, 0))
        self.drone.setAngularVelocity(Vec3(0, 0, 0))

        self.rotorForce = np.array([0, 0, 9.81], dtype=np.float)

        #define new target:
        self.target = 8 * (2 * np.random.rand(3) - 1)
        #self.target = np.zeros((3))
        self.target[2] = np.abs(self.target[2])
        self.target[1] = np.abs(self.target[1])
        self.targetObj.setPos(
            Vec3(self.target[0], self.target[1], self.target[2]))

        self.ep += 1
        self.t = 0
        self.ep_rew = 0

        state = self.getState()

        return state

    def stepTask(self, task):

        dt = globalClock.getDt()

        if self.visualize:
            self.world.doPhysics(dt)
        else:
            self.world.doPhysics(0.1)

        self.drone.setDeactivationEnabled(False)

        #application of force
        force = Vec3(self.rotorForce[0], self.rotorForce[1],
                     self.rotorForce[2])
        self.drone.applyCentralForce(force)  #should be action

        po = self.drone.transform.pos
        position = np.array([po[0], po[1], po[2]])

        return task.cont

    def step(self, action):

        done = False
        reward = 0

        self.t += 1
        reward = self.getReward()
        self.ep_rew += reward
        state = self.getState()

        basis = np.array([0, 0, 9.81], dtype=np.float)
        self.rotorForce = basis + 0.2 * action  #0.1 *action

        #10 sub steps in each step
        for i in range(5):
            c = taskMgr.step()
            self.rotorForce -= 0.05 * (self.rotorForce - basis)

        #time constraint
        if self.t > 150:
            done = True

        return state, reward, done, {}

    def PlotReward(self):

        c = range(len(self.percentages))
        plt.plot(self.percentMean, c='b', alpha=0.8)
        plt.fill_between(
            c,
            np.array(self.percentMean) + np.array(self.percentStd),
            np.array(self.percentMean) - np.array(self.percentStd),
            color='g',
            alpha=0.3,
            label='Objective 1')

        plt.grid()
        plt.savefig('rews.png')
        plt.close()