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
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)
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
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
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)
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]
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)
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
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
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')
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
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()
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')
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
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)
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())
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()
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
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"
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
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
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
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
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()
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
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
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
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()
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
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]
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()
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
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
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
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
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
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')
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)
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))
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
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
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
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
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() """
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
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
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
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)
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]
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()