class Mouse(DirectObject): def __init__(self, levelNP): self.setCursor() # store the nodepath to the level collisions # will be used to check for intersections with the mouse ray self.levelNP = levelNP # Setup a traverser for the picking collisions self.picker = CollisionTraverser() # Setup mouse ray self.pq = CollisionHandlerQueue() # Create a collision Node pickerNode = CollisionNode('MouseRay') # set the nodes collision bitmask pickerNode.setFromCollideMask(BitMask32.bit(1))#GeomNode.getDefaultCollideMask()) # create a collision ray self.pickerRay = CollisionRay() # add the ray as a solid to the picker node pickerNode.addSolid(self.pickerRay) # create a nodepath with the camera to the picker node self.pickerNP = base.camera.attachNewNode(pickerNode) # add the nodepath to the base traverser self.picker.addCollider(self.pickerNP, self.pq) def setCursor(self): base.win.clearRejectedProperties() props = WindowProperties() if sys.platform.startswith('linux'): props.setCursorFilename("./assets/cursor.x11") else: props.setCursorFilename("./assets/cursor.ico") base.win.requestProperties(props) def getMousePos(self): # check if we have a mouse on the window if base.mouseWatcherNode.hasMouse(): # get the mouse position on the screen mpos = base.mouseWatcherNode.getMouse() # set the ray's position self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) # Now call the traverse function to let the traverser check for collisions # with the added colliders and the levelNP self.picker.traverse(self.levelNP) # check if we have a collision if self.pq.getNumEntries() > 0: # sort the entries to get the closest first self.pq.sortEntries() # This is the point at where the mouse ray and the level plane intersect hitPos = self.pq.getEntry(0).getSurfacePoint(render) return hitPos return Point3(0, 0, 0) task.cont
def get_dist_to_cell(self, pos): """Given a position, return the distance to the nearest cell below that position. If no cell is found, returns None.""" self.ray.setOrigin(pos) queue = CollisionHandlerQueue() self.traverser.addCollider(self.ray_nodepath, queue) self.traverser.traverse(self.cell_picker_world) self.traverser.removeCollider(self.ray_nodepath) queue.sortEntries() if not queue.getNumEntries(): return None entry = queue.getEntry(0) return (entry.getSurfacePoint(self.cell_picker_world) - pos).length()
class Projectile(NetEnt): def __init__(self, parent=None, pitch=None, id=None): NetEnt.__init__(self, id) self.node = NetNodePath(PandaNode('projectile')) if parent: self.parent = parent self.node.setPos(parent.node.getPos() + (0,0,1)) self.node.setHpr(parent.node.getHpr()) self.node.setP(pitch) self.node.reparentTo(render) ProjectilePool.add(self) #print 'there are',len(ProjectilePool.values()),'projectiles' self.flyTime = 0 self.sprite = Sprite2d('resources/missile.png', rows=3, cols=1, rowPerFace=(0,1,2,1), anchorY=Sprite2d.ALIGN_CENTER) self.sprite.node.reparentTo(self.node) # set up 'from' collisions - for detecting projectile hitting things self.collisionHandler = CollisionHandlerQueue() self.fromCollider = self.node.attachNewNode(CollisionNode('fromCollider')) self.fromCollider.node().addSolid(CollisionRay(0,0,0,0,1,0)) self.fromCollider.node().setIntoCollideMask(BITMASK_EMPTY) self.fromCollider.node().setFromCollideMask(BITMASK_TERRAIN | BITMASK_CHARACTER) if SHOW_COLLISIONS: self.fromCollider.show() Character.collisionTraverser.addCollider(self.fromCollider,self.collisionHandler) def getState(self): dataDict = NetObj.getState(self) dataDict[0] = self.node.getState() return dataDict def setState(self, weightOld, dataDictOld, weightNew, dataDictNew): oldNode = None if not dataDictOld else dataDictOld.get(0,None) self.node.setState(weightOld, oldNode, weightNew, dataDictNew[0]) def movePostCollide(self, deltaT): desiredDistance = 30*deltaT self.collisionHandler.sortEntries() ch = self.collisionHandler for e in [ch.getEntry(i) for i in range(ch.getNumEntries())]: collisionDist = (self.node.getPos() - e.getSurfacePoint(render)).length() if collisionDist > desiredDistance: break # only accept collisions that aren't with parent if e.getIntoNode().getParent(0).getTag('ID') != str(self.parent.id): return False self.node.setY(self.node, desiredDistance) self.flyTime += deltaT return self.flyTime < 4 def __del__(self): #print 'PROJECTILE BEING REMOVED' self.node.removeNode()
def get_cell(self, pos): """Given a position, return the nearest cell below that position. If no cell is found, returns None.""" self.ray.setOrigin(pos) queue = CollisionHandlerQueue() self.traverser.addCollider(self.ray_nodepath, queue) self.traverser.traverse(self.cell_picker_world) self.traverser.removeCollider(self.ray_nodepath) queue.sortEntries() if not queue.getNumEntries(): return None entry = queue.getEntry(0) cnode = entry.getIntoNode() try: return self.cells_by_collider[cnode] except KeyError: raise Warning('collision ray collided with something ' 'other than a cell: %s' % cnode)
class Player(GameObject): def __init__(self): GameObject.__init__( self, Vec3(0, 0, 0), "Models/PandaChan/act_p3d_chan", { "stand": "Models/PandaChan/a_p3d_chan_idle", "walk": "Models/PandaChan/a_p3d_chan_run" }, 5, 10, "player") self.actor.getChild(0).setH(180) mask = BitMask32() mask.setBit(1) self.collider.node().setIntoCollideMask(mask) mask = BitMask32() mask.setBit(1) self.collider.node().setFromCollideMask(mask) base.pusher.addCollider(self.collider, self.actor) base.cTrav.addCollider(self.collider, base.pusher) self.ray = CollisionRay(0, 0, 0, 0, 1, 0) rayNode = CollisionNode("playerRay") rayNode.addSolid(self.ray) mask = BitMask32() mask.setBit(2) rayNode.setFromCollideMask(mask) mask = BitMask32() rayNode.setIntoCollideMask(mask) self.rayNodePath = render.attachNewNode(rayNode) self.rayQueue = CollisionHandlerQueue() base.cTrav.addCollider(self.rayNodePath, self.rayQueue) self.beamModel = loader.loadModel("Models/Misc/bambooLaser") self.beamModel.reparentTo(self.actor) self.beamModel.setZ(1.5) self.beamModel.setLightOff() self.beamModel.hide() self.damagePerSecond = -5.0 self.actor.loop("stand") def update(self, keys, dt): GameObject.update(self, dt) self.walking = False if keys["up"]: self.walking = True self.velocity.addY(self.acceleration * dt) if keys["down"]: self.walking = True self.velocity.addY(-self.acceleration * dt) if keys["left"]: self.walking = True self.velocity.addX(-self.acceleration * dt) if keys["right"]: self.walking = True self.velocity.addX(self.acceleration * dt) if self.walking: standControl = self.actor.getAnimControl("stand") if standControl.isPlaying(): standControl.stop() walkControl = self.actor.getAnimControl("walk") if not walkControl.isPlaying(): self.actor.loop("walk") else: standControl = self.actor.getAnimControl("stand") if not standControl.isPlaying(): self.actor.stop("walk") self.actor.loop("stand") if keys["shoot"]: if self.rayQueue.getNumEntries() > 0: self.rayQueue.sortEntries() rayHit = self.rayQueue.getEntry(0) hitPos = rayHit.getSurfacePoint(render) hitNodePath = rayHit.getIntoNodePath() if hitNodePath.hasPythonTag("owner"): hitObject = hitNodePath.getPythonTag("owner") if not isinstance(hitObject, TrapEnemy): hitObject.alterHealth(self.damagePerSecond * dt) beamLength = (hitPos - self.actor.getPos()).length() self.beamModel.setSy(beamLength) self.beamModel.show() else: self.beamModel.hide() def cleanup(self): base.cTrav.removeCollider(self.rayNodePath) GameObject.cleanup(self)
class Player(DirectObject): def __init__(self, _main): self.main = _main # Stats self.moveSpeed = 8 self.inventory = [] self.maxCarryWeight = 20.0 #kg ? self.currentInventoryWeight = 0.0 # Inventory GUI self.inventoryGui = Inventory() self.inventoryGui.hide() self.inventoryActive = False self.craftInventory = CraftInventory() self.craftInventory.hide() # enable movements through the level self.keyMap = {"left":0, "right":0, "forward":0, "backward":0} self.player = NodePath("Player")#loader.loadModel("smiley") self.player.setPos(149.032, 329.324, 11.3384) self.player.setH(180) self.player.reparentTo(render) self.accept("w", self.setKey, ["forward",1]) self.accept("w-up", self.setKey, ["forward",0]) self.accept("a", self.setKey, ["left",1]) self.accept("a-up", self.setKey, ["left",0]) self.accept("s", self.setKey, ["backward",1]) self.accept("s-up", self.setKey, ["backward",0]) self.accept("d", self.setKey, ["right",1]) self.accept("d-up", self.setKey, ["right",0]) self.accept("mouse1", self.handleLeftMouse) self.accept("i", self.toggleInventory) self.accept("c", self.toggleCraftInventory) # screen sizes self.winXhalf = base.win.getXSize() / 2 self.winYhalf = base.win.getYSize() / 2 self.mouseSpeedX = 0.1 self.mouseSpeedY = 0.1 camera.setH(180) camera.reparentTo(self.player) camera.setZ(self.player, 2) base.camLens.setFov(75) base.camLens.setNear(0.8) # Mouse controls self.mouseNode = CollisionNode('mouseRay') self.mouseNodeNP = camera.attachNewNode(self.mouseNode) self.mouseNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.mouseRay = CollisionRay() self.mouseNode.addSolid(self.mouseRay) self.mouseRayHandler = CollisionHandlerQueue() # Collision Traverser self.traverser = CollisionTraverser("Player Traverser") base.cTrav = self.traverser self.traverser.addCollider(self.mouseNodeNP, self.mouseRayHandler) def run(self): taskMgr.add(self.move, "moveTask", priority=-4) def pause(self): taskMgr.remove("moveTask") def setKey(self, key, value): self.keyMap[key] = value def move(self, task): if not base.mouseWatcherNode.hasMouse(): return task.cont pointer = base.win.getPointer(0) mouseX = pointer.getX() mouseY = pointer.getY() if base.win.movePointer(0, self.winXhalf, self.winYhalf): # calculate the looking up/down of the camera. # NOTE: for first person shooter, the camera here can be replaced # with a controlable joint of the player model p = camera.getP() - (mouseY - self.winYhalf) * self.mouseSpeedY if p <-80: p = -80 elif p > 90: p = 90 camera.setP(p) # rotate the player's heading according to the mouse x-axis movement h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX if h <-360: h = 360 elif h > 360: h = -360 self.player.setH(h) # basic movement of the player if self.keyMap["left"] != 0: self.player.setX(self.player, self.moveSpeed * globalClock.getDt()) if self.keyMap["right"] != 0: self.player.setX(self.player, -self.moveSpeed * globalClock.getDt()) if self.keyMap["forward"] != 0: self.player.setY(self.player, -self.moveSpeed * globalClock.getDt()) if self.keyMap["backward"] != 0: self.player.setY(self.player, self.moveSpeed * globalClock.getDt()) # keep the player on the ground elevation = self.main.t.terrain.getElevation(self.player.getX(), self.player.getY()) self.player.setZ(elevation*self.main.t.zScale) return task.cont def toggleInventory(self): if self.inventoryActive: self.inventoryGui.hide() self.inventoryActive = False self.run() else: self.inventoryGui.show() self.inventoryActive = True self.pause() def toggleCraftInventory(self): if self.inventoryActive: self.craftInventory.hide() self.inventoryActive = False self.run() else: self.craftInventory.updateList(self.inventory) self.craftInventory.show() self.inventoryActive = True self.pause() def handleLeftMouse(self): # Do the mining if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.mouseRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(render) # Assume for simplicity's sake that myHandler is a CollisionHandlerQueue. if self.mouseRayHandler.getNumEntries() > 0: # This is so we get the closest object. self.mouseRayHandler.sortEntries() pickedObj = self.mouseRayHandler.getEntry(0).getIntoNodePath() # Range check if (self.player.getPos() - pickedObj.getPos(render)).length() <= 3.0: self.mine(pickedObj) else: print "You are to far, move closer!" def mine(self, _nodeNP): self.nodeNP = _nodeNP # get the object class for node in self.main.nodeGen.currentNodes: if self.main.nodeGen.currentNodes[node] in self.inventory: print "new Loot:", self.main.nodeGen.currentNodes[node].giveLoot() self.inventory.append(self.main.nodeGen.currentNodes[node]) if self.main.nodeGen.currentNodes[node].lootLeft == 0: self.main.nodeGen.currentNodes[node].removeModel() break break # if mining node else: if self.main.nodeGen.currentNodes[node].model and self.main.nodeGen.currentNodes[node].model.getPos() == self.nodeNP.getPos(render): #self.main.nodeGen.currentNodes[node].removeModel() self.inventory.append(self.main.nodeGen.currentNodes[node]) self.currentInventoryWeight += self.main.nodeGen.currentNodes[node].weight self.inventoryGui.updateList(self.inventory) print "You received:", self.main.nodeGen.currentNodes[node].giveLoot(), self.main.nodeGen.currentNodes[node].giveType(), "Ores" print "Inventory:", self.inventory print "Current Weight:", self.currentInventoryWeight break print self.player.getPos()
class Mouse(): def __init__(self): self.enabled = False self.locked = False self.position = Vec3(0, 0, 0) self.delta = Vec3(0, 0, 0) self.prev_x = 0 self.prev_y = 0 self.velocity = Vec3(0, 0, 0) self.prev_click_time = time.time() self.double_click_distance = .5 self.hovered_entity = None self.left = False self.right = False self.middle = False self.delta_drag = Vec3(0, 0, 0) self.i = 0 self.update_rate = 10 self._mouse_watcher = None self._picker = CollisionTraverser() # Make a traverser self._pq = CollisionHandlerQueue() # Make a handler self._pickerNode = CollisionNode('mouseRay') self._pickerNP = camera.attach_new_node(self._pickerNode) self._pickerRay = CollisionRay() # Make our ray self._pickerNode.addSolid(self._pickerRay) self._picker.addCollider(self._pickerNP, self._pq) self.raycast = True self.collision = None self.enabled = True @property def x(self): if not self._mouse_watcher.has_mouse(): return 0 return self._mouse_watcher.getMouseX( ) / 2 * window.aspect_ratio # same space as ui stuff @property def y(self): if not self._mouse_watcher.has_mouse(): return 0 return self._mouse_watcher.getMouseY() / 2 def __setattr__(self, name, value): if name == 'visible': window.set_cursor_hidden(not value) application.base.win.requestProperties(window) if name == 'locked': try: object.__setattr__(self, name, value) window.set_cursor_hidden(value) application.base.win.requestProperties(window) except: pass try: super().__setattr__(name, value) # return except: pass def input(self, key): if not self.enabled: return if key.endswith('mouse down'): self.start_x = self.x self.start_y = self.y elif key.endswith('mouse up'): self.delta_drag = Vec3(self.x - self.start_x, self.y - self.start_y, 0) if key == 'left mouse down': self.left = True if self.hovered_entity: if hasattr(self.hovered_entity, 'on_click'): self.hovered_entity.on_click() for s in self.hovered_entity.scripts: if hasattr(s, 'on_click'): s.on_click() # double click if time.time( ) - self.prev_click_time <= self.double_click_distance: base.input('double click') if self.hovered_entity: if hasattr(self.hovered_entity, 'on_double_click'): self.hovered_entity.on_double_click() for s in self.hovered_entity.scripts: if hasattr(s, 'on_double_click'): s.on_double_click() self.prev_click_time = time.time() if key == 'left mouse up': self.left = False if key == 'right mouse down': self.right = True if key == 'right mouse up': self.right = False if key == 'middle mouse down': self.middle = True if key == 'middle mouse up': self.middle = False def update(self): if not self.enabled or not self._mouse_watcher.has_mouse(): self.velocity = Vec3(0, 0, 0) return self.position = Vec3(self.x, self.y, 0) self.moving = self.x + self.y != self.prev_x + self.prev_y if self.moving: if self.locked: self.velocity = self.position application.base.win.move_pointer(0, int(window.size[0] / 2), int(window.size[1] / 2)) else: self.velocity = Vec3(self.x - self.prev_x, (self.y - self.prev_y) / window.aspect_ratio, 0) else: self.velocity = Vec3(0, 0, 0) if self.left or self.right or self.middle: self.delta = Vec3(self.x - self.start_x, self.y - self.start_y, 0) self.prev_x = self.x self.prev_y = self.y self.i += 1 if self.i < self.update_rate: return # collide with ui self._pickerNP.reparent_to(scene.ui_camera) self._pickerRay.set_from_lens(camera._ui_lens_node, self.x * 2 / window.aspect_ratio, self.y * 2) self._picker.traverse(camera.ui) if self._pq.get_num_entries() > 0: # print('collided with ui', self._pq.getNumEntries()) self.find_collision() return # collide with world self._pickerNP.reparent_to(camera) self._pickerRay.set_from_lens(scene.camera.lens_node, self.x * 2 / window.aspect_ratio, self.y * 2) self._picker.traverse(base.render) if self._pq.get_num_entries() > 0: # print('collided with world', self._pq.getNumEntries()) self.find_collision() return # else: # print('mouse miss', base.render) # unhover all if it didn't hit anything for entity in scene.entities: if hasattr(entity, 'hovered') and entity.hovered: entity.hovered = False self.hovered_entity = None if hasattr(entity, 'on_mouse_exit'): entity.on_mouse_exit() for s in entity.scripts: if hasattr(s, 'on_mouse_exit'): s.on_mouse_exit() @property def normal(self): if not self.collision: return None if not self.collision.has_surface_normal(): print('no surface normal') return None n = self.collision.get_surface_normal( self.collision.get_into_node_path().parent) return (n[0], n[2], n[1]) @property def world_normal(self): if not self.collision: return None if not self.collision.has_surface_normal(): print('no surface normal') return None n = self.collision.get_surface_normal(render) return (n[0], n[2], n[1]) @property def point(self): if self.hovered_entity: p = self.collision.getSurfacePoint(self.hovered_entity) return Point3(p[0], p[2], p[1]) else: return None @property def world_point(self): if self.hovered_entity: p = self.collision.getSurfacePoint(render) return Point3(p[0], p[2], p[1]) else: return None def find_collision(self): if not self.raycast: return self._pq.sortEntries() if len(self._pq.get_entries()) == 0: self.collision = None return self.collisions = list() for entry in self._pq.getEntries(): # print(entry.getIntoNodePath().parent) for entity in scene.entities: if entry.getIntoNodePath().parent == entity: if entity.collision: self.collisions.append( Hit( hit=entry.collided(), entity=entity, distance=0, point=entry.getSurfacePoint(entity), world_point=entry.getSurfacePoint(scene), normal=entry.getSurfaceNormal(entity), world_normal=entry.getSurfaceNormal(scene), )) break self.collision = self._pq.getEntry(0) nP = self.collision.getIntoNodePath().parent for entity in scene.entities: if not hasattr(entity, 'collision' ) or not entity.collision or not entity.collider: continue # if hit entity is not hovered, call on_mouse_enter() if entity == nP: if not entity.hovered: entity.hovered = True self.hovered_entity = entity # print(entity.name) if hasattr(entity, 'on_mouse_enter'): entity.on_mouse_enter() for s in entity.scripts: if hasattr(s, 'on_mouse_enter'): s.on_mouse_enter() # unhover the rest else: if entity.hovered: entity.hovered = False if hasattr(entity, 'on_mouse_exit'): entity.on_mouse_exit() for s in entity.scripts: if hasattr(s, 'on_mouse_exit'): s.on_mouse_exit()
class Fighter(): def __init__(self,characterPath , callOnDeath , side , name = None): #side indicates if the player is on the left or right side. #TODO: add collision tests against ring-out geometry in the arena, self.fsm = FighterFsm(self,characterPath) self.inputHandler = InputHandler(self.fsm,side) self.side = side self.wins = 0 #counting won rounds, a double-ko/draw counts as win for both. self.faceOpp = True #looking at opponent self.callOnDeath = callOnDeath self.statusBitMask = BitMask32() self.defenseBitMask = BitMask32() #active defense parts get a 1 #the attack bitmask is generated by the fsm and passed to the attack method directly if not name: name = "player"+str(1+bool(side)) self.healthBar = PlayerHud(side, name ) self.fighterNP = render.attachNewNode(name) self.collTrav = CollisionTraverser(name) fromObject = self.fighterNP.attachNewNode(CollisionNode('colNode'+name)) fromObject.node().addSolid(CollisionRay(0, 0, 2,0,0, -1)) fromObject.node().setFromCollideMask(BitMask32.bit(1)) fromObject.node().setIntoCollideMask(BitMask32.allOff()) self.queue = CollisionHandlerQueue() self.collTrav.addCollider(fromObject, self.queue) self.fsm.getNP().reparentTo(self.fighterNP) #fromObject.show() #more debug collision visuals #self.collTrav.showCollisions(render) #debug visuals for collision self.prepareFighter() def updateState(self,newState = None): if newState: if "enter" + state in dir(self.fsm): self.fsm.forceTransition(newState) else: self.inputHandler.pollEvents() def prepareFighter(self): taskMgr.remove("player"+str(self.side)) self.speed = (0,0) self.fsm.forceTransition("Idle") self.health= 100 self.healthBar.setHealth(self.health) self.healthBar.setRoundIndicator('V'*self.wins) if self.side: self.fighterNP.setX(5) else: self.fighterNP.setX(-5) self.fighterNP.setY(0) taskMgr.add(self._playertask, "player"+str(self.side)) def setStatusBitMask(self,bitmask): self.statusBitMask = bitmask def setDefenseBitMask(self,bitmask): self.defenseBitMask = bitmask #getters and setters are a bit stupid here. properties from python 3 would be nice def fighterWin(self): #request a win-anim from the fsm if there are any self.wins += 1 self.healthBar.setRoundIndicator('V'*self.wins) def getWins(self): return self.wins def getHealth(self): return self.health def getNP(self): return self.fighterNP def setOpponent(self,opponent): self.opponent = opponent self.fighterNP.lookAt(self.opponent.getNP()) def attack(self,attackBitMask,attackrange,damageHit,damageDodge=0,angle=30): #those variables will be supplied by the fsm states later on. #function is pretty redundant... for structure only, and for early days attackstatus = self.opponent.getAttacked(attackBitMask,attackrange,damageHit,damageDodge,angle) return attackstatus def _testHit(self,node1,node2,threshold=30, dist = 1): #node1 which looks for a target , node2 is the target , threshold is the max-attack-angle, dist the dist dirVec = node1.getRelativePoint(node2,Vec3(0,0,0)) dirVec = Vec3(dirVec[0],dirVec[1],dirVec[2]) dirVec.normalize() angle = dirVec.angleDeg(Vec3(0,1,0)) if angle < threshold and dist > node1.getDistance(node2): #print "hit at "+str(angle)+" degree!" return True else: #print angle,node1.getDistance(node2) return False def getAttacked(self,attackBitMask,attackrange,damageHit,damageDodge=0,angle = 30): """ returns 0 if not hit, 1 if hit was blocked, 2 if hit, 3 for hit+KO """ if self.health <=0: return 4 #player is ko already if not self._testHit(self.opponent.getNP(),self.fighterNP ,angle,attackrange ) : #instead of 0, a sligtly positive values makes thinks look better. #attack misses due to out of range. return 0 if (self.statusBitMask & attackBitMask).getWord() == 0: # attak misses cause the player avoided it. went low or so. return 0 if (self.defenseBitMask & attackBitMask).getWord(): self.health -= damageDodge self.healthBar.setHealth(self.health) return 1 #hit,... but blocked so no combos else: self.health -= damageHit self.healthBar.setHealth(self.health) if self.health <= 0 : #if KO taskMgr.remove("player"+str(self.side)) self.fsm.forceTransition("Ko") #actually make the match.py allow the other player to KO (in case of doubleKO,befor calling round end. taskMgr.doMethodLater(0.5,self.callOnDeath,"RoundEnd") return 3 #TODO: requesting the same state as you are in doesnt work well.sorta need to re-enter the hit state if "Crouch" in self.fsm.state: self.fsm.forceTransition("CrouchHit") elif self.fsm.state: self.fsm.forceTransition("Hit") return 2 #regular hit def setSpeed(self,x,y): self.speed = (x,y) def faceOpponent(self,facing): self.faceOpp = facing #true if yuo look at the other player (usualy true unless attacking), so you can dodge an attack by evading. def _playertask(self,task): oldpos = self.fighterNP.getPos() dist = self.fighterNP.getY(self.opponent.getNP()) if dist > 3 or self.speed[0]<0: #prevert players from walking throug each other , too troublesome atm self.fighterNP.setX(self.fighterNP,self.speed[1]*globalClock.getDt()) self.fighterNP.setY(self.fighterNP,self.speed[0]*globalClock.getDt()) else : self.speed = ( min(2,self.speed[0] ), self.speed[1]) #also push back other player self.opponent.getNP().setY(self.opponent.getNP(),-self.speed[0]*globalClock.getDt() ) self.collTrav.traverse(render) self.queue.sortEntries() for i in range(self.queue.getNumEntries()): entry = self.queue.getEntry(i) if "ground" in entry.getIntoNodePath().getName() : break if "out" in entry.getIntoNodePath().getName() : pass #ring out self.fighterNP.setPos(oldpos) #for now reset him as we have no ring-out anim yet #TODO: add ring out anim! break if self.queue.getNumEntries() == 0: #if there is no ground and no ring out, propably a wall or no thin like that. just reset the pos self.fighterNP.setPos(oldpos) print "resetting fighter" if self.faceOpp: self.fighterNP.lookAt(self.opponent.getNP()) return task.cont
class Editor(DirectObject): # Конструктор def __init__(self, map_manager): # сохраняем ссылку на объект менеджера карты self.map_manager = map_manager # режим редактирования self.edit_mode = True # создание обходчика столкновений self.traverser = CollisionTraverser() # очередь обработки столкновений self.collisQueue = CollisionHandlerQueue() # узел для луча столкновений collisionNode = CollisionNode('centerRay') # устанавливаем маску проверки столкновений ОТ collisionNode.setFromCollideMask(BitMask32.bit(1)) # сбрасываем маску проверки столкновений ДО collisionNode.setIntoCollideMask(BitMask32.allOff()) # создаём луч self.collisRay = CollisionRay() # и прикрепляем к созданному ранее узлу collisionNode.addSolid(self.collisRay) # закрепляем узел на камере collisCamNode = base.camera.attachNewNode(collisionNode) # уведомляем обходчик о новом «объекте ОТ» self.traverser.addCollider(collisCamNode, self.collisQueue) # визуализируем столкновения (раскомментировать/закоментировать) #self.traverser.showCollisions(base.render) # позиция для добавления нового блока self.new_position = None # ключ выделенного блока self.selected_key = None # узел выделенного блока self.selected_node = None # запускаем задачу проверки выделения блоков taskMgr.doMethodLater(0.02, self.testBlocksSelection, "test_block-task") # регистрируем на нажатие левой кнопки мыши # событие добавления блока self.accept('mouse1', self.addBlock) # регистрируем на нажатие правой кнопки мыши # событие удаления блока self.accept('mouse3', self.delBlock) #метод установки режима редактирования def setEditMode(self, mode): self.edit_mode = mode if self.edit_mode: # сбрасываем выделение self.resetSelectedBlock() # запускаем задачу проверки выделения блоков taskMgr.doMethodLater(0.02, self.testBlocksSelection, "test_block-task") else: # удаляем задачу проверки выделения блоков taskMgr.remove("test_block-task") # снимаем выделение со всех блоков self.map_manager.deselectAllBlocks() # Метод сброса свойств выделенного блока def resetSelectedBlock(self): self.new_position = None self.selected_key = None self.selected_node = None # Метод добавления блока def addBlock(self): # если есть позиция для нового блока if self.new_position: # добавляем блок в эту позицию self.map_manager.addBlock(self.new_position) # сбрасываем выделение self.resetSelectedBlock() # Метод удаления блока def delBlock(self): # удаляем выделенный блок self.map_manager.deleteSelectedBlock() # сбрасываем выделение self.resetSelectedBlock() # Метод проверки проверки выделения блоков def testBlocksSelection(self, task): # устанавливаем позицию луча столкновений в центр экрана self.collisRay.setFromLens(base.camNode, 0, 0) # запускаем обходчик на проверку self.traverser.traverse(base.render) # если обходчик обнаружил какие-то столкновения if self.collisQueue.getNumEntries() > 0: # сортируем их, чтобы получить ближайшее self.collisQueue.sortEntries() # получаем описание ближайшего столкновения collisionEntry = self.collisQueue.getEntry(0) # получаем узел с «объектом ДО» и ключ выделенного блока key = collisionEntry.getIntoNodePath().getTag('key') # если найден новый блок if key != self.selected_key: # обновляем ключ выделенного блока self.selected_key = key # выделяем новый блок self.selected_node = self.map_manager.selectBlock(key) # если есть выделенный блок if self.selected_node: # координаты выделенного блока selected_position = self.selected_node.getPos() # вектор нормали к поверхности на выделенном блоке normal = collisionEntry.getSurfaceNormal(self.selected_node) # позиция для добавления нового блока self.new_position = selected_position + normal else: # снимаем выделение со всех блоков self.map_manager.deselectAllBlocks() # сбрасываем выделение self.resetSelectedBlock() # сообщаем о необходимости повторного запуска задачи return task.again
class MousePicker(object): def __init__(self, pickTag='MyPickingTag', nodeName='pickRay', showCollisions=False): self.pickTag = pickTag self.nodeName = nodeName self.showCollisions = showCollisions def create(self): self.mPickerTraverser = CollisionTraverser() self.mCollisionQue = CollisionHandlerQueue() self.mPickRay = CollisionRay() self.mPickRay.setOrigin(base.camera.getPos(base.render)) self.mPickRay.setDirection( base.render.getRelativeVector(base.camera, Vec3(0, 1, 0))) #create our collison Node to hold the ray self.mPickNode = CollisionNode(self.nodeName) self.mPickNode.addSolid(self.mPickRay) #Attach that node to the camera since the ray will need to be positioned #relative to it, returns a new nodepath #well use the default geometry mask #this is inefficent but its for mouse picking only self.mPickNP = base.camera.attachNewNode(self.mPickNode) #we'll use what panda calls the "from" node. This is reall a silly convention #but from nodes are nodes that are active, while into nodes are usually passive environments #this isnt a hard rule, but following it usually reduces processing #Everything to be picked will use bit 1. This way if we were doing other #collision we could seperate it, we use bitmasks to determine what we check other objects against #if they dont have a bitmask for bit 1 well skip them! self.mPickNode.setFromCollideMask(BitMask32(1)) #Register the ray as something that can cause collisions self.mPickerTraverser.addCollider(self.mPickNP, self.mCollisionQue) #Setup 2D picker self.mPickerTraverser2D = CollisionTraverser() self.mCollisionQue2D = CollisionHandlerQueue() self.mPickNode2D = CollisionNode('2D PickNode') self.mPickNode2D.setFromCollideMask(BitMask32(1)) self.mPickNode2D.setIntoCollideMask(BitMask32.allOff()) self.mPick2DNP = base.camera2d.attachNewNode(self.mPickNode2D) self.mPickRay2D = CollisionRay() self.mPickNode2D.addSolid(self.mPickRay2D) self.mPickerTraverser2D.addCollider(self.mPick2DNP, self.mCollisionQue2D) if self.showCollisions: self.mPickerTraverser.showCollisions(base.render) self.mPickerTraverser2D.showCollisions(base.aspect2d) def mousePick(self, traverse=None, tag=None): #do we have a mouse if (base.mouseWatcherNode.hasMouse() == False): return None, None traverse = traverse or base.render tag = tag or self.pickTag mpos = base.mouseWatcherNode.getMouse() #Set the position of the ray based on the mouse position self.mPickRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.mPickerTraverser.traverse(traverse) if (self.mCollisionQue.getNumEntries() > 0): self.mCollisionQue.sortEntries() for entry in self.mCollisionQue.getEntries(): pickedObj = entry.getIntoNodePath() pickedObj = pickedObj.findNetTag(tag) if not pickedObj.isEmpty(): pos = entry.getSurfacePoint(base.render) return pickedObj, pos return None, None def mousePick2D(self, traverse=None, tag=None, all=False): #do we have a mouse if (base.mouseWatcherNode.hasMouse() == False): return None, None traverse = traverse or base.render tag = tag or self.pickTag mpos = base.mouseWatcherNode.getMouse() self.mPickRay2D.setFromLens(base.cam2d.node(), mpos.getX(), mpos.getY()) self.mPickerTraverser2D.traverse(base.aspect2d) if self.mCollisionQue2D.getNumEntries() > 0: self.mCollisionQue2D.sortEntries() if all: return [(entry.getIntoNodePath().findNetTag(tag), entry.getSurfacePoint(base.aspect2d)) for entry in self.mCollisionQue2D.getEntries()], None else: entry = self.mCollisionQue2D.getEntry(0) pickedObj = entry.getIntoNodePath() pickedObj = pickedObj.findNetTag(tag) if not pickedObj.isEmpty(): pos = entry.getSurfacePoint(base.aspect2d) return pickedObj, pos return None, None
class Physics: def __init__(self): self.rayCTrav = CollisionTraverser("collision traverser for ray tests") #self.pusher = PhysicsCollisionHandler() self.pusher = CollisionHandlerPusher() self.pusher.addInPattern('%fn-in-%in') self.pusher.addOutPattern('%fn-out-%in') self.pusher.addInPattern('%fn-in') self.pusher.addOutPattern('%fn-out') def startPhysics(self): #self.actorNode = ActorNode("playerPhysicsControler") #base.physicsMgr.attachPhysicalNode(self.actorNode) #self.actorNode.getPhysicsObject().setMass(self.player_mass) #self.mainNode = render.attachNewNode(self.actorNode) self.mainNode = render.attachNewNode("CharacterColliders") self.reparentTo(self.mainNode) charCollisions = self.mainNode.attachNewNode( CollisionNode(self.char_collision_name)) #charCollisions.node().addSolid(CollisionSphere(0, 0, self.player_height/4.0, self.player_height/4.0)) #charCollisions.node().addSolid(CollisionSphere(0, 0, self.player_height/4.0*3.05, self.player_height/4.0)) charCollisions.node().addSolid( CollisionSphere(0, 0, self.player_height / 2.0, self.player_height / 4.0)) charCollisions.node().setIntoCollideMask(BitMask32(0x80)) # 1000 0000 if self.show_collisions: charCollisions.show() self.pusher.addCollider(charCollisions, self.mainNode) base.cTrav.addCollider(charCollisions, self.pusher) charFFootCollisions = self.attachNewNode(CollisionNode("floor_ray")) charFFootCollisions.node().addSolid(CollisionRay(0, 0, 0.5, 0, 0, -1)) #charFFootCollisions.node().addSolid(CollisionSegment((0, 0, 0.2), (0, 0, -1))) charFFootCollisions.node().setIntoCollideMask(BitMask32.allOff()) charFFootCollisions.node().setFromCollideMask( BitMask32(0x7f)) # 0111 1111 if self.show_collisions: charFFootCollisions.show() self.floor_handler = CollisionHandlerFloor() self.floor_handler.addCollider(charFFootCollisions, self.mainNode) #self.floor_handler.setOffset(0) self.floor_handler.setMaxVelocity(5) base.cTrav.addCollider(charFFootCollisions, self.floor_handler) self.accept("{}-in".format(self.char_collision_name), self.checkCharCollisions) self.raytest_segment = CollisionSegment(0, 1) self.raytest_np = render.attachNewNode(CollisionNode("testRay")) self.raytest_np.node().addSolid(self.raytest_segment) self.raytest_np.node().setIntoCollideMask(BitMask32.allOff()) self.raytest_np.node().setFromCollideMask(BitMask32(0x7f)) # 0111 1111 if self.show_collisions: self.raytest_np.show() self.raytest_queue = CollisionHandlerQueue() self.rayCTrav.addCollider(self.raytest_np, self.raytest_queue) def stopPhysics(self): self.raytest_segment.removeNode() self.pusher.clearColliders() self.floor_handler.clearColliders() self.rayCTrav.clearColliders() def updatePlayerPos(self, speed, heading, dt): if heading is not None: self.mainNode.setH(camera, heading) self.mainNode.setP(0) self.mainNode.setR(0) self.mainNode.setFluidPos(self.mainNode, speed) self.doStep() def checkCharCollisions(self, args): self.doStep() def doStep(self): # do the step height check tmpNP = self.mainNode.attachNewNode("temporary") tmpNP.setPos(self.mainNode, 0, 0, -self.stepheight) pointA = self.mainNode.getPos(render) pointA.setZ(pointA.getZ() + self.player_height / 1.8) pointB = tmpNP.getPos(render) if pointA == pointB: return char_step_collision = self.getFirstCollisionInLine(pointA, pointB) tmpNP.removeNode() if char_step_collision is not None: self.mainNode.setFluidZ(char_step_collision.getZ()) return True return False def getFirstCollisionInLine(self, pointA, pointB): """A simple raycast check which will return the first collision point as seen from point A towards pointB""" self.raytest_segment.setPointA(pointA) self.raytest_segment.setPointB(pointB) self.rayCTrav.traverse(render) self.raytest_queue.sortEntries() pos = None if self.raytest_queue.getNumEntries() > 0: pos = self.raytest_queue.getEntry(0).getSurfacePoint(render) return pos
class Picker(object): """ Generic object picker class for Panda3d. Given a top Node Path to search, it finds the closest collision object under the mouse pointer. Picker takes a topNode to test for mouse ray collisions. the pick() method returns (NodePathPicked, 3dPosition, rawNode) underneath the mouse position. If no collision was detected, it returns None, None, None. 'NodePathPicked' is the deepest NAMED node path that was collided with, this is usually what you want. rawNode is the deep node (such as geom) if you want to play with that. 3dPosition is where the mouse ray touched the surface. The picker object uses base.camera to collide, so if you have a custom camera, well, sorry bout that. pseudo code: p = Picker(mycollisionTopNode) thingPicked, positionPicked, rawNode = p.pick() if thingPicked: # do something here like thingPicked.ls() """ def __init__(self, topNode, cameraObject = None): self.traverser = CollisionTraverser() self.handler = CollisionHandlerQueue() self.topNode = topNode self.cam = cameraObject pickerNode = CollisionNode('MouseRay') #NEEDS to be set to global camera. boo hoo self.pickerNP = base.camera.attachNewNode(pickerNode) # this seems to enter the bowels of the node graph, making it # difficult to perform logic on pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.pickRay = CollisionRay() #pickerNode.setCollideMask(BitMask32.allOff()) pickerNode.addSolid(self.pickRay) self.traverser.addCollider(self.pickerNP, self.handler) def setTopNode(self, topNode): """set the topmost node to traverse when detecting collisions""" self.topNode = topNode def destroy(self): """clean up my stuff.""" self.ignoreAll() # remove colliders, subnodes and such self.pickerNP.remove() self.traverser.clearColliders() def pick(self): """ pick closest object under the mouse if available. returns ( NodePathPicked, surfacePoint, rawNode ) or (None, None None) """ if not self.topNode: return None, None, None if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.traverser.traverse(self.topNode) if self.handler.getNumEntries() > 0: self.handler.sortEntries() picked = self.handler.getEntry(0).getIntoNodePath() thepoint = self.handler.getEntry(0).getSurfacePoint(self.topNode) return self.getFirstParentWithName(picked), thepoint, picked return None, None, None def getFirstParentWithName(self, pickedObject): """ return first named object up the node chain from the picked node. This helps remove drudgery when you just want to find a simple object to work with. Normally, you wouldn't use this method directly. """ name = pickedObject.getName() parent = pickedObject while not name: parent = parent.getParent() if not parent: raise Exception("Node '%s' needs a parent with a name to accept clicks." % (str(pickedObject))) name = parent.getName() if parent == self.topNode: raise Exception("Collision parent '%s' is top Node, surely you wanted to click something beneath it..." % (str(parent))) return parent
class HasSelectables(HasKeybinds): #mixin see chessboard example def __init__(self): #selection detection self.picker = CollisionTraverser() self.pq = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) #self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) #TODO WOW geometry collision is SUPER slow... self.pickerNode.setFromCollideMask(BitMask32.bit(BITMASK_COLL_CLICK)) #render.find('**selectable').node().setIntoCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.picker.addCollider(self.pickerNP, self.pq) #self.picker.showCollisions(render) #box selection detection HINT: start with drawing the 2d thing yo! self.__shift__ = False self.accept("shift", self.shiftOn) self.accept("shift-up", self.shiftOff) self.__ctrl__ = False self.accept("control", self.ctrlOn) self.accept("control-up", self.ctrlOff) #mouse handling self.accept("mouse1", self.clickHandler) self.accept("shift-mouse1", self.clickHandler) self.accept("mouse1-up", self.releaseHandler) #dragging self.dragTask = taskMgr.add(self.dragTask, 'dragTask') def getClickTarget(self,rootSelNode=None): """ traverse from the root of the selectable tree """ #print('getting target....') if rootSelNode == None: rootSelNode = render if base.mouseWatcherNode.hasMouse(): self.pickerRay.setFromLens(base.camNode, *base.mouseWatcherNode.getMouse()) self.picker.traverse(rootSelNode) if self.pq.getNumEntries() > 0: #if we got something sort it self.pq.sortEntries() return self.pq.getEntry(0) #nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin()) #nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection()) #thingToDrag.obj.setPos(PointAtZ(.5, nearPoint, nearVec)) #not sure how this works def ctrlOn(self): self.__ctrl__ = True def ctrlOff(self): self.__ctrl__ = False def shiftOn(self): self.__shift__ = True def shiftOff(self): self.__shift__ = False @event_callback def clickHandler(self): pass @event_callback def releaseHandler(self): pass def dragTask(self, task): pass def clickSelectObject(self): #shif to multiselect... ?? to unselect invidiual?? pass def dragSelectObjects(self): #always drag in the plane of the camera pass
class World(DirectObject): def __init__(self): #turn off mouse control, otherwise camera is not repositionable self.lightables = [] self.cameraPositions = [((0, 5000, 5300), (180, -35, 0)),((0, 3000, 1300), (180, -15, 0))] self.cameraIndex = 0 base.disableMouse() base.enableParticles() self.setupLights() self.setupPicking() #Prepare the vehicular manslaughter! self.boosterLightNP = None self.flameLights = None self.player = Vehicle("models/panda-model", "panda-walk4", self) self.loadModels() # self.player.setPos(self.env.find("**/start_point").getPos()) self.player.setPos(0,0,0) self.setupIntervals() camera.reparentTo(self.player) camera.setPosHpr(0, 5000, 5300, 180, -35, 0) self.setupCollisions() render.setShaderAuto() #you probably want to use this self.keyMap = {"left":0, "right":0, "forward":0, "backwards":0} taskMgr.add(self.player.move, "moveTask") #Give the vehicle direct access to the keyMap self.player.addKeyMap(self.keyMap) self.prevtime = 0 self.isMoving = False self.speed_norm = 8 self.speed = self.speed_norm self.accept("escape", sys.exit) self.accept("arrow_up", self.setKey, ["forward", 1]) self.accept("w", self.setKey, ["forward", 1]) self.accept("arrow_right", self.setKey, ["right", 1]) self.accept("d", self.setKey, ["right", 1]) self.accept("arrow_left", self.setKey, ["left", 1]) self.accept("a", self.setKey, ["left", 1]) self.accept("arrow_down", self.setKey, ["backwards", 1]) self.accept("s", self.setKey, ["backwards", 1]) self.accept("arrow_up-up", self.setKey, ["forward", 0]) self.accept("w-up", self.setKey, ["forward", 0]) self.accept("arrow_right-up", self.setKey, ["right", 0]) self.accept("d-up", self.setKey, ["right", 0]) self.accept("arrow_left-up", self.setKey, ["left", 0]) self.accept("a-up", self.setKey, ["left", 0]) self.accept("arrow_down-up", self.setKey, ["backwards", 0]) self.accept("s-up", self.setKey, ["backwards", 0]) self.accept("mouse1", self.startShoot) self.accept("mouse1-up", self.stopShoot) self.accept("tab", self.shiftCamera) self.accept("space", self.player.startBoosters) self.accept("ate-smiley", self.eat) self.accept("ground_collide", self.player.collider) self.p1 = ParticleEffect() self.p2 = ParticleEffect() #Show collisiony stuff base.cTrav.showCollisions(render) def setupPicking(self): self.picker = CollisionTraverser() self.pq = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.picker.addCollider(self.pickerNP, self.pq) self.targetRoot = render.attachNewNode('targetRoot') self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask') def mouseTask(self, task): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.picker.traverse(self.targetRoot) if self.pq.getNumEntries() > 0: self.pq.sortEntries() i = int(self.pq.getEntry(0).getIntoNode().getTag('target')) print("Found target: " + str(i)) return Task.cont def setupIntervals(self): self.lightOn = LerpFunc(self.lightModify, fromData=0, toData=100, duration=0.2, blendType='noBlend', extraArgs=[True], name="LightUp") self.lightOff = LerpFunc(self.lightModify, fromData=0, toData=100, duration=0.2, blendType='noBlend', extraArgs=[False], name="LightDown") self.cameraMove = None def setKey(self, key, value): self.keyMap[key] = value def setWorldLight(self, object): self.lightables.append(object) object.setLight(self.keyLightNP) object.setLight(self.fillLightNP) object.setLight(self.boosterLightNP) for light in self.flameLights: object.setLight(light[1]) def shiftCamera(self): if self.cameraMove: self.cameraMove.finish() old = self.cameraIndex self.cameraIndex += 1 if self.cameraIndex == len(self.cameraPositions): self.cameraIndex = 0 self.cameraMove=LerpPosHprInterval(camera, .7, self.cameraPositions[self.cameraIndex][0], self.cameraPositions[self.cameraIndex][1], camera.getPos(), camera.getHpr()) self.cameraMove.start() def loadModels(self): """loads models into the world""" #eat no longer exists? Phooey self.flameLights = [] shadowcam = Spotlight('shadowlight') shadowcam.setColor(VBase4(0,0,0,1)) lens = PerspectiveLens() shadowcam.setLens(lens) shadowcam.setAttenuation(Point3(0, 0.001, 0.001)) shadowNP = self.player.attachNewNode(shadowcam) shadowNP.setPos(0, -1400, 450) shadowNP.lookAt(self.player) shadowNP.setScale(200) shadowNP.node().setShadowCaster(True) self.flameLights.append((shadowcam, shadowNP)) for i in range(2): slight = PointLight('plight') slight.setColor(VBase4(0, 0, 0, 1)) slight.setAttenuation(Point3(0, 0.001, 0.001)) slnp = self.player.attachNewNode(slight) slnp.setPos(0, -750 - (950 * i), 450) slnp.setHpr(180, 0, 0) slnp.setScale(200) self.flameLights.append((slight, slnp)) self.player.setupBooster() #self.env = loader.loadModel("models/environment") #self.env.reparentTo(render) #self.env.setScale(.25) #self.env.setPos(-8, 42, 0) self.env = loader.loadModel("models/terrain2") self.env.reparentTo(render) self.env.setPos(0,0,0) self.setWorldLight(self.env) #load targets self.targets = [] for i in range (10): target = loader.loadModel("smiley") target.setScale(.5) target.setPos(random.uniform(-20, 20), random.uniform(-15, 15), 2) target.reparentTo(self.targetRoot) self.targets.append(target) self.setWorldLight(target) def setupLights(self): #ambient light self.ambientLight = AmbientLight("ambientLight") #four values, RGBA (alpha is largely irrelevent), value range is 0:1 self.ambientLight.setColor((.10, .10, .10, 1)) self.ambientLightNP = render.attachNewNode(self.ambientLight) #the nodepath that calls setLight is what gets illuminated by the light render.setLight(self.ambientLightNP) #call clearLight() to turn it off self.keyLight = DirectionalLight("keyLight") self.keyLight.setColor((.20,.20,.20, 1)) self.keyLightNP = render.attachNewNode(self.keyLight) self.keyLightNP.setHpr(0, -26, 0) self.fillLight = DirectionalLight("fillLight") self.fillLight.setColor((.05,.05,.05, 1)) self.fillLightNP = render.attachNewNode(self.fillLight) self.fillLightNP.setHpr(30, 0, 0) def drive(self): """compound interval for driveing""" #some interval methods: # start(), loop(), pause(), resume(), finish() # start() can take arguments: start(starttime, endtime, playrate) dist = 5 angle = deg2Rad(self.player.getH()) dx = dist * math.sin(angle) dy = dist * -math.cos(angle) playerdrive = Parallel(self.player.posInterval(1, (self.player.getX() + dx, self.player.getY() + dy, 0)), \ self.player.actorInterval("drive", loop=1, duration=2)) playerdrive.start() def setupCollisions(self): #instantiates a collision traverser and sets it to the default base.cTrav = CollisionTraverser() self.cHandler = CollisionHandlerEvent() #set pattern for event sent on collision # "%in" is substituted with the name of the into object self.cHandler.setInPattern("ate-%in") cSphere = CollisionSphere((0,0,200), 450) #because the player is scaled way down self.playerRay = CollisionRay() self.playerRay.setOrigin(0,0,2000) self.playerRay.setDirection(0,0,-1) self.playerNode = CollisionNode("playerRay") self.playerNode.addSolid(self.playerRay) self.playerNode.setFromCollideMask(BitMask32.bit(0)) self.playerNode.setIntoCollideMask(BitMask32.allOff()) self.playerNodePath = self.player.attachNewNode(self.playerNode) self.playerNodePath.show() self.playerGroundHandler = CollisionHandlerFloor() self.playerGroundHandler.addCollider(self.playerNodePath, self.player) base.cTrav.addCollider(self.playerNodePath, self.playerGroundHandler) cNode = CollisionNode("player") cNode.addSolid(cSphere) cNode.setIntoCollideMask(BitMask32.allOff()) #player is *only* a from object #cNode.setFromCollideMask(BitMask32.bit(0)) cNodePath = self.player.attachNewNode(cNode) #registers a from object with the traverser with a corresponding handler base.cTrav.addCollider(cNodePath, self.cHandler) i = 0 for target in self.targets: cSphere = CollisionSphere((0,0,0), 2) cNode = CollisionNode("smiley") cNode.addSolid(cSphere) cNode.setIntoCollideMask(BitMask32.bit(1)) cNode.setTag('target', str(i)) cNodePath = target.attachNewNode(cNode) i += 1 def lightModify(self, t, which_way): if which_way: #which_way == true then make it brighter value = t/100 * MAX_LIGHT else: #which_way == true then make it darker value = (100 - t)/100 * MAX_LIGHT for light in self.flameLights: light[0].setColor(VBase4(value,value,value,1)) def startShoot(self): self.loadParticleConfig('flamethrower4.ptf') self.lightOff.finish() self.lightOn.start() def stopShoot(self): self.p1.softStop() self.p2.softStop() self.lightOn.finish() self.lightOff.start() def loadParticleConfig(self, file): self.p1.reset() self.p1 = ParticleEffect() self.p1.loadConfig(Filename(file)) self.p1.start(self.player) self.p1.setPos(-250, -700, 275) self.p1.setHpr(0, 90, 0) self.p1.setScale(200) self.p1.setLightOff() self.p2.reset() self.p2 = ParticleEffect() self.p2.loadConfig(Filename(file)) self.p2.start(self.player) self.p2.setPos(250, -700, 275) self.p2.setHpr(0, 90, 0) self.p2.setScale(200) self.p2.setLightOff() def eat(self, cEntry): """handles the player eating a smiley""" #remove target from list of targets self.targets.remove(cEntry.getIntoNodePath().getParent()) #remove from scene graph cEntry.getIntoNodePath().getParent().remove()
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.disableMouse() camera.setPosHpr(0, -12, 8, 0, -35, 0) """ self.environ = self.loader.loadModel("models/environment") # Reparent the model to render. self.environ.reparentTo(self.render) # Apply scale and position transforms on the model. self.environ.setScale(0.25, 0.25, 0.25) self.environ.setPos(-8, 42, 0) self.torus = loader.loadModel("torus.egg") self.torus.reparentTo(self.render) self.torus.setPos(circPos(0,1)) self.torus.setColor(BLACK) self.torus.setScale(0.5,0.5,0.5) """ self.setupLights() self.ended = False self.currentB = False self.firstTurn = True # Since we are using collision detection to do picking, we set it up like # any other collision detection system with a traverser and a handler self.picker = CollisionTraverser() # Make a traverser self.pq = CollisionHandlerQueue() # Make a handler # Make a collision node for our picker ray self.pickerNode = CollisionNode('mouseRay') # Attach that node to the camera since the ray will need to be positioned # relative to it self.pickerNP = camera.attachNewNode(self.pickerNode) # Everything to be picked will use bit 1. This way if we were doing other # collision we could seperate it self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() # Make our ray # Add it to the collision node self.pickerNode.addSolid(self.pickerRay) # Register the ray as something that can cause collisions self.picker.addCollider(self.pickerNP, self.pq) self.picker.showCollisions(render) self.whiteTurn = True # Now we create the chess board and its pieces # We will attach all of the squares to their own root. This way we can do the # collision pass just on the sqaures and save the time of checking the rest # of the scene self.batonsRoot = render.attachNewNode("batonsRoot") self.batons = [None for i in range(9)] self.torus = [[None for j in range(3)] for i in range(9)] self.org = [[[None for j in range(3)] for i in range(3)] for i in range(3)] for i in range(9): # Load, parent, color, and position the model (a single square # polygon) self.batons[i] = loader.loadModel("bois.egg") self.batons[i].reparentTo(self.batonsRoot) self.batons[i].setPos(circPos(i,0)) self.batons[i].setColor(0.75,0.5,0) self.batons[i].setScale(0.75,0.75,0.5) # Set the model itself to be collideable with the ray. If this model was # any more complex than a single polygon, you should set up a collision # sphere around it instead. But for single polygons this works # fine. self.batons[i].find("**/Cylinder").node().setIntoCollideMask( BitMask32.bit(1)) # Set a tag on the square's node so we can look up what square this is # later during the collision pass self.batons[i].find("**/Cylinder").setTag('baton', str(i)) # We will use this variable as a pointer to whatever piece is currently # in this square self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask') self.accept("mouse1", self.click) self.accept("w", self.bestPossibleMove) def setupLights(self): # This function sets up some default lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.8, .8, .8, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(LVector3(0, 45, -45)) directionalLight.setColor((0.2, 0.2, 0.2, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight)) def mouseTask(self, task): # This task deals with the highlighting and dragging based on the mouse # Check to see if we can access the mouse. We need it to do anything # else if self.mouseWatcherNode.hasMouse(): # get the mouse position mpos = self.mouseWatcherNode.getMouse() # Set the position of the ray based on the mouse position self.pickerRay.setFromLens(self.camNode, mpos.getX(), mpos.getY()) if self.currentB is not False: self.batons[self.currentB].setColor(0.75,0.5,0) self.currentB = False # Do the actual collision pass (Do it only on the squares for # efficiency purposes) self.picker.traverse(self.batonsRoot) if self.pq.getNumEntries() > 0: # if we have hit something, sort the hits so that the closest # is first, and highlight that node self.pq.sortEntries() self.currentB = int(self.pq.getEntry(0).getIntoNode().getTag('baton')) # Set the highlight on the picked square self.batons[self.currentB].setColor(HIGHLIGHT) self.currentB return Task.cont def click(self): if self.currentB is not False and not self.ended: self.addTorus(self.currentB) def testMorp(self, z, y, x): print(z,y,x) print([j for j in [self.org[w][y][w]for w in range(3)]if j == None]) print([j for j in [self.org[w][y][w]for w in range(3)]if j == False]) print(len([j for j in [self.org[w][y][w]for w in range(3)]if j == False])) if len([j for j in self.org[z][y] if j == None]) == 0: if len([j for j in self.org[z][y] if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in self.org[z][y] if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[z][w][x]for w in range(3)] if j == None]) == 0: if len([j for j in [self.org[z][w][x]for w in range(3)] if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[z][w][x]for w in range(3)] if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[w][y][x]for w in range(3)] if j==None]) == 0: if len([j for j in [self.org[w][y][x]for w in range(3)] if j==False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[w][y][x]for w in range(3)] if j==True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[z][w][w]for w in range(3)]if j == None]) == 0: if len([j for j in [self.org[z][w][w]for w in range(3)]if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[z][w][w]for w in range(3)]if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[z][w][2 - w]for w in range(3)]if j == None]) == 0: if len([j for j in [self.org[z][w][2 - w]for w in range(3)]if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[z][w][2 - w]for w in range(3)]if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[w][w][x]for w in range(3)]if j == None]) == 0: if len([j for j in [self.org[w][w][x]for w in range(3)]if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[w][w][x]for w in range(3)]if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[w][2-w][x]for w in range(3)]if j == None]) == 0: if len([j for j in [self.org[w][2-w][x]for w in range(3)]if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[w][2-w][x]for w in range(3)]if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[w][y][w]for w in range(3)]if j == None]) == 0: print("wyw") if len([j for j in [self.org[w][y][w]for w in range(3)]if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[w][y][w]for w in range(3)]if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[2-w][y][w]for w in range(3)]if j == None]) == 0: if len([j for j in [self.org[2-w][y][w]for w in range(3)]if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[2-w][y][w]for w in range(3)]if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[w][w][w]for w in range(3)]if j == None]) == 0: if len([j for j in [self.org[w][w][w]for w in range(3)]if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[w][w][w]for w in range(3)]if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[2-w][w][w]for w in range(3)]if j == None]) == 0: if len([j for j in [self.org[2-w][w][w]for w in range(3)]if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[2-w][w][w]for w in range(3)]if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[w][w][2-w]for w in range(3)]if j == None]) == 0: if len([j for j in [self.org[w][w][2-w]for w in range(3)]if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[w][w][2-w]for w in range(3)]if j == True]) == 0: self.ended = True return "blackWin" if len([j for j in [self.org[2-w][w][2-w]for w in range(3)]if j == None]) == 0: if len([j for j in [self.org[2-w][w][2-w]for w in range(3)]if j == False]) == 0: self.ended = True return "whiteWin" elif len([j for j in [self.org[2-w][w][2-w]for w in range(3)]if j == True]) == 0: self.ended = True return "blackWin" return "launched" def addTorus(self, i): minim = False for j,x in enumerate(self.torus[i]): if x is None: minim = j break if minim is not False: print(minim) print(self.whiteTurn) print() if (self.whiteTurn and not self.firstTurn) or (self.firstTurn and not (minim == 0 and i//3 == 1 and i%3 == 1)): self.torus[i][minim] = loader.loadModel("torus.egg") self.torus[i][minim].reparentTo(self.render) self.torus[i][minim].setPos(circPos(i,j-1)) self.torus[i][minim].setColor(WHITE) self.torus[i][minim].setScale(0.75,0.75,1.5) self.org[minim][i//3][i%3] = self.whiteTurn self.whiteTurn = not self.whiteTurn if self.firstTurn: self.firstTurn = False elif not self.firstTurn: self.torus[i][minim] = loader.loadModel("torus.egg") self.torus[i][minim].reparentTo(self.render) self.torus[i][minim].setPos(circPos(i,j-1)) self.torus[i][minim].setColor(BLACK) self.torus[i][minim].setScale(0.75,0.75,1.5) self.org[minim][i//3][i%3] = self.whiteTurn self.whiteTurn = not self.whiteTurn print(self.testMorp(minim, i//3, i%3)) def possibleMoves(self, state, first): possibilities = [] for r in range(9): if (((r is not 4) and first) or (not first)) and state[2][r//3][r%3] == None: possibilities.append(r) return possibilities def bestPossibleMove(self): temp = state for p in possibleMoves(self, state, first): p = 0 def valeurBranche(self, state, first, Wturn, n): vblancs = 0 vnoirs = 0 pos = [None for p in possibleMoves(self, state, first) ] depth = pos for i,p in enumerate(possibleMoves(self, state, first)): tempEtat = addTorustemp(p, WTurn, state) temp = testMorptemp(tempEtat) if temp == 1 and Wturn: pos[i] = 1 depth[i] = n + 1 elif temp ==0 and Wturn: if first: temp2 = valeurBranche(self, temp,not first, not Wturn,n+1) if not (temp2[0] == 0): pos[i] = -temp2[0] depth[i] = temp2[1] else: pos[i] = 0 depth[i] = temp2[1] else: temp2 = valeurBranche(self, temp, first, not Wturn,n+1) if not (temp2[0] == 0): pos[i] = -temp2[0] depth[i] = temp2[1] else : pos[i] = 0 depth[i] = temp2[1] elif temp == 2 and (not Wturn): pos[i] = 1 elif temp ==0 and (not Wturn): if first: temp2 = valeurBranche(self, temp,not first, not Wturn,n+1) if not (temp2[0] == 0): pos[i] = -temp2[0] depth[i] = temp2[1] else: pos[i] = 0 depth[i] = temp2[1] else: temp2 = valeurBranche(self, temp, first, not Wturn,n+1) if not (temp2[0] == 0): pos[i] = -temp2[0] depth[i] = temp2[1] else : pos[i] = 0 depth[i] = temp2[1] else: print("tu sais pas coder guillaume") if pos == []: return (0, n) else: vic = [] zero = [] for i,j in enumerate(pos): if j == 1: vic.append(i) elif j == 0: zero.append(i) if vic is not []: return 1, n elif zero is not []: dmax = 0 for i in zero: if depth[i] > dmax: dmax = depth[i] return 0, dmax else: return -1, n def addTorustemp(self, i, whiteTurn, state): minim = False temp = state for j,x in enumerate([state[w][i//3][i%3] for w in range(3)]): if x is None: minim = j break if minim is not False: print(minim) print(whiteTurn) temp[minim][i//3][i%3] = whiteTurn return temp def testMorptemp(self, torg): for m in range(27): z = m//9 y = m//3 x = m%3 if len([j for j in torg[z][y] if j == None]) == 0: if len([j for j in torg[z][y] if j == False]) == 0: return 1 elif len([j for j in torg[z][y] if j == True]) == 0: return 2 if len([j for j in [torg[z][w][x]for w in range(3)] if j == None]) == 0: if len([j for j in [torg[z][w][x]for w in range(3)] if j == False]) == 0: return 1 elif len([j for j in [torg[z][w][x]for w in range(3)] if j == True]) == 0: return 2 if len([j for j in [torg[w][y][x]for w in range(3)] if j==None]) == 0: if len([j for j in [torg[w][y][x]for w in range(3)] if j==False]) == 0: return 1 elif len([j for j in [torg[w][y][x]for w in range(3)] if j==True]) == 0: return 2 if len([j for j in [torg[z][w][w]for w in range(3)]if j == None]) == 0: if len([j for j in [torg[z][w][w]for w in range(3)]if j == False]) == 0: return 1 elif len([j for j in [torg[z][w][w]for w in range(3)]if j == True]) == 0: return 2 if len([j for j in [torg[z][w][2 - w]for w in range(3)]if j == None]) == 0: if len([j for j in [torg[z][w][2 - w]for w in range(3)]if j == False]) == 0: return 1 elif len([j for j in [torg[z][w][2 - w]for w in range(3)]if j == True]) == 0: return 2 if len([j for j in [torg[w][w][x]for w in range(3)]if j == None]) == 0: if len([j for j in [torg[w][w][x]for w in range(3)]if j == False]) == 0: return 1 elif len([j for j in [torg[w][w][x]for w in range(3)]if j == True]) == 0: return 2 if len([j for j in [torg[w][2-w][x]for w in range(3)]if j == None]) == 0: if len([j for j in [torg[w][2-w][x]for w in range(3)]if j == False]) == 0: return 1 elif len([j for j in [torg[w][2-w][x]for w in range(3)]if j == True]) == 0: return 2 if len([j for j in [torg[w][y][w]for w in range(3)]if j == None]) == 0: if len([j for j in [torg[w][y][w]for w in range(3)]if j == False]) == 0: return 1 elif len([j for j in [torg[w][y][w]for w in range(3)]if j == True]) == 0: return 2 if len([j for j in [torg[2-w][y][w]for w in range(3)]if j == None]) == 0: if len([j for j in [torg[2-w][y][w]for w in range(3)]if j == False]) == 0: return 1 elif len([j for j in [torg[2-w][y][w]for w in range(3)]if j == True]) == 0: return 2 if len([j for j in [torg[w][w][w]for w in range(3)]if j == None]) == 0: if len([j for j in [torg[w][w][w]for w in range(3)]if j == False]) == 0: return 1 elif len([j for j in [torg[w][w][w]for w in range(3)]if j == True]) == 0: return 2 if len([j for j in [torg[2-w][w][w]for w in range(3)]if j == None]) == 0: if len([j for j in [torg[2-w][w][w]for w in range(3)]if j == False]) == 0: return 1 elif len([j for j in [torg[2-w][w][w]for w in range(3)]if j == True]) == 0: return 2 if len([j for j in [torg[w][w][2-w]for w in range(3)]if j == None]) == 0: if len([j for j in [torg[w][w][2-w]for w in range(3)]if j == False]) == 0: return 1 elif len([j for j in [torg[w][w][2-w]for w in range(3)]if j == True]) == 0: return 2 if len([j for j in [torg[2-w][w][2-w]for w in range(3)]if j == None]) == 0: if len([j for j in [torg[2-w][w][2-w]for w in range(3)]if j == False]) == 0: return 1 elif len([j for j in [torg[2-w][w][2-w]for w in range(3)]if j == True]) == 0: return 2 return 0
class LocalToon(DistributedToon): neverDisable = 1 def __init__(self, cr): try: self.LocalToon_initialized return except: self.LocalToon_initialized = 1 DistributedToon.__init__(self, cr) self.avatarChoice = cr.localAvChoice self.smartCamera = SmartCamera() self.chatInput = ChatInput() self.moneyGui = MoneyGui() self.laffMeter = LaffOMeter() self.positionExaminer = PositionExaminer() self.friendRequestManager = FriendRequestManager() self.friendsList = FriendsList() self.panel = ToonPanel() friendsgui = loader.loadModel('phase_3.5/models/gui/friendslist_gui.bam') self.friendButton = DirectButton(geom=(friendsgui.find('**/FriendsBox_Closed'), friendsgui.find('**/FriendsBox_Rollover'), friendsgui.find('**/FriendsBox_Rollover')), text=('', 'Friends', 'Friends', ''), text_fg=(1, 1, 1, 1), text_shadow=(0, 0, 0, 1), text_scale=0.065, text_pos=(0, -0.2), relief=None, parent=base.a2dTopRight, pos=(-0.18, 0.0, -0.17), command=self.friendsButtonClicked, scale=0.75) friendsgui.removeNode() del friendsgui self.hideFriendButton() self.runSfx = base.loadSfx('phase_3.5/audio/sfx/AV_footstep_runloop.wav') self.runSfx.setLoop(True) self.walkSfx = base.loadSfx('phase_3.5/audio/sfx/AV_footstep_walkloop.wav') self.walkSfx.setLoop(True) self.controlManager = ControlManager.ControlManager(True, False) self.offset = 3.2375 self.movementKeymap = {'forward': 0, 'backward': 0, 'left': 0, 'right': 0, 'jump': 0} self.avatarMovementEnabled = False self.isMoving_forward = False self.isMoving_side = False self.isMoving_back = False self.isMoving_jump = False self.pieThrowBtn = None self.myBattle = None self.invGui = None self.pickerTrav = None self.pickerRay = None self.pickerRayNode = None self.pickerHandler = None self.rolledOverTag = None self.inTutorial = False self.hasDoneJump = False self.lastState = None self.lastAction = None return def hasDiscoveredHood(self, zoneId): return zoneId in self.hoodsDiscovered def hasTeleportAccess(self, zoneId): return zoneId in self.teleportAccess def tutorialCreated(self, zoneId): self.cr.tutorialCreated(zoneId) def friendsButtonClicked(self): self.hideFriendButton() self.friendsList.fsm.request('onlineFriendsList') def hideFriendButton(self): self.friendButton.hide() def showFriendButton(self): self.friendButton.show() def gotoNode(self, node, eyeHeight = 3): possiblePoints = (Point3(3, 6, 0), Point3(-3, 6, 0), Point3(6, 6, 0), Point3(-6, 6, 0), Point3(3, 9, 0), Point3(-3, 9, 0), Point3(6, 9, 0), Point3(-6, 9, 0), Point3(9, 9, 0), Point3(-9, 9, 0), Point3(6, 0, 0), Point3(-6, 0, 0), Point3(6, 3, 0), Point3(-6, 3, 0), Point3(9, 9, 0), Point3(-9, 9, 0), Point3(0, 12, 0), Point3(3, 12, 0), Point3(-3, 12, 0), Point3(6, 12, 0), Point3(-6, 12, 0), Point3(9, 12, 0), Point3(-9, 12, 0), Point3(0, -6, 0), Point3(-3, -6, 0), Point3(0, -9, 0), Point3(-6, -9, 0)) for point in possiblePoints: pos = self.positionExaminer.consider(node, point, eyeHeight) if pos: self.setPos(node, pos) self.lookAt(node) self.setHpr(self.getH() + random.choice((-10, 10)), 0, 0) return self.setPos(node, 0, 0, 0) def setFriendsList(self, friends): DistributedToon.setFriendsList(self, friends) self.cr.friendsManager.d_requestFriendsList() self.panel.maybeUpdateFriendButton() def d_requestAddFriend(self, avId): self.sendUpdate('requestAddFriend', [avId]) def setupPicker(self): self.pickerTrav = CollisionTraverser('LT.pickerTrav') self.pickerRay = CollisionRay() rayNode = CollisionNode('LT.pickerNode') rayNode.addSolid(self.pickerRay) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask) self.pickerRayNode = base.camera.attachNewNode(rayNode) self.pickerHandler = CollisionHandlerQueue() self.pickerTrav.addCollider(self.pickerRayNode, self.pickerHandler) def enablePicking(self): self.accept('mouse1', self.pickedSomething_down) self.accept('mouse1-up', self.pickedSomething_up) base.taskMgr.add(self.__travMousePicker, 'LT.travMousePicker') def disablePicking(self): base.taskMgr.remove('LT.travMousePicker') self.ignore('mouse1') self.ignore('mouse1-up') def pickedSomething_down(self): if self.rolledOverTag: base.playSfx(DGG.getDefaultClickSound()) avatar = self.cr.doId2do.get(self.rolledOverTag) avatar.nameTag.setPickerState('down') def pickedSomething_up(self): if self.rolledOverTag: avatar = self.cr.doId2do.get(self.rolledOverTag) avatar.nameTag.setPickerState('up') self.panel.makePanel(self.rolledOverTag) def __travMousePicker(self, task): if not base.mouseWatcherNode.hasMouse(): return task.cont else: mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.pickerTrav.traverse(render) if self.pickerHandler.getNumEntries() > 0: self.pickerHandler.sortEntries() pickedObject = self.pickerHandler.getEntry(0).getIntoNodePath() avatarId = pickedObject.getParent().getPythonTag('avatar') if avatarId != None: for do in self.cr.doId2do.values(): if do.__class__.__name__ == 'DistributedToon': if do.doId == avatarId: if do.nameTag.getClickable() == 1: if do.nameTag.fsm.getCurrentState().getName() != 'rollover' and do.nameTag.fsm.getCurrentState().getName() != 'down': do.nameTag.setPickerState('rollover') base.playSfx(DGG.getDefaultRolloverSound()) self.rolledOverTag = avatarId break elif do.__class__.__name__ == 'DistributedToon': if do.nameTag.fsm.getCurrentState().getName() != 'up': do.nameTag.setPickerState('up') elif self.rolledOverTag: avatar = self.cr.doId2do.get(self.rolledOverTag) if avatar: if avatar.nameTag.fsm.getCurrentState().getName() != 'up': avatar.nameTag.setPickerState('up') self.rolledOverTag = None return task.cont def prepareToSwitchControlType(self): inputs = ['run', 'forward', 'reverse', 'turnLeft', 'turnRight', 'slideLeft', 'slideRight', 'jump'] for inputName in inputs: try: inputState.releaseInputs(inputName) except: pass def getBackpack(self): return DistributedToon.getBackpack(self) def setMyBattle(self, battle): self.myBattle = battle def getMyBattle(self): return self.myBattle def ghostOn(self): self.getGeomNode().setTransparency(1) self.getGeomNode().setColorScale(1, 1, 1, 0.25) def ghostOff(self): self.getGeomNode().setColorScale(1, 1, 1, 1) self.getGeomNode().setTransparency(0) def enterReadBook(self, ts = 0, callback = None, extraArgs = []): self.stopLookAround() self.b_lookAtObject(0, -45, 0) DistributedToon.enterReadBook(self, ts, callback, extraArgs) def exitReadBook(self): DistributedToon.exitReadBook(self) self.startLookAround() def getAirborneHeight(self): return self.offset + 0.025 def setupControls(self): self.walkControls = GravityWalker(legacyLifter=False) self.walkControls.setWallBitMask(CIGlobals.WallBitmask) self.walkControls.setFloorBitMask(CIGlobals.FloorBitmask) self.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) self.walkControls.initializeCollisions(base.cTrav, self, floorOffset=0.025, reach=4.0) self.walkControls.setAirborneHeightFunc(self.getAirborneHeight) def setWalkSpeedNormal(self): self.walkControls.setWalkSpeed(CIGlobals.ToonForwardSpeed, CIGlobals.ToonJumpForce, CIGlobals.ToonReverseSpeed, CIGlobals.ToonRotateSpeed) def setWalkSpeedSlow(self): self.walkControls.setWalkSpeed(CIGlobals.ToonForwardSlowSpeed, CIGlobals.ToonJumpSlowForce, CIGlobals.ToonReverseSlowSpeed, CIGlobals.ToonRotateSlowSpeed) def setupCamera(self): base.camLens.setMinFov(CIGlobals.DefaultCameraFov / (4.0 / 3.0)) base.camLens.setNearFar(CIGlobals.DefaultCameraNear, CIGlobals.DefaultCameraFar) camHeight = max(self.getHeight(), 3.0) heightScaleFactor = camHeight * 0.3333333333 defLookAt = Point3(0.0, 1.5, camHeight) camPos = (Point3(0.0, -9.0 * heightScaleFactor, camHeight), defLookAt, Point3(0.0, camHeight, camHeight * 4.0), Point3(0.0, camHeight, camHeight * -1.0), 0) self.smartCamera.initializeSmartCamera() self.smartCamera.setIdealCameraPos(camPos[0]) self.smartCamera.setLookAtPoint(defLookAt) def setDNAStrand(self, dnaStrand): DistributedToon.setDNAStrand(self, dnaStrand) self.initCollisions() self.setupCamera() def setMoney(self, money): DistributedToon.setMoney(self, money) self.moneyGui.update(money) def setupNameTag(self, tempName = None): DistributedToon.setupNameTag(self, tempName) if self.nameTag: self.nameTag.setColorLocal() def d_broadcastPositionNow(self): self.d_clearSmoothing() self.d_broadcastPosHpr() def b_setAnimState(self, anim, callback = None, extraArgs = []): if self.anim != anim: self.d_setAnimState(anim) DistributedToon.setAnimState(self, anim, callback=callback, extraArgs=extraArgs) def attachCamera(self): camera.reparentTo(self) camera.setPos(self.smartCamera.getIdealCameraPos()) def startSmartCamera(self): self.smartCamera.startUpdateSmartCamera() def resetSmartCamera(self): self.stopSmartCamera() self.startSmartCamera() def stopSmartCamera(self): self.smartCamera.stopUpdateSmartCamera() def detachCamera(self): camera.reparentTo(render) camera.setPos(0, 0, 0) camera.setHpr(0, 0, 0) def handleSuitAttack(self, attack_id, suit_id): DistributedToon.handleSuitAttack(self, attack_id, suit_id) if not self.isDead() and base.config.GetBool('want-sa-reactions'): base.taskMgr.remove('LT.attackReactionDone') attack = SuitAttacks.SuitAttackLengths.keys()[attack_id] suit = self.cr.doId2do.get(suit_id) animToPlay = None timeToWait = 3.0 if attack not in ('pickpocket', 'fountainpen'): suitH = suit.getH(render) % 360 myH = self.getH(render) % 360 if -90.0 <= suitH - myH <= 90.0: animToPlay = 'fallFWD' else: animToPlay = 'fallBCK' elif attack in ('pickpocket',): animToPlay = 'cringe' elif attack in ('fountainpen',): animToPlay = 'conked' timeToWait = 5.0 self.cr.playGame.getPlace().fsm.request('stop') self.b_setAnimState(animToPlay) base.taskMgr.doMethodLater(timeToWait, self.__attackReactionDone, 'LT.attackReactionDone') return def __attackReactionDone(self, task): self.cr.playGame.hood.loader.place.fsm.request('walk') self.b_setAnimState('neutral') return Task.done def enableAvatarControls(self): self.walkControls.enableAvatarControls() self.accept('control', self.updateMovementKeymap, ['jump', 1]) self.accept('control-up', self.updateMovementKeymap, ['jump', 0]) taskMgr.add(self.movementTask, 'avatarMovementTask') self.avatarMovementEnabled = True self.playMovementSfx(None) return def disableAvatarControls(self): self.walkControls.disableAvatarControls() self.ignore('arrow_up') self.ignore('arrow_up-up') self.ignore('arrow_down') self.ignore('arrow_down-up') self.ignore('arrow_left') self.ignore('arrow_left-up') self.ignore('arrow_right') self.ignore('arrow_right-up') self.ignore('control') self.ignore('control-up') taskMgr.remove('avatarMovementTask') self.isMoving_forward = False self.isMoving_side = False self.isMoving_back = False self.isMoving_jump = False self.avatarMovementEnabled = False self.playMovementSfx(None) for k, _ in self.movementKeymap.items(): self.updateMovementKeymap(k, 0) return def updateMovementKeymap(self, key, value): self.movementKeymap[key] = value def getMovementKeyValue(self, key): return self.movementKeymap[key] def playMovementSfx(self, movement): if movement == 'run': self.walkSfx.stop() self.runSfx.play() elif movement == 'walk': self.runSfx.stop() self.walkSfx.play() else: self.runSfx.stop() self.walkSfx.stop() def __forward(self): self.resetHeadHpr() self.stopLookAround() if self.getHealth() < 1: self.playMovementSfx('walk') self.setPlayRate(1.2, 'dwalk') self.setAnimState('deadWalk') else: self.playMovementSfx('run') self.setAnimState('run') self.isMoving_side = False self.isMoving_back = False self.isMoving_forward = True self.isMoving_jump = False def __turn(self): self.resetHeadHpr() self.stopLookAround() self.playMovementSfx('walk') if self.getHealth() < 1: self.setPlayRate(1.2, 'dwalk') self.setAnimState('deadWalk') else: self.setPlayRate(1.0, 'walk') self.setAnimState('walk') self.isMoving_forward = False self.isMoving_back = False self.isMoving_side = True self.isMoving_jump = False def __reverse(self): self.resetHeadHpr() self.stopLookAround() self.playMovementSfx('walk') if self.getHealth() < 1: self.setPlayRate(-1.0, 'dwalk') self.setAnimState('deadWalk') else: self.setAnimState('walkBack') self.isMoving_side = False self.isMoving_forward = False self.isMoving_back = True self.isMoving_jump = False def __jump(self): self.playMovementSfx(None) if base.localAvatar.getHealth() > 0: if self.playingAnim == 'run' or self.playingAnim == 'walk': self.b_setAnimState('leap') else: self.b_setAnimState('jump') self.isMoving_side = False self.isMoving_forward = False self.isMoving_back = False self.isMoving_jump = True return def __neutral(self): self.resetHeadHpr() self.startLookAround() self.playMovementSfx(None) if base.localAvatar.getHealth() > 0: self.setAnimState('neutral') else: self.setPlayRate(1.0, 'dneutral') self.setAnimState('deadNeutral') self.isMoving_side = False self.isMoving_forward = False self.isMoving_back = False self.isMoving_jump = False return def movementTask(self, task): if self.getMovementKeyValue('jump') == 1: if not self.walkControls.isAirborne: if self.walkControls.mayJump: self.__jump() self.hasDoneJump = True elif self.hasDoneJump: if self.getHealth() > 0: self.b_setAnimState('Happy') self.hasDoneJump = False elif not self.walkControls.isAirborne: if self.hasDoneJump: if self.getHealth() > 0: self.b_setAnimState('Happy') self.hasDoneJump = False return task.cont def startTrackAnimToSpeed(self): base.taskMgr.add(self.trackAnimToSpeed, self.uniqueName('trackAnimToSpeed')) def stopTrackAnimToSpeed(self): base.taskMgr.remove(self.uniqueName('trackAnimToSpeed')) def trackAnimToSpeed(self, task): speed, rotSpeed, slideSpeed = self.walkControls.getSpeeds() state = None if self.getHealth() > 0: state = 'Happy' else: state = 'Sad' if state != self.lastState: self.lastState = state self.b_setAnimState(state) if state == 'Sad': self.setWalkSpeedSlow() else: self.setWalkSpeedNormal() action = self.setSpeed(speed, rotSpeed) if action != self.lastAction: self.lastAction = action if action == CIGlobals.WALK_INDEX or action == CIGlobals.REVERSE_INDEX: self.resetHeadHpr() self.stopLookAround() self.playMovementSfx('walk') elif action == CIGlobals.RUN_INDEX: self.resetHeadHpr() self.stopLookAround() self.playMovementSfx('run') else: self.resetHeadHpr() self.startLookAround() self.playMovementSfx(None) return task.cont def createLaffMeter(self): r, g, b, _ = self.getHeadColor() animal = self.getAnimal() maxHp = self.getMaxHealth() hp = self.getHealth() self.laffMeter.generate(r, g, b, animal, maxHP=maxHp, initialHP=hp) self.laffMeter.start() def disableLaffMeter(self): self.laffMeter.stop() self.laffMeter.disable() def deleteLaffMeter(self): self.laffMeter.delete() def setLoadout(self, gagIds): DistributedToon.setLoadout(self, gagIds) if base.cr.playGame.getPlace() and base.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'shtickerBook': if hasattr(base.cr.playGame.getPlace(), 'shtickerBookStateData'): if base.cr.playGame.getPlace().shtickerBookStateData.fsm.getCurrentState().getName() == 'inventoryPage': base.cr.playGame.getPlace().shtickerBookStateData.gui.fsm.request('idle') def enablePies(self, andKeys = 0): if self.avatarMovementEnabled and andKeys: self.enablePieKeys() self.backpack = DistributedToon.getBackpack(self) self.invGui = InventoryGui() self.invGui.createGui() self.invGui.setBackpack(self.backpack) for gag in self.backpack.getGags(): gag.setAvatar(self) self.backpack.setGagGUI(self.invGui) if self.backpack.getCurrentGag(): self.invGui.setWeapon(self.backpack.getCurrentGag().getName(), playSound=False) def enablePieKeys(self): if self.pieThrowBtn: if not self.backpack: self.backpack = DistributedToon.getBackpack(self) self.pieThrowBtn.bind(DGG.B1PRESS, self.startGag) self.pieThrowBtn.bind(DGG.B1RELEASE, self.throwGag) self.accept('delete', self.startGag) self.accept('delete-up', self.throwGag) def disablePieKeys(self): if self.pieThrowBtn: self.pieThrowBtn.unbind(DGG.B1PRESS) self.pieThrowBtn.unbind(DGG.B1RELEASE) self.ignore('delete') self.ignore('delete-up') def disablePies(self): self.disablePieKeys() self.invGui.deleteGui() if hasattr(self, 'backpack'): if self.backpack: self.backpack.setCurrentGag(None) return def setWeaponType(self, weaponType): enableKeysAgain = 0 if weaponType != self.weaponType: enableKeysAgain = 1 self.weaponType = weaponType if enableKeysAgain: self.disablePieKeys() self.enablePieKeys() def createMoney(self): self.moneyGui.createGui() self.moneyGui.update(self.money) def handleMoneyChanged(self): self.moneyGui.update() def disableMoney(self): self.moneyGui.deleteGui() def resetHeadHpr(self): self.b_lookAtObject(0, 0, 0, blink=0) def startGag(self, start = True): if not self.backpack or not self.backpack.getCurrentGag(): return if self.backpack.getSupply() > 0: if self.pieThrowBtn: self.pieThrowBtn.unbind(DGG.B1PRESS) if self.backpack.getActiveGag(): if self.backpack.getActiveGag().getState() != GagState.LOADED: return self.ignore('delete') self.backpack.getCurrentGag().setAvatar(self) self.resetHeadHpr() self.b_gagStart(self.backpack.getCurrentGag().getID()) def throwGag(self, start = True): if not self.backpack or not self.backpack.getCurrentGag() or not self.backpack.getActiveGag(): return if self.backpack.getSupply() > 0: if self.pieThrowBtn: self.pieThrowBtn.unbind(DGG.B1RELEASE) self.ignore('delete-up') if self.backpack.getActiveGag().getType() == GagType.SQUIRT and self.backpack.getActiveGag().getName() == CIGlobals.SeltzerBottle: self.b_gagRelease(self.backpack.getActiveGag().getID()) else: self.b_gagThrow(self.backpack.getActiveGag().getID()) activeGag = self.backpack.getActiveGag() if not activeGag: activeGag = self.backpack.getCurrentGag() if not activeGag.doesAutoRelease(): Sequence(Wait(0.75), Func(self.releaseGag), Wait(0.3), Func(self.enablePieKeys)).start() def releaseGag(self): if not self.backpack or not self.backpack.getActiveGag(): return if self.backpack.getSupply() > 0: gag = self.backpack.getActiveGag() if not gag: gag = self.backpack.getCurrentGag() if gag.getState() != GagState.RELEASED: gagName = gag.getName() self.b_gagRelease(GagGlobals.getIDByName(gagName)) def checkSuitHealth(self, suit): pass def handleLookSpot(self, hpr): h, p, r = hpr self.d_lookAtObject(h, p, r, blink=1) def showPieButton(self): geom = CIGlobals.getDefaultBtnGeom() self.pieThrowBtn = DirectButton(geom=geom, geom_scale=(0.75, 1, 1), text='Throw Gag', text_scale=0.05, text_pos=(0, -0.01), relief=None, parent=base.a2dTopCenter, pos=(0, 0, -0.1)) self.pieThrowBtn.setBin('gui-popup', 60) return def hidePieButton(self): self.pieThrowBtn.removeNode() self.pieThrowBtn = None return def showBookButton(self, inBook = 0): self.book_gui = loader.loadModel('phase_3.5/models/gui/sticker_open_close_gui.bam') self.book_btn = DirectButton(geom=(self.book_gui.find('**/BookIcon_CLSD'), self.book_gui.find('**/BookIcon_OPEN'), self.book_gui.find('**/BookIcon_RLVR')), relief=None, pos=(-0.175, 0, 0.163), command=self.bookButtonClicked, scale=(0.7, 0.8, 0.8), parent=base.a2dBottomRight) self.book_btn.setBin('gui-popup', 60) if inBook: self.book_btn['geom'] = (self.book_gui.find('**/BookIcon_OPEN'), self.book_gui.find('**/BookIcon_CLSD'), self.book_gui.find('**/BookIcon_RLVR2')) self.book_btn['command'] = self.bookButtonClicked self.book_btn['extraArgs'] = [0] return def hideBookButton(self): if hasattr(self, 'book_gui'): self.book_gui.removeNode() del self.book_gui if hasattr(self, 'book_btn'): self.book_btn.destroy() del self.book_btn def bookButtonClicked(self, openIt = 1): if openIt: base.cr.playGame.getPlace().fsm.request('shtickerBook') else: base.cr.playGame.getPlace().shtickerBookStateData.finished('resume') def startMonitoringHP(self): taskMgr.add(self.monitorHealth, 'localToon-monitorHealth') def monitorHealth(self, task): if self.isDead(): base.taskMgr.remove('LT.attackReactionDone') if self.cr.playGame.hood.id != ZoneUtil.getHoodId(self.zoneId): self.cr.playGame.getPlace().fsm.request('died', [{}, self.diedStateDone]) return task.done return task.cont def stopMonitoringHP(self): taskMgr.remove('localToon-monitorHealth') def setHealth(self, hp): if hp > 0 and self.getHealth() < 1: if self.cr.playGame.getPlace(): if self.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'walk': if self.cr.playGame.getPlace().walkStateData.fsm.getCurrentState().getName() == 'deadWalking': self.cr.playGame.getPlace().walkStateData.fsm.request('walking') if self.animFSM.getCurrentState().getName() == 'deadNeutral': self.playMovementSfx(None) self.b_setAnimState('neutral') elif self.animFSM.getCurrentState().getName() == 'deadWalk': self.playMovementSfx('run') self.b_setAnimState('run') DistributedToon.setHealth(self, hp) return def diedStateDone(self, requestStatus): hood = self.cr.playGame.hood.id if hood == CIGlobals.BattleTTC: hood = CIGlobals.ToontownCentral toZone = ZoneUtil.getZoneId(hood) if self.zoneId != toZone: requestStatus = {'zoneId': toZone, 'hoodId': hood, 'where': ZoneUtil.getWhereName(toZone), 'avId': self.doId, 'loader': ZoneUtil.getLoaderName(toZone), 'shardId': None, 'wantLaffMeter': 1, 'how': 'teleportIn'} self.cr.playGame.getPlace().doneStatus = requestStatus messenger.send(self.cr.playGame.getPlace().doneEvent) else: return return def teleportToCT(self): toZone = CIGlobals.CogTropolisId hood = CIGlobals.CogTropolis requestStatus = {'zoneId': toZone, 'hoodId': hood, 'where': ZoneUtil.getWhereName(toZone), 'avId': self.doId, 'loader': ZoneUtil.getLoaderName(toZone), 'shardId': None, 'wantLaffMeter': 1, 'how': 'teleportIn'} self.cr.playGame.getPlace().fsm.request('teleportOut', [requestStatus]) return def createChatInput(self): self.chatInput.load() self.chatInput.enter() def disableChatInput(self): self.chatInput.exit() self.chatInput.unload() def collisionsOn(self): self.controlManager.collisionsOn() def collisionsOff(self): self.controlManager.collisionsOff() def generate(self): DistributedToon.generate(self) def delete(self): DistributedToon.delete(self) self.deleteLaffMeter() def disable(self): base.camLens.setMinFov(CIGlobals.OriginalCameraFov / (4.0 / 3.0)) self.friendsList.destroy() self.friendsList = None self.positionExaminer.delete() self.positionExaminer = None self.disablePicking() self.stopMonitoringHP() taskMgr.remove('resetHeadColorAfterFountainPen') taskMgr.remove('LT.attackReactionDone') self.stopLookAround() DistributedToon.disable(self) self.disableAvatarControls() self.disableLaffMeter() self.disablePies() self.disableChatInput() self.weaponType = None self.pieType = None self.myBattle = None self.ignore('gotLookSpot') return def announceGenerate(self): DistributedToon.announceGenerate(self) self.setupPicker() self.setupControls() self.startLookAround() self.friendRequestManager.watch() self.accept('gotLookSpot', self.handleLookSpot) def printAvPos(self): print 'Pos: %s, Hpr: %s' % (self.getPos(), self.getHpr())
class PositionExaminer(DirectObject, NodePath): def __init__(self): try: self.__initialized return except: self.__initialized = 1 NodePath.__init__(self, hidden.attachNewNode('PositionExaminer')) self.cRay = CollisionRay(0.0, 0.0, 6.0, 0.0, 0.0, -1.0) self.cRayNode = CollisionNode('cRayNode') self.cRayNode.addSolid(self.cRay) self.cRayNodePath = self.attachNewNode(self.cRayNode) self.cRayNodePath.hide() self.cRayBitMask = CIGlobals.FloorBitmask self.cRayNode.setFromCollideMask(self.cRayBitMask) self.cRayNode.setIntoCollideMask(BitMask32.allOff()) self.cSphere = CollisionSphere(0.0, 0.0, 0.0, 1.5) self.cSphereNode = CollisionNode('cSphereNode') self.cSphereNode.addSolid(self.cSphere) self.cSphereNodePath = self.attachNewNode(self.cSphereNode) self.cSphereNodePath.hide() self.cSphereBitMask = CIGlobals.WallBitmask self.cSphereNode.setFromCollideMask(self.cSphereBitMask) self.cSphereNode.setIntoCollideMask(BitMask32.allOff()) self.ccLine = CollisionSegment(0.0, 0.0, 0.0, 1.0, 0.0, 0.0) self.ccLineNode = CollisionNode('ccLineNode') self.ccLineNode.addSolid(self.ccLine) self.ccLineNodePath = self.attachNewNode(self.ccLineNode) self.ccLineNodePath.hide() self.ccLineBitMask = CIGlobals.CameraBitmask self.ccLineNode.setFromCollideMask(self.ccLineBitMask) self.ccLineNode.setIntoCollideMask(BitMask32.allOff()) self.cRayTrav = CollisionTraverser('PositionExaminer.cRayTrav') self.cRayTrav.setRespectPrevTransform(False) self.cRayQueue = CollisionHandlerQueue() self.cRayTrav.addCollider(self.cRayNodePath, self.cRayQueue) self.cSphereTrav = CollisionTraverser('PositionExaminer.cSphereTrav') self.cSphereTrav.setRespectPrevTransform(False) self.cSphereQueue = CollisionHandlerQueue() self.cSphereTrav.addCollider(self.cSphereNodePath, self.cSphereQueue) self.ccLineTrav = CollisionTraverser('PositionExaminer.ccLineTrav') self.ccLineTrav.setRespectPrevTransform(False) self.ccLineQueue = CollisionHandlerQueue() self.ccLineTrav.addCollider(self.ccLineNodePath, self.ccLineQueue) def delete(self): del self.cRay del self.cRayNode self.cRayNodePath.removeNode() del self.cRayNodePath del self.cSphere del self.cSphereNode self.cSphereNodePath.removeNode() del self.cSphereNodePath del self.ccLine del self.ccLineNode self.ccLineNodePath.removeNode() del self.ccLineNodePath del self.cRayTrav del self.cRayQueue del self.cSphereTrav del self.cSphereQueue del self.ccLineTrav del self.ccLineQueue def consider(self, node, pos, eyeHeight): self.reparentTo(node) self.setPos(pos) result = None self.cRayTrav.traverse(render) if self.cRayQueue.getNumEntries() != 0: self.cRayQueue.sortEntries() floorPoint = self.cRayQueue.getEntry(0).getSurfacePoint(self.cRayNodePath) if abs(floorPoint[2]) <= 4.0: pos += floorPoint self.setPos(pos) self.cSphereTrav.traverse(render) if self.cSphereQueue.getNumEntries() == 0: self.ccLine.setPointA(0, 0, eyeHeight) self.ccLine.setPointB(-pos[0], -pos[1], eyeHeight) self.ccLineTrav.traverse(render) if self.ccLineQueue.getNumEntries() == 0: result = pos self.reparentTo(hidden) self.cRayQueue.clearEntries() self.cSphereQueue.clearEntries() self.ccLineQueue.clearEntries() return result
class ChessboardDemo(): def __init__(self, mission): # Initialize the ShowBase class from which we inherit, which will # create a window and set up everything we need for rendering into it. self.mission = mission self.player = mission.player self.menu = mission.menu self.state = 0 self.frame = DirectFrame(frameColor=(0.1, 0.1, 0.1, 0.5), frameSize=(-2, 2, -2, 2), pos=(0, 0, 0)) self.frame.hide() self.dr2 = base.win.makeDisplayRegion() #self.dr2.setActive(False) # self.frame.attachNewNode(self.dr2.node()) #self.dr2.setActive(False) self.dr2.setClearColorActive(True) self.dr2.setClearColor(VBase4(0.1, 0.1, 0.1, 1)) self.dr2.setClearDepthActive(True) # base.win.setClearColor(VBase4(0.1,0.1,0.1,1)) # base.win.setClearDepthActive() # base.win.setClearDepth(1) self.render2 = NodePath("render2") self.camNode = Camera("cam2") self.cam2 = self.render2.attachNewNode(self.camNode) self.dr2.setCamera(self.cam2) self.cam2.setPosHpr(0, -18, 10, 0, -30, 0) # Escape quits base.disableMouse() # Disble mouse camera control # camera.setPosHpr(0, -12, 8, 0, -35, 0) # Set the camera self.setupLights() # Setup default lighting # Since we are using collision detection to do picking, we set it up like # any other collision detection system with a traverser and a handler self.picker = CollisionTraverser() # Make a traverser self.pq = CollisionHandlerQueue() # Make a handler # Make a collision node for our picker ray self.pickerNode = CollisionNode('mouseRay') # Attach that node to the camera since the ray will need to be positioned # relative to it # self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNP = self.cam2.attachNewNode(self.pickerNode) # Everything to be picked will use bit 1. This way if we were doing other # collision we could separate it self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() # Make our ray # Add it to the collision node self.pickerNode.addSolid(self.pickerRay) # Register the ray as something that can cause collisions self.picker.addCollider(self.pickerNP, self.pq) # self.picker.showCollisions(render) # Now we create the chess board and its pieces # We will attach all of the squares to their own root. This way we can do the # collision pass just on the squares and save the time of checking the rest # of the scene self.squareRoot = self.render2.attachNewNode("squareRoot") # For each square self.squares = [None for i in range(64)] self.pieces = [None for i in range(64)] for i in range(64): # Load, parent, color, and position the model (a single square # polygon) # self.squares[i] = loader.loadModel("../res/models/Scene3/Scene3Cat/hall/square") self.squares[i] = loader.loadModel( "res/models/Scene3/Scene3Cat/hall/square") self.squares[i].reparentTo(self.squareRoot) self.squares[i].setPos(SquarePos(i)) self.squares[i].setColor(SquareColor(i)) # Set the model itself to be collideable with the ray. If this model was # any more complex than a single polygon, you should set up a collision # sphere around it instead. But for single polygons this works # fine. self.squares[i].find("**/polygon").node().setIntoCollideMask( BitMask32.bit(1)) # Set a tag on the square's node so we can look up what square this is # later during the collision pass self.squares[i].find("**/polygon").node().setTag('square', str(i)) # We will use this variable as a pointer to whatever piece is currently # in this square # The order of pieces on a chessboard from white's perspective. This list # contains the constructor functions for the piece classes defined # below pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook) self.pieces[40] = Queen(self, 40, WHITE) self.pieces[51] = Bishop(self, 51, PIECEBLACK) self.pieces[33] = Knight(self, 33, PIECEBLACK) self.pieces[9] = Rook(self, 9, PIECEBLACK) self.pieces[20] = Rook(self, 20, PIECEBLACK) # This will represent the index of the currently highlited square self.hiSq = False # This wil represent the index of the square where currently dragged piece # was grabbed from self.dragging = False # self.eight = OnscreenText(text="8", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), # pos=(-0.9, 0.35), scale=.07) # self.seven = OnscreenText(text="7", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), # pos=(-0.93, 0.27), scale=.07) # self.six = OnscreenText(text="6", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), # pos=(-0.97, 0.18), scale=.07) # self.five = OnscreenText(text="5", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), # pos=(-1.02, 0.1), scale=.07) # self.four = OnscreenText(text="4", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), # pos=(-1.06, 0.02), scale=.07) # self.three = OnscreenText(text="3", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), # pos=(-1.12, -0.1), scale=.07) # self.two = OnscreenText(text="2", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), # pos=(-1.16, -0.18), scale=.07) # self.one = OnscreenText(text="1", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), # pos=(-1.23, -0.32), scale=.07) x = -0.91 y = 0.33 dx = 0.04 dy = 0.09 self.eight = OnscreenText(text="8", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(x, y), scale=.07) x -= dx y -= dy self.seven = OnscreenText(text="7", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(x, y), scale=.07) x -= dx y -= dy self.six = OnscreenText(text="6", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(x, y), scale=.07) x -= dx y -= dy self.five = OnscreenText(text="5", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(x, y), scale=.07) x -= dx y -= dy self.four = OnscreenText(text="4", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(x, y), scale=.07) x -= dx y -= dy self.three = OnscreenText(text="3", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(x, y), scale=.07) x -= dx y -= dy self.two = OnscreenText(text="2", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(x, y), scale=.07) x -= dx y -= dy self.one = OnscreenText(text="1", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(x, y), scale=.07) self.A = OnscreenText(text="A", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(-1.05, -0.5), scale=.07) self.B = OnscreenText(text="B", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(-0.75, -0.5), scale=.07) self.C = OnscreenText(text="C", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(-0.45, -0.5), scale=.07) self.D = OnscreenText(text="D", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(-0.15, -0.5), scale=.07) self.E = OnscreenText(text="E", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(0.15, -0.5), scale=.07) self.F = OnscreenText(text="F", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(0.45, -0.5), scale=.07) self.G = OnscreenText(text="G", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(0.75, -0.5), scale=.07) self.H = OnscreenText(text="H", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(1.05, -0.5), scale=.07) self.A.reparentTo(self.frame) self.B.reparentTo(self.frame) self.C.reparentTo(self.frame) self.D.reparentTo(self.frame) self.E.reparentTo(self.frame) self.F.reparentTo(self.frame) self.G.reparentTo(self.frame) self.H.reparentTo(self.frame) self.one.reparentTo(self.frame) self.two.reparentTo(self.frame) self.three.reparentTo(self.frame) self.four.reparentTo(self.frame) self.five.reparentTo(self.frame) self.six.reparentTo(self.frame) self.seven.reparentTo(self.frame) self.eight.reparentTo(self.frame) self.hide() # Start the task that handles the picking self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask') base.accept("mouse1", self.grabPiece) # left-click grabs a piece base.accept("mouse1-up", self.releasePiece) # releasing places it base.accept("escape", self.hide) def hide(self): self.frame.hide() self.dr2.setActive(False) self.A.hide() self.B.hide() self.C.hide() self.D.hide() self.E.hide() self.F.hide() self.G.hide() self.H.hide() self.one.hide() self.two.hide() self.three.hide() self.four.hide() self.five.hide() self.six.hide() self.seven.hide() self.eight.hide() base.accept("escape", self.menu.game.pauseGame) base.accept("mouse1", self.player.__setattr__, ["LeftButton", 1]) base.accept("mouse1-up", self.player.__setattr__, ["LeftButton", 0]) self.mission.resume() self.player.initTask() def show(self): self.frame.show() self.dr2.setActive(True) self.A.show() self.B.show() self.C.show() self.D.show() self.E.show() self.F.show() self.G.show() self.H.show() self.one.show() self.two.show() self.three.show() self.four.show() self.five.show() self.six.show() self.seven.show() self.eight.show() base.accept("escape", self.hide) # This function swaps the positions of two pieces def swapPieces(self, fr, to): temp = self.pieces[fr] self.pieces[fr] = self.pieces[to] self.pieces[to] = temp if self.pieces[fr]: self.pieces[fr].square = fr self.pieces[fr].obj.setPos(SquarePos(fr)) if self.pieces[to]: self.pieces[to].square = to self.pieces[to].obj.setPos(SquarePos(to)) def mouseTask(self, task): # This task deals with the highlighting and dragging based on the mouse # First, clear the current highlight if self.hiSq is not False: self.squares[self.hiSq].setColor(SquareColor(self.hiSq)) self.hiSq = False # Check to see if we can access the mouse. We need it to do anything # else if base.mouseWatcherNode.hasMouse(): # get the mouse position mpos = base.mouseWatcherNode.getMouse() # Set the position of the ray based on the mouse position self.pickerRay.setFromLens(self.camNode, mpos.getX(), mpos.getY()) # If we are dragging something, set the position of the object # to be at the appropriate point over the plane of the board if self.dragging is not False: # Gets the point described by pickerRay.getOrigin(), which is relative to # camera, relative instead to render # nearPoint = render.getRelativePoint( # camera, self.pickerRay.getOrigin()) nearPoint = render.getRelativePoint(self.cam2, self.pickerRay.getOrigin()) # Same thing with the direction of the ray # nearVec = render.getRelativeVector( # camera, self.pickerRay.getDirection()) nearVec = render.getRelativeVector( self.cam2, self.pickerRay.getDirection()) self.pieces[self.dragging].obj.setPos( PointAtZ(.5, nearPoint, nearVec)) # Do the actual collision pass (Do it only on the squares for # efficiency purposes) self.picker.traverse(self.squareRoot) if self.pq.getNumEntries() > 0: # if we have hit something, sort the hits so that the closest # is first, and highlight that node self.pq.sortEntries() i = int(self.pq.getEntry(0).getIntoNode().getTag('square')) # Set the highlight on the picked square self.squares[i].setColor(HIGHLIGHT) self.hiSq = i return Task.cont def grabPiece(self): # If a square is highlighted and it has a piece, set it to dragging # mode if self.hiSq is not False and self.pieces[self.hiSq]: self.dragging = self.hiSq self.hiSq = False def releasePiece(self): # Letting go of a piece. If we are not on a square, return it to its original # position. Otherwise, swap it with the piece in the new square # Make sure we really are dragging something if self.dragging is not False: # We have let go of the piece, but we are not on a square if self.hiSq is False: self.pieces[self.dragging].obj.setPos(SquarePos(self.dragging)) else: if self.state == 0: if self.dragging == 51 and self.hiSq == 58: self.swapPieces(self.dragging, self.hiSq) self.swapPieces(40, 32) self.state = self.state + 1 self.mission.manager.GoodsIta[ 'studydoor_box'].state = 'unlockedOpen' self.mission.manager.GoodsIta[ 'studydoor_box'].OpenDoor() self.menu.infoDialog.show() self.menu.infoLabel['text'] = '似乎传来咔嚓一声开锁的声音' self.mission.skip() self.hide() else: self.pieces[self.dragging].obj.setPos( SquarePos(self.dragging)) if self.dragging != self.hiSq: self.player.EROSION += 10 self.player.erosionUpdateTemp() elif self.state == 1: if self.dragging == 33 and self.hiSq == 18: self.swapPieces(self.dragging, self.hiSq) self.state = self.state + 1 self.mission.manager.GoodsIta[ 'chessdoor_box'].state = 'unlockedOpen' self.mission.manager.GoodsIta[ 'chessdoor_box'].OpenDoor() self.mission.menu.infoDialog.show() self.mission.menu.infoLabel['text'] = '棋盘上弹出一张纸条「pass。这又不是\n' \ '真的国际象棋,我选择PASS你又能怎样?\n' \ '你是无法将死我的。」' self.mission.skip() self.hide() else: self.pieces[self.dragging].obj.setPos( SquarePos(self.dragging)) if self.dragging != self.hiSq: self.player.EROSION += 10 self.player.erosionUpdateTemp() elif self.state == 2: if self.dragging == 20 and self.hiSq == 36: self.swapPieces(self.dragging, self.hiSq) self.state = self.state + 1 self.mission.manager.GoodsIta[ 'exit_box'].state = 'unlockedOpen' self.mission.menu.infoDialog.show() self.mission.menu.infoLabel[ 'text'] = '可恶 失策了……这里居然…还有一个城堡么…' self.mission.skip() if self.mission.hiddenState: self.mission.end('hiddenEnd') self.hide() else: self.pieces[self.dragging].obj.setPos( SquarePos(self.dragging)) if self.dragging != self.hiSq: self.player.EROSION += 10 self.player.erosionUpdateTemp() elif self.state == 3: self.pieces[self.dragging].obj.setPos( SquarePos(self.dragging)) # We are no longer dragging anything self.dragging = False def setupLights(self): # This function sets up some default lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.8, .8, .8, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(LVector3(0, 45, -45)) directionalLight.setColor((0.2, 0.2, 0.2, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight)) def initPos(self, state): if state == 0: self.pieces[40] = Queen(self, 40, WHITE) self.pieces[51] = Bishop(self, 51, PIECEBLACK) self.pieces[33] = Knight(self, 33, PIECEBLACK) self.pieces[9] = Rook(self, 9, PIECEBLACK) self.pieces[20] = Rook(self, 20, PIECEBLACK) elif state == 1: self.pieces[32] = Queen(self, 32, WHITE) self.pieces[58] = Bishop(self, 58, PIECEBLACK) self.pieces[33] = Knight(self, 33, PIECEBLACK) self.pieces[9] = Rook(self, 9, PIECEBLACK) self.pieces[20] = Rook(self, 20, PIECEBLACK) elif state == 2: self.pieces[32] = Queen(self, 32, WHITE) self.pieces[58] = Bishop(self, 58, PIECEBLACK) self.pieces[18] = Knight(self, 18, PIECEBLACK) self.pieces[9] = Rook(self, 9, PIECEBLACK) self.pieces[20] = Rook(self, 20, PIECEBLACK) elif state == 3: self.pieces[32] = Queen(self, 32, WHITE) self.pieces[58] = Bishop(self, 58, PIECEBLACK) self.pieces[18] = Knight(self, 18, PIECEBLACK) self.pieces[9] = Rook(self, 9, PIECEBLACK) self.pieces[36] = Rook(self, 36, PIECEBLACK)
class CogdoFlyingCameraManager: def __init__(self, cam, parent, player, level): self._toon = player.toon self._camera = cam self._parent = parent self._player = player self._level = level self._enabled = False def enable(self): if self._enabled: return self._toon.detachCamera() self._prevToonY = 0.0 levelBounds = self._level.getBounds() l = Globals.Camera.LevelBoundsFactor self._bounds = ((levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]), (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]), (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2])) self._lookAtZ = self._toon.getHeight( ) + Globals.Camera.LookAtToonHeightOffset self._camParent = NodePath('CamParent') self._camParent.reparentTo(self._parent) self._camParent.setPos(self._toon, 0, 0, 0) self._camParent.setHpr(180, Globals.Camera.Angle, 0) self._camera.reparentTo(self._camParent) self._camera.setPos(0, Globals.Camera.Distance, 0) self._camera.lookAt(self._toon, 0, 0, self._lookAtZ) self._cameraLookAtNP = NodePath('CameraLookAt') self._cameraLookAtNP.reparentTo(self._camera.getParent()) self._cameraLookAtNP.setPosHpr(self._camera.getPos(), self._camera.getHpr()) self._levelBounds = self._level.getBounds() self._enabled = True self._frozen = False self._initCollisions() def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode('CameraToonRay') camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask(OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath('trans') self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin('fixed', 10000) def _destroyCollisions(self): self._collTrav.removeCollider(self._camCollNP) self._camCollNP.removeNode() del self._camCollNP del self._camCollRay del self._collHandler del self._collOffset del self._betweenCamAndToon self._transNP.removeNode() del self._transNP def freeze(self): self._frozen = True def unfreeze(self): self._frozen = False def disable(self): if not self._enabled: return self._destroyCollisions() self._camera.wrtReparentTo(render) self._cameraLookAtNP.removeNode() del self._cameraLookAtNP self._camParent.removeNode() del self._camParent del self._prevToonY del self._lookAtZ del self._bounds del self._frozen self._enabled = False def update(self, dt=0.0): self._updateCam(dt) self._updateCollisions() def _updateCam(self, dt): toonPos = self._toon.getPos() camPos = self._camParent.getPos() x = camPos[0] z = camPos[2] toonWorldX = self._toon.getX(render) maxX = Globals.Camera.MaxSpinX toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX) spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / ( maxX * maxX) newH = 180.0 + spinAngle self._camParent.setH(newH) spinAngle = spinAngle * (pi / 180.0) distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle) distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle) d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0]) if abs(d) > Globals.Camera.LeewayX: if d > Globals.Camera.LeewayX: x = toonPos[0] + Globals.Camera.LeewayX else: x = toonPos[0] - Globals.Camera.LeewayX x = self._toon.getX(render) + distToRightOfToon boundToonZ = min(toonPos[2], self._bounds[2][1]) d = z - boundToonZ if d > Globals.Camera.MinLeewayZ: if self._player.velocity[2] >= 0 and toonPos[ 1] != self._prevToonY or self._player.velocity[2] > 0: z = boundToonZ + d * INVERSE_E**(dt * Globals.Camera.CatchUpRateZ) elif d > Globals.Camera.MaxLeewayZ: z = boundToonZ + Globals.Camera.MaxLeewayZ elif d < -Globals.Camera.MinLeewayZ: z = boundToonZ - Globals.Camera.MinLeewayZ if self._frozen: y = camPos[1] else: y = self._toon.getY(render) - distBehindToon self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z)) if toonPos[2] < self._bounds[2][1]: h = self._cameraLookAtNP.getH() if d >= Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ) elif d <= -Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._camParent, 0, 0, self._lookAtZ) self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0) self._camera.setHpr( smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr())) self._prevToonY = toonPos[1] def _updateCollisions(self): pos = self._toon.getPos(self._camera) + self._collOffset self._camCollRay.setOrigin(pos) direction = -Vec3(pos) direction.normalize() self._camCollRay.setDirection(direction) self._collTrav.traverse(render) nodesInBetween = {} if self._collHandler.getNumEntries() > 0: self._collHandler.sortEntries() for entry in self._collHandler.getEntries(): name = entry.getIntoNode().getName() if name.find('col_') >= 0: np = entry.getIntoNodePath().getParent() if np not in nodesInBetween: nodesInBetween[np] = np.getParent() for np in nodesInBetween.keys(): if np in self._betweenCamAndToon: del self._betweenCamAndToon[np] else: np.setTransparency(True) np.wrtReparentTo(self._transNP) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').hide() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').hide() for np, parent in self._betweenCamAndToon.items(): np.wrtReparentTo(parent) np.setTransparency(False) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').show() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').show() self._betweenCamAndToon = nodesInBetween
class p3dApp(ShowBase): def __init__(self): ShowBase.__init__(self); # setup the environment or model self.model = \ self.loader.loadModel("/usr/share/panda3d/models/box"); self.model.reparentTo(self.render); self.model.setTag('Model', '1'); self.model.setScale(1.5, 1.5, 1.5); # setup camera self.camera.setPos(5,5,5) self.camera.lookAt(0,0,0) # Disable mouse control self.disableMouse(); # Handle mouse events. self.accept('mouse1', self.mouse_down); # convert image from opencv to panda3d texture # self.taskMgr.add(self.read_image_cv, "cvImageTask"); # Setup collision handler self.handler = CollisionHandlerQueue() self.traverser = CollisionTraverser('ColTraverser') self.traverser.traverse(self.model) self.ray = CollisionRay() pickerNode = CollisionNode('MouseRay') pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) pickerNP = self.camera.attachNewNode(pickerNode) pickerNode.addSolid(self.ray) self.traverser.addCollider(pickerNP, self.handler) self.load_shader(); self.first_frame_loaded = False; def read_image_cv(self): """ Pulls the next frame from the opencv part, and converts to a panda3d texture and display it on the screen. """ cvim = self.cvapp.pull_frame() w = cvim.shape[1]; h = cvim.shape[0]; cvim = cv2.flip(cvim, 0); self.im = Texture("cvIm"); self.im.setCompression(Texture.CMOff); self.im.setup2dTexture(w, h, Texture.TUnsignedByte, Texture.FLuminance); self.im.setRamImage(cvim); self.screen_im = OnscreenImage(parent=self.render2d, image=self.im, scale=(1, 1, 1), pos=(0, 0, 0)); self.cam2d.node().getDisplayRegion(0).setSort(-20); def load_shader(self): """ The function loads the vertex and fragment shader. It provides an example of sending the model-view-projection matrix to the shader program when it's calculated. """ self.shader = Shader.load(Shader.SL_GLSL, "vertex.glsl", "fragment.glsl"); self.model.set_shader(self.shader) self.model.set_shader_input("my_ModelViewProjectionMatrix", LMatrix4f()) def mouse_down(self): """ This function is called as a result of a mouse click. It gets the vertex that was clicked by the mouse. It sends the mouse position and the vertex position to the cv app. """ if (self.first_frame_loaded == False): self.first_frame_loaded = True self.read_image_cv() return; xPos = self.mouseWatcherNode.getMouseX() yPos = self.mouseWatcherNode.getMouseY() self.ray.setFromLens(self.camNode, xPos, yPos) self.traverser.traverse(self.model) self.handler.sortEntries() if (self.handler.getNumEntries() > 0): entry = self.handler.getEntry(0) # CollisionEntry vpos = entry.getSurfacePoint(self.model) res = self.cvapp.mouse_clicked(LPoint3f(xPos, yPos), vpos) if (res == 1): self.read_image_cv() def set_cv_app(self, cvapp): self.cvapp = cvapp;
class DistributedLevel(DistributedObject): """ An instance of these is created and placed in the middle of the zone. It serves to illustrate the creation of AI-side objects to populate the world, and a general mechanism for making them react to the avatars. """ def __init__(self, cr): DistributedObject.__init__(self, cr) #self.model = loader.loadModel('environment') #self.model.setZ(0) #self.builder = Builder(self, "map.txt", "development") plane = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0))) cnode = CollisionNode('cnode') cnode.setIntoCollideMask(BitMask32.bit(1)) cnode.setFromCollideMask(BitMask32.bit(1)) cnode.addSolid(plane) self.planeNP = self.model.attachNewNode(cnode) self.planeNP.show() # Setup a traverser for the picking collisions self.picker = CollisionTraverser() # Setup mouse ray self.pq = CollisionHandlerQueue() # Create a collision Node pickerNode = CollisionNode('MouseRay') # set the nodes collision bitmask pickerNode.setFromCollideMask(BitMask32.bit(1)) # create a collision ray self.pickerRay = CollisionRay() # add the ray as a solid to the picker node pickerNode.addSolid(self.pickerRay) # create a nodepath with the camera to the picker node self.pickerNP = base.camera.attachNewNode(pickerNode) # add the nodepath to the base traverser self.picker.addCollider(self.pickerNP, self.pq) print "model loaded" #TODO: check how to load multiple levels and set players in specific levels! self.accept("mouse1", self.mouseClick) def announceGenerate(self): """ This method is called after generate(), after all of the required fields have been filled in. At the time of this call, the distributed object is ready for use. """ DistributedObject.announceGenerate(self) # Now that the object has been fully manifested, we can parent # it into the scene. print "render the model" self.model.reparentTo(render) def disable(self): # Take it out of the scene graph. self.detachNode() DistributedObject.disable(self) def checkMousePos(self, mpos, camPos, camHpr): lens = LenseNode.copyLens(base.camNode) lens.setPos(camPos) lens.setHpr(camHpr) help(mpos) mpos = Point2(mpos.x, mpos.y) pos = self.getClickPosition(mpos, lens) print "mouse clicked at:", pos def mouseClick(self): """Send an event to the server that will check where the mouse will hit and what action needs to be done""" hitPos = (0, 0, 0) # check if we have a mouse on the window if base.mouseWatcherNode.hasMouse(): # get the mouse position on the screen mpos = base.mouseWatcherNode.getMouse() print mpos # set the ray's position self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) # Now call the traverse function to let the traverser check for collisions # with the added colliders and the levelNP self.picker.traverse(self.planeNP) # check if we have a collision if self.pq.getNumEntries() > 0: # sort the entries to get the closest first self.pq.sortEntries() # This is the point at where the mouse ray and the level plane intersect hitPos = self.pq.getEntry(0).getSurfacePoint(render) base.messenger.send("clickPosition", [hitPos])
class Projectile(NetEnt): def __init__(self, parent=None, pitch=None, id=None): NetEnt.__init__(self, id) self.node = NetNodePath(PandaNode('projectile')) if parent: self.parent = parent self.node.setPos(parent.node.getPos() + (0, 0, 1)) self.node.setHpr(parent.node.getHpr()) self.node.setP(pitch) self.node.reparentTo(render) ProjectilePool.add(self) #print 'there are',len(ProjectilePool.values()),'projectiles' self.flyTime = 0 self.sprite = Sprite2d('resources/missile.png', rows=3, cols=1, rowPerFace=(0, 1, 2, 1), anchorY=Sprite2d.ALIGN_CENTER) self.sprite.node.reparentTo(self.node) # set up 'from' collisions - for detecting projectile hitting things self.collisionHandler = CollisionHandlerQueue() self.fromCollider = self.node.attachNewNode( CollisionNode('fromCollider')) self.fromCollider.node().addSolid(CollisionRay(0, 0, 0, 0, 1, 0)) self.fromCollider.node().setIntoCollideMask(BITMASK_EMPTY) self.fromCollider.node().setFromCollideMask(BITMASK_TERRAIN | BITMASK_CHARACTER) if SHOW_COLLISIONS: self.fromCollider.show() Character.collisionTraverser.addCollider(self.fromCollider, self.collisionHandler) def getState(self): dataDict = NetObj.getState(self) dataDict[0] = self.node.getState() return dataDict def setState(self, weightOld, dataDictOld, weightNew, dataDictNew): oldNode = None if not dataDictOld else dataDictOld.get(0, None) self.node.setState(weightOld, oldNode, weightNew, dataDictNew[0]) def movePostCollide(self, deltaT): desiredDistance = 30 * deltaT self.collisionHandler.sortEntries() ch = self.collisionHandler for e in [ch.getEntry(i) for i in range(ch.getNumEntries())]: collisionDist = (self.node.getPos() - e.getSurfacePoint(render)).length() if collisionDist > desiredDistance: break # only accept collisions that aren't with parent if e.getIntoNode().getParent(0).getTag('ID') != str( self.parent.id): return False self.node.setY(self.node, desiredDistance) self.flyTime += deltaT return self.flyTime < 4 def __del__(self): #print 'PROJECTILE BEING REMOVED' self.node.removeNode()
class GameEngine( DirectObject ): def __init__(self): print 'Game Engine Started' self.lastBlock = 0 self.map = [] self.startBlock = 0 self.endBlock = 0 self.mapName = 'test2' self.loadEnvironment(self.mapName) self.loadCursorPicker() self.camera = RTS_Camera() self.loadSimpleLighting() self.waveController = WaveController(self.mapName, self.startBlock, self.map) self.towerController = TowerController(self.waveController) self.setupKeyListeners() self.EFT = taskMgr.add(self.everyFrameTask, "everyFrameTask") # The task that is run every frame def everyFrameTask(self, task): self.camera.handleMouseInput() self.checkCursorCollision() self.towerController.updateTowers() return task.cont # Loads the level from the text file. Puts each # row into an array then creates the rows in the # 1st quadrant def loadEnvironment(self, file): fileName = 'maps/' + file + '.map' rows = [] self.environmentRoot = render.attachNewNode('environmentRoot') FILE = open(fileName, 'r') while( 1 ): line = FILE.readline() if( not line ): break print line, if( line[-1] == '\n' ): line = line[:-1] rows.append(line) rows.reverse() for i, row in enumerate(rows): self.createRow( i, row ) # Loads the models corresponding to the # characters in the map file for an entire row def createRow(self, rowIndex, row): mapRow = [] for colIndex, block in enumerate(row): block = BLOCK_CHAR_TO_MODEL[block]( self.environmentRoot, colIndex + 0.5, rowIndex + 0.5 ) mapRow.append( block ) block.setIndex( str(rowIndex) + ' ' + str(colIndex) ) if( block.isType(StartBlock) ): self.startBlock = block elif( block.isType(EndBlock) ): self.endBlock = block self.map.append(mapRow) # Creates necessary collision parts to determine what object # the cursor is hovering def loadCursorPicker(self): self.picker = CollisionTraverser() self.pq = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.picker.addCollider(self.pickerNP, self.pq) def checkCursorCollision(self): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens( base.camNode, mpos.getX(), mpos.getY() ) self.picker.traverse( self.environmentRoot ) if( self.pq.getNumEntries() > 0 ): self.pq.sortEntries() (row, ignore, col) = self.pq.getEntry(0).getIntoNode().getTag('index').partition(' ') row = int(row) col = int(col) block = self.map[row][col] if( block != self.lastBlock ): block.highlight() if( self.lastBlock ): self.lastBlock.unHighlight() self.lastBlock = block else: if( self.lastBlock ): self.lastBlock.unHighlight() self.lastBlock = 0 def mouseClick(self): if( self.lastBlock ): self.towerController.addTower(self.lastBlock) def spawnEnemy(self): e = Enemy(self.startBlock, self.map) e.moveToEnd() def setTowerType(self, type): self.towerController.currentTowerType = type def setupKeyListeners(self): self.accept('mouse1', self.mouseClick) self.accept('q', self.waveController.start) self.accept('1', self.setTowerType, [NormalTower]) self.accept('2', self.setTowerType, [SlowTower]) self.accept('3', self.setTowerType, [StunTower]) def loadSimpleLighting(self): ambientLight = AmbientLight( "ambientLight" ) ambientLight.setColor( Vec4(.8, .8, .8, 1) ) directionalLight = DirectionalLight( "directionalLight" ) directionalLight.setDirection( Vec3( 0, 45, -45 ) ) directionalLight.setColor( Vec4( 0.2, 0.2, 0.2, 0.6 ) ) render.setLight(render.attachNewNode( directionalLight ) ) render.setLight(render.attachNewNode( ambientLight ) )
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) # Create a traverser and a handler self.cTrav = CollisionTraverser() self.cQueue = CollisionHandlerQueue() # Create the collision node that will store the collision # ray solid self.pickerNode = CollisionNode('mouseRay') # Set bitmask for efficiency, only hit from objects with same mask self.pickerNode.setFromCollideMask(BitMask32.bit(1)) # Attach collision node to camera, since that is the source self.pickerNP = camera.attachNewNode(self.pickerNode) # Add collision solid(ray) to collision node self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) # Add collidable node(pickerNP) to the traverser # Collisions detected when traversed will go to cQueue self.cTrav.addCollider(self.pickerNP, self.cQueue) # Create visible sphere self.tmpSphere = self.loader.loadModel("models/misc/sphere") self.tmpSphere.reparentTo(self.render) self.tmpSphere.setColor(1, 1, 1, 1) self.tmpSphere.setPos(0, 100, 0) # Create collision sphere and attach to tmpSphere cSphere = CollisionSphere(0, 0, 0, 3) cnodePath = self.tmpSphere.attachNewNode(CollisionNode('cnode')) # Add collision solid(sphere) to collision node # Because tmpSphere/cSphere is child of render, which we traverse # later, it becomes a from collider automatically, we don't # need to addCollider since that is only for from collision nodes cnodePath.node().addSolid(cSphere) # Set bitmask to match the from collisionnode mask for efficiency cnodePath.setCollideMask(BitMask32.bit(1)) # Show the collision sphere visibly, for debugging. cnodePath.show() # Set a custom tag on the collision node which becomes available # inside the collision event stored in the collision handler cnodePath.setTag('someTag', '1') # Add task to run every frame - set collision solid(ray) # to start at the current camera position, self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask') def mouseTask(self, task): if self.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() # Set collision ray to start at camera lens and endpoint at mouse self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) # Perform the collision traverse - follows the ray and logs # all collisions to the handler set earlier self.cTrav.traverse(self.render) # Get info from entries and use them if self.cQueue.getNumEntries() > 0: self.cQueue.sortEntries() print("Collision!") entry = self.cQueue.getEntry(0) print(entry) someTag = int(entry.getIntoNode().getTag('someTag')) print(someTag) # Collision detected, mouse must be over sphere self.tmpSphere.setColor(0, 1, 0, 1) else: # No collisions, mouse is not over sphere, unset color # Not ideal to "unset" the color each frame self.tmpSphere.setColor(1, 1, 1, 1) return task.cont
class Mouse(): def __init__(self): self.enabled = False self.locked = False self.position = Vec3(0, 0, 0) self.delta = Vec3(0, 0, 0) self.prev_x = 0 self.prev_y = 0 self.start_x = 0 self.start_y = 0 self.velocity = Vec3(0, 0, 0) self.prev_click_time = time.time() self.double_click_distance = .5 self.hovered_entity = None self.left = False self.right = False self.middle = False self.delta_drag = Vec3(0, 0, 0) self.update_step = 1 self.traverse_target = scene self._i = 0 self._mouse_watcher = None self._picker = CollisionTraverser() # Make a traverser self._pq = CollisionHandlerQueue() # Make a handler self._pickerNode = CollisionNode('mouseRay') self._pickerNP = camera.attach_new_node(self._pickerNode) self._pickerRay = CollisionRay() # Make our ray self._pickerNode.addSolid(self._pickerRay) self._picker.addCollider(self._pickerNP, self._pq) self._pickerNode.set_into_collide_mask(0) self.raycast = True self.collision = None self.collisions = list() self.enabled = True @property def x(self): if not self._mouse_watcher.has_mouse(): return 0 return self._mouse_watcher.getMouseX( ) / 2 * window.aspect_ratio # same space as ui stuff @x.setter def x(self, value): self.position = (value, self.y) @property def y(self): if not self._mouse_watcher.has_mouse(): return 0 return self._mouse_watcher.getMouseY() / 2 @y.setter def y(self, value): self.position = (self.x, value) @property def position(self): return Vec3(self.x, self.y, 0) @position.setter def position(self, value): base.win.move_pointer( 0, round(value[0] + (window.size[0] / 2) + (value[0] / 2 * window.size[0]) * 1.124), # no idea why I have * with 1.124 round(value[1] + (window.size[1] / 2) - (value[1] * window.size[1])), ) def __setattr__(self, name, value): if name == 'visible': window.set_cursor_hidden(not value) application.base.win.requestProperties(window) if name == 'locked': try: object.__setattr__(self, name, value) window.set_cursor_hidden(value) if value: window.set_mouse_mode(window.M_relative) else: window.set_mouse_mode(window.M_absolute) application.base.win.requestProperties(window) except: pass try: super().__setattr__(name, value) # return except: pass def input(self, key): if not self.enabled: return if key.endswith('mouse down'): self.start_x = self.x self.start_y = self.y elif key.endswith('mouse up'): self.delta_drag = Vec3(self.x - self.start_x, self.y - self.start_y, 0) if key == 'left mouse down': self.left = True if self.hovered_entity: if hasattr(self.hovered_entity, 'on_click'): self.hovered_entity.on_click() for s in self.hovered_entity.scripts: if hasattr(s, 'on_click'): s.on_click() # double click if time.time( ) - self.prev_click_time <= self.double_click_distance: base.input('double click') if self.hovered_entity: if hasattr(self.hovered_entity, 'on_double_click'): self.hovered_entity.on_double_click() for s in self.hovered_entity.scripts: if hasattr(s, 'on_double_click'): s.on_double_click() self.prev_click_time = time.time() if key == 'left mouse up': self.left = False if key == 'right mouse down': self.right = True if key == 'right mouse up': self.right = False if key == 'middle mouse down': self.middle = True if key == 'middle mouse up': self.middle = False def update(self): if not self.enabled or not self._mouse_watcher.has_mouse(): self.velocity = Vec3(0, 0, 0) return self.moving = self.x + self.y != self.prev_x + self.prev_y if self.moving: if self.locked: self.velocity = self.position self.position = (0, 0) else: self.velocity = Vec3(self.x - self.prev_x, (self.y - self.prev_y) / window.aspect_ratio, 0) else: self.velocity = Vec3(0, 0, 0) if self.left or self.right or self.middle: self.delta = Vec3(self.x - self.start_x, self.y - self.start_y, 0) self.prev_x = self.x self.prev_y = self.y self._i += 1 if self._i < self.update_step: return # collide with ui self._pickerNP.reparent_to(scene.ui_camera) self._pickerRay.set_from_lens(camera._ui_lens_node, self.x * 2 / window.aspect_ratio, self.y * 2) self._picker.traverse(camera.ui) if self._pq.get_num_entries() > 0: # print('collided with ui', self._pq.getNumEntries()) self.find_collision() return # collide with world self._pickerNP.reparent_to(camera) self._pickerRay.set_from_lens(scene.camera.lens_node, self.x * 2 / window.aspect_ratio, self.y * 2) try: self._picker.traverse(self.traverse_target) except: # print('error: mouse._picker could not traverse', self.traverse_target) return if self._pq.get_num_entries() > 0: self.find_collision() else: # print('mouse miss', base.render) # unhover all if it didn't hit anything for entity in scene.entities: if hasattr(entity, 'hovered') and entity.hovered: entity.hovered = False self.hovered_entity = None if hasattr(entity, 'on_mouse_exit'): entity.on_mouse_exit() for s in entity.scripts: if hasattr(s, 'on_mouse_exit'): s.on_mouse_exit() @property def normal(self): if not self.collision: return None return self.collision.normal @property def world_normal(self): if not self.collision: return None return self.collision.world_normal @property def point(self): if self.collision: return self.collision.point return None @property def world_point(self): if self.collision: return self.collision.world_point return None def find_collision(self): self.collisions = list() self.collision = None if not self.raycast or self._pq.get_num_entries() == 0: self.unhover_everything_not_hit() return False self._pq.sortEntries() for entry in self._pq.getEntries(): for entity in scene.entities: if entry.getIntoNodePath( ).parent == entity and entity.collision: if entity.collision: hit = HitInfo( hit=entry.collided(), entity=entity, distance=distance(entry.getSurfacePoint(scene), camera.getPos()), point=entry.getSurfacePoint(entity), world_point=entry.getSurfacePoint(scene), normal=entry.getSurfaceNormal(entity), world_normal=entry.getSurfaceNormal(scene), ) self.collisions.append(hit) break if self.collisions: self.collision = self.collisions[0] self.hovered_entity = self.collision.entity if not self.hovered_entity.hovered: self.hovered_entity.hovered = True if hasattr(self.hovered_entity, 'on_mouse_enter'): self.hovered_entity.on_mouse_enter() for s in self.hovered_entity.scripts: if hasattr(s, 'on_mouse_enter'): s.on_mouse_enter() self.unhover_everything_not_hit() def unhover_everything_not_hit(self): for e in scene.entities: if e == self.hovered_entity: continue if e.hovered: e.hovered = False if hasattr(e, 'on_mouse_exit'): e.on_mouse_exit() for s in e.scripts: if hasattr(s, 'on_mouse_exit'): s.on_mouse_exit()
class Life(ShowBase): def __init__(self): ShowBase.__init__(self) base.disableMouse() base.setFrameRateMeter(True) mydir = os.path.abspath(sys.path[0]) mydir = Filename.fromOsSpecific(mydir).getFullpath() self.bgmusic = self.loader.loadMusic(mydir + '/../sounds/bgmusic.ogg') self.bgmusic.play() # Setup collision for 3d picking self.picker = CollisionTraverser() self.pq = CollisionHandlerQueue() # Make a collision node for our picker ray self.pickerNode = CollisionNode('mouseRay') # Attach that node to the camera since the ray will need to be positioned # relative to it self.pickerNP = camera.attachNewNode(self.pickerNode) # Everything to be picked will use bit 1. This way if we were doing other # collision we could separate it self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) # Register the ray as something that can cause collisions self.picker.addCollider(self.pickerNP, self.pq) #self.picker.showCollisions(render) # Configure boxes and textures self.box = [[None for x in range(CELL_WIDTH)] for x in range(CELL_HEIGHT)] self.textureempty = self.loader.loadTexture(mydir + '/../textures/box.png') self.texturefull = self.loader.loadTexture(mydir + '/../textures/boxfull.png') self.textureempty.setMagfilter(Texture.FTLinear) self.textureempty.setMinfilter(Texture.FTLinearMipmapLinear) self.texturefull.setMagfilter(Texture.FTLinear) self.texturefull.setMinfilter(Texture.FTLinearMipmapLinear) self.worldnode = render.attachNewNode('worldnode') self.boxnode = self.worldnode.attachNewNode('boxnode') self.worldnode.setPos(0, 200, 0) for row in range(CELL_HEIGHT): for col in range(CELL_WIDTH): box = self.loader.loadModel(mydir + '/../models/cube') box.reparentTo(self.boxnode) box.setPos((CELL_WIDTH * -1) + (col * 2), 0, CELL_HEIGHT - (row * 2)) box.setTexture(self.textureempty) # Cube is the name of the polygon set in blender box.find("**/Cube").node().setIntoCollideMask(BitMask32.bit(1)) box.find("**/Cube").node().setTag('square', str(row) + '-' + str(col)) self.box[row][col] = box # Configure cell data self.cells = [[0 for x in range(CELL_WIDTH)] for x in range(CELL_HEIGHT)] self.cells[3][6] = 1 self.cells[4][7] = 1 self.cells[5][5] = 1 self.cells[5][6] = 1 self.cells[5][7] = 1 self.editmode = False taskMgr.add(self.start, 'start') # Setup initial event handling self.accept('escape', sys.exit) self.accept('enter', self.startgame) self.accept('mouse1', self.startgame) # Prep the main screen self.boxnode.setPosHpr(self.worldnode, -5, -160, 0, 60, -25, 0) self.readyText = OnscreenText(text='Life', pos=(0.91, 0.7), scale=0.2, fg=(255, 255, 255, 255), shadow=(0, 0, 0, 100)) def mouserotation(self, task): if not self.editmode and base.mouseWatcherNode.hasMouse(): self.boxnode.setH(self.worldnode, base.mouseWatcherNode.getMouseX() * 60) self.boxnode.setP(self.worldnode, -base.mouseWatcherNode.getMouseY() * 60) return task.cont def startgame(self): # Transition to the game start state taskMgr.add(self.transition, 'transition') interval = LerpPosHprInterval(self.boxnode, TRANSITIONPERIOD, Point3(0, 0, 0), Point3(0, 0, 0), other=self.worldnode, blendType='easeInOut') interval.start() def transition(self, task): self.ignore('enter') self.ignore('mouse1') self.readyText.setFg((255, 255, 255, (max(0, TRANSITIONPERIOD - task.time) / TRANSITIONPERIOD))) self.readyText.setShadow((0, 0, 0, (max(0, TRANSITIONPERIOD - task.time) / TRANSITIONPERIOD))) if task.time > TRANSITIONPERIOD: self.accept('enter', self.handleenter) self.accept('mouse1', self.selectpiece) taskMgr.add(self.mouserotation, 'mouserotation') return task.done else: return task.cont def selectpiece(self): if self.editmode: mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) #Do the actual collision pass (Do it only on the squares for #efficiency purposes) self.picker.traverse(self.boxnode) if self.pq.getNumEntries() > 0: # If we have hit something, sort the hits so that the closest # is first, and highlight that node self.pq.sortEntries() tag = self.pq.getEntry(0).getIntoNode().getTag('square') tagsplit = tag.split('-') row = int(tagsplit[0]) col = int(tagsplit[1]) # Set the highlight on the picked square self.cells[row][col] = (0 if self.cells[row][col] == 1 else 1) def start(self, task): if not self.editmode: self.processcells(self.cells) for row in range(CELL_HEIGHT): for col in range(CELL_WIDTH): if self.cells[row][col] == 1: self.box[row][col].setTexture(self.texturefull) else: self.box[row][col].setTexture(self.textureempty) return task.cont def handleenter(self): self.editmode = not self.editmode @staticmethod def countsiblingcells(cells, x, y): return cells[y - 1][x - 1] + \ cells[y][x - 1] + \ cells[(y + 1) % CELL_HEIGHT][x - 1] + \ cells[y - 1][x] + \ cells[(y + 1) % CELL_HEIGHT][x] + \ cells[y - 1][(x + 1) % CELL_WIDTH] + \ cells[y][(x + 1) % CELL_WIDTH] + \ cells[(y + 1) % CELL_HEIGHT][(x + 1) % CELL_WIDTH] def processcells(self, cells): newcells = copy.deepcopy(cells) for row in range(CELL_HEIGHT): for col in range(CELL_WIDTH): neighbours = self.countsiblingcells(newcells, col, row) if newcells[row][col] == 1: if neighbours < 2: cells[row][col] = 0 elif 2 <= neighbours <= 3: pass elif neighbours > 3: cells[row][col] = 0 else: if neighbours == 3: cells[row][col] = 1
class Grabber(object): def __init__( self, levitNP): """ A widget to position, rotate, and scale Panda 3D Models and Actors * handleM1 decides what to do with a mouse1 click -- object selection by calling handleSelection when the grabModel is inactive (hidden) -- object manipulation by calling handleManipulationSetup (sets the stage for and launches the dragTask) isHidden() when nothing is selected isDragging means not running collision checks for selection setup and LMB is pressed call handleM1 from another class to push control up in the program hierarchy (remove inner class calls) """ # TODO remove selection functionality from grabber and put it in a selector class self.levitorNP = levitNP # TODO remove this and use barebonesNP self.selected = None self.initialize() def initialize(self): """Reset everything except LevitorNP and selected, also called inside __init__""" self.notify = DirectNotify().newCategory('grabberErr') self.currPlaneColNorm = Vec3(0.0) self.isCameraControlOn = False self.isDragging = False self.isMultiselect = False self.grabScaleFactor = .075 self.currTransformDir = Point3(0.0) self.interFrameMousePosition = Point3(0.0) self.init3DemVal = Point3(0.0) # initCommVal holds the value before a command operation has taken place self.initialCommandTrgVal = None # To load the grabber model, this climbs up the absolute path to /barebones/ to gain access to the model folder self.grabModelNP = loader.loadModel(Filename.fromOsSpecific( ntpath.split( ntpath.split(inspect.stack()[0][1])[0] )[0]) + '/EditorModels/widget') self.grabModelNP.setPos(0.0, 0.0, 0.0) self.grabModelNP.setBin("fixed", 40) self.grabModelNP.setDepthTest(False) self.grabModelNP.setDepthWrite(False) self.transformOpEnum = Enum('rot, scale, trans') self.currTransformOperation = None # TODO For readability, use this enum in the nested if/else as was the original intent. self.grabInd = Enum('xRot, yRot, zRot, xScaler, yScaler, zScaler, xTrans, yTrans, zTrans, xyTrans, xzTrans, zyTrans, grabCore') grbrNodLst = [self.grabModelNP.find("**/XRotator;+h-s-i"), # 0 self.grabModelNP.find("**/YRotator;+h-s-i"), # 1 self.grabModelNP.find("**/ZRotator;+h-s-i"), # 2 end rotate self.grabModelNP.find("**/XScaler;+h-s-i"), # 3 self.grabModelNP.find("**/YScaler;+h-s-i"), # 4 self.grabModelNP.find("**/ZScaler;+h-s-i"), # 5 end scale self.grabModelNP.find("**/XTranslator;+h-s-i"), # 6 self.grabModelNP.find("**/YTranslator;+h-s-i"), # 7 self.grabModelNP.find("**/ZTranslator;+h-s-i"), # 8 end translate / end single dir operations self.grabModelNP.find("**/XYTranslator;+h-s-i"), # 9 self.grabModelNP.find("**/XZTranslator;+h-s-i"), # 10 self.grabModelNP.find("**/ZYTranslator;+h-s-i"), # 11 end bi-directional operations self.grabModelNP.find("**/WidgetCore;+h-s-i")] # 12 #Mat4.yToZUpMat() # change coordinate to z up grbrNodLst[12].getParent().setHprScale(0, 0, 0, 1, 1, -1) self.grabModelNP.setPythonTag('grabberRoot', grbrNodLst) self.grabModelNP.reparentTo(BBGlobalVars.bareBonesObj.levitorNP) self.grabModelNP.hide() #self.grabIntoBitMask = COLLISIONMASKS self.grabModelNP.setCollideMask(COLLISIONMASKS['default']) self.grabModelNP.setPythonTag('grabber', self) ############################################################################## # This whole section is the basics for setting up mouse selection # --The mouse events are added in the events section (next) # Create the collision node for the picker ray to add traverser as a 'from' collider self.grabberColNode = CollisionNode('grabberMouseRay') # Set the collision bitmask # TODO: define collision bitmask (let user define thiers? likely not) self.defaultBitMask = GeomNode.getDefaultCollideMask() self.grabberColNode.setFromCollideMask(self.defaultBitMask) self.grabberRayColNP = camera.attachNewNode(self.grabberColNode) # Create the grabberRay and add it to the picker CollisionNode self.grabberRay = CollisionRay(0.0, 0.0, 0.0, 0.0, 1.0, 0.0) self.grabberRayNP = self.grabberColNode.addSolid(self.grabberRay) # create a collision queue for the traverser self.colHandlerQueue = CollisionHandlerQueue() # Create collision traverser self.colTraverser = CollisionTraverser('grabberTraverser') # Set the collision traverser's 'fromObj' and handler # e.g. trav.addCollider( fromObj, handler ) self.colTraverser.addCollider(self.grabberRayColNP, self.colHandlerQueue) ############################################################ # setup event handling with the messenger # URGENT remove all of this messenger code throughout Grabber, especially the camera control # disable the mouse when the ~ is pressed (w/o shift) self.disableCamera() # disable camera control by the mouse messenger.accept('`', self, self.enableCamera) # enable camera control when the ~ key is pressed w/o shift messenger.accept('`-up', self, self.disableCamera) # disable camera control when the ~ key is released # handle mouse selection/deselection & manipulating the scene messenger.accept('mouse1', self, self.handleM1, persistent=1) # deselect in event handler taskMgr.add(self.scaleGrabber, 'scaleGrabber') # //////////////////////////////////////////////////////////////////// # comment out: good for debug info #taskMgr.add(self.watchMouseColl, name='grabberDebug') #this is only good for seeing types and hierarchy #self.grabModelNP.ls() #render.ls() # self.frames = 0 #remove # self.axis = loader.loadModel("zup-axis") # self.axis.reparentTo(self.grabModelNP) # self.axis.setScale(.15) # self.axis.setPos(0.0) # self.grabModelNP.append( 'newAttrib', self) # setattr( self.grabModelNP, 'newAttrib', self) def prepareForPickle(self): self.colTraverser = None # Traversers are not picklable self.defaultBitMask = None # BitMasks "..." # self.grabIntoBitMask = None # "..." self.colHandlerQueue = None # CollisonHandlerQueue "..." self.grabModelNP.removeNode() self.grabModelNP = None taskMgr.remove('scaleGrabber') def recoverFromPickle(self): self.initialize() if self.selected is not None: self.grabModelNP.setPos(render, self.selected.getPos(render)) self.grabModelNP.show() print "grabber sel ", self.selected, " isHidden() ", self.grabModelNP.isHidden(), '\n' taskMgr.add(self.scaleGrabber, 'scaleGrabber') #### May use to gain control over pickling. # def __repr__(self): # for pickling purposes # if self.colTraverser: # self.colTraverser = None # # dictrepr = dict.__repr__(self.__dict__) # dictrepr = '%r(%r)' % (type(self).__name__, dictrepr) # print dictrepr # REMOVE # return dictrepr def watchMouseColl(self, task): """ This exists for debugging purposes to perpetually watch mouse collisions. """ # TODO make this highlight objects under the mouse for predictable object selection/grabber operations self.colTraverser.showCollisions(render) if base.mouseWatcherNode.hasMouse() and False == self.isCameraControlOn: # This gives the screen coordinates of the mouse. mPos = base.mouseWatcherNode.getMouse() # This makes the ray's origin the camera and makes the ray point # to the screen coordinates of the mouse. self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY()) # traverses the graph for collisions self.colTraverser.traverse(render) return task.cont def scaleGrabber(self, task): if self.grabModelNP.isHidden(): return task.cont coreLst = self.grabModelNP.getPythonTag('grabberRoot') camPos = self.grabModelNP.getRelativePoint(self.grabModelNP, camera.getPos()) if camPos.z >= 0: # 1-4 if camPos.x > 0.0 <= camPos.y: # quad 1 coreLst[12].getParent().setScale( 1, 1, -1) elif camPos.x < 0.0 <= camPos.y: # quad 2 coreLst[12].getParent().setScale( -1, 1, -1) elif camPos.x < 0.0 >= camPos.y: # quad 3 coreLst[12].getParent().setScale( -1, -1, -1) elif camPos.x > 0.0 >= camPos.y: # quad 4 coreLst[12].getParent().setScale( 1, -1, -1) else: self.notify.warning("if-else default, scaleGrabber cam.z > 0") else: # 5-8 if camPos.x > 0.0 <= camPos.y: # quad 5 coreLst[12].getParent().setScale( 1, 1, 1) elif camPos.x < 0.0 <= camPos.y: # quad 6 coreLst[12].getParent().setScale( -1, 1, 1) elif camPos.x < 0.0 >= camPos.y: # quad 7 coreLst[12].getParent().setScale( -1, -1, 1) elif camPos.x > 0.0 >= camPos.y: # quad 8 coreLst[12].getParent().setScale( 1, -1, 1) else: self.notify.warning("if-else default, scaleGrabber cam.z z < 0") distToCam = (camera.getPos() - render.getRelativePoint(BBGlobalVars.currCoordSysNP, self.grabModelNP.getPos())).length() self.grabModelNP.setScale(self.grabScaleFactor * distToCam, self.grabScaleFactor * distToCam, self.grabScaleFactor * distToCam) # keep the position identical to the selection # for when outside objects like undo/redo move selected self.grabModelNP.setPos(render, self.selected.getPos(render)) return task.cont # TODO find a way to move camera control to a proper camera handler, perhaps move these to a global def enableCamera(self): self.isCameraControlOn = True PanditorEnableMouseFunc() def disableCamera(self): self.isCameraControlOn = False PanditorDisableMouseFunc() def handleM3(self): """Deselect the selected object.""" if not self.grabModelNP.isHidden() and not self.isCameraControlOn: # if the grab model is in the scene and the camera is not in control if base.mouseWatcherNode.hasMouse() and not self.isDragging: # we're ignoring accidental mouse3 clicks while dragging here with not isDragging self.selected = None # empty the selected, will be turned back on once something's selected messenger.ignore('mouse3', self) # turn the deselect event off self.grabModelNP.hide() # hide the grab model and set it back to render's pos self.grabModelNP.setPos(0.0) def handleM1Up(self): """Stop dragging the selected object.""" taskMgr.remove('mouse1Dragging') self.isDragging = False self.currTransformOperation = None # NOTE other references have been added, but no other object references them # record the mouse1 operation BBGlobalVars.undoHandler.record(self.selected, CommandUndo([self.initialCommandTrgVal], self.selected.setMat, self.selected.getMat(render))) messenger.ignore('mouse1-up', self) def handleM1(self): """Decides how to handle a mouse1 click.""" if self.isCameraControlOn: return if base.mouseWatcherNode.hasMouse(): # give the grabber first chance if self.grabModelNP.isHidden(): # no collisions w/ grabber or nothing selected # handle selection with scene objects self.handleSelection() elif not self.isDragging: # The grabber is in place but not dragging. Get ready to drag. self.handleManipulationSetup() # it'll call self.handleSelection() if no collision w/ grabber # TODO (if warranted) make self.handleManipulationSetup() return false if no col w/ grabber, call selection here instead def handleManipulationSetup(self): """Sets up all the attributes needed for the mouse dragging task.""" # This makes the ray's origin the camera and makes the ray point # to the screen coordinates of the mouse. if self.isDragging: return camVec = self.grabModelNP.getRelativeVector(self.grabModelNP, camera.getPos()) mPos = base.mouseWatcherNode.getMouse() self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY()) self.colTraverser.traverse(self.grabModelNP) # look for collisions on the grabber if not self.isCameraControlOn and self.colHandlerQueue.getNumEntries() > 0 and not self.grabModelNP.isHidden(): # see if collided with the grabber if not handle re or multi selection self.colHandlerQueue.sortEntries() grabberObj = self.colHandlerQueue.getEntry(0).getIntoNodePath() grabberLst = self.grabModelNP.getPythonTag('grabberRoot') # see __init__ # the index gives the operations rot < 3 scale < 6 trans < 9 trans2D < 12 # mod index gives axis 0 == x, 1 == y, 2 == z ind = -1 for i in range(0, 13): if grabberObj == grabberLst[i]: ind = i grabberObj = grabberLst[i] # ensure we are not picking ourselves, ahem, the grabber assert(not self.grabModelNP.isAncestorOf(self.selected)) mPos3D = Point3(0.0) xVec = Vec3(1, 0, 0) yVec = Vec3(0, 1, 0) zVec = Vec3(0, 0, 1) # TODO: ??? break this up into translate rotate and scale function to make it readable if -1 < ind < 3: # rotate if ind % 3 == 0: # x self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.rot, Point3(mPos.getX(), mPos.getY(), 0.0)) elif ind % 3 == 1: # y self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.rot, Point3(mPos.getX(), mPos.getY(), 0.0)) else: # z self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.rot, Point3(mPos.getX(), mPos.getY(), 0.0)) elif ind < 6: # scale if ind % 3 == 0: # x self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.scale, Point3(mPos.getX(), mPos.getY(), 0.0)) elif ind % 3 == 1: # y # self.currTransformDir = Point3( 0.0, 1.0, 0.0) self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.scale, Point3(mPos.getX(), mPos.getY(), 0.0)) else: # z # self.currTransformDir = Point3( 0.0, 0.0, 1.0) self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.scale, Point3(mPos.getX(), mPos.getY(), 0.0)) elif ind < 9: # translate if ind % 3 == 0: # x # if the camera's too flat to the collision plane bad things happen if camVec.angleDeg( zVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, zVec): self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec) elif self.getMousePlaneIntersect(mPos3D, yVec): self.initializeManipVars(Point3(1.0, 0.0, 0.0), self.transformOpEnum.trans, mPos3D, yVec) elif ind % 3 == 1: # y if camVec.angleDeg( zVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, zVec): self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec) elif self.getMousePlaneIntersect(mPos3D, xVec): self.initializeManipVars(Point3(0.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, xVec) else: # z if camVec.angleDeg( yVec) < 89.0 and self.getMousePlaneIntersect(mPos3D, yVec): self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, yVec) elif self.getMousePlaneIntersect(mPos3D, xVec): self.initializeManipVars(Point3(0.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, xVec) elif ind < 12: # translate 2D if ind % 3 == 0: # xy if self.getMousePlaneIntersect(mPos3D, zVec): self.initializeManipVars(Point3(1.0, 1.0, 0.0), self.transformOpEnum.trans, mPos3D, zVec) elif ind % 3 == 1: # xz if self.getMousePlaneIntersect(mPos3D, yVec): self.initializeManipVars(Point3(1.0, 0.0, 1.0), self.transformOpEnum.trans, mPos3D, yVec) else: # zy if self.getMousePlaneIntersect(mPos3D, xVec): self.initializeManipVars(Point3(0.0, 1.0, 1.0), self.transformOpEnum.trans, mPos3D, xVec) elif ind == 12: # scale in three directions self.initializeManipVars(Point3(1.0, 1.0, 1.0), self.transformOpEnum.scale, Point3(mPos.getX(), mPos.getY(), 0.0)) else: self.notify.warning("Grabber Err: no grabber collision when col entries > 0 AND grabber not hidden") # Save initial value for save/undo. # The end result of the operation is sent to the undo handler on mouse up event. if self.selected: self.initialCommandTrgVal = self.selected.getMat(render) else: # no collisions w/ grabber or nothing selected # handle reselection or multi-selection (not yet implemented) with other scene obj self.handleSelection() def handleSelection(self): if self.isDragging: return # First check that the mouse is not outside the screen. if base.mouseWatcherNode.hasMouse() and False == self.isCameraControlOn: self.grabberColNode.setFromCollideMask(self.defaultBitMask) # This gives the screen coordinates of the mouse. mPos = base.mouseWatcherNode.getMouse() # This makes the ray's origin the camera and makes the ray point # to the screen coordinates of the mouse. self.colHandlerQueue.clearEntries() self.grabberRay.setFromLens(base.camNode, mPos.getX(), mPos.getY()) self.colTraverser.traverse(render) # look for collisions if self.colHandlerQueue.getNumEntries() > 0: self.colHandlerQueue.sortEntries() grabbedObj = self.colHandlerQueue.getEntry(0).getIntoNodePath() if not grabbedObj.findNetTag('pickable').isEmpty(): grabbedObj = grabbedObj.findNetTag('pickable') self.selected = grabbedObj self.grabModelNP.setPos(render, grabbedObj.getPos(render).x, grabbedObj.getPos(render).y, grabbedObj.getPos(render).z) self.grabModelNP.show() messenger.accept('mouse3', self, self.handleM3) def handleDragging(self, task): """ Does the actual work of manipulating objects, once the needed attributes have been setup by handleManipulationSetup(). """ if not self.isDragging: return task.done mPos3D = Point3(0.0) # # This section handles the actual translating rotating or scale after it's been set up in mouse1SetupManip...() # ONLY one operation is preformed per frame if self.currTransformOperation == self.transformOpEnum.trans: # 1st translation, rotation's section is at next elif if self.getMousePlaneIntersect(mPos3D, self.currPlaneColNorm): # get the difference between the last mouse and this frames mouse selectedNewPos = mPos3D - self.interFrameMousePosition # store this frames mouse self.interFrameMousePosition = mPos3D # add the difference to the selected object's pos self.selected.setPos(render, self.selected.getPos(render).x + self.currTransformDir.x * selectedNewPos.x, self.selected.getPos(render).y + self.currTransformDir.y * selectedNewPos.y, self.selected.getPos(render).z + self.currTransformDir.z * selectedNewPos.z) self.grabModelNP.setPos(render, self.selected.getPos(render)) elif self.currTransformOperation == self.transformOpEnum.rot: # 2nd rotation, followed finally by scaling # if operating on the z-axis, use the y (vertical screen coordinates otherwise use x (horizontal) mPos = base.mouseWatcherNode.getMouse() #rotMag = 0.0 if self.currTransformDir == Vec3( 0.0, 0.0, 1.0): rotMag = (mPos.x - self.interFrameMousePosition.x) * 1000 else: rotMag = (self.interFrameMousePosition.y - mPos.y) * 1000 initPos = self.selected.getPos() initPar = self.selected.getParent() self.selected.wrtReparentTo(render) self.selected.setMat(self.selected.getMat() * Mat4.rotateMat(rotMag, self.currTransformDir)) self.selected.wrtReparentTo(initPar) self.selected.setPos(initPos) self.interFrameMousePosition = Point3(mPos.x, mPos.y, 0.0) elif self.currTransformOperation == self.transformOpEnum.scale: # 3rd and final is scaling mPos = base.mouseWatcherNode.getMouse() # TODO: make dragging away from the object larger and to the object smaller (not simply left right up down) # td The problem with this MAY come if negative, mirrored, scaling is implemented. # if operating on the z-axis, use the y (vertical screen coordinates otherwise use x (horizontal) if self.currTransformDir == Point3( 0.0, 0.0, 1.0): sclMag = (mPos.y - self.interFrameMousePosition.y) * 5.5 elif self.currTransformDir == Point3( 0.0, 1.0, 0.0): sclMag = (mPos.x - self.interFrameMousePosition.x) * 5.5 else: sclMag = (self.interFrameMousePosition.x - mPos.x) * 5.5 # This is the line that prevents scaling past the origin. Flipping the faces doesn't seem to work. if -0.0001 < sclMag < 0.0001: sclMag = 0.000001 # create a dummy node to parent to and position such that applying scale to it will scale selected properly dummy = self.levitorNP.attachNewNode('dummy') initScl = dummy.getScale() # Don't forget the parent. Selected needs put back in place initPar = self.selected.getParent() initPos = self.selected.getPos() self.selected.wrtReparentTo(dummy) dummy.setScale(initScl.x + sclMag * self.currTransformDir.x, initScl.y + sclMag * self.currTransformDir.y, initScl.z + sclMag * self.currTransformDir.z) # reset selected's parent then destroy dummy self.selected.wrtReparentTo(initPar) self.selected.setPos(initPos) dummy.removeNode() dummy = None self.interFrameMousePosition = Point3( mPos.x, mPos.y, 0.0) else: self.notify.error("Err: Dragging with invalid curTransformOperation enum in handleDragging") return task.cont # ended by handleM1Up(), the mouse1-up event handler def initializeManipVars(self, transformDir, transformOp, mPos3D, planeNormVec=None): self.currTransformDir = transformDir self.currPlaneColNorm = planeNormVec # set the norm for the collision plane to be used in mouse1Dragging self.interFrameMousePosition = mPos3D self.currTransformOperation = transformOp self.isDragging = True taskMgr.add(self.handleDragging, 'mouse1Dragging') messenger.accept('mouse1-up', self, self.handleM1Up) def getMousePlaneIntersect(self, mPos3Dref, normVec): mPos = base.mouseWatcherNode.getMouse() plane = Plane(normVec, self.grabModelNP.getPos()) nearPoint = Point3() farPoint = Point3() base.camLens.extrude(mPos, nearPoint, farPoint) if plane.intersectsLine(mPos3Dref, render.getRelativePoint(camera, nearPoint), render.getRelativePoint(camera, farPoint)): return True return False def destroy(self): raise NotImplementedError('Make sure messenger etc are cleared of refs and the model node is deleted') self.grabModelNP.clearPythonTag('grabberRoot') self.grabModelNP.clearPythonTag('grabber') self.grabModelNP = None messenger.ignoreAll(self)
class CameraManager(): ZOOM_SPEED = 50 CAM_X = 'camX' CAM_Y = 'camY' CAM_Z = 'camZ' def __init__(self, showBase, camDict): self.showBase = showBase self.showBase.disableMouse() self.setSettings(camDict) self.initMouseToWorldCoordConversion() self.initMouseRayCollision() self.savedCollisionPoint = Vec3(0, 0, 0) # End """ init helpers """ def setSettings(self, camDict): cam = self.showBase.camera cam.setPos(50, 0, -1000) self.camPos = cam.getPos() cam.setHpr(0, 90, 0) self.showBase.camLens.setFov(10) self.dragging = False self.loadSettings(camDict) def initMouseRayCollision(self): z = 0 self.plane = Plane(Vec3(0, 0, 1), Point3(0, 0, z)) def initMouseToWorldCoordConversion(self): self.picker = CollisionTraverser() self.pq = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = self.showBase.camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.picker.addCollider(self.pickerNP, self.pq) """ Events """ def zoomIn(self): camera = self.showBase.camera curPos = camera.getPos() curPos.z += CameraManager.ZOOM_SPEED camera.setPos(curPos) self.saveSettings(self.camDict) def zoomOut(self): camera = self.showBase.camera curPos = camera.getPos() curPos.z += -CameraManager.ZOOM_SPEED camera.setPos(curPos) self.saveSettings(self.camDict) def mouse1Down(self): self.savedCollisionPoint = self.getMouseCollisionToPlane(self.plane) # print("mouse1Down") def mouseMove(self, task): collisionPoint = self.getMouseCollisionToPlane(self.plane) delta = self.getDelta(collisionPoint, self.savedCollisionPoint) self.addToCameraPos(delta) # Collision point changes if camera position changes collisionPoint = self.getMouseCollisionToPlane(self.plane) self.savedCollisionPoint = collisionPoint return Task.cont """ mouse1Down and mouseMove helpers """ def getMouseCollisionToPlane(self, plane): mouseWatcherNode = self.showBase.mouseWatcherNode if mouseWatcherNode.hasMouse(): mpos = mouseWatcherNode.getMouse() pos3d = Point3() nearPoint = Point3() farPoint = Point3() self.showBase.camLens.extrude(mpos, nearPoint, farPoint) render = self.showBase.render camera = self.showBase.camera if plane.intersectsLine(pos3d, render.getRelativePoint(camera, nearPoint), render.getRelativePoint(camera, farPoint)): return pos3d return None """ mouseMove helpers """ def getDelta(self, point1, point2): delta = Vec3() if point1 is not None: if point1.almostEqual(point2) is False: delta = point2 - point1 return delta def addToCameraPos(self, delta): camera = self.showBase.camera curPos = camera.getPos() camera.setPos(curPos + delta) self.saveSettings(self.camDict) def setViewBasedOnNodePos(self, pos): camera = self.showBase.camera newPos = Vec3(camera.getPos()) newPos.x = pos.x newPos.y = pos.y camera.setPos(newPos) # NodePath datection is manage internally in Panda3D, NodeManager should have been # managing NodePath, but it can be handled by communication with Camera and # Panda3D already, so NodeManager is not needed anymore here # TODO: Refactor def getClickedNodePath(self): mouseWatcherNode = self.showBase.mouseWatcherNode if mouseWatcherNode.hasMouse(): mpos = mouseWatcherNode.getMouse() self.pickerRay.setFromLens(self.showBase.camNode, mpos.getX(), mpos.getY()) self.picker.traverse(self.showBase.render) if self.pq.getNumEntries() > 0: self.pq.sortEntries() return self.pq.getEntry(0).getIntoNodePath() return None def getCoordinates(self): mouseWatcherNode = self.showBase.mouseWatcherNode mpos = mouseWatcherNode.getMouse() self.pickerRay.setFromLens(self.showBase.camNode, mpos.getX(), mpos.getY()) render = self.showBase.render camera = self.showBase.camera nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin()) return mpos, nearPoint def saveSettings(self, camDict): self.camDict = camDict cam = self.showBase.camera pos = cam.getPos() camDict[CameraManager.CAM_X] = pos.x camDict[CameraManager.CAM_Y] = pos.y camDict[CameraManager.CAM_Z] = pos.z def loadSettings(self, camDict): self.camDict = camDict if camDict is None: self.camDict = {} if camDict.get(CameraManager.CAM_X) is not None: camera = self.showBase.camera camera.setPos(camDict[CameraManager.CAM_X], camDict[CameraManager.CAM_Y], camDict[CameraManager.CAM_Z]) def showValues(self): print("camera pos " + str(self.showBase.camera.getPos())) print("camera hpr " + str(self.showBase.camera.getHpr())) print("camera x " + str(self.showBase.camera.getX())) print("camera y " + str(self.showBase.camera.getY())) print("camera z " + str(self.showBase.camera.getZ()))
class World(DirectObject): def __init__(self, mode, ip=None): if mode==CLIENT and not ip: #Don't let this happen. print "WTF programmer" sys.exit() #current dialog box self.d = None #top-left of screen; contains instructions on how to exit the game. self.quitInstructions = OnscreenText(text='Press ESC to exit.', pos=(-1, 0.95), scale=0.05, fg=(1,1,1,1), bg=(0,0,0,0), mayChange=False) #bottom of screen self.turnIndicator = OnscreenText(text='', pos=(0,-0.8), scale=0.1, fg=(1,1,1,1), bg=(0,0,0,0), mayChange=True) #Saving some values, some default values self.mode = mode self.player = {SERVER: PIECEWHITE, CLIENT: PIECEBLACK}[self.mode] self.ip = ip #Panda3D, by default, allows for camera control with the mouse. base.disableMouse() self.setupMouse() self.setupBoard() self.setupCamera() self.setupPieces() self.setupNetwork() self.setupLights() #some internal state for making clicky moves self.hiSq = None self.dragOrigin = None #keyboard, mouse self.mouseTask = taskMgr.add(self.tskMouse, 'mouseTask') self.accept('mouse1', self.handleClick) self.accept('f2', lambda: base.setFrameRateMeter(True)) self.accept('f3', lambda: base.setFrameRateMeter(False)) self.accept('escape', sys.exit) #first turn self.turn = PIECEWHITE #### INITIALIZATION #### def setupBoard(self): #We will attach all of the squares to their own root. This way we can do the #collision pass just on the sqaures and save the time of checking the rest #of the scene self.squareRoot = render.attachNewNode("squareRoot") #For each square self.squares = dict(((i,j), None) for i in range(8) for j in range(8)) for place in self.squares: #Load, parent, color, and position the model (a single square polygon) self.squares[place] = loader.loadModel("models/square") self.squares[place].reparentTo(self.squareRoot) self.squares[place].setPos(SquarePos(place)) self.squares[place].setColor(SquareColor(place)) #Set the model itself to be collideable with the ray. If this model was #any more complex than a single polygon, you should set up a collision #sphere around it instead. But for single polygons this works fine. self.squares[place].find("**/polygon").node().setIntoCollideMask( BitMask32.bit(1)) #Set a tag on the square's node so we can look up what square this is #later during the collision pass self.squares[place].find("**/polygon").node().setTag('square', ' '.join(map(str,place))) self.squares[place].setTransparency(TransparencyAttrib.MAlpha) def setupPieces(self): #Default dictionaries work decently well as an easy two-dimensional array. self.pieces = defaultdict(lambda: None) #The order of pieces on a chessboard from white's perspective pieceOrder = [Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook] for i in xrange(8): #load white pawns self.pieces[i, 1] = Pawn((i,1), PIECEWHITE) #load black pawns self.pieces[i, 6] = Pawn((i, 6), PIECEBLACK) #load white specials self.pieces[i, 0] = pieceOrder[i]((i,0), PIECEWHITE) #load black specials self.pieces[i, 7] = pieceOrder[i]((i,7), PIECEBLACK) for p in self.pieces.values(): p.obj.setTransparency(TransparencyAttrib.MAlpha) # TODO: Notice when the other side disconnects def setupNetwork(self): if self.mode == CLIENT: self.setupClient(self.ip) else: self.setupServer() # A lot of the below two methods is boilerplate straight from Panda3D documentation. def setupServer(self): self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager,0) self.oppConnection = None port = 15905 # Chosen by fair dice roll. # Guaranteed to be random. backlog = 1000 tcpSocket = self.cManager.openTCPServerRendezvous(port, backlog) self.cListener.addConnection(tcpSocket) def tskListenerPoll(task): if self.cListener.newConnectionAvailable() and not self.oppConnection: rendezvous = PointerToConnection() addr = NetAddress() newCon = PointerToConnection() if self.cListener.getNewConnection(rendezvous, addr, newCon): newConnection = newCon.p() print "Received connection from %s" % newConnection.getAddress() self.oppConnection = newConnection self.cReader.addConnection(newConnection) #server starts the game self.turnIndicator['text'] = 'Your turn!' self.showVisibleSquares() #remove the dialog node from below if self.d: self.d.removeNode() return Task.done if not self.d: self.d = DirectDialog(text="Waiting for client to connect...", buttonTextList=[], buttonValueList=[]) return Task.cont taskMgr.add(tskListenerPoll, "Poll the connection listener") taskMgr.add(self.tskReaderPoll, "Poll the connection reader") def setupClient(self, ip): self.cManager = QueuedConnectionManager() self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager,0) self.oppConnection = None port = 15905 timeout = 3000 myConnection = self.cManager.openTCPClientConnection(ip, port, timeout) if myConnection: self.cReader.addConnection(myConnection) self.oppConnection = myConnection taskMgr.add(self.tskReaderPoll, "Poll the connection reader") self.showVisibleSquares() else: self.d = OkDialog(text="Could not connect to server at '%s'" % ip, command=sys.exit) # Makes sure player gets a decent view of the game board, and *not* of the hidden pieces below the board. Shhhh... def setupCamera(self): if self.player == PIECEWHITE: camera.setPos(0, -13.75, 8) camera.lookAt(self.squareRoot) camera.setH(0) else: camera.setPos(0, 13.75, 8) camera.lookAt(self.squareRoot) camera.setH(180) # Adds some ambient lights and a directional light def setupLights(self): #This is one area I know hardly anything about. I really don't know how to get this to behave nicely. #The black pieces are hardly distinguishable. ambientLight = AmbientLight( "ambientLight" ) ambientLight.setColor( Vec4(.8, .8, .8, 1) ) directionalLight = DirectionalLight( "directionalLight" ) directionalLight.setDirection( Vec3( 0, 45, -45 ) ) directionalLight.setColor( Vec4( 0.2, 0.2, 0.2, 1 ) ) render.setLight(render.attachNewNode( directionalLight ) ) render.setLight(render.attachNewNode( ambientLight ) ) # Sets up collision detection for the mouse cursor. def setupMouse(self): #Since we are using collision detection to do picking, we set it up like #any other collision detection system with a traverser and a handler self.picker = CollisionTraverser() #Make a traverser self.pq = CollisionHandlerQueue() #Make a handler #Make a collision node for our picker ray self.pickerNode = CollisionNode('mouseRay') #Attach that node to the camera since the ray will need to be positioned #relative to it self.pickerNP = camera.attachNewNode(self.pickerNode) #Everything to be picked will use bit 1. This way if we were doing other #collision we could seperate it self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() #Make our ray self.pickerNode.addSolid(self.pickerRay) #Add it to the collision node #Register the ray as something that can cause collisions self.picker.addCollider(self.pickerNP, self.pq) #### TASKS #### # Checks for incoming data on the connection def tskReaderPoll(self, task): if self.cReader.dataAvailable(): datagram = NetDatagram() if self.cReader.getData(datagram): self.receiveData(datagram) return Task.cont # Runs every frame, checks whether the mouse is highlighting something or another def tskMouse(self, task): #This task deals with the highlighting and dragging based on the mouse #First, clear the current highlight if self.hiSq: self.squares[self.hiSq].setColor(SquareColor(self.hiSq)) self.hiSq = None #Check to see if we can access the mouse. We need it to do anything else if base.mouseWatcherNode.hasMouse(): #get the mouse position mpos = base.mouseWatcherNode.getMouse() #Set the position of the ray based on the mouse position self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) #If we are dragging something, set the position of the object #to be at the appropriate point over the plane of the board if self.dragOrigin: #camera, relative instead to render #Gets the point described by pickerRay.getOrigin(), which is relative to nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin()) #Same thing with the direction of the ray nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection()) self.pieces[self.dragOrigin].obj.setPos( PointAtZ(.5, nearPoint, nearVec)) #Do the actual collision pass (Do it only on the squares for #efficiency purposes) self.picker.traverse(self.squareRoot) if self.pq.getNumEntries() > 0: #if we have hit something, sort the hits so that the closest #is first, and highlight that node self.pq.sortEntries() p = tuple(map(int, (self.pq.getEntry(0).getIntoNode().getTag('square')).split())) if self.pieces[p] and self.pieces[p].color == self.turn == self.player and not self.dragOrigin or self.dragOrigin and self.pieces[self.dragOrigin].isValidMove(p, self.pieces): #Set the highlight on the picked square self.hiSq = p self.squares[self.hiSq].setColor(HIGHLIGHT) return Task.cont def handleClick(self): # Disabled when a dialog box is on-screen. Pay attention to what I'm telling you, user! if not self.d: if self.dragOrigin: self.releasePiece() else: self.grabPiece() # Comes from handleClick def grabPiece(self): #If a square is highlighted and it has a piece, set it to dragging mode if self.hiSq and self.pieces[self.hiSq] and self.pieces[self.hiSq].color == self.turn: self.dragOrigin = self.hiSq self.hiSq = None def releasePiece(self): #Letting go of a piece. If we are not on a square, return it to its original #position. if self.dragOrigin: #Make sure we really are dragging something if self.hiSq and self.hiSq != self.dragOrigin and self.pieces[self.dragOrigin].isValidMove(self.hiSq, self.pieces): # Verify that this doesn't put the king in check # Make backup of the pieces dictionary oldPieces = self.pieces.copy() self.pieces[self.hiSq] = self.pieces[self.dragOrigin] self.pieces[self.dragOrigin] = None if self.inCheck(self.turn): self.pieces = oldPieces self.pieces[self.dragOrigin].obj.setPos(SquarePos(self.dragOrigin)) print "Invalid move -- King is in check" def closeDialog(): self.d.removeNode() self.d = OkDialog(text="That move would put your King in check!", command=closeDialog) else: self.pieces = oldPieces self.makeMove(self.dragOrigin, self.hiSq, dt=0, callback=self.showVisibleSquares).start() self.sendMove(self.dragOrigin, self.hiSq) self.squares[self.dragOrigin].setColor(SquareColor(self.dragOrigin)) #no longer our turn self.turnIndicator['text'] = '' else: self.pieces[self.dragOrigin].obj.setPos(SquarePos(self.dragOrigin)) print "Invalid move" #We are no longer dragging anything self.dragOrigin = False #### CHESS UPDATES #### # Moves a piece from one space to another. # This should be called to update internal state, whether the piece is already in the correct location or not. # Also handles captures. def makeMove(self, fr, to, dt=1, callback=None): print "Making move %s -> %s" % (str(fr), str(to)) frP = self.pieces[fr] toP = self.pieces[to] if not frP: return False if toP and frP.color == toP.color: return False if not frP.isValidMove(to, self.pieces): return False # Callback function for the movement. # Updates pieces' internal state, as well as the true state of the board (self.pieces) def updateState(): self.destroy(toP) frP.square = to frP.haveMoved = True self.pieces[fr] = None self.pieces[to] = frP self.turn = flip[self.turn] if self.inCheck(self.player): def dismiss(val): self.d.removeNode() self.d = OkDialog(text="You are in check!", command=dismiss) s = Sequence( frP.obj.posInterval(dt, self.squares[to].getPos()), Func(updateState) ) if callback: s.append(Func(callback)) return s # Removes the piece. This method is passed a Piece object, not a location! # Possible improvements: Particle effects! :D def destroy(self, piece): if piece: piece.obj.removeNode() # Determines whether the player specified by "color" is in check at the current time # Future improvements: Calculate the same thing for possible future moves (i.e. if I move here am I therefore in check?) def inCheck(self, color): #find the king kingPlace = [p for p in self.pieces if self.pieces[p] and self.pieces[p].color == color and self.pieces[p].model == "models/king"][0] for p in self.pieces: if self.pieces[p] and self.pieces[p].color != color and self.pieces[p].isValidMove(kingPlace, self.pieces): return True return False # Currently unused, but could be useful in an (extremely primitive) AI in the future. # I ran out of time to put it in this version. def makeRandomMove(self): move = None while not move: chosenPiece = random.choice([(x,y) for (x,y) in self.pieces if 0 <= x < 8 and 0 <= y < 8 and self.pieces[x,y] and self.pieces[x,y].color == self.turn]) if not self.pieces[chosenPiece].validMoves(self.pieces): continue destSquare = random.choice([s for s in self.pieces[chosenPiece].validMoves(self.pieces)]) move = (chosenPiece, destSquare) self.makeMove(*move).start() #### VISIBILITY UPDATES #### def isVisible(self, sq): return self.squares[sq].getColorScale()[3] == 1.0 # The next two methods deal with hiding and showing the squares of the board. def hideSquare(self, sq, dt="default", callback=None): if self.squares[sq] and self.isVisible(sq): if dt == "default": dt = 1.0 par = Parallel( LerpFunctionInterval(self.squares[sq].setAlphaScale, toData=0.0, fromData=1.0, duration=dt), ) if self.pieces[sq]: par.append(LerpFunctionInterval(self.pieces[sq].obj.setAlphaScale, toData=0.0, fromData=1.0, duration=dt)) s = Sequence(par) if callback: s.append(Func(callback)) return s else: s = Sequence() if callback: s.append(Func(callback)) return s def showSquare(self, sq, dt="default", callback=None): if self.squares[sq] and not self.isVisible(sq): if dt == "default": dt = 1.0 par = Parallel( LerpFunctionInterval(self.squares[sq].setAlphaScale, toData=1.0, fromData=0.0, duration=dt), ) if self.pieces[sq]: par.append(LerpFunctionInterval(self.pieces[sq].obj.setAlphaScale, toData=1.0, fromData=0.0, duration=dt)) s = Sequence(par) if callback: s.append(Func(callback)) return s else: s = Sequence() if callback: s.append(Func(callback)) return s # Shows the path that a piece takes on its way IF any part of it is visible to the current player def showPathIfVisible(self, fr, to): if self.pieces[fr]: path = set() showSquareSequences = Parallel() if self.pieces[fr]: path.update(self.pieces[fr].path(to)) if any(self.isVisible(sq) for sq in path): for sq in path: showSquareSequences.append(self.showSquare(sq)) return showSquareSequences else: return Parallel() # Shows the path that a piece takes on its path from its origin to its destination def showPath(self, fr, to): path = set() showSquareSequences = Parallel() if self.pieces[fr]: path.update(self.pieces[fr].path(to)) for sq in path: showSquareSequences.append(self.showSquare(sq)) return showSquareSequences # Updates the board to show only the squares that are visible at the current time. def showVisibleSquares(self, dt="default"): visibles = defaultdict(lambda: False) for p in [(x,y) for (x,y) in self.pieces if 0 <= x < 8 and 0 <= y < 8]: if self.pieces[p]: if self.pieces[p].color == self.player: for s in self.pieces[p].visibleSquares(self.pieces): visibles[s] = True par = Parallel() for s in self.squares: if visibles[s]: par.append(self.showSquare(s, dt)) else: par.append(self.hideSquare(s, dt)) par.start() return par #### NETWORK I/O #### def sendMove(self, fr, to): dg = PyDatagram() dg.addUint8(fr[0]) dg.addUint8(fr[1]) dg.addUint8(to[0]) dg.addUint8(to[1]) print "Sent move (%d, %d) -> (%d, %d)" % (fr[0], fr[1], to[0], to[1]) self.cWriter.send(dg, self.oppConnection) def receiveData(self, dg): dg = PyDatagramIterator(dg) fr = (dg.getUint8(), dg.getUint8()) to = (dg.getUint8(), dg.getUint8()) print "Received move %s -> %s" % (fr, to) def indicate(): self.turnIndicator['text'] = 'Your turn!' self.sfx = loader.loadSfx('audio/ding.wav') self.sfx.play() seq = Sequence() seq.append(self.showPathIfVisible(fr, to)) seq.append(self.makeMove(fr, to)) seq.append(Func(indicate)) seq.append(Func(self.showVisibleSquares)) seq.start()
class SmartCamera: UPDATE_TASK_NAME = 'update_smartcamera' notify = directNotify.newCategory('SmartCamera') def __init__(self): self.cTrav = CollisionTraverser('cam_traverser') base.pushCTrav(self.cTrav) self.cTrav.setRespectPrevTransform(1) self.default_pos = None self.parent = None self.initialized = False self.started = False self.camFloorRayNode = None self.ccRay2 = None self.ccRay2Node = None self.ccRay2NodePath = None self.ccRay2BitMask = None self.ccRay2MoveNodePath = None self.camFloorCollisionBroadcaster = None self.notify.debug('SmartCamera initialized!') return def lerpCameraFov(self, fov, time): taskMgr.remove('cam-fov-lerp-play') oldFov = base.camLens.getHfov() if abs(fov - oldFov) > 0.1: def setCamFov(fov): base.camLens.setMinFov(fov / (4.0 / 3.0)) self.camLerpInterval = LerpFunctionInterval(setCamFov, fromData=oldFov, toData=fov, duration=time, name='cam-fov-lerp') self.camLerpInterval.start() def setCameraFov(self, fov): self.fov = fov if not (self.isPageDown or self.isPageUp): base.camLens.setMinFov(self.fov / (4.0 / 3.0)) def initCameraPositions(self): camHeight = max(base.localAvatar.getHeight(), 3.0) nrCamHeight = base.localAvatar.getHeight() heightScaleFactor = camHeight * 0.3333333333 defLookAt = Point3(0.0, 1.5, camHeight) self.firstPersonCamPos = Point3(0.0, 0.7, nrCamHeight * 5.0) scXoffset = 3.0 scPosition = (Point3(scXoffset - 1, -10.0, camHeight + 5.0), Point3(scXoffset, 2.0, camHeight)) self.cameraPositions = [ (Point3(0.0, -9.0 * heightScaleFactor, camHeight), defLookAt, Point3(0.0, camHeight, camHeight * 4.0), Point3(0.0, camHeight, camHeight * -1.0), 0), ( Point3(0.0, 0.7, camHeight), defLookAt, Point3(0.0, camHeight, camHeight * 1.33), Point3(0.0, camHeight, camHeight * 0.66), 1), ( Point3(5.7 * heightScaleFactor, 7.65 * heightScaleFactor, camHeight + 2.0), Point3(0.0, 1.0, camHeight), Point3(0.0, 1.0, camHeight * 4.0), Point3(0.0, 1.0, camHeight * -1.0), 0), ( Point3(0.0, 8.65 * heightScaleFactor, camHeight), Point3(0.0, 1.0, camHeight), Point3(0.0, 1.0, camHeight * 4.0), Point3(0.0, 1.0, camHeight * -1.0), 0), ( Point3(0.0, -24.0 * heightScaleFactor, camHeight + 4.0), defLookAt, Point3(0.0, 1.5, camHeight * 4.0), Point3(0.0, 1.5, camHeight * -1.0), 0), ( Point3(0.0, -12.0 * heightScaleFactor, camHeight + 4.0), defLookAt, Point3(0.0, 1.5, camHeight * 4.0), Point3(0.0, 1.5, camHeight * -1.0), 0)] def pageUp(self): if not base.localAvatar.avatarMovementEnabled: return if not self.isPageUp: self.isPageDown = 0 self.isPageUp = 1 self.lerpCameraFov(70, 0.6) self.setCameraPositionByIndex(self.cameraIndex) else: self.clearPageUpDown() def pageDown(self): if not base.localAvatar.avatarMovementEnabled: return if not self.isPageDown: self.isPageUp = 0 self.isPageDown = 1 self.lerpCameraFov(70, 0.6) self.setCameraPositionByIndex(self.cameraIndex) else: self.clearPageUpDown() def clearPageUpDown(self): if self.isPageDown or self.isPageUp: self.lerpCameraFov(self.fov, 0.6) self.isPageDown = 0 self.isPageUp = 0 self.setCameraPositionByIndex(self.cameraIndex) def nextCameraPos(self, forward): if not base.localAvatar.avatarMovementEnabled: return self.__cameraHasBeenMoved = 1 if forward: self.cameraIndex += 1 if self.cameraIndex > len(self.cameraPositions) - 1: self.cameraIndex = 0 else: self.cameraIndex -= 1 if self.cameraIndex < 0: self.cameraIndex = len(self.cameraPositions) - 1 self.setCameraPositionByIndex(self.cameraIndex) def setCameraPositionByIndex(self, index): self.notify.debug('switching to camera position %s' % index) self.setCameraSettings(self.cameraPositions[index]) def setCameraSettings(self, camSettings): self.setIdealCameraPos(camSettings[0]) if self.isPageUp and self.isPageDown or not self.isPageUp and not self.isPageDown: self.__cameraHasBeenMoved = 1 self.setLookAtPoint(camSettings[1]) else: if self.isPageUp: self.__cameraHasBeenMoved = 1 self.setLookAtPoint(camSettings[2]) else: if self.isPageDown: self.__cameraHasBeenMoved = 1 self.setLookAtPoint(camSettings[3]) else: self.notify.error('This case should be impossible.') self.__disableSmartCam = camSettings[4] if self.__disableSmartCam: self.putCameraFloorRayOnAvatar() self.cameraZOffset = 0.0 def set_default_pos(self, pos): self.default_pos = pos def get_default_pos(self): return self.default_pos def set_parent(self, parent): self.parent = parent def get_parent(self): return self.parent def getVisibilityPoint(self): return Point3(0.0, 0.0, base.localAvatar.getHeight()) def setLookAtPoint(self, la): self.__curLookAt = Point3(la) def getLookAtPoint(self): return Point3(self.__curLookAt) def setIdealCameraPos(self, pos): self.__idealCameraPos = Point3(pos) self.updateSmartCameraCollisionLineSegment() def getIdealCameraPos(self): return Point3(self.__idealCameraPos) def getCompromiseCameraPos(self): if self.__idealCameraObstructed == 0: compromisePos = self.getIdealCameraPos() else: visPnt = self.getVisibilityPoint() idealPos = self.getIdealCameraPos() distance = Vec3(idealPos - visPnt).length() ratio = self.closestObstructionDistance / distance compromisePos = idealPos * ratio + visPnt * (1 - ratio) liftMult = 1.0 - ratio * ratio compromisePos = Point3(compromisePos[0], compromisePos[1], compromisePos[2] + base.localAvatar.getHeight() * 0.4 * liftMult) compromisePos.setZ(compromisePos[2] + self.cameraZOffset) return compromisePos def updateSmartCameraCollisionLineSegment(self): pointB = self.getIdealCameraPos() pointA = self.getVisibilityPoint() vectorAB = Vec3(pointB - pointA) lengthAB = vectorAB.length() if lengthAB > 0.001: self.ccLine.setPointA(pointA) self.ccLine.setPointB(pointB) def initializeSmartCamera(self): self.__idealCameraObstructed = 0 self.closestObstructionDistance = 0.0 self.cameraIndex = 0 self.cameraPositions = [] self.auxCameraPositions = [] self.cameraZOffset = 0.0 self.setGeom(render) self.__onLevelGround = 0 self.__camCollCanMove = 0 self.__disableSmartCam = 0 self.initializeSmartCameraCollisions() self._smartCamEnabled = False self.isPageUp = 0 self.isPageDown = 0 self.fov = CIGlobals.DefaultCameraFov def enterFirstPerson(self): self.stop_smartcamera() if hasattr(self.get_parent(), 'toon_head'): head = self.get_parent().toon_head camera.reparentTo(head) camera.setPos(0, -0.35, 0) camera.setHpr(0, 0, 0) def exitFirstPerson(self): self.initialize_smartcamera() self.initialize_smartcamera_collisions() self.start_smartcamera() def putCameraFloorRayOnAvatar(self): self.camFloorRayNode.setPos(base.localAvatar, 0, 0, 5) def putCameraFloorRayOnCamera(self): self.camFloorRayNode.setPos(self.ccSphereNodePath, 0, 0, 0) def recalcCameraSphere(self): nearPlaneDist = base.camLens.getNear() hFov = base.camLens.getHfov() vFov = base.camLens.getVfov() hOff = nearPlaneDist * math.tan(deg2Rad(hFov / 2.0)) vOff = nearPlaneDist * math.tan(deg2Rad(vFov / 2.0)) camPnts = [Point3(hOff, nearPlaneDist, vOff), Point3(-hOff, nearPlaneDist, vOff), Point3(hOff, nearPlaneDist, -vOff), Point3(-hOff, nearPlaneDist, -vOff), Point3(0.0, 0.0, 0.0)] avgPnt = Point3(0.0, 0.0, 0.0) for camPnt in camPnts: avgPnt = avgPnt + camPnt avgPnt = avgPnt / len(camPnts) sphereRadius = 0.0 for camPnt in camPnts: dist = Vec3(camPnt - avgPnt).length() if dist > sphereRadius: sphereRadius = dist avgPnt = Point3(avgPnt) self.ccSphereNodePath.setPos(avgPnt) self.ccSphereNodePath2.setPos(avgPnt) self.ccSphere.setRadius(sphereRadius) def setGeom(self, geom): self.__geom = geom def initializeSmartCameraCollisions(self): if self.initialized: return self.ccTrav = CollisionTraverser('LocalAvatar.ccTrav') self.ccLine = CollisionSegment(0.0, 0.0, 0.0, 1.0, 0.0, 0.0) self.ccLineNode = CollisionNode('ccLineNode') self.ccLineNode.addSolid(self.ccLine) self.ccLineNodePath = base.localAvatar.attachNewNode(self.ccLineNode) self.ccLineBitMask = CIGlobals.CameraBitmask self.ccLineNode.setFromCollideMask(self.ccLineBitMask) self.ccLineNode.setIntoCollideMask(BitMask32.allOff()) self.camCollisionQueue = CollisionHandlerQueue() self.ccTrav.addCollider(self.ccLineNodePath, self.camCollisionQueue) self.ccSphere = CollisionSphere(0, 0, 0, 1) self.ccSphereNode = CollisionNode('ccSphereNode') self.ccSphereNode.addSolid(self.ccSphere) self.ccSphereNodePath = base.camera.attachNewNode(self.ccSphereNode) self.ccSphereNode.setFromCollideMask(CIGlobals.CameraBitmask) self.ccSphereNode.setIntoCollideMask(BitMask32.allOff()) self.camPusher = CollisionHandlerPusher() self.camPusher.addCollider(self.ccSphereNodePath, base.camera) self.camPusher.setCenter(base.localAvatar) self.ccPusherTrav = CollisionTraverser('LocalAvatar.ccPusherTrav') self.ccSphere2 = self.ccSphere self.ccSphereNode2 = CollisionNode('ccSphereNode2') self.ccSphereNode2.addSolid(self.ccSphere2) self.ccSphereNodePath2 = base.camera.attachNewNode(self.ccSphereNode2) self.ccSphereNode2.setFromCollideMask(CIGlobals.CameraBitmask) self.ccSphereNode2.setIntoCollideMask(BitMask32.allOff()) self.camPusher2 = CollisionHandlerPusher() self.ccPusherTrav.addCollider(self.ccSphereNodePath2, self.camPusher2) self.camPusher2.addCollider(self.ccSphereNodePath2, base.camera) self.camPusher2.setCenter(base.localAvatar) self.camFloorRayNode = base.localAvatar.attachNewNode('camFloorRayNode') self.ccRay = CollisionRay(0.0, 0.0, 0.0, 0.0, 0.0, -1.0) self.ccRayNode = CollisionNode('ccRayNode') self.ccRayNode.addSolid(self.ccRay) self.ccRayNodePath = self.camFloorRayNode.attachNewNode(self.ccRayNode) self.ccRayBitMask = CIGlobals.FloorBitmask self.ccRayNode.setFromCollideMask(self.ccRayBitMask) self.ccRayNode.setIntoCollideMask(BitMask32.allOff()) self.ccTravFloor = CollisionTraverser('LocalAvatar.ccTravFloor') self.camFloorCollisionQueue = CollisionHandlerQueue() self.ccTravFloor.addCollider(self.ccRayNodePath, self.camFloorCollisionQueue) self.ccTravOnFloor = CollisionTraverser('LocalAvatar.ccTravOnFloor') self.ccRay2 = CollisionRay(0.0, 0.0, 0.0, 0.0, 0.0, -1.0) self.ccRay2Node = CollisionNode('ccRay2Node') self.ccRay2Node.addSolid(self.ccRay2) self.ccRay2NodePath = self.camFloorRayNode.attachNewNode(self.ccRay2Node) self.ccRay2BitMask = CIGlobals.FloorBitmask self.ccRay2Node.setFromCollideMask(self.ccRay2BitMask) self.ccRay2Node.setIntoCollideMask(BitMask32.allOff()) self.ccRay2MoveNodePath = hidden.attachNewNode('ccRay2MoveNode') self.camFloorCollisionBroadcaster = CollisionHandlerFloor() self.camFloorCollisionBroadcaster.setInPattern('on-floor') self.camFloorCollisionBroadcaster.setOutPattern('off-floor') self.camFloorCollisionBroadcaster.addCollider(self.ccRay2NodePath, self.ccRay2MoveNodePath) self.cTrav.addCollider(self.ccRay2NodePath, self.camFloorCollisionBroadcaster) self.initialized = True def deleteSmartCameraCollisions(self): del self.ccTrav del self.ccLine del self.ccLineNode self.ccLineNodePath.removeNode() del self.ccLineNodePath del self.camCollisionQueue del self.ccRay del self.ccRayNode self.ccRayNodePath.removeNode() del self.ccRayNodePath del self.ccRay2 del self.ccRay2Node self.ccRay2NodePath.removeNode() del self.ccRay2NodePath self.ccRay2MoveNodePath.removeNode() del self.ccRay2MoveNodePath del self.ccTravOnFloor del self.ccTravFloor del self.camFloorCollisionQueue del self.camFloorCollisionBroadcaster del self.ccSphere del self.ccSphereNode self.ccSphereNodePath.removeNode() del self.ccSphereNodePath del self.camPusher del self.ccPusherTrav del self.ccSphere2 del self.ccSphereNode2 self.ccSphereNodePath2.removeNode() del self.ccSphereNodePath2 del self.camPusher2 self.initialized = False def startUpdateSmartCamera(self): if self.started: return self.__floorDetected = 0 self.__cameraHasBeenMoved = 1 self.recalcCameraSphere() self.__instantaneousCamPos = camera.getPos() self.cTrav.addCollider(self.ccSphereNodePath, self.camPusher) self.ccTravOnFloor.addCollider(self.ccRay2NodePath, self.camFloorCollisionBroadcaster) self.__disableSmartCam = 0 self.__lastPosWrtRender = camera.getPos(render) + 1 self.__lastHprWrtRender = camera.getHpr(render) + 1 taskName = base.localAvatar.taskName('updateSmartCamera') taskMgr.remove(taskName) taskMgr.add(self.updateSmartCamera, taskName, priority=47) self.started = True def stopUpdateSmartCamera(self): self.cTrav.removeCollider(self.ccSphereNodePath) self.ccTravOnFloor.removeCollider(self.ccRay2NodePath) taskName = base.localAvatar.taskName('updateSmartCamera') taskMgr.remove(taskName) camera.setPos(self.getIdealCameraPos()) self.started = False def updateSmartCamera(self, task): if not self.__camCollCanMove and not self.__cameraHasBeenMoved: if self.__lastPosWrtRender == camera.getPos(render): if self.__lastHprWrtRender == camera.getHpr(render): return Task.cont self.__cameraHasBeenMoved = 0 self.__lastPosWrtRender = camera.getPos(render) self.__lastHprWrtRender = camera.getHpr(render) self.__idealCameraObstructed = 0 if not self.__disableSmartCam: self.ccTrav.traverse(self.__geom) if self.camCollisionQueue.getNumEntries() > 0: try: self.camCollisionQueue.sortEntries() self.handleCameraObstruction(self.camCollisionQueue.getEntry(0)) except AssertionError: pass if not self.__onLevelGround: self.handleCameraFloorInteraction() if not self.__idealCameraObstructed: self.nudgeCamera() if not self.__disableSmartCam: self.ccPusherTrav.traverse(self.__geom) self.putCameraFloorRayOnCamera() self.ccTravOnFloor.traverse(self.__geom) return Task.cont def positionCameraWithPusher(self, pos, lookAt): camera.setPos(pos) self.ccPusherTrav.traverse(self.__geom) camera.lookAt(lookAt) def nudgeCamera(self): CLOSE_ENOUGH = 0.1 curCamPos = self.__instantaneousCamPos curCamHpr = camera.getHpr() targetCamPos = self.getCompromiseCameraPos() targetCamLookAt = self.getLookAtPoint() posDone = 0 if Vec3(curCamPos - targetCamPos).length() <= CLOSE_ENOUGH: camera.setPos(targetCamPos) posDone = 1 camera.setPos(targetCamPos) camera.lookAt(targetCamLookAt) targetCamHpr = camera.getHpr() hprDone = 0 if Vec3(curCamHpr - targetCamHpr).length() <= CLOSE_ENOUGH: hprDone = 1 if posDone and hprDone: return lerpRatio = 0.15 lerpRatio = 1 - pow(1 - lerpRatio, globalClock.getDt() * 30.0) self.__instantaneousCamPos = targetCamPos * lerpRatio + curCamPos * (1 - lerpRatio) if self.__disableSmartCam or not self.__idealCameraObstructed: newHpr = targetCamHpr * lerpRatio + curCamHpr * (1 - lerpRatio) else: newHpr = targetCamHpr camera.setPos(self.__instantaneousCamPos) camera.setHpr(newHpr) def popCameraToDest(self): newCamPos = self.getCompromiseCameraPos() newCamLookAt = self.getLookAtPoint() self.positionCameraWithPusher(newCamPos, newCamLookAt) self.__instantaneousCamPos = camera.getPos() def handleCameraObstruction(self, camObstrCollisionEntry): collisionPoint = camObstrCollisionEntry.getSurfacePoint(self.ccLineNodePath) collisionVec = Vec3(collisionPoint - self.ccLine.getPointA()) distance = collisionVec.length() self.__idealCameraObstructed = 1 self.closestObstructionDistance = distance self.popCameraToDest() def handleCameraFloorInteraction(self): self.putCameraFloorRayOnCamera() self.ccTravFloor.traverse(self.__geom) if self.__onLevelGround: return if self.camFloorCollisionQueue.getNumEntries() == 0: return self.camFloorCollisionQueue.sortEntries() camObstrCollisionEntry = self.camFloorCollisionQueue.getEntry(0) camHeightFromFloor = camObstrCollisionEntry.getSurfacePoint(self.ccRayNodePath)[2] self.cameraZOffset = camera.getPos()[2] + camHeightFromFloor if self.cameraZOffset < 0: self.cameraZOffset = 0 if self.__floorDetected == 0: self.__floorDetected = 1 self.popCameraToDest()
class Picker(Viewer): """ View and click objects in a scene.""" def __init__(self): # Parent init. super(Picker, self).__init__() self.disableMouse() # Picker stuff. self.contact_margin = Vec3(0.01, 0.01, 0.01) self.parser = None self.marked = None self.attached_pairs = set() self.contacts = None self.contact_points = None self.contact_bottoms = None self.compound_components = [] self.compound_objects = [] self.joints = JointManager() self.wire_attrib = RenderModeAttrib.make( RenderModeAttrib.MWireframe, 4.) self.attachment_colors = (Vec4(0.1, 0.1, 1., 1.), Vec4(0.1, 0.8, 0.1, 1.), Vec4(1., 0.1, 1., 1.), Vec4(1., 0.5, 0.1, 1.), Vec4(1., 1., 1., 1.)) self.max_attach = 999 self.permanent_events += ["mouse1"] # Make cursor dot. self.cursor = self._build_cursor("cross") s = 0.08 self.cursor.setScale(s, s, s) self.cursor.setColor(1, 1, 1, 1) self.cursor.reparentTo(self.aspect2d) self.taskMgr.add(self.draw_cursor2d, "draw_cursor2d") self.permanent_tasks.append("draw_cursor2d") def init_ssos(self, *args, **kwargs): super(Picker, self).init_ssos(*args, **kwargs) def init_physics(self, *args, **kwargs): super(Picker, self).init_physics(*args, **kwargs) self.joints.bbase = self.bbase def init_picker(self): # Collision traverser self.traverser = CollisionTraverser("traverser") # Collision handler self.handler = CollisionHandlerQueue() # Initialize and set up picker ray node and NodePath self.picker = CollisionNode("mouse_ray") self.pickerNP = self.camera.attachNewNode(self.picker) self.picker.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.picker_ray = CollisionRay() self.picker.addSolid(self.picker_ray) self.traverser.addCollider(self.pickerNP, self.handler) mark_color = (1, 1, 1, 0.3) self.base_mark = self.create_mark(color=mark_color) connector_color = (1, 1, 1, 1) self.base_connector = self.create_connector(color=connector_color) def _build_cursor(self, shape="sphere"): if shape == "sphere": cursor = self._load("sphere.bam") elif shape == "cross": cursor = LineNodePath() lines = [[Point3(-0.5, 0, 0), Point3(0.5, 0, 0)], [Point3(0, 0, -0.5), Point3(0, 0, 0.5)]] cursor.drawLines(lines) cursor.setThickness(1) cursor.create() # cursor = NodePath("cross") # S = {"cylinderX.bam": ((0., 0., 0.), (1., 0.1, 0.1)), # "cylinderY.bam": ((0., 0., 0.), (0.1, 1., 0.1)), # "cylinderZ.bam": ((0., 0., 0.), (0.1, 0.1, 1.))} # for k, v in S.iteritems(): # m = self._load(k) # m.setName(k) # m.setPos(*v[0]) # m.setScale(*v[1]) # m.reparentTo(cursor) #BP() return cursor def create_mark(self, color): """ Makes a graphical mark object.""" # Make a graphical box. props = dict(name="mark", color=color, model="box-round.egg") obj = GSO(props=props) return obj def create_connector(self, color): """ Makes a graphical connector object.""" # Make a graphical box. props = dict(name="connector", color=color, model="connector.egg") obj = GSO(props=props) return obj def start_picker(self, pickables): # Set pickable objs. for i, obj in enumerate(pickables): obj.setTag("pickable", str(i)) # Add mouse events. self.accept("mouse1", self.clicked, extraArgs=[1]) # Start contact detector. detector = ContactDetector(self.bbase.world, self.scene, margin=self.contact_margin) self.contacts = detector.contacts self.contact_bodies = detector.bodies self.contact_points = detector.points parser = Parser(self.contacts, self.contact_bodies) self.contact_bottoms = parser.bottom_bodies self.connectors = {} def stop_picker(self): self.removeTask("mouse1") def goto_sso(self, *args, **kwargs): self.clear_attachments() self.stop_picker() super(Picker, self).goto_sso(*args, **kwargs) self.remove_physics() # Start picker. pickables = self.sso.descendants(type_=PSO) self.start_picker(pickables) self.attach_physics() def get_picked_obj(self): mpos = self.mouseWatcherNode.getMouse() self.picker_ray.setFromLens(self.cam.node(), mpos.getX(), mpos.getY()) self.traverser.traverse(self.render) if self.handler.getNumEntries() > 0: # This is so we get the closest object self.handler.sortEntries() entries = self.handler.getEntries() for entry in entries: picked_obj = entry.getIntoNodePath().findNetTag("pickable") if not picked_obj.isEmpty(): break if picked_obj.isEmpty(): picked_obj = None else: picked_obj = None return picked_obj def clicked(self, button): """ Mouse click handler.""" if self.mouseWatcherNode.hasMouse(): # Get picked object picked_obj = self.get_picked_obj() if picked_obj is not None: if self.marked is None: # New mark activated. self.marked = picked_obj self.show_marked(picked_obj, True) event = "mark" elif picked_obj == self.marked: # Existing mark deactivated. self.show_marked(picked_obj, False) self.marked = None event = "unmark" else: # New attachment or detachment. pair = tuple(sorted((self.marked, picked_obj))) ij = tuple(sorted((self.contact_bodies.index(pair[0]), self.contact_bodies.index(pair[1])))) if ij in self.contacts: f_add = (ij, pair) not in self.attached_pairs if (not f_add or len(self.attached_pairs) < self.max_attach): self.store_attachment(ij, pair, f_add) self.show_marked(self.marked, False) self.marked = None event = "attach" if f_add else "detach" else: print("Max attachments already reached.") event = "max-attach" else: event = "non-contact" else: event = "non-pick" return picked_obj, event def store_attachment(self, ij, pair, f_add): """ Stores the attached objects, and draws them.""" if f_add: self.attached_pairs.add((ij, pair)) self.show_attachment(ij, True) self.attach_pair(pair, True) else: try: self.attached_pairs.remove((ij, pair)) except KeyError: pass else: self.attach_pair(pair, False) self.show_attachment(ij, False) def clear_attachments(self): """ Clear all attachments.""" if self.marked: self.show_marked(self.marked, False) self.marked = None self.mark = None for ij, pair in self.attached_pairs: self.attach_pair(pair, False) self.show_attachment(ij, False) self.attached_pairs = set() # self.reset_compounds() self.contacts = None self.contact_bodies = None self.contact_points = None self.contact_bottoms = None def _make_mark(self, node, extent, name): """ Makes a mark GSO.""" mark = self.base_mark.copy() mat = node.getMat(self.scene) mark.apply_prop(dict(name=name), other=self.scene) mark.setMat(self.scene, mat) mark.setScale(self.scene, mark.getScale(self.scene) + extent) mark.wrtReparentTo(node) return mark def show_marked(self, node, f_on): """ Turns on/off marked graphic.""" if f_on: extent = Vec3(0.15, 0.15, 0.15) name = "mark" self.mark = self._make_mark(node, extent, name) self.mark.init_tree(tags=("model",)) # Exclude object from casting shadows self.mark.hide(self.shadow_mask) self.mark.setTransparency(TransparencyAttrib.MAlpha) self.mark.setDepthWrite(False) self.mark.setBin("fixed", 0, priority=5) else: self.mark.removeNode() def _make_connector(self, parent, points, extent, name): """ Makes connector object.""" connector = self.base_connector.copy() scale = Vec3(*(np.ptp(points, axis=0))) scale_extended = scale + extent pos = Point3(*(np.min(points, axis=0) + scale / 2.)) connector.apply_prop(dict(name=name, scale=scale_extended, pos=pos), other=self.scene) connector.wrtReparentTo(parent) return connector def show_attachment(self, ij, f_on): """ Turns on/off attachment graphic.""" if f_on: parent = self.contact_bottoms[ij] points = self.contact_points[ij] extent = Vec3(0.15, 0.15, 0.15) name = "connector_%d-%d" % ij self.connectors[ij] = self._make_connector(parent, points, extent, name) self.connectors[ij].init_tree(tags=("model",)) else: self.connectors.pop(ij).removeNode() # def attach_pair(self, pair, f_on): # """ Adds/removes physical attachment between a pair of nodes.""" # key = tuple(sorted(p.node() for p in pair)) # # key = frozenset(pair) # if f_on: # # Create the joint and add it. # self.joints[key] = self.joints.make_fixed(*pair) # else: # # Remove it. # del self.joints[key] def attach_physics(self): # Attach `self.scene` to the physics world. try: exclude = zip(*self.compound_components)[0] except IndexError: exclude = [] bnodes = [bnode for bnode in self.scene.descendants(type_=PSO) if bnode not in exclude] for bnode in bnodes: bnode.init_resources(tags=("shape",)) bnode.setCollideMask(BitMask32.allOn()) bnode.node().setDeactivationEnabled(False) self.bbase.attach(bnodes) def reset_compounds(self): for n, p in self.compound_components: n.wrtReparentTo(p) self.compound_components = [] for cnode in self.compound_objects: cnode.destroy_resources() cnode.removeNode() self.compound_objects = [] def make_attachment_graph(self): if not self.contact_bodies: return None n = len(self.contact_bodies) mtx = np.zeros((n, n), dtype="i") for (i, j), _ in self.attached_pairs: # i = self.contact_bodies.index(pair[0]) # j = self.contact_bodies.index(pair[1]) mtx[i, j] = 1 # mtx[j, i] = 1 graph = nx.from_numpy_matrix(mtx) return graph def attach_pair(self, pair, f_on): """ Adds/removes physical attachment between a pair of nodes.""" # Get the connected subgroups. graph = self.make_attachment_graph() sgs = [sg for sg in nx.connected_components(graph) if len(sg) > 1] self.reset_compounds() # Iterate over subgroups, creating compound shapes. for sg in sgs: nodes = [self.contact_bodies[i] for i in sg] parents = [c.getParent() for c in nodes] self.compound_components.extend(zip(nodes, parents)) cname = "+".join([str(i) for i in sorted(sg)]) cnode = CPSO(cname) cnode.reparentTo(self.scene) cnode.add(nodes) cnode.init_tree(tags=("shape",)) cnode.destroy_component_shapes() self.compound_objects.append(cnode)
class World(DirectObject): mySound = base.loader.loadSfx("trial.mp3") #Used for adding a virus at a randomly generated position def random_vgen(self): print 'I am in random' for i in range(0,5): self.a[random.randint(0,7)][random.randint(0,7)] = 1 def initializer(self,level): self.turns = 0 ## Level Definition def levelone(): self.a[4][4] = 1 self.a[4][5] = 1 self.a[4][6] = 1 self.a[5][2] = 1 self.a[3][5] = 1 self.a[4][6] = 1 self.a[5][5] = 1 def leveltwo(): self.a[4][3] = 1 self.a[4][5] = 1 self.a[4][7] = 1 self.a[5][2] = 1 self.a[3][5] = 1 self.a[2][2] = 1 self.a[5][3] = 1 self.a[1][2] = 1 def levelthree(): self.a[4][4] = 1 self.a[4][5] = 1 self.a[4][6] = 1 self.a[5][2] = 1 self.a[3][5] = 1 self.a[4][6] = 1 self.a[5][5] = 1 self.a[4][3] = 1 self.a[4][5] = 1 self.a[4][7] = 1 self.a[5][2] = 1 self.a[3][5] = 1 self.a[2][2] = 1 self.a[5][3] = 1 options = {1: levelone, 2: leveltwo, 3: levelthree } options[level]() print self.a temp = [] count = 0 for element in reversed(self.a): for ele in element: #print 'cheking element is 1 : ' + str(ele) if ele == 1: temp.append(count) self.pieces[count] = Monster(count,WHITE) #self.squares[count].setColor(HIGHLIGHT) count = count + 1 self.list=temp def showscore(self): try: self.score.destroy() except: pass self.score = OnscreenText(text = 'Number of Turns : %s'%(self.turns), pos = (0.5, 0.95), scale = 0.07, mayChange = True) def menuscreen(self): # Callback function to set text def setText(): b.destroy() helptext.destroy() # Add button b = DirectButton(text = ("START", "START", "START", "disabled"), scale=0.15, command=setText, pos=(0,0,0.85)) helptext = OnscreenText(text =''' STORY: Hello Mad Scientist! You are so close to finding the cure to aids! You understood the behaviour and can finally manipulate the virus to kill itself! But time is running out! You have a red and white blood cell sample infected with AIDS Virus. INSTRUCTIONS: The AIDS Virus obeys the Conway's Game of Life. Who would have guessed? 1. If virus is surrounded by more than 3 viruses, it dies of suffocation 2. If virus is surrounded by less than 2 viruses, it dies of underpopulation 3. If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned due to breeding. AIM: To kill all the viruses, by moving one of them every turn. ''', pos = (-0.90,0.72),frame = (123,123,123,1), wordwrap = 25, align = TextNode.ALeft, bg = (0.23,0.243,0.13,0.9)) def endscreen(self): def restart(): taskMgr.remove(self.mouseTask) for i in range(64): self.squares[i].setColor(SquareColor(i)) scorecard.destroy() restartb.destroy() end.destroy() nextlevelb.destroy() self.reference.destroy() self.mySound.stop() try: self.score.destroy() except: pass print 'restarting' print self.a print self.list World() def quitgame(): sys.exit() def nextLevel(): self.currlevel = self.currlevel + 1 nextlevelb.destroy() scorecard.destroy() restartb.destroy() end.destroy() self.score.destroy() self.initializer(self.currlevel) # Add button scorecard = OnscreenText(text = 'You finished it in %s turns! '%(self.turns),frame = (123,123,123,0), wordwrap = 25, bg = (0.2,0,0.8,1)) nextlevelb = DirectButton(text = ("NEXT LEVEL", "NEXT LEVEL", "NEXT LEVEL", "disabled"), scale=0.15, command=nextLevel, pos=(0,0,-0.15)) restartb = DirectButton(text = ("RESTART", "RESTART", "RESTART", "disabled"), scale=0.15, command=restart, pos=(0,0,-0.35)) end = DirectButton(text = ("QUIT", "QUIT", "QUIT", "disabled"), scale=0.15, command=quitgame, pos=(0,0,-0.55)) if self.currlevel == self.maxlevel: nextlevelb.destroy() def __init__(self): #music self.mySound.play() print 'I am being initialized' self.menuscreen() self.list = [] self.turns = 0 self.maxlevel = 3 self.currlevel = 1 self.a =[[0 for x in range(8)] for y in range(8)] #This code puts the standard title and instruction text on screen self.title = OnscreenText(text="Game of Life : Help in ending AIDS!", style=1, fg=(1,1,1,1), pos=(0,-0.95), scale = .07) self.escapeEvent = OnscreenText( text="ESC: Quit", style=1, fg=(1,1,1,1), pos=(-1.3, 0.95), align=TextNode.ALeft, scale = .05) ## self.mouse1Event = OnscreenText( ## text="Left-click and drag: Pick up virus and drag it to a new bloodcell", ## style=1, fg=(1,1,1,1), pos=(-1.3, 0.90), ## align=TextNode.ALeft, scale = .05) ## self.accept('escape', sys.exit) #Escape quits base.disableMouse() #Disble mouse camera control camera.setPosHpr(0, -13.75, 6, 0, -25, 0) #Set the camera self.setupLights() #Setup default lighting #Since we are using collision detection to do picking, we set it up like #any other collision detection system with a traverser and a handler self.picker = CollisionTraverser() #Make a traverser self.pq = CollisionHandlerQueue() #Make a handler #Make a collision node for our picker ray self.pickerNode = CollisionNode('mouseRay') #Attach that node to the camera since the ray will need to be positioned #relative to it self.pickerNP = camera.attachNewNode(self.pickerNode) #Everything to be picked will use bit 1. This way if we were doing other #collision we could seperate it self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() #Make our ray self.pickerNode.addSolid(self.pickerRay) #Add it to the collision node #Register the ray as something that can cause collisions self.picker.addCollider(self.pickerNP, self.pq) #self.picker.showCollisions(render) #We will attach all of the squares to their own root. This way we can do the #collision pass just on the sqaures and save the time of checking the rest #of the scene self.squareRoot = render.attachNewNode("squareRoot") #For each square self.squares = [None for i in range(64)] self.pieces = [None for i in range(64)] for i in range(64): #Load, parent, color, and position the model (a single square polygon) self.squares[i] = loader.loadModel("models/square") self.squares[i].reparentTo(self.squareRoot) self.squares[i].setPos(SquarePos1(i)) self.squares[i].setColor(SquareColor(i)) #Set the model itself to be collideable with the ray. If this model was #any more complex than a single polygon, you should set up a collision #sphere around it instead. But for single polygons this works fine. self.squares[i].find("**/polygon").node().setIntoCollideMask( BitMask32.bit(1)) #Set a tag on the square's node so we can look up what square this is #later during the collision pass self.squares[i].find("**/polygon").node().setTag('square', str(i)) #We will use this variable as a pointer to whatever piece is currently #in this square self.initializer(self.currlevel) #This will represent the index of the currently highlited square self.hiSq = False #This wil represent the index of the square where currently dragged piece #was grabbed from self.dragging = False #Start the task that handles the picking self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask') #self.trial = taskMgr.add(self.trial,'trial') self.accept("mouse1", self.grabPiece) #left-click grabs a piece self.accept("mouse1-up", self.releasePiece) #releasing places it #This function swaps the positions of two pieces def swapPieces(self, fr, to): temp = self.pieces[fr] self.pieces[fr] = self.pieces[to] self.pieces[to] = temp if self.pieces[fr]: print 'imma swapping' self.pieces[fr].square = fr print fr print SquarePos(fr) try: self.pieces[fr].obj.setPos(SquarePos(fr)) except: pass print 'done' if self.pieces[to]: self.pieces[to].square = to try: self.pieces[to].obj.setPos(SquarePos(to)) except: pass def trial(self): self.turns = self.turns + 1 try: self.reference.destroy() except: pass self.reference = OnscreenText( text=''' Reference: virus is surrounded by more than 3 viruses, it dies virus is surrounded by less than 2 viruses, it dies If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned. ''' , style=1, fg=(1,1,1,1), pos=(-1, 0.95), align=TextNode.ALeft, scale = .05) self.showscore() a = self.a while True: for i in self.list: #insert deletion code print 'imma deleting the sq : ' + str(i) self.pieces[i].obj.delete() self.squares[i].setColor(SquareColor(i)) count = 0 a=[[([[sum(b[y1][x1] for b in [[[((-1<x2+dx<len(a[0])) and (-1<y2+dy<len(a))) and a[y2+dy][x2+dx] or 0 for x2 in range(len(a[0]))] for y2 in range(len(a))] for (dx,dy) in [(dx,dy) for dx in [-1,0,1] for dy in [-1,0,1] if (dy!=0 or dx!=0)]]) for x1 in range(len(a[0]))] for y1 in range(len(a))][y][x]== 3 or ([[sum(c[y3][x3] for c in [[[((-1<x4+dx<len(a[0])) and (-1<y4+dy<len(a))) and a[y4+dy][x4+dx] or 0 for x4 in range(len(a[0]))] for y4 in range(len(a))] for (dx,dy) in [(dx,dy) for dx in [-1,0,1] for dy in [-1,0,1] if (dy!=0 or dx!=0)]]) for x3 in range(len(a[0]))] for y3 in range(len(a))][y][x] == 2 and a[y][x]==1)) and 1 or 0 for x in range(len(a[0]))] for y in range(len(a))] lis = [] #insert a random virus at a probability of 1/5 diceroll = random.randint(0,5) if diceroll == 2: self.random_vgen() for element in reversed(a): for ele in element: #print 'cheking element is 1 : ' + str(ele) if ele == 1: lis.append(count) count = count + 1 print lis self.list = lis self.a = a print self.list for i in self.list: self.pieces[i] = Monster(i,WHITE) #self.squares[i].setColor(HIGHLIGHT) print 'leaving trial' if len(self.list)==0: self.endscreen() break return def mouseTask(self, task): #This task deals with the highlighting and dragging based on the mouse #First, clear the current highlight if self.hiSq is not False: self.squares[self.hiSq].setColor(SquareColor(self.hiSq)) self.hiSq = False #Check to see if we can access the mouse. We need it to do anything else if base.mouseWatcherNode.hasMouse(): #get the mouse position mpos = base.mouseWatcherNode.getMouse() #Set the position of the ray based on the mouse position self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) #If we are dragging something, set the position of the object #to be at the appropriate point over the plane of the board if self.dragging is not False: #Gets the point described by pickerRay.getOrigin(), which is relative to #camera, relative instead to render nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin()) #Same thing with the direction of the ray nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection()) try: self.pieces[self.dragging].obj.setPos(PointAtZ(.5, nearPoint, nearVec)) except: pass #Do the actual collision pass (Do it only on the squares for #efficiency purposes) self.picker.traverse(self.squareRoot) if self.pq.getNumEntries() > 0: #if we have hit something, sort the hits so that the closest #is first, and highlight that node self.pq.sortEntries() i = int(self.pq.getEntry(0).getIntoNode().getTag('square')) #Set the highlight on the picked square self.squares[i].setColor(HIGHLIGHT) self.hiSq = i #print 'selected is ' + str(i) return Task.cont def grabPiece(self): #If a square is highlighted and it has a piece, set it to dragging mode if (self.hiSq is not False and self.pieces[self.hiSq]): self.dragging = self.hiSq self.hiSq = False def releasePiece(self): #Letting go of a piece. If we are not on a square, return it to its original #position. Otherwise, swap it with the piece in the new square if self.dragging is not False: #Make sure we really are dragging something #We have let go of the piece, but we are not on a square if self.hiSq is False: try: self.pieces[self.dragging].obj.setPos(SquarePos(self.dragging)) except: pass else: #Otherwise, swap the pieces self.swapPieces(self.dragging, self.hiSq) #self.draggin is the from print self.list print 'you picked this, so Imma deleting this ' + str(self.dragging) #deletion of i after picking it up. try: self.list.remove(self.dragging) except: pass temp2 = [] temp2 = SquarePosTuple(self.dragging) self.a[temp2[0]][temp2[1]] = 0 i = self.hiSq print self.list print 'highlighted sq is ' + str(i) templis = [] templis = SquarePosTuple(i) print templis self.list.append(i) print self.list print templis self.a[templis[0]][templis[1]] = 1 for line in self.a: print line self.trial() #We are no longer dragging anything self.dragging = False def setupLights(self): #This function sets up some default lighting ambientLight = AmbientLight( "ambientLight" ) ambientLight.setColor( Vec4(.8, .8, .8, 1) ) directionalLight = DirectionalLight( "directionalLight" ) directionalLight.setDirection( Vec3( 0, 45, -45 ) ) directionalLight.setColor( Vec4( 0.2, 0.2, 0.2, 1 ) ) render.setLight(render.attachNewNode( directionalLight ) ) render.setLight(render.attachNewNode( ambientLight ) )
class MouseHandler(object): def __init__(self,pandaScene): self.pandaScene = pandaScene def setupMouseCollisionWM(self): self.mouseTraverser = CollisionTraverser() self.mouseCollisionQueue = CollisionHandlerQueue() self.mouseRay = CollisionRay() self.mouseRay.setOrigin(self.pandaScene.worldMapCam.getPos(self.pandaScene.render)) self.mouseRay.setDirection(self.pandaScene.render.getRelativeVector(self.pandaScene.worldMapCam, Vec3(0,1,0))) self.mouseNode = CollisionNode('mouseRay') self.mouseNode.addSolid(self.mouseRay) self.mouseNodePath = self.pandaScene.worldMapCam.attachNewNode(self.mouseNode) self.mouseNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.mouseTraverser.addCollider(self.mouseNodePath, self.mouseCollisionQueue) # uncomment to see the collisions # self.mouseTraverser.showCollisions(self.pandaScene.render) def selectedObjectIdWM(self): if (self.pandaScene.worldMapMouse.hasMouse() == False): return 0,None mpos = self.pandaScene.worldMapMouse.getMouse() self.mouseRay.setFromLens(self.pandaScene.camNode, mpos.getX(), mpos.getY()) self.mouseTraverser.traverse(self.pandaScene.render) if (self.mouseCollisionQueue.getNumEntries() > 0): self.mouseCollisionQueue.sortEntries() entry = self.mouseCollisionQueue.getEntry(0); selectedObj = entry.getIntoNodePath() selectedObj = selectedObj.findNetTag('selectable') if not selectedObj.isEmpty(): return selectedObj.getTag('id'),selectedObj else: return 0,None return 0,None def selectedObjectId(self): if (self.pandaScene.mouseWatcherNode.hasMouse() == False): return 0,None mpos = base.mouseWatcherNode.getMouse() self.mouseRay.setFromLens(self.pandaScene.camNode, mpos.getX(), mpos.getY()) self.mouseTraverser.traverse(self.pandaScene.render) if (self.mouseCollisionQueue.getNumEntries() > 0): self.mouseCollisionQueue.sortEntries() entry = self.mouseCollisionQueue.getEntry(0); selectedObj = entry.getIntoNodePath() selectedObj = selectedObj.findNetTag('selectable') if not selectedObj.isEmpty(): return selectedObj.getTag('id'),selectedObj else: return 0,None return 0,None def setupMouseCollision(self): self.mouseTraverser = CollisionTraverser() self.mouseCollisionQueue = CollisionHandlerQueue() self.mouseRay = CollisionRay() self.mouseRay.setOrigin(self.pandaScene.camera.getPos(self.pandaScene.render)) self.mouseRay.setDirection(self.pandaScene.render.getRelativeVector(self.pandaScene.camera, Vec3(0,1,0))) self.mouseNode = CollisionNode('mouseRay') self.mouseNode.addSolid(self.mouseRay) self.mouseNodePath = self.pandaScene.camera.attachNewNode(self.mouseNode) self.mouseNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.mouseTraverser.addCollider(self.mouseNodePath, self.mouseCollisionQueue)
class World(DirectObject): def __init__(self): self.winprops=WindowProperties() self.winprops.setCursorFilename(Filename.binaryFilename("question-icon.ico")) base.win.setClearColorActive(True) base.win.setClearColor(VBase4(0, 0, 0, 1)) base.win.requestProperties(self.winprops) self.enemyLights = [] self.cameraPositions = [((0, 95, 75), (180, -27, 0)),((0, 55, 25), (180, -15, 0)),((0, -55, 25), (0, -15, 0))] self.cameraIndex = 0 base.disableMouse() base.enableParticles() self.setupLights() self.setupPicking() #Prepare the vehicular manslaughter! self.boosterLightNP = None self.flameLights = None self.player = Vehicle("ralph_models/vampire_car", "ralph_models/vampire_car", self, "player") self.finalGas = None self.livesFrame = DirectFrame(frameColor=(0, 0, 0, 0), parent = base.a2dTopLeft) self.livesSprites = list() for i in range(0,self.player.health): sprite = OnscreenImage(image = 'images/healthicon.png', parent = self.livesFrame, scale = 0.08, pos = (0.2*i+0.1,0,-0.1)) sprite.setTransparency(TransparencyAttrib.MAlpha) self.livesSprites.append(sprite) self.progressFrame = DirectFrame(frameColor=(0, 0, 0, 0), parent = base.a2dpTopRight) gasIcon = OnscreenImage(image = 'images/gas_icon.png', parent = self.progressFrame, scale = 0.04, pos = (-1,0,-0.05)) # gasIcon.reparentTo(aspect2d) gasIcon.setTransparency(TransparencyAttrib.MAlpha) # gasBar = OnscreenImage(image = 'images/gas_bar.png', parent = self.progressFrame, scale = 0.4)#, pos = (-0.9,0,-0.05)) self.gasMax = DirectFrame(frameColor=(.133, .149, .149, 1),frameSize=(-1, 1, -1, 1), parent = self.progressFrame, scale = (0.432,1,0.055625), pos = (-.5,0,-0.04)) self.gasLevel = DirectFrame(frameColor=(.433, .149, .149, 1),frameSize=(-1, -1, -1, 1), parent = self.progressFrame, scale = (0.432,1,0.055625), pos = (-.5,0,-0.04)) gasBar = OnscreenImage(image = 'images/gas_bar_border.png', scale = (1,1,.9), pos = (-.0005,0,-0.04)) gasBar.reparentTo(self.gasLevel) gasBar.setTransparency(TransparencyAttrib.MAlpha) timeBar = OnscreenImage(image = 'images/time_bar.png', parent = self.progressFrame, scale = (0.44,1,0.0525), pos = (-.47,0,-0.15)) self.timePointer = OnscreenImage(image = 'images/time_bar_marker.png', parent = timeBar, scale = (0.05, 0, .2222), pos = (-.83,0,-0.15)) # self.timePointer = OnscreenImage(image = 'images/time_bar_marker.png', parent = self.timeBar, scale = (0.44,1,0.0525), pos = (-.47,0,-0.2)) timeBar.setTransparency(TransparencyAttrib.MAlpha) taskMgr.add(self.updateGasBar, "Update gas") self.loadModels() self.player.setPos(0,0,0) self.setupIntervals() camera.reparentTo(self.player) camera.setPos(self.cameraPositions[0][0][0],self.cameraPositions[0][0][1],self.cameraPositions[0][0][2]) camera.setHpr(self.cameraPositions[0][1][0],self.cameraPositions[0][1][1],self.cameraPositions[0][1][2]) self.setupCollisions() render.setShaderAuto() #you probably want to use this self.keyMap = {"left":0, "right":0, "forward":0, "backwards":0} taskMgr.add(self.player.move, "moveTask") #Give the vehicle direct access to the keyMap self.player.addKeyMap(self.keyMap) #Player Death taskMgr.add(self.deathChecker, "deathTask") #Sounds! self.loadSounds() self.currIcon = "" self.prevtime = 0 self.isMoving = False self.accept("escape", sys.exit) self.accept("arrow_up", self.setKey, ["forward", 1]) self.accept("w", self.setKey, ["forward", 1]) self.accept("arrow_right", self.setKey, ["right", 1]) self.accept("d", self.setKey, ["right", 1]) self.accept("arrow_left", self.setKey, ["left", 1]) self.accept("a", self.setKey, ["left", 1]) self.accept("arrow_down", self.setKey, ["backwards", 1]) self.accept("s", self.setKey, ["backwards", 1]) self.accept("arrow_up-up", self.setKey, ["forward", 0]) self.accept("w-up", self.setKey, ["forward", 0]) self.accept("arrow_right-up", self.setKey, ["right", 0]) self.accept("d-up", self.setKey, ["right", 0]) self.accept("arrow_left-up", self.setKey, ["left", 0]) self.accept("a-up", self.setKey, ["left", 0]) self.accept("arrow_down-up", self.setKey, ["backwards", 0]) self.accept("s-up", self.setKey, ["backwards", 0]) self.accept("mouse1", self.startShoot) self.accept("mouse1-up", self.stopShoot) self.accept("mouse3", self.startDrain ) self.accept("mouse3-up" , self.stopDrain) self.accept("tab", self.shiftCamera) self.accept("space", self.player.startBoosters) self.accept("ate-smiley", self.eat) self.p1 = ParticleEffect() self.p2 = ParticleEffect() self.alan_var = False #Show collisiony stuff if DEBUG: base.cTrav.showCollisions(render) #f = open('testLog.txt', 'r+') #self.dfs(file = f) self.gasPlaying = False self.setLights() self.draining = False taskMgr.add(self.drain, 'drain') self.drainTime = 0.0 self.flamethrowerActive = False self.gasLossTime = 0.0 self.gasLossRate = 1.0 taskMgr.add(self.loseHealth, "loseGas") #After all the loading, we need to calculate our start time self.startTime = datetime.datetime.now() self.timeLimit = datetime.timedelta(seconds=175) timeInterval = LerpPosInterval(self.timePointer, self.timeLimit.seconds, (.8,0,-0.2)) timeInterval.start() def setupPicking(self): self.picker = CollisionTraverser() self.pq = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.picker.addCollider(self.pickerNP, self.pq) self.staticRoot = render.attachNewNode('staticRoot') self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask') def dfs(self, item = render, depth = 0, file = None): if file: file.write(("-" * depth) + item.getName() + ": \n") # print(("-" * depth) + item.getName() + ": ") for i in range(item.getNumNodes()): if file: file.write((" " * depth) + "+" + item.getNode(i).getName() + ": " + str(item.getNode(i).getClassType()) + "\n") # print((" " * depth) + "+" + item.getNode(i).getName() + ": " + str(item.getNode(i).getClassType())) for i in range(item.getNumChildren()): self.dfs(item.getChild(i), depth + 1, file) def startDrain(self): if not self.flamethrowerActive: prevDraining = self.draining #previous value of draining if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.picker.traverse(self.staticRoot) if self.pq.getNumEntries() > 0: self.pq.sortEntries() for i in range(self.pq.getNumEntries()): if self.pq.getEntry(i).getIntoNode().getTag('car') != "": self.target = int(self.pq.getEntry(i).getIntoNode().getTag('car')) self.draining = True #Start sounds if self.draining started if self.draining and not prevDraining: self.drainSound.play() def drain(self, task): if self.draining and task.time - self.drainTime > DRAIN_DELAY: carpos = self.staticCars[self.target].getPos() playerpos = self.player.getPos() dist = math.sqrt( (carpos[0] - playerpos[0])**2 + (carpos[1] - playerpos[1])**2 + (carpos[2] - playerpos[2])**2 ) if self.gasList[self.target] > 0 and dist < DRAIN_DIST: if not self.gasPlaying: self.gasP.reset() self.gasP = ParticleEffect() self.gasP.loadConfig(Filename('oil.ptf')) self.gasP.start(self.player) self.gasNode.lookAt(self.staticCars[self.target]) self.gasP.setPos(0,0,2) self.gasP.setScale(1.5) self.gasP.setLightOff() self.gasPlaying = True self.alan_var = False self.gasNode.lookAt(self.staticCars[self.target]) self.gasP.setHpr(self.gasNode.getH() + 180, 90, 0) self.player.totalGas = self.player.totalGas + 1 self.gasList[self.target] = self.gasList[self.target] - 1 else: self.alan_var = True # print "TotalGas: " + str(self.player.totalGas) self.drainTime = task.time elif not self.draining or self.alan_var: self.gasP.softStop() self.drainSound.stop() self.gasPlaying = False return Task.cont def stopDrain(self): self.draining = False def loseHealth(self, task): if task.time - self.gasLossTime > GAS_TIME: if self.player.direction != 0: self.player.totalGas = self.player.totalGas - self.gasLossRate elif self.flamethrowerActive: self.player.totalGas = self.player.totalGas - self.gasLossRate self.gasLossTime = task.time # print self.player.totalGas return Task.cont def mouseTask(self, task): j = -1 if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.picker.traverse(self.staticRoot) if self.pq.getNumEntries() > 0: self.pq.sortEntries() for i in range(self.pq.getNumEntries()): if self.pq.getEntry(i).getIntoNode().getTag('car') != "": j = int(self.pq.getEntry(i).getIntoNode().getTag('car')) carpos = self.staticCars[j].getPos() playerpos = self.player.getPos() dist = math.sqrt( (carpos[0] - playerpos[0])**2 + (carpos[1] - playerpos[1])**2 + (carpos[2] - playerpos[2])**2 ) if self.gasList[j] > 0 and dist < DRAIN_DIST: self.winprops.setCursorFilename(Filename.binaryFilename("vamp-icon.ico")) base.win.requestProperties(self.winprops) elif self.gasList[j] > 0: self.winprops.setCursorFilename(Filename.binaryFilename("vamp-off.ico")) base.win.requestProperties(self.winprops) else: self.winprops.setCursorFilename(Filename.binaryFilename("empty-icon.ico")) base.win.requestProperties(self.winprops) break if j == -1: self.winprops.setCursorFilename(Filename.binaryFilename("question-icon.ico")) base.win.requestProperties(self.winprops) #print j return Task.cont def setupIntervals(self): self.lightOn = LerpFunc(self.lightModify, fromData=0, toData=100, duration=0.2, blendType='noBlend', extraArgs=[True], name="LightUp") self.lightOff = LerpFunc(self.lightModify, fromData=0, toData=100, duration=0.2, blendType='noBlend', extraArgs=[False], name="LightDown") self.cameraMove = None def setKey(self, key, value): self.keyMap[key] = value def setWorldLight(self, object): object.setLight(self.keyLightNP) object.setLight(self.fillLightNP) object.setLight(self.boosterLightNP) for light in self.enemyLights: object.setLight(light) def setLights(self): self.setWorldLight(self.player) self.setWorldLight(self.env) for enemy in self.enemies: self.setWorldLight(enemy) for car in self.staticCars: self.setWorldLight(car) def shiftCamera(self): if self.cameraMove: self.cameraMove.finish() old = self.cameraIndex self.cameraIndex += 1 if self.cameraIndex == len(self.cameraPositions): self.cameraIndex = 0 self.cameraMove=LerpPosHprInterval(camera, .7, self.cameraPositions[self.cameraIndex][0], self.cameraPositions[self.cameraIndex][1], camera.getPos(), camera.getHpr()) self.cameraMove.start() def loadModels(self): self.player.setupBooster() self.env = loader.loadModel("ralph_models/final_terrain") self.env.reparentTo(render) self.env.setScale(8) # Gas particles self.gasP = ParticleEffect() self.gasNode = self.player.attachNewNode('gasNode') # Node Map map = Node.NodeMap("nodes.txt") # enemies self.enemies = [] file = open('levels/enemies.txt' ) line = file.readline().rstrip() self.staticCars = [] self.gasList = [] for currCar in carLocations.cars: target = loader.loadModel("ralph_models/" + currCar['color'] + "_car") target.setPos(currCar['position']) target.setHpr(currCar['direction']) target.reparentTo(self.staticRoot) self.staticCars.append(target) self.gasList.append(currCar['gas']) while line != "" : nums = line.split(',') convertedNums = [] for i in range(len(nums)): if i != 0: convertedNums.append(int(nums[i])) nodePos = map.nodeList[int(nums[0])].getPos() newEnemy = Enemy.Enemy(map, convertedNums, self, nodePos[0], nodePos[1], nodePos[2] ) self.enemies.append( newEnemy ) taskMgr.add(newEnemy.move, "Enemy Move " + str(i), extraArgs = [map], appendTask = True) line = file.readline().rstrip() i = i + 1 def loadSounds(self): self.flamethrowerSound = base.loader.loadSfx("sound/dragonflameloop2.wav") self.flamethrowerEndSound = base.loader.loadSfx("sound/dragonflameend.wav") self.collideSound = base.loader.loadSfx("sound/collide.wav") self.drainSound = base.loader.loadSfx("sound/gas_pump.wav") self.drainSound.setLoop(True) def setupLights(self): #ambient light self.ambientLight = AmbientLight("ambientLight") #four values, RGBA (alpha is largely irrelevent), value range is 0:1 self.ambientLight.setColor((.30, .30, .30, 1)) self.ambientLightNP = render.attachNewNode(self.ambientLight) #the nodepath that calls setLight is what gets illuminated by the light render.setLight(self.ambientLightNP) #call clearLight() to turn it off self.keyLight = DirectionalLight("keyLight") self.keyLight.setColor((.50,.50,.50, 1)) self.keyLightNP = render.attachNewNode(self.keyLight) self.keyLightNP.setHpr(0, -26, 0) self.fillLight = DirectionalLight("fillLight") self.fillLight.setColor((.05,.05,.05, 1)) self.fillLightNP = render.attachNewNode(self.fillLight) self.fillLightNP.setHpr(30, 0, 0) def setupCollisions(self): base.cTrav = CollisionTraverser() self.playerRay = CollisionRay() self.playerRay.setOrigin(0,0,1000) self.playerRay.setDirection(0,0,-1) self.playerNode = CollisionNode("playerRay") self.playerNode.addSolid(self.playerRay) self.playerNode.setFromCollideMask(BitMask32.bit(0)) self.playerNode.setIntoCollideMask(BitMask32.allOff()) self.playerNodePath = self.player.attachNewNode(self.playerNode) self.playerNodePath.show() self.playerGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.playerNodePath, self.playerGroundHandler) envcNode1 = CollisionNode("lot_bottom") envcNode1.setFromCollideMask(BitMask32.bit(0)) temp = CollisionPolygon(Point3(12.56, 19.182, 0), Point3(12.56, -21.261, 0), Point3(-13.217, -21.261, 0), Point3(-13.217, 19.182, 0)) envcNode1.addSolid(temp) envcNode2 = CollisionNode("lot_ramp_bottom") envcNode2.setFromCollideMask(BitMask32.bit(0)) temp = CollisionPolygon(Point3(32.715, -14.923, 3.5), Point3(32.715, -21.261, 3.5), Point3(12.56, -21.261, 0), Point3(12.56, -14.923, 0)) envcNode2.addSolid(temp) envcNode3 = CollisionNode("lot_middle") envcNode3.setFromCollideMask(BitMask32.bit(0)) temp = CollisionPolygon(Point3(42.715, -14.923, 3.5), Point3(42.715, -21.261, 3.5), Point3(32.715, -21.261, 3.5), Point3(32.715, -14.923, 3.5)) envcNode3.addSolid(temp) envcNode4 = CollisionNode("lot_ramp_top") envcNode4.setFromCollideMask(BitMask32.bit(0)) temp = CollisionPolygon(Point3(42.715, -8.845, 6), Point3(42.715, -14.923, 3.5), Point3(32.715, -14.923, 3.5), Point3(32.715, -8.845, 6)) envcNode4.addSolid(temp) envcNode5 = CollisionNode("lot_top") envcNode5.setFromCollideMask(BitMask32.bit(0)) temp = CollisionPolygon(Point3(42.715, 16.155, 6), Point3(42.715, -8.845, 6), Point3(17.715, -8.845, 6), Point3(17.715, 16.155, 6)) envcNode5.addSolid(temp) wallCNode = CollisionNode("fence") wallCNode.setFromCollideMask(BitMask32.bit(0)) temp = CollisionPolygon(Point3(12.56, 19.182, 0), Point3(12.56, -14.923, 0), Point3(12.56, -14.923, 10), Point3(12.56, 19.182, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(12.56, -14.923, 0), Point3(32.715, -14.923, 3.5), Point3(32.715, -14.923, 10), Point3(12.56, -14.923, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(32.715, -14.923, 3.5), Point3(32.715, -8.845, 6), Point3(32.715, -8.845, 10), Point3(32.715, -14.923, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(32.715, -8.845, 6), Point3(17.715, -8.845, 6), Point3(17.715, -8.845, 10), Point3(32.715, -8.845, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(17.715, -8.845, 6), Point3(17.715, 16.155, 6), Point3(17.715, 16.155, 10), Point3(17.715, -8.845, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(17.715, 16.155, 6), Point3(42.715, 16.155, 6), Point3(42.715, 16.155, 10), Point3(17.715, 16.155, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(42.715, 16.155, 6), Point3(42.715, -8.845, 6), Point3(42.715, -8.845, 10), Point3(42.715, 16.155, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(42.715, -8.845, 6), Point3(42.715, -14.923, 3.5), Point3(42.715, -14.923, 10), Point3(42.715, -8.845, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(42.715, -14.923, 3.5), Point3(42.715, -21.261, 3.5), Point3(42.715, -21.261, 10), Point3(42.715, -14.923, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(42.715, -21.261, 3.5), Point3(32.715, -21.261, 3.5), Point3(32.715, -21.261, 10), Point3(42.715, -21.261, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(32.715, -21.261, 3.5), Point3(12.56, -21.261, 0), Point3(12.56, -21.261, 10), Point3(32.715, -21.261, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(12.56, -21.261, 0), Point3(-13.217, -21.261, 0), Point3(-13.217, -21.261, 10), Point3(12.56, -21.261, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(-13.217, -21.261, 0), Point3(-13.217, 19.182, 0), Point3(-13.217, 19.182, 10), Point3(-13.217, -21.261, 10)) wallCNode.addSolid(temp) temp = CollisionPolygon(Point3(-13.217, 19.182, 0), Point3(12.56, 19.182, 0), Point3(12.56, 19.182, 10), Point3(-13.217, 19.182, 10)) wallCNode.addSolid(temp) envcNodePath1 = self.env.attachNewNode(envcNode1) envcNodePath2 = self.env.attachNewNode(envcNode2) envcNodePath3 = self.env.attachNewNode(envcNode3) envcNodePath4 = self.env.attachNewNode(envcNode4) envcNodePath5 = self.env.attachNewNode(envcNode5) self.cHandler = CollisionHandlerEvent() pusher = CollisionHandlerPusher() self.wallNode = self.env.attachNewNode('wallNode') wallCNodePath = self.wallNode.attachNewNode(wallCNode) if DEBUG: wallCNodePath.show() cNode = CollisionNode("player") temp = CollisionSphere((0,-5.5,10), 4) cNode.addSolid(temp) temp = CollisionSphere((0,-0.5,10), 4) cNode.addSolid(temp) temp = CollisionSphere((0,3.5,10), 4) cNode.addSolid(temp) cNode.setIntoCollideMask(BitMask32.allOff()) #player is *only* a from object cNodePath = self.player.attachNewNode(cNode) if DEBUG: cNodePath.show() base.cTrav.addCollider(cNodePath, pusher) pusher.addCollider(cNodePath, self.player) pusher.addInPattern('%fn-into-%in') self.accept('player-into-fence', self.collideWithFence) self.accept('player-into-staticCar', self.collideOther) self.accept('player-into-droneNode', self.collideOther) self.playerLightCollision = CollisionHandlerEvent() self.playerLightCollision.addInPattern('into-%in') cNode2 = CollisionNode("playerinto") #cNode.addSolid(segment1) #cNode.addSolid(segment2) #cNode.addSolid(segment3) #cNode.addSolid(segment4) temp = CollisionSphere((0,-5.5,1), 4) cNode2.addSolid(temp) temp = CollisionSphere((0,-0.5,1), 4) cNode2.addSolid(temp) temp = CollisionSphere((0,3.5,1), 4) cNode2.addSolid(temp) cNode2.setFromCollideMask(BitMask32.allOff()) #player is *only* a from object cNodePath2 = self.player.attachNewNode(cNode2) if DEBUG: cNodePath2.show() # FLAMETHROWER COLLISIONS # left flamethrowerLeft = CollisionSegment() flamethrowerLeft.setPointA(-2 , -4, 10) flamethrowerLeft.setPointB( -2 , -20 , 10 ) # middle flamethrowerMiddle = CollisionSegment() flamethrowerMiddle.setPointA(0 , -4, 10) flamethrowerMiddle.setPointB( 0 , -20 , 10 ) # right flamethrowerRight = CollisionSegment() flamethrowerRight.setPointA(2, -4, 10) flamethrowerRight.setPointB( 2 , -20 , 10 ) flamethrowerNode = CollisionNode("flamethrower") flamethrowerNode.addSolid(flamethrowerLeft) flamethrowerNode.addSolid(flamethrowerMiddle) flamethrowerNode.addSolid(flamethrowerRight) flamethrowerNode.setIntoCollideMask(BitMask32.allOff()) flamethrowerNode.setFromCollideMask(BitMask32.allOn()) flamethrowerNodePath = self.player.attachNewNode(flamethrowerNode) #flamethrowerNodePath.show() self.flamethrowerCollision = CollisionHandlerEvent() self.flamethrowerCollision.addInPattern('into-%in') base.cTrav.addCollider(flamethrowerNodePath, self.flamethrowerCollision) self.accept('into-droneNode', self.hitEnemy) for i in range(len(self.staticCars)): staticNode = CollisionNode("staticCar") temp = CollisionSphere((0,-5.2,10), 4) staticNode.addSolid(temp) temp = CollisionSphere((0,-0.5,10), 4) staticNode.addSolid(temp) temp = CollisionSphere((0,5.5,10), 4) staticNode.addSolid(temp) staticNode.setIntoCollideMask(BitMask32.bit(1)) staticNode.setFromCollideMask(BitMask32.bit(0)) staticNodePath = self.staticCars[i].attachNewNode(staticNode) temp = CollisionTube(0,7,3,0,-6,3,3.5) sN = CollisionNode("staticTube") sN.addSolid(temp) staticNode.setFromCollideMask(BitMask32.bit(0)) sNP = self.staticCars[i].attachNewNode(sN) sN.setTag('car', str(i)) self.enemyHandler = CollisionHandlerEvent() for i in range(len(self.enemies)): collideNode = CollisionNode("droneNode") temp = CollisionSphere((0,0,10), 4) collideNode.addSolid(temp) collideNode.setIntoCollideMask(BitMask32.bit(1)) collideNode.setFromCollideMask(BitMask32.bit(0)) enemycollideNodePath = self.enemies[i].attachNewNode(collideNode) collideNode.setTag('enemy',str(i)) self.enemies[i].lightRay = CollisionSegment() self.enemies[i].lightRay.setPointA(0, -4, 4) self.enemies[i].lightRay.setPointB( 0 , -100 , 0 ) # left self.enemies[i].lightRayLeft = CollisionSegment() self.enemies[i].lightRayLeft.setPointA(0, -4, 4) self.enemies[i].lightRayLeft.setPointB( -5 , -100 , 0 ) # right self.enemies[i].lightRayRight = CollisionSegment() self.enemies[i].lightRayRight.setPointA(0, -4, 4) self.enemies[i].lightRayRight.setPointB( 5 , -100 , 0 ) self.enemies[i].lightRayNode = CollisionNode("lightRay") self.enemies[i].lightRayNode.addSolid(self.enemies[i].lightRay) self.enemies[i].lightRayNode.addSolid(self.enemies[i].lightRayLeft) self.enemies[i].lightRayNode.addSolid(self.enemies[i].lightRayRight) self.enemies[i].lightRayNode.setTag('enemy',str(i)) self.enemies[i].lightRayNode.setIntoCollideMask(BitMask32.allOff()) self.enemies[i].lightRayNodePath = self.enemies[i].attachNewNode(self.enemies[i].lightRayNode) if DEBUG: self.enemies[i].lightRayNodePath.show() base.cTrav.addCollider(self.enemies[i].lightRayNodePath, self.playerLightCollision) self.accept('into-playerinto', self.player.takeHit) def collideWithFence(self, entry): self.player.speed = self.player.speed * 0.9 if self.collideSound.status() != AudioSound.PLAYING: self.collideSound.play() def collideOther(self, entry): self.player.speed = self.player.speed * 0.9 if self.collideSound.status() != AudioSound.PLAYING: self.collideSound.play() def lightModify(self, t, which_way): if which_way: #which_way == true then make it brighter value = t/100 * MAX_LIGHT else: #which_way == true then make it darker value = (100 - t)/100 * MAX_LIGHT for light in self.flameLights: light[0].setColor(VBase4(value,value,value,1)) def startShoot(self): self.loadParticleConfig('flamethrower6.ptf') #self.lightOff.finish() #self.lightOn.start() #Get the flame noise started! self.flamethrowerSound.setLoop(True) self.flamethrowerSound.play() self.flamethrowerActive = True self.draining = False self.gasLossRate = 2.0 def stopShoot(self): self.p1.softStop() self.p2.softStop() #self.lightOn.finish() #self.lightOff.start() self.flamethrowerSound.stop() self.flamethrowerEndSound.play() self.flamethrowerActive = False self.gasLossRate = 1.0 def hitEnemy(self, entry): if self.flamethrowerActive: index = int(entry.getIntoNode().getTag('enemy')) if self.enemies[index].phase != STOPPED: self.enemies[index].prevPhase = self.enemies[index].phase self.enemies[index].phase = STOPPED self.enemies[index].headlight1.setColor(VBase4(0, 0, 0, 0)) def loadParticleConfig(self, file): self.p1.reset() self.p1 = ParticleEffect() self.p1.loadConfig(Filename(file)) self.p1.start(self.player) self.p1.setPos(-1.75, -10, 1.375) self.p1.setHpr(0, 90, 0) self.p1.setScale(2.0) self.p1.setLightOff() self.p2.reset() self.p2 = ParticleEffect() self.p2.loadConfig(Filename(file)) self.p2.start(self.player) self.p2.setPos(1.75, -10, 1.375) self.p2.setHpr(0, 90, 0) self.p2.setScale(2.0) self.p2.setLightOff() def eat(self, cEntry): """handles the player eating a smiley""" #remove target from list of targets self.targets.remove(cEntry.getIntoNodePath().getParent()) #remove from scene graph cEntry.getIntoNodePath().getParent().remove() def changeMouseCursor(self, cursorFile): if self.currIcon != cursorFile: self.currIcon = cursorFile # winprops.getParentWindow().getXSize() # print winprops.getXSize() # print "test" self.winprops.setCursorFilename(Filename.binaryFilename(cursorFile)) def deathChecker(self, task): font = loader.loadFont('fonts/beneg.ttf') #Check for out of time currTime = datetime.datetime.now() if currTime > self.startTime + self.timeLimit or self.player.totalGas >= MAX_GAS: #print "OUT OF TIME!!!!!!!!!!!" if self.finalGas is None: self.finalGas = self.player.totalGas taskMgr.doMethodLater(5, self.STOPGAME, 'tickTask') self.loading = OnscreenImage(image = 'images/victory.png', scale = (1.3333333,0, 1)) self.text = OnscreenText(text = "Gas Collected%s" %(self.finalGas), font = font, pos = (0,.2), fg = (255,255,255,1)) #Check for death elif self.player.dead: if self.finalGas is None: self.finalGas = self.player.totalGas #print "THE PLAYER IS DEAD!!!!!!!!!!" taskMgr.doMethodLater(5, self.STOPGAME, 'tickTask') self.loading = OnscreenImage(image = 'images/lose_death.png', scale = (1.3333333,0, 1)) self.text = OnscreenText(text = "Gas Collected %s" %(self.finalGas), font = font, pos = (0,.1), fg = (255,255,255,1)) elif self.player.totalGas <= 0: #print "YOU SUCK. YOU RAN OUT OF GAS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" taskMgr.doMethodLater(5, self.STOPGAME, 'tickTask') self.loading = OnscreenImage(image = 'images/lose_nogas.png', scale = (1.3333333,0, 1)) return Task.cont def updateGasBar(self, task): self.gasLevel['frameSize'] = (-1,(self.player.totalGas / MAX_GAS)*2 - 1, -1, 1) return Task.cont def STOPGAME(self, SOMETHNG): taskMgr.stop()
class CollisionAvatar(): """Collision for avatar """ def __init__(self, game): self.game = game self.enable = False self.camera = self.game.gui.camera self.debug = False self.sphere_node = CollisionNode('Sphere') self.sphere_nodepath = self.game.world.avatar.attachNewNode(self.sphere_node) self.sphere_node.setFromCollideMask(BitMask32.bit(2)) self.sphere_node.setIntoCollideMask(BitMask32.bit(4)) self.sphere = CollisionSphere(0, 0, 0.5, 0.5) self.sphere_node.addSolid(self.sphere) self.sphere_handler = CollisionHandlerQueue() self.ray_node = CollisionNode('downRay') self.ray_nodepath = self.game.world.avatar.attachNewNode(self.ray_node) self.ray_node.setFromCollideMask(BitMask32.bit(1)) self.ray_node.setIntoCollideMask(BitMask32.bit(3)) self.ray = CollisionRay() self.ray.setOrigin(0, 0, 5) self.ray.setDirection(0, 0, -1) self.ray_node.addSolid(self.ray) self.ray_handler = CollisionHandlerQueue() def set_debug(self, value): """docstring for debug """ self.debug = value if self.debug: self.ray_nodepath.show() self.sphere_nodepath.show() else: self.ray_nodepath.hide() self.sphere_nodepath.hide() def set_enable(self, value, Fly = True): self.enable = value self.fly = Fly if self.enable: self.game.gui.cTrav.addCollider(self.ray_nodepath, self.ray_handler) self.game.gui.cTrav.addCollider(self.sphere_nodepath, self.sphere_handler) else: self.game.gui.cTrav.removeCollider(self.ray_nodepath) self.game.gui.cTrav.removeCollider(self.sphere_nodepath) def detector(self): if not self.enable: return self.game.gui.cTrav.traverse(self.game.world.root_node) if self.sphere_handler.getNumEntries() > 0: #self.sphere_handler.sortEntries() self.game.world.avatar.setPos(self.game.world.root_node, self.lastpos) if self.ray_handler.getNumEntries() > 0: self.ray_handler.sortEntries() pickedObj = self.ray_handler.getEntry(0).getIntoNodePath() pickedObj = pickedObj.findNetTag('Chunk') if not pickedObj.isEmpty(): Z = self.ray_handler.getEntry(0).\ getSurfacePoint(self.game.world.root_node).getZ() if self.fly: if Z > self.game.world.avatar.getZ(self.game.world.root_node): self.game.world.avatar.setZ(self.game.world.root_node, Z) else: self.game.world.avatar.setZ(self.game.world.root_node, Z)
class World(DirectObject): mySound = base.loader.loadSfx("trial.mp3") def random_vgen(self): print 'I am in random' for i in range(0, 5): self.a[random.randint(0, 7)][random.randint(0, 7)] = 1 def initializer(self, level): self.turns = 0 ## Level Definition def levelone(): self.a[4][4] = 1 self.a[4][5] = 1 self.a[4][6] = 1 self.a[5][2] = 1 self.a[3][5] = 1 self.a[4][6] = 1 self.a[5][5] = 1 def leveltwo(): self.a[4][3] = 1 self.a[4][5] = 1 self.a[4][7] = 1 self.a[5][2] = 1 self.a[3][5] = 1 self.a[2][2] = 1 self.a[5][3] = 1 self.a[1][2] = 1 def levelthree(): self.a[4][4] = 1 self.a[4][5] = 1 self.a[4][6] = 1 self.a[5][2] = 1 self.a[3][5] = 1 self.a[4][6] = 1 self.a[5][5] = 1 self.a[4][3] = 1 self.a[4][5] = 1 self.a[4][7] = 1 self.a[5][2] = 1 self.a[3][5] = 1 self.a[2][2] = 1 self.a[5][3] = 1 options = {1: levelone, 2: leveltwo, 3: levelthree} options[level]() temp = [] count = 0 for element in reversed(self.a): for ele in element: #print 'cheking element is 1 : ' + str(ele) if ele == 1: temp.append(count) self.pieces[count] = Pawn(count, WHITE) #self.squares[count].setColor(HIGHLIGHT) count = count + 1 self.list = temp def showscore(self): try: self.score.destroy() except: pass self.score = OnscreenText(text='Number of Turns : %s' % (self.turns), pos=(0.5, 0.95), scale=0.07, mayChange=True) def menuscreen(self): # Callback function to set text def setText(): b.destroy() helptext.destroy() # Add button b = DirectButton(text=("START", "START", "START", "disabled"), scale=0.15, command=setText, pos=(0, 0, 0.85)) helptext = OnscreenText(text=''' STORY: Hello Mad Scientist! You are so close to finding the cure to aids! You understood the behaviour and can finally manipulate the virus to kill itself! But time is running out! You have a red and white blood cell sample infected with AIDS Virus. INSTRUCTIONS: The AIDS Virus obeys the Conway's Game of Life. Who would have guessed? 1. If virus is surrounded by more than 3 viruses, it dies of suffocation 2. If virus is surrounded by less than 2 viruses, it dies of underpopulation 3. If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned due to breeding. AIM: To kill all the viruses, by moving one of them every turn. ''', pos=(-0.90, 0.72), frame=(123, 123, 123, 1), wordwrap=25, align=TextNode.ALeft, bg=(0.23, 0.243, 0.13, 0.9)) def endscreen(self): def restart(): scorecard.destroy() restartb.destroy() end.destroy() nextlevelb.destroy() self.reference.destroy() self.mySound.stop() try: self.score.destroy() except: pass World() def quitgame(): sys.exit() def nextLevel(): self.currlevel = self.currlevel + 1 nextlevelb.destroy() scorecard.destroy() restartb.destroy() end.destroy() self.score.destroy() self.initializer(self.currlevel) # Add button scorecard = OnscreenText(text='You finished it in %s turns! ' % (self.turns), frame=(123, 123, 123, 0), wordwrap=25, bg=(0.2, 0, 0.8, 1)) nextlevelb = DirectButton(text=("NEXT LEVEL", "NEXT LEVEL", "NEXT LEVEL", "disabled"), scale=0.15, command=nextLevel, pos=(0, 0, -0.15)) restartb = DirectButton(text=("RESTART", "RESTART", "RESTART", "disabled"), scale=0.15, command=restart, pos=(0, 0, -0.35)) end = DirectButton(text=("QUIT", "QUIT", "QUIT", "disabled"), scale=0.15, command=quitgame, pos=(0, 0, -0.55)) if self.currlevel == self.maxlevel: nextlevelb.destroy() def __init__(self): #music self.mySound.play() print 'I am being initialized' self.menuscreen() self.list = [] self.turns = 0 self.maxlevel = 3 self.currlevel = 1 self.a = [[0 for x in range(8)] for y in range(8)] #This code puts the standard title and instruction text on screen self.title = OnscreenText(text="Game of Life : Help in ending AIDS!", style=1, fg=(1, 1, 1, 1), pos=(0, -0.95), scale=.07) self.escapeEvent = OnscreenText(text="ESC: Quit", style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.95), align=TextNode.ALeft, scale=.05) ## self.mouse1Event = OnscreenText( ## text="Left-click and drag: Pick up virus and drag it to a new bloodcell", ## style=1, fg=(1,1,1,1), pos=(-1.3, 0.90), ## align=TextNode.ALeft, scale = .05) ## self.accept('escape', sys.exit) #Escape quits base.disableMouse() #Disble mouse camera control camera.setPosHpr(0, -13.75, 6, 0, -25, 0) #Set the camera self.setupLights() #Setup default lighting #Since we are using collision detection to do picking, we set it up like #any other collision detection system with a traverser and a handler self.picker = CollisionTraverser() #Make a traverser self.pq = CollisionHandlerQueue() #Make a handler #Make a collision node for our picker ray self.pickerNode = CollisionNode('mouseRay') #Attach that node to the camera since the ray will need to be positioned #relative to it self.pickerNP = camera.attachNewNode(self.pickerNode) #Everything to be picked will use bit 1. This way if we were doing other #collision we could seperate it self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() #Make our ray self.pickerNode.addSolid(self.pickerRay) #Add it to the collision node #Register the ray as something that can cause collisions self.picker.addCollider(self.pickerNP, self.pq) #self.picker.showCollisions(render) #Now we create the chess board and its pieces #We will attach all of the squares to their own root. This way we can do the #collision pass just on the sqaures and save the time of checking the rest #of the scene self.squareRoot = render.attachNewNode("squareRoot") #For each square self.squares = [None for i in range(64)] self.pieces = [None for i in range(64)] for i in range(64): #Load, parent, color, and position the model (a single square polygon) self.squares[i] = loader.loadModel("models/square") self.squares[i].reparentTo(self.squareRoot) self.squares[i].setPos(SquarePos1(i)) self.squares[i].setColor(SquareColor(i)) #Set the model itself to be collideable with the ray. If this model was #any more complex than a single polygon, you should set up a collision #sphere around it instead. But for single polygons this works fine. self.squares[i].find("**/polygon").node().setIntoCollideMask( BitMask32.bit(1)) #Set a tag on the square's node so we can look up what square this is #later during the collision pass self.squares[i].find("**/polygon").node().setTag('square', str(i)) #We will use this variable as a pointer to whatever piece is currently #in this square #The order of pieces on a chessboard from white's perspective. This list #contains the constructor functions for the piece classes defined below self.initializer(self.currlevel) #Load the white pawns #This will represent the index of the currently highlited square self.hiSq = False #This wil represent the index of the square where currently dragged piece #was grabbed from self.dragging = False #Start the task that handles the picking self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask') #self.trial = taskMgr.add(self.trial,'trial') self.accept("mouse1", self.grabPiece) #left-click grabs a piece self.accept("mouse1-up", self.releasePiece) #releasing places it #This function swaps the positions of two pieces def swapPieces(self, fr, to): temp = self.pieces[fr] self.pieces[fr] = self.pieces[to] self.pieces[to] = temp if self.pieces[fr]: print 'imma swapping' self.pieces[fr].square = fr print fr print SquarePos(fr) try: self.pieces[fr].obj.setPos(SquarePos(fr)) except: pass print 'done' if self.pieces[to]: self.pieces[to].square = to try: self.pieces[to].obj.setPos(SquarePos(to)) except: pass def trial(self): self.turns = self.turns + 1 try: self.reference.destroy() except: pass self.reference = OnscreenText(text=''' Reference: virus is surrounded by more than 3 viruses, it dies virus is surrounded by less than 2 viruses, it dies If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned. ''', style=1, fg=(1, 1, 1, 1), pos=(-1, 0.95), align=TextNode.ALeft, scale=.05) self.showscore() a = self.a while True: for i in self.list: #insert deletion code print 'imma deleting the sq : ' + str(i) self.pieces[i].obj.delete() self.squares[i].setColor(SquareColor(i)) count = 0 a = [[([[ sum(b[y1][x1] for b in [[[( (-1 < x2 + dx < len(a[0])) and (-1 < y2 + dy < len(a))) and a[y2 + dy][x2 + dx] or 0 for x2 in range(len(a[0]))] for y2 in range(len(a))] for (dx, dy) in [(dx, dy) for dx in [-1, 0, 1] for dy in [-1, 0, 1] if (dy != 0 or dx != 0)]]) for x1 in range(len(a[0])) ] for y1 in range(len(a))][y][x] == 3 or ([[ sum(c[y3][x3] for c in [[[( (-1 < x4 + dx < len(a[0])) and (-1 < y4 + dy < len(a))) and a[y4 + dy][x4 + dx] or 0 for x4 in range(len(a[0]))] for y4 in range(len(a))] for (dx, dy) in [(dx, dy) for dx in [-1, 0, 1] for dy in [-1, 0, 1] if (dy != 0 or dx != 0)]]) for x3 in range(len(a[0])) ] for y3 in range(len(a))][y][x] == 2 and a[y][x] == 1)) and 1 or 0 for x in range(len(a[0]))] for y in range(len(a))] lis = [] diceroll = random.randint(0, 5) if diceroll == 2: self.random_vgen() for element in reversed(a): for ele in element: #print 'cheking element is 1 : ' + str(ele) if ele == 1: lis.append(count) count = count + 1 print lis self.list = lis self.a = a print self.list for i in self.list: self.pieces[i] = Pawn(i, WHITE) #self.squares[i].setColor(HIGHLIGHT) print 'leaving trial' if len(self.list) == 0: self.endscreen() break return def mouseTask(self, task): #This task deals with the highlighting and dragging based on the mouse #First, clear the current highlight if self.hiSq is not False: self.squares[self.hiSq].setColor(SquareColor(self.hiSq)) self.hiSq = False #Check to see if we can access the mouse. We need it to do anything else if base.mouseWatcherNode.hasMouse(): #get the mouse position mpos = base.mouseWatcherNode.getMouse() #Set the position of the ray based on the mouse position self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) #If we are dragging something, set the position of the object #to be at the appropriate point over the plane of the board if self.dragging is not False: #Gets the point described by pickerRay.getOrigin(), which is relative to #camera, relative instead to render nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin()) #Same thing with the direction of the ray nearVec = render.getRelativeVector( camera, self.pickerRay.getDirection()) try: self.pieces[self.dragging].obj.setPos( PointAtZ(.5, nearPoint, nearVec)) except: pass #Do the actual collision pass (Do it only on the squares for #efficiency purposes) self.picker.traverse(self.squareRoot) if self.pq.getNumEntries() > 0: #if we have hit something, sort the hits so that the closest #is first, and highlight that node self.pq.sortEntries() i = int(self.pq.getEntry(0).getIntoNode().getTag('square')) #Set the highlight on the picked square self.squares[i].setColor(HIGHLIGHT) self.hiSq = i #print 'selected is ' + str(i) return Task.cont def grabPiece(self): #If a square is highlighted and it has a piece, set it to dragging mode if (self.hiSq is not False and self.pieces[self.hiSq]): self.dragging = self.hiSq self.hiSq = False def releasePiece(self): #Letting go of a piece. If we are not on a square, return it to its original #position. Otherwise, swap it with the piece in the new square if self.dragging is not False: #Make sure we really are dragging something #We have let go of the piece, but we are not on a square if self.hiSq is False: try: self.pieces[self.dragging].obj.setPos( SquarePos(self.dragging)) except: pass else: #Otherwise, swap the pieces self.swapPieces(self.dragging, self.hiSq) #self.draggin is the from print self.list print 'you picked this, so Imma deleting this ' + str( self.dragging) #deletion of i after picking it up. try: self.list.remove(self.dragging) except: pass temp2 = [] temp2 = SquarePosTuple(self.dragging) self.a[temp2[0]][temp2[1]] = 0 i = self.hiSq print self.list print 'highlighted sq is ' + str(i) templis = [] templis = SquarePosTuple(i) print templis self.list.append(i) print self.list print templis self.a[templis[0]][templis[1]] = 1 for line in self.a: print line self.trial() #We are no longer dragging anything self.dragging = False def setupLights(self): #This function sets up some default lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.8, .8, .8, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0, 45, -45)) directionalLight.setColor(Vec4(0.2, 0.2, 0.2, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight))
class Player(GameObject, ArmedObject): def __init__(self, shipSpec): GameObject.__init__(self, Vec3(0, 0, 0), None, None, shipSpec.maxShields, shipSpec.maxSpeed, "player", MASK_INTO_PLAYER, 2) ArmedObject.__init__(self) self.acceleration = shipSpec.acceleration self.turnRate = shipSpec.turnRate self.numGuns = len(shipSpec.gunPositions) self.numMissiles = shipSpec.numMissiles self.maxEnergy = shipSpec.maxEnergy self.energyRechargeRate = shipSpec.energyRechargeRate self.shieldRechargeRate = shipSpec.shieldRechargeRate self.energy = shipSpec.maxEnergy for gunPos in shipSpec.gunPositions: np = self.actor.attachNewNode(PandaNode("gun node")) np.setPos(gunPos) gun = BlasterWeapon() self.addWeapon(gun, 0, np) missileSetCounter = 1 for missilePos in shipSpec.missilePositions: np = self.actor.attachNewNode(PandaNode("missile node")) np.setPos(missilePos) gun = RocketWeapon() self.addWeapon(gun, missileSetCounter, np) missileSetCounter += 1 self.numMissileSets = missileSetCounter - 1 self.missileSetIndex = 0 light = PointLight("basic light") light.setColor(Vec4(1, 1, 1, 1)) light.setAttenuation((1, 0.01, 0.001)) self.lightNP = self.root.attachNewNode(light) self.lightNP.setZ(1) Common.framework.showBase.render.setLight(self.lightNP) self.colliderNP.node().setFromCollideMask(MASK_WALLS | MASK_FROM_PLAYER) Common.framework.pusher.addCollider(self.colliderNP, self.root) Common.framework.traverser.addCollider(self.colliderNP, Common.framework.pusher) Common.framework.showBase.camera.reparentTo(self.actor) Common.framework.showBase.camera.setPos(0, 0, 0) Common.framework.showBase.camera.setHpr(0, 0, 0) lens = Common.framework.showBase.camLens lens.setNear(0.03) ratio = lens.getAspectRatio() lens.setFov(75 * ratio) self.lastMousePos = Vec2(0, 0) self.mouseSpeedHori = 50.0 self.mouseSpeedVert = 30.0 self.mouseSensitivity = 1.0 self.targetingRay = CollisionSegment(0, 0, 0, 0, 100, 0) self.targetingRayNode = CollisionNode("lock ray") self.targetingRayNode.addSolid(self.targetingRay) self.targetingRayNode.setFromCollideMask(MASK_ENEMY_LOCK_SPHERE) self.targetingRayNode.setIntoCollideMask(0) self.targetingRayNP = self.actor.attachNewNode(self.targetingRayNode) self.targetingQueue = CollisionHandlerQueue() self.prospectiveLockTarget = None self.lockTargetTimer = 0 self.lockDuration = 1 Common.framework.traverser.addCollider(self.targetingRayNP, self.targetingQueue) #rayNodePath.show() self.uiRoot = aspect2d.attachNewNode(PandaNode("player UI")) cardMaker = CardMaker("UI maker") cardMaker.setFrame(-1, 1, -1, 1) self.centreSpot = self.uiRoot.attachNewNode(cardMaker.generate()) self.centreSpot.setTexture( Common.framework.showBase.loader.loadTexture( "../Section2SpaceflightDocking/UI/spot.png")) self.centreSpot.setTransparency(True) self.centreSpot.setPos(0, 0, 0) self.centreSpot.setScale(0.01) self.centreSpot.setAlphaScale(0.5) self.directionIndicator = self.uiRoot.attachNewNode( cardMaker.generate()) self.directionIndicator.setTexture( Common.framework.showBase.loader.loadTexture( "../Section2SpaceflightDocking/UI/directionIndicator.png")) self.directionIndicator.setTransparency(True) self.directionIndicator.setScale(0.05) self.directionIndicator.hide() self.lockMarkerRoot = self.uiRoot.attachNewNode( PandaNode("lock marker root")) for i in range(4): markerRotationNP = self.lockMarkerRoot.attachNewNode( PandaNode("lock marker rotation")) marker = markerRotationNP.attachNewNode(cardMaker.generate()) marker.setTexture( Common.framework.showBase.loader.loadTexture( "../Section2SpaceflightDocking/UI/lockMarker.png")) marker.setTransparency(True) markerRotationNP.setScale(0.04) markerRotationNP.setR(i * 90) self.lockMarkerRoot.hide() self.lockBar = Common.framework.showBase.loader.loadModel( "../Section2SpaceflightDocking/UI/uiLockBar") self.lockBar.reparentTo(self.uiRoot) self.lockBar.setScale(0.15) #self.lockBar.hide() cardMaker.setFrame(-1, 1, 0, 1) self.cockpit = Common.framework.showBase.loader.loadModel( "../Section2SpaceflightDocking/Models/{0}".format( shipSpec.cockpitModelFile)) self.cockpit.reparentTo(self.actor) healthBarRoot = self.cockpit.find("**/healthBar") if healthBarRoot is None or healthBarRoot.isEmpty(): healthBarRoot = self.uiRoot.attachNewNode( PandaNode("health bar root")) print("No health bar root found!") energyBarRoot = self.cockpit.find("**/energyBar") if energyBarRoot is None or energyBarRoot.isEmpty(): energyBarRoot = self.uiRoot.attachNewNode( PandaNode("energy bar root")) print("No energy bar root found!") missileCounterRoot = self.cockpit.find("**/missileCounter") if missileCounterRoot is None or missileCounterRoot.isEmpty(): missileCounterRoot = self.uiRoot.attachNewNode( PandaNode("missile counter root")) print("No missile counter root found!") radarRoot = self.cockpit.find("**/radar") if radarRoot is None or radarRoot.isEmpty(): radarRoot = self.uiRoot.attachNewNode(PandaNode("radar root")) print("No radar root found!") speedometerRoot = self.cockpit.find("**/speedometer") if speedometerRoot is None or speedometerRoot.isEmpty(): speedometerRoot = self.uiRoot.attachNewNode( PandaNode("speedometer root")) print("No speedometer root found!") self.radarDrawer = MeshDrawer() self.radarDrawer.setBudget(4096) self.radarDrawerNP = self.radarDrawer.getRoot() self.radarDrawerNP.reparentTo(radarRoot) self.radarDrawerNP.setTwoSided(True) self.radarDrawerNP.setLightOff() self.radarDrawerNP.setDepthWrite(False) self.radarDrawerNP.setTransparency(True) self.healthBar = healthBarRoot.attachNewNode(cardMaker.generate()) self.healthBar.setSx(0.05) self.energyBar = energyBarRoot.attachNewNode(cardMaker.generate()) self.energyBar.setSx(0.05) self.healthBarScalar = 0.00175 self.energyBarScalar = 0.00175 self.missileCounter = DirectLabel(text="", text_mayChange=True, scale=0.09, relief=None, parent=missileCounterRoot) self.maxRadarRange = 700 self.radarSize = 0.3 self.speedometer = DirectLabel(text="", text_mayChange=True, scale=0.09, relief=None, parent=speedometerRoot) self.updateHealthUI() self.updateEnergyUI() self.updateMissileUI() self.updateRadar() self.updateSpeedometer() self.updatingEffects = [] def update(self, keys, dt): GameObject.update(self, dt) self.updateSpeedometer() self.walking = False quat = self.root.getQuat(Common.framework.showBase.render) forward = quat.getForward() right = quat.getRight() up = quat.getUp() if keys["up"]: self.walking = True self.velocity += forward * self.acceleration * dt if keys["down"]: self.walking = True self.velocity -= forward * self.acceleration * dt if keys["left"]: self.walking = True self.velocity -= right * self.acceleration * dt if keys["right"]: self.walking = True self.velocity += right * self.acceleration * dt if self.walking: self.inControl = True mouseWatcher = base.mouseWatcherNode if mouseWatcher.hasMouse(): xSize = base.win.getXSize() ySize = base.win.getYSize() xPix = float(xSize % 2) / xSize yPix = float(ySize % 2) / ySize mousePos = Vec2(base.mouseWatcherNode.getMouse()) mousePos.addX(-xPix) mousePos.addY(-yPix) if abs(mousePos.x) < xPix: mousePos.x = 0 if abs(mousePos.y) < yPix: mousePos.y = 0 else: mousePos = self.lastMousePos if mousePos.length() > 0.01: axis = right * (mousePos.y) + up * (-mousePos.x) axis.normalize() angle = mousePos.length() * self.turnRate * dt rotQuat = Quat() rotQuat.setFromAxisAngle(angle, axis) self.root.setQuat(quat * rotQuat) if not self.weaponSets[0][0].active: self.alterEnergy( math.sin(1.071 * self.energy / self.maxEnergy + 0.5) * self.energyRechargeRate * dt) self.updateEnergyUI() self.updateHealthUI() self.updateRadar() #self.root.setH(self.root.getH() - mousePos.x*self.mouseSpeedHori*self.mouseSensitivity) #self.actor.setP(self.actor.getP() + mousePos.y*self.mouseSpeedVert*self.mouseSensitivity) if keys["shoot"]: self.startFiringSet(0) else: self.ceaseFiringSet(0) if keys["shootSecondary"]: self.startFiringSet(self.missileSetIndex + 1) else: for i in range(self.numMissileSets): self.ceaseFiringSet(i + 1) [effect.update(self, dt) for effect in self.updatingEffects] [ effect.cleanup() for effect in self.updatingEffects if not effect.active ] self.updatingEffects = [ effect for effect in self.updatingEffects if effect.active ] if self.targetingQueue.getNumEntries() > 0: self.targetingQueue.sortEntries() entry = self.targetingQueue.getEntry(0) intoNP = entry.getIntoNodePath() if intoNP.hasPythonTag(TAG_OWNER): other = intoNP.getPythonTag(TAG_OWNER) if other is self.prospectiveLockTarget and other is not self.lockedTarget: self.lockTargetTimer += dt if self.lockTargetTimer >= self.lockDuration: self.lockedTarget = other else: self.lockTargetTimer = 0 self.prospectiveLockTarget = other else: self.lockTargetTimer = 0 else: self.lockTargetTimer = 0 perc = self.lockTargetTimer / self.lockDuration self.lockBar.setTexOffset(TextureStage.getDefault(), 0, -perc * 1.1) if self.lockedTarget is not None: if self.lockedTarget.health <= 0: self.lockedTarget = None else: relPos = self.lockedTarget.root.getPos(self.root) planarVec = relPos.getXz() relDist = relPos.length() if relDist == 0: angle = 0 else: angle = math.acos(relPos.y / relDist) if relDist > 200 or angle > 1.7453: self.lockedTarget = None else: if self.lockMarkerRoot.isHidden(): self.lockMarkerRoot.show() camPt = Point2() convertedPt = Common.framework.showBase.cam.getRelativePoint( Common.framework.showBase.render, self.lockedTarget.root.getPos( Common.framework.showBase.render)) if Common.framework.showBase.camLens.project( convertedPt, camPt): self.lockMarkerRoot.setPos( Common.framework.showBase.render2d, camPt.x, 0, camPt.y) if self.lockMarkerRoot.isHidden(): self.lockMarkerRoot.show() for child in self.lockMarkerRoot.getChildren(): child.getChild(0).setZ( (1.0 - min(1, relDist / 100)) * 5 + 0.2) elif not self.lockMarkerRoot.isHidden(): self.lockMarkerRoot.hide() if relPos.y < 0 or angle > 0.6: planarVec.normalize() self.directionIndicator.setPos(planarVec.x * 0.4, 0, planarVec.y * 0.4) angle = math.degrees( math.atan2(planarVec.x, planarVec.y)) self.directionIndicator.setR(angle) if self.directionIndicator.isHidden(): self.directionIndicator.show() elif not self.directionIndicator.isHidden(): self.directionIndicator.hide() else: if not self.directionIndicator.isHidden(): self.directionIndicator.hide() if not self.lockMarkerRoot.isHidden(): self.lockMarkerRoot.hide() def weaponReset(self, weapon): ArmedObject.weaponFired(self, weapon) if isinstance(weapon, RocketWeapon): self.ceaseFiringSet(self.missileSetIndex + 1) self.missileSetIndex += 1 if self.missileSetIndex >= self.numMissileSets: self.missileSetIndex = 0 def attackPerformed(self, weapon): ArmedObject.attackPerformed(self, weapon) def postTraversalUpdate(self, dt): ArmedObject.update(self, dt) def alterHealth(self, dHealth, incomingImpulse, knockback, flinchValue, overcharge=False): GameObject.alterHealth(self, dHealth, incomingImpulse, knockback, flinchValue, overcharge) self.updateHealthUI() #self.hurtSound.play() def alterEnergy(self, dEnergy): self.energy += dEnergy if self.energy < 0: self.energy = 0 elif self.energy > self.maxEnergy: self.energy = self.maxEnergy def alterMissileCount(self, dMissiles): self.numMissiles += dMissiles if self.numMissiles < 0: self.numMissiles = 0 self.updateMissileUI() def updateHealthUI(self): perc = self.health / self.maxHealth newVal = max(0.01, self.health * self.healthBarScalar) self.healthBar.setSz(newVal) self.healthBar.setColorScale(1.0 - (perc - 0.5) / 0.5, min(1, perc / 0.5), 0, 1) #self.healthCounter.setText("{0:-.0f}".format(self.health)) #self.healthCounter.setColorScale(1.0 - (perc - 0.5)/0.5, min(1, perc/0.5), 0, 1) def updateEnergyUI(self): perc = self.energy / self.maxEnergy newVal = max(0.01, self.energy * self.energyBarScalar) self.energyBar.setSz(newVal) self.energyBar.setColorScale(1.0 - (perc - 0.5) / 0.5, min(1, perc / 0.5), 0, 1) def updateMissileUI(self): self.missileCounter["text"] = "Missiles:\n{0}".format(self.numMissiles) self.missileCounter.setText() self.missileCounter.resetFrameSize() def updateSpeedometer(self): self.speedometer["text"] = "Speed:\n{0:0=2.0f}m/s".format( self.velocity.length() * 2) self.speedometer.setText() self.speedometer.resetFrameSize() def updateRadar(self): if Common.framework.currentLevel is not None: self.radarDrawer.begin(Common.framework.showBase.cam, Common.framework.showBase.render) uvs = Vec2(0, 0) spotSize = 0.015 self.radarDrawer.tri(Vec3(-spotSize, 0, -spotSize), Vec4(0, 1, 0, 1), uvs, Vec3(spotSize, 0, -spotSize), Vec4(0, 1, 0, 1), uvs, Vec3(-spotSize, 0, spotSize), Vec4(0, 1, 0, 1), uvs) self.radarDrawer.tri(Vec3(-spotSize, 0, spotSize), Vec4(0, 1, 0, 1), uvs, Vec3(spotSize, 0, -spotSize), Vec4(0, 1, 0, 1), uvs, Vec3(spotSize, 0, spotSize), Vec4(0, 1, 0, 1), uvs) selfForward = Vec3(0, 1, 0) for enemy in Common.framework.currentLevel.enemies: enemyPos = enemy.root.getPos(self.root) dist = enemyPos.length() if dist < self.maxRadarRange: distPerc = dist / self.maxRadarRange enemyPos.normalize() anglePerc = selfForward.angleDeg(enemyPos) / 180 enemyPos.setY(0) enemyPos.normalize() enemyPos *= anglePerc * self.radarSize colour = Vec4(1, 0, 0, math.sin(max(0, 1 - distPerc) * 1.571)) self.radarDrawer.tri( Vec3(-spotSize, 0, 0) + enemyPos, colour, uvs, Vec3(spotSize, 0, 0) + enemyPos, colour, uvs, Vec3(0, 0, spotSize) + enemyPos, colour, uvs) self.radarDrawer.tri( Vec3(spotSize, 0, 0) + enemyPos, colour, uvs, Vec3(-spotSize, 0, 0) + enemyPos, colour, uvs, Vec3(0, 0, -spotSize) + enemyPos, colour, uvs) self.radarDrawer.end() def addUpdatingEffect(self, effect): self.updatingEffects.append(effect) effect.start(self) def cleanup(self): if self.uiRoot is not None: self.uiRoot.removeNode() self.uiRoot = None self.healthBar = None if self.lightNP is not None: Common.framework.showBase.render.clearLight(self.lightNP) self.lightNP.removeNode() self.lightNP = None for effect in self.updatingEffects: effect.cleanup() self.updatingEffects = [] ArmedObject.cleanup(self) GameObject.cleanup(self)
class Player(object): """ Player is the main actor in the fps game """ FORWARD = Vec3(0,2,0) BACK = Vec3(0,-1,0) LEFT = Vec3(-1,0,0) RIGHT = Vec3(1,0,0) FLYUP = Vec3(0,0,1) FLYDN = Vec3(0,0,-1) STOP = Vec3(0) PORTAL_CYCLE = { 'blue' : 'orange', 'orange' : 'blue', } def __init__(self, base, fps, osd): self.base = base self.fps = fps self.osd = osd self.speed = RUN_SPEED self.walk = self.STOP self.readyToJump = False self.intoPortal = None self.mass = Mass() self.origin = self.fps.level.settings.origin self.bporigin = (999,999,999) self.oporigin = (999,999,999) self.current_target = None self.canPortal = [] self.canSetTarget = True self.selectedCubes = [] self.editorTextureStage = TextureStage('editor') self.editorSelectedTexture = loader.loadTexture('models/tex/selected.png') self.selectingForMulti = False # Init functions self.loadModel() self.makePortals() self.setUpCamera() if self.fps.editor_mode: self.createMouseCollisions() self.speed = self.speed * 5 self.attachEditorControls() self.attachEditorTasks() else: self.createCollisions() self.attachStandardControls() self.attachStandardTasks() def loadModel(self): """ make the nodepath for player """ self.node = NodePath('player') self.node.reparentTo(render) self.node.setPos(*self.origin) self.node.setScale(0.05) self.mass.pos = VBase3(self.node.getX(), self.node.getY(), self.node.getZ()) def makePortals(self): # The BLUE CUBE bpor = loader.loadModel("cube_nocol") bpor.setTag('noportals', '1') bpor.reparentTo(render) bpor.setPos(*self.bporigin) bpor.setScale(0.3,0.02,0.5) # The BLUE CUBE's camera bbuffer = self.base.win.makeTextureBuffer("B Buffer", 512, 512) bbuffer.setSort(-100) bcamera = self.base.makeCamera(bbuffer) bcamera.node().getLens().setAspectRatio(0.3/0.5) bcamera.node().getLens().setFov(15) bcamera.reparentTo(bpor) bcamera.node().setScene(render) # The ORANGE CUBE opor = loader.loadModel("cube_nocol") opor.setTag('noportals', '1') opor.reparentTo(render) opor.setPos(*self.oporigin) opor.setScale(0.3,0.02,0.5) # The ORANGE CUBE's camera obuffer = self.base.win.makeTextureBuffer("O Buffer", 512, 512) obuffer.setSort(-100) ocamera = self.base.makeCamera(obuffer) ocamera.node().getLens().setAspectRatio(0.3/0.5) ocamera.node().getLens().setFov(15) ocamera.reparentTo(opor) ocamera.node().setScene(render) # Assign the textures bpor.setTexture(obuffer.getTexture()) opor.setTexture(bbuffer.getTexture()) # Store the portals and theirs cameras self.bluePortal = bpor self.bluePortal.setHpr(0,90,0) self.orangePortal = opor self.orangePortal.setHpr(0,-90,0) self.bcamera = bcamera self.ocamera = ocamera def setUpCamera(self): """ puts camera at the players node """ pl = self.base.cam.node().getLens() pl.setFov(70) self.base.cam.node().setLens(pl) self.base.camera.reparentTo(self.node) self.base.camLens.setFov(100) if self.fps.editor_mode: self.node.lookAt(self.fps.level.cubes_hash.keys()[0]) def createCollisions(self): self.createPlayerCollisions() self.createMouseCollisions() self.createPortalCollisions() def createPlayerCollisions(self): """ create a collision solid and ray for the player """ cn = CollisionNode('player') cn.setFromCollideMask(COLLISIONMASKS['geometry']) cn.setIntoCollideMask(COLLISIONMASKS['portals'] | COLLISIONMASKS['exit'] | COLLISIONMASKS['lava']) cn.addSolid(CollisionSphere(0,0,0,3)) solid = self.node.attachNewNode(cn) # TODO : find a way to remove that, it's the cause of the little # "push me left" effect we see sometime when exiting a portal self.base.cTrav.addCollider(solid,self.base.pusher) self.base.pusher.addCollider(solid,self.node, self.base.drive.node()) # init players floor collisions ray = CollisionRay() ray.setOrigin(0,0,-.2) ray.setDirection(0,0,-1) cn = CollisionNode('playerRay') cn.setFromCollideMask(COLLISIONMASKS['player']) cn.setIntoCollideMask(BitMask32.allOff()) cn.addSolid(ray) solid = self.node.attachNewNode(cn) self.nodeGroundHandler = CollisionHandlerQueue() self.base.cTrav.addCollider(solid, self.nodeGroundHandler) # init players ceil collisions ray = CollisionRay() ray.setOrigin(0,0,.2) ray.setDirection(0,0,1) cn = CollisionNode('playerUpRay') cn.setFromCollideMask(COLLISIONMASKS['player']) cn.setIntoCollideMask(BitMask32.allOff()) cn.addSolid(ray) solid = self.node.attachNewNode(cn) self.ceilGroundHandler = CollisionHandlerQueue() self.base.cTrav.addCollider(solid, self.ceilGroundHandler) def createMouseCollisions(self): # Fire the portals firingNode = CollisionNode('mouseRay') firingNP = self.base.camera.attachNewNode(firingNode) firingNode.setFromCollideMask(COLLISIONMASKS['geometry']) firingNode.setIntoCollideMask(BitMask32.allOff()) firingRay = CollisionRay() firingRay.setOrigin(0,0,0) firingRay.setDirection(0,1,0) firingNode.addSolid(firingRay) self.firingHandler = CollisionHandlerQueue() self.base.cTrav.addCollider(firingNP, self.firingHandler) def createPortalCollisions(self): # Enter the portals cn = CollisionNode('bluePortal') cn.setFromCollideMask(COLLISIONMASKS['portals']) cn.setIntoCollideMask(BitMask32.allOff()) np = self.bluePortal.attachNewNode(cn) cn.addSolid(CollisionSphere(0,0,0,2)) h = CollisionHandlerEvent() h.addInPattern('%fn-into-%in') h.addOutPattern('%fn-outof-%in') self.base.cTrav.addCollider(np, h) cn = CollisionNode('orangePortal') cn.setFromCollideMask(COLLISIONMASKS['portals']) cn.setIntoCollideMask(BitMask32.allOff()) np = self.orangePortal.attachNewNode(cn) cn.addSolid(CollisionSphere(0,0,0,2)) h = CollisionHandlerEvent() h.addInPattern('%fn-into-%in') h.addOutPattern('%fn-outof-%in') self.base.cTrav.addCollider(np, h) def attachCommonControls(self): self.base.accept( "z" if AZERTY else "w" , self.addWalk,[self.FORWARD]) self.base.accept( "z-up" if AZERTY else "w-up" , self.addWalk,[-self.FORWARD] ) self.base.accept( "s" , self.addWalk,[self.BACK] ) self.base.accept( "s-up" , self.addWalk,[-self.BACK] ) self.base.accept( "q" if AZERTY else "a" , self.addWalk,[self.LEFT]) self.base.accept( "q-up" if AZERTY else "a-up" , self.addWalk,[-self.LEFT] ) self.base.accept( "d" , self.addWalk,[self.RIGHT] ) self.base.accept( "d-up" , self.addWalk,[-self.RIGHT] ) self.base.accept( "r-up" , self.resetPosition ) self.base.accept( "p-up" , self.showPosition ) self.base.accept( "b-up" , self.deBug ) def attachStandardControls(self): self.attachCommonControls() self.base.accept( "space" , self.__setattr__,["readyToJump",True]) self.base.accept( "space-up" , self.__setattr__,["readyToJump",False]) self.base.accept( "c-up" , self.__setattr__,["intoPortal",None] ) self.base.accept( "e-up" , self.erasePortals ) self.base.accept( "mouse1" , self.fireBlue ) self.base.accept( "mouse3" , self.fireOrange ) # Events self.base.accept( "bluePortal-into-player" , self.enterPortal, ["blue"] ) self.base.accept( "orangePortal-into-player" , self.enterPortal, ["orange"] ) self.base.accept( "bluePortal-outof-player" , self.exitPortal, ["blue"] ) self.base.accept( "orangePortal-outof-player" , self.exitPortal, ["orange"] ) self.base.accept( "levelExit-into-player" , self.levelExit) self.base.accept( "lava-into-player" , self.fallIntoLava) def attachStandardTasks(self): taskMgr.add(self.mouseUpdate, 'mouse-task') taskMgr.add(self.moveUpdate, 'move-task') taskMgr.add(self.jumpUpdate, 'jump-task') def attachEditorControls(self): self.attachCommonControls() self.base.accept( "space" , self.__setattr__, ['selectingForMulti', 1]) self.base.accept( "space-up" , self.__setattr__, ['selectingForMulti', 0]) self.base.accept( "shift-space" , self.__setattr__, ['selectingForMulti', 2]) self.base.accept( "shift-space-up" , self.__setattr__, ['selectingForMulti', 0]) self.base.accept( "c-up" , self.clearMultiSelectedCubes) self.base.accept( "mouse1" , self.selectCubeForCopy, [1]) self.base.accept( "wheel_up" , self.selectCubeForChange, [1] ) self.base.accept( "wheel_down" , self.selectCubeForChange, [-1] ) self.base.accept( "mouse3" , self.selectCubeForDelete ) self.base.accept("f11", self.saveLevel) self.base.accept("x", self.selectCubeForRectangle) self.base.accept("shift-x", self.selectCubeForRectangle, [True]) self.base.accept("l", self.addLightHere) self.base.accept("u", self.fps.level.undo, [1]) for i in range(1,10): self.base.accept( "%i-up" % (i,), self.selectCubeForCopy, [i]) for key, vec in [("a" if AZERTY else "q", self.FLYUP),("w" if AZERTY else "z", self.FLYDN)]: self.base.accept(key, self.addWalk, [vec]) self.base.accept(key + "-up", self.addWalk, [-vec]) def attachEditorTasks(self): taskMgr.add(self.mouseUpdate, 'mouse-task') taskMgr.add(self.moveInEditor, 'move-task') def deBug(self): import pdb pdb.set_trace() def showPosition(self): print self.node.getPos() print self.mass def fallIntoLava(self, *args, **kwargs): # TODO : sound and message + little delay self.erasePortals() self.resetPosition() def resetPosition(self, *args, **kwargs): self.node.setHpr(VBase3(0,0,0)) self.mass.pos = VBase3(*self.origin) self.mass.vel = VBase3(0,0,0) self.mass.force = VBase3(0,0,0) self.node.setPos(self.mass.pos) def erasePortals(self): self.bluePortal.setPos(*self.bporigin) self.orangePortal.setPos(*self.oporigin) self.bluePortal.detachNode() self.orangePortal.detachNode() self.intoPortal = None self.canPortal = [] #@oldpostracker def mouseUpdate(self,task): """ this task updates the mouse """ md = self.base.win.getPointer(0) x = md.getX() y = md.getY() if self.base.win.movePointer(0, self.base.win.getXSize()/2, self.base.win.getYSize()/2): self.node.setH(self.node.getH() - (x - self.base.win.getXSize()/2)*0.1) if self.fps.editor_mode: self.node.setP(self.node.getP() - (y - self.base.win.getYSize()/2)*0.1) else: self.base.camera.setP(self.base.camera.getP() - (y - self.base.win.getYSize()/2)*0.1) self.canSetTarget = True self.bcamera.lookAt(self.bluePortal, self.node.getPos(self.orangePortal)) self.ocamera.lookAt(self.orangePortal, self.node.getPos(self.bluePortal)) #self.canPortal = ['blue','orange'] if self.fps.editor_mode: cube, point, normal = self.selectCube() self.osd.updateTargetPosition(cube) if self.selectingForMulti: self.selectCubeForMulti() return task.cont def addWalk(self, vec): self.walk += vec def moveUpdate(self,task): """ this task makes the player move """ # move where the keys set it self.node.setPos(self.node, self.walk*globalClock.getDt()*self.speed) return task.cont #@oldpostracker def jumpUpdate(self,task): """ this task simulates gravity and makes the player jump """ # get the highest Z from the down casting ray highestZ = -100 lowestZ = 100 for i in range(self.nodeGroundHandler.getNumEntries()): entry = self.nodeGroundHandler.getEntry(i) z = entry.getSurfacePoint(render).getZ() if z > highestZ and entry.getIntoNode().getName() in ( "CollisionStuff", "Plane", "Cube" ): highestZ = z for i in range(self.ceilGroundHandler.getNumEntries()): entry = self.ceilGroundHandler.getEntry(i) z = entry.getSurfacePoint(render).getZ() if z < lowestZ and entry.getIntoNode().getName() in ( "CollisionStuff", "Plane", "Cube" ): lowestZ = z # gravity effects and jumps self.mass.simulate(globalClock.getDt()) self.node.setZ(self.mass.pos.getZ()) if highestZ > self.node.getZ()-PLAYER_TO_FLOOR_TOLERANCE: self.mass.zero() self.mass.pos.setZ(highestZ+PLAYER_TO_FLOOR_TOLERANCE) self.node.setZ(highestZ+PLAYER_TO_FLOOR_TOLERANCE) if lowestZ < self.node.getZ()+PLAYER_TO_FLOOR_TOLERANCE: self.mass.zero() self.mass.pos.setZ(lowestZ-PLAYER_TO_FLOOR_TOLERANCE) self.node.setZ(lowestZ-PLAYER_TO_FLOOR_TOLERANCE) if self.readyToJump and self.node.getZ() < highestZ + PLAYER_TO_FLOOR_TOLERANCE_FOR_REJUMP: self.mass.jump(JUMP_FORCE) return task.cont def firePortal(self, name, node): def hasTagValue(node, tag, value): if node.getTag(tag) == value: return True for pnum in range(node.getNumParents()): return hasTagValue(node.getParent(pnum), tag, value) return False self.firingHandler.sortEntries() if self.firingHandler.getNumEntries() > 0: closest = self.firingHandler.getEntry(0) if hasTagValue(closest.getIntoNode(), 'noportals', '1'): return point = closest.getSurfacePoint(render) normal = closest.getSurfaceNormal(render) node.setPos(point) node.lookAt(point + normal) node.reparentTo(render) dest = self.PORTAL_CYCLE[name] if dest not in self.canPortal: self.canPortal.append(dest) def fireBlue(self, *arg, **kwargs): self.firePortal("blue", self.bluePortal) def fireOrange(self, *arg, **kwargs): self.firePortal("orange", self.orangePortal) #@oldpostracker def enterPortal(self, color, collision): if self.intoPortal is None and color in self.canPortal: self.intoPortal = color portal = {"orange": self.bluePortal, "blue": self.orangePortal}.get(color) otherportal = {"orange": self.orangePortal, "blue": self.bluePortal}.get(color) # Handle horizontal portals : if portal.getH() == 0: self.node.setP(0) self.node.setR(0) elif otherportal.getH() == 0: self.node.setH(portal.getH()) self.node.setP(0) self.node.setR(0) else: # New HPR is relative to 'new' portal but it the 'same' value # as the old HPR seen from the 'other' portal oldh_fromportal = self.node.getH(otherportal) self.node.setHpr(Vec3(0,0,0)) self.node.setH(portal, 180-oldh_fromportal) newh_fromportal = self.node.getH(portal) self.node.setPos(portal, self.walk * 10.) self.mass.pos = self.node.getPos() # Make half a turn (only if we straffing without walking) if self.walk.getY() == 0 and self.walk.getX() != 0: self.node.setH(self.node, 180) self.node.setPos(self.node, self.walk * 10) #@oldpostracker def exitPortal(self, color, collision): # When you entered the blue portal, you have to exit the orange one if self.intoPortal != color: self.intoPortal = None def levelExit(self, event): if self.fps.level.settings.next_level: self.fps.level.loadlevel(self.fps.level.settings.next_level) self.origin = self.fps.level.settings.origin self.resetPosition() self.erasePortals() self.walk = self.STOP else: print "You won !" sys.exit(0) # EDITOR MODE def selectCube(self): self.firingHandler.sortEntries() if self.firingHandler.getNumEntries() > 0: closest = self.firingHandler.getEntry(0) return closest.getIntoNodePath().getParent().getParent(), closest.getSurfacePoint(render), closest.getSurfaceNormal(render) # render/cube.egg/-PandaNode/-GeomNode else: return None, None, None def clearMultiSelectedCubes(self): for c in self.selectedCubes: c.clearTexture(self.editorTextureStage) self.selectedCubes = [] def selectCubeForMulti(self): cube, point, normal = self.selectCube() if cube: if self.selectingForMulti == 1: cube.setTexture(self.editorTextureStage, self.editorSelectedTexture) if cube not in self.selectedCubes: self.selectedCubes.append(cube) elif cube in self.selectedCubes: cube.clearTexture(self.editorTextureStage) self.selectedCubes.remove(cube) def selectCubeForCopy(self, qty = 1): cube, point, normal = self.selectCube() if not (cube and point and normal): return if self.selectedCubes: for c in self.selectedCubes: self.fps.level.copyCube(c, normal, qty) self.clearMultiSelectedCubes() else: self.fps.level.copyCube(cube, normal, qty) def selectCubeForDelete(self): cube, point, normal = self.selectCube() if not (cube and point and normal): return if self.selectedCubes: for c in self.selectedCubes: self.fps.level.deleteCube(c) self.clearMultiSelectedCubes() else: self.fps.level.deleteCube(cube) def selectCubeForChange(self, step = 1): cube, point, normal = self.selectCube() if not (cube and point and normal): return if self.selectedCubes: for c in self.selectedCubes: self.fps.level.changeCube(c, step) else: self.fps.level.changeCube(cube, step) def selectCubeForRectangle(self, makeRoom = False): cube, point, normal = self.selectCube() if makeRoom: self.fps.level.createRoom(cube, self.node) # creates a room from the selected cube to the player(camera) position else: self.fps.level.createRectangle(cube, self.node) # creates a rectangle from the selected cube to the player(camera) position def saveLevel(self): camerapos = [self.node.getX(), self.node.getY(), self.node.getZ()] levelname = self.fps.levelname self.fps.level.savelevel(levelname, camerapos) def addLightHere(self): camerapos = [self.node.getX(), self.node.getY(), self.node.getZ()] self.fps.level.addLightHere(camerapos) def moveInEditor(self,task): self.node.setPos(self.node, self.walk*globalClock.getDt()*self.speed) self.osd.updatePosition(self.node) return task.cont
class GamingCam(object,DirectObject): yshift,zshift=5,5 ymin,ymax=10,70 zmin,zmax=10,70 zoom_speed=.1 move_speed=.5 def __init__(self,gmap,gaming_zone): DirectObject.__init__(self) #gaming zone (used for mouse movement), as a tools.Rectangle self.gaming_zone=gaming_zone #actual camera node self.p3dcam=base.camera #what the cam is oriented to self._target=base.render.attachNewNode('GaminCam.target') #range=[0,1] between min and max closeness to ground self.level=.7 # #keys_down acts as a pool containing keys (+mouse buttons) currently down self.keys_down=[] update_list.append(self.update) #setup for mouse picking picker_node=CollisionNode('gcam_to_mouse_ray')#general collision node picker_node.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.picker_ray=CollisionRay()#solid ray to attach to coll node picker_node.addSolid(self.picker_ray) self.picker_np=self.p3dcam.attachNewNode(picker_node)#attach this node to gcam self.collision_queue=CollisionHandlerQueue()#stores collisions self.collision_traverser=CollisionTraverser('gcam_traverser')#actual computer self.collision_traverser.addCollider(self.picker_np,self.collision_queue) base.cTrav=self.collision_traverser self.gmap=gmap #stack of states (state=pos+zoom) self.states_stack=[] #enable the cam to move according to keyboard and mouse self.move_enabled=True def __del__(self): update_list.remove(self.update) self.ignoreAll() def center(self): self._target.setPos(0,0,0) def disable_move(self): self.move_enabled=False def enable_move(self): self.move_enabled=True def get_level(self): return self._level def get_picked_tile(self): ''' returns ''' if base.mouseWatcherNode.hasMouse(): #get the mouse position mpos = base.mouseWatcherNode.getMouse() #Set the position of the ray based on the mouse position # self.picker_ray.setFromLens(self.p3dcam.node().getLens(), mpos.getX(), mpos.getY()) self.picker_ray.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.collision_traverser.traverse(self.gmap.tile_matrix_node) if self.collision_queue.getNumEntries()>0: #useless since collision test is done against a single object self.collision_queue.sortEntries() entry=self.collision_queue.getEntry(0) x,y,_=entry.getSurfacePoint(self.gmap.tile_matrix_node) x=(x+self.gmap.resx)/2. y=(y+self.gmap.resy)/2. x=max(x,0) x=min(x,self.gmap.resx) y=max(y,0) y=min(y,self.gmap.resy) x=int(x) y=int(y) #out(pos=(x,y,z)) return self.gmap.tile_matrix[x][y] return None def get_picked_unit(self): if base.mouseWatcherNode.hasMouse(): #get the mouse position mpos = base.mouseWatcherNode.getMouse() #Set the position of the ray based on the mouse position # self.picker_ray.setFromLens(self.p3dcam.node().getLens(), mpos.getX(), mpos.getY()) self.picker_ray.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.collision_traverser.traverse(self.gmap.units_node) if self.collision_queue.getNumEntries()>0: #useless since collision test is done against a single object self.collision_queue.sortEntries() entry=self.collision_queue.getEntry(0) return entry.getIntoNodePath().findNetTag('GUnit-pickable') return None def get_target(self): return self._target def mouse_up(self,btn): if btn=='left': target=self.get_picked_tile() #out(target) #print NodePath(self.gmap.tile_matrix_node).ls() #print render.analyze() if target: network.serverproxy.send({network.cts_dbg_dump_entity:{'eid':target.eid}}) elif btn=='middle': self.set_level(.7) self.set_target(Vec3(0,-9,0)) def move(self,dx=0,dy=0): self._target.setPos(self._target,dx,dy,0) self.update_cam() def push_state(self): out('GCam.push_state()') pos,zoom=self._target.getPos(),self.level self.states_stack.append((pos,zoom)) def pop_state(self): out('GCam.pop_state()') pos,zoom=self.states_stack.pop(-1) self._target.setPos(*pos) self.level=zoom self.update_cam() def set_level(self,level): self._level=level self.update_cam() def set_target(self,target): ''' make the cam look at the given target. target can be a set of coordinates, or a node/nodepath. ''' if isinstance(target,PandaNode) or isinstance(target,NodePath): self._target.setPos(target,0,0,0) if isinstance(target,tuple): self._target.setPos(Vec3(*target)) else: self._target.setPos(target) self.update_cam() def start_accepting(self): ''' the gaming cam is created at gmap creation, so it has to wait until all data structures are created before accepting events. ''' self.accept(ConfigVariableString('key-cam-zoom-in').getValue()+'-up',self.zoom,extraArgs=[-GamingCam.zoom_speed]) self.accept(ConfigVariableString('key-cam-zoom-out').getValue()+'-up',self.zoom,extraArgs=[GamingCam.zoom_speed]) self.accept(ConfigVariableString('key-cam-right').getValue(),self.keys_down.append,extraArgs=['r']) self.accept(ConfigVariableString('key-cam-right').getValue()+'-up',self.keys_down.remove,extraArgs=['r']) self.accept(ConfigVariableString('key-cam-up').getValue(),self.keys_down.append,extraArgs=['u']) self.accept(ConfigVariableString('key-cam-up').getValue()+'-up',self.keys_down.remove,extraArgs=['u']) self.accept(ConfigVariableString('key-cam-left').getValue(),self.keys_down.append,extraArgs=['l']) self.accept(ConfigVariableString('key-cam-left').getValue()+'-up',self.keys_down.remove,extraArgs=['l']) self.accept(ConfigVariableString('key-cam-down').getValue(),self.keys_down.append,extraArgs=['d']) self.accept(ConfigVariableString('key-cam-down').getValue()+'-up',self.keys_down.remove,extraArgs=['d']) self.accept('mouse1-up',self.mouse_up,extraArgs=['left']) self.accept('mouse2-up',self.mouse_up,extraArgs=['middle']) def update(self): dx,dy=0,0 for k in self.keys_down: if k=='r':dx+=GamingCam.move_speed if k=='l':dx-=GamingCam.move_speed if k=='u':dy+=GamingCam.move_speed if k=='d':dy-=GamingCam.move_speed if k=='m': pass #dx+=mouse.getMouseX() #dy+=mouse.getMouseY() if self.move_enabled: self.move(dx,dy) def update_cam(self): self.p3dcam.setPos( self._target, 0, -(GamingCam.ymin+GamingCam.yshift+self._level*GamingCam.ymax), GamingCam.zmin+GamingCam.zshift+self._level*GamingCam.zmax ) self.p3dcam.lookAt(self._target) def zoom(self,delta): #TODO: smoothen the zoom with a task (interpolation) if 0<self._level+delta<1.: self.level+=delta level=property(get_level,set_level) target=property(get_target,set_target)
class MyApp(ShowBase): def __init__(self): global collide ShowBase.__init__(self) self.traverser = CollisionTraverser('traverser1') base.cTrav = self.traverser #traverser.addCollider(cnode1, handler) entry = 1 imageObject = OnscreenImage(image = '/Users/devanshi/Downloads/sky.png', pos = (0, 0, 0), scale = 2) imageObject.setTransparency(TransparencyAttrib.MAlpha) base.cam.node().getDisplayRegion(0).setSort(20) self.forest=NodePath(PandaNode("Forest Root")) self.forest.reparentTo(render) loader.loadModel("models/background").reparentTo(self.forest) loader.loadModel("models/foliage01").reparentTo(self.forest) loader.loadModel("models/foliage02").reparentTo(self.forest) loader.loadModel("models/foliage03").reparentTo(self.forest) loader.loadModel("models/foliage04").reparentTo(self.forest) loader.loadModel("models/foliage05").reparentTo(self.forest) loader.loadModel("models/foliage06").reparentTo(self.forest) loader.loadModel("models/foliage07").reparentTo(self.forest) loader.loadModel("models/foliage08").reparentTo(self.forest) loader.loadModel("models/foliage09").reparentTo(self.forest) self.forest1=NodePath(PandaNode("Forest Root")) self.forest1.reparentTo(render) loader.loadModel("models/foliage01").reparentTo(self.forest1) loader.loadModel("models/foliage02").reparentTo(self.forest1) loader.loadModel("models/foliage03").reparentTo(self.forest1) loader.loadModel("models/foliage04").reparentTo(self.forest1) loader.loadModel("models/foliage05").reparentTo(self.forest1) loader.loadModel("models/foliage06").reparentTo(self.forest1) loader.loadModel("models/foliage07").reparentTo(self.forest1) loader.loadModel("models/foliage08").reparentTo(self.forest1) loader.loadModel("models/foliage09").reparentTo(self.forest1) self.forest.hide(BitMask32.bit(1)) self.forest.setScale(2.5, 2.5, 2.5) self.forest.setPos(0, 0, -2) self.forest1.hide(BitMask32.bit(1)) self.forest1.setScale(1.5, 1.5, 1.5) self.forest1.setPos(-1,-1, 0) self.forest2=NodePath(PandaNode("Forest Root")) self.forest2.reparentTo(render) loader.loadModel("models/foliage01").reparentTo(self.forest2) loader.loadModel("models/foliage02").reparentTo(self.forest2) loader.loadModel("models/foliage03").reparentTo(self.forest2) loader.loadModel("models/foliage04").reparentTo(self.forest2) loader.loadModel("models/foliage05").reparentTo(self.forest2) loader.loadModel("models/foliage06").reparentTo(self.forest2) loader.loadModel("models/foliage07").reparentTo(self.forest2) loader.loadModel("models/foliage08").reparentTo(self.forest2) loader.loadModel("models/foliage09").reparentTo(self.forest2) self.forest2.hide(BitMask32.bit(1)) self.forest1.setScale(1.5, 1.5, 1.5) self.forest1.setPos(1,1, 0) self.stall = self.loader.loadModel("models/patch/cornfield") self.stall.reparentTo(self.render) self.stall.setScale(0.5) self.stall.setPos(40,0,1) self.stall.setHpr(0,0,0) self.tex1=self.loader.loadTexture("models/water.png") self.stall.setTexture(self.tex1,1) self.flock = Actor("models/goose/goosemodelonly", {"gfly":"models/goose/gooseanimationonly" }) self.flock.setScale(0.05, 0.05, 0.05) self.flock.setPos(0,-30,13) self.flock.reparentTo(self.render) self.flock.loop("gfly") self.tex2=self.loader.loadTexture("models/orange.jpg") self.flock.setTexture(self.tex2,1) self.camera.setPos(0,0,0) self.camera.setHpr(90,0,0) # Create the four lerp intervals needed for the panda to # walk back and forth. pandaPosInterval1 = self.flock.posInterval(13, Point3(-5, -30, 13), startPos=Point3(5, -30, 13)) pandaPosInterval2 = self.flock.posInterval(13, Point3(5, -30, 13), startPos=Point3(-5, -30, 13)) pandaHprInterval1 = self.flock.hprInterval(3, Point3(0, 0, 0), startHpr=Point3(180, 0, 0)) pandaHprInterval2 = self.flock.hprInterval(3, Point3(180, 0, 0), startHpr=Point3(0, 0, 0)) # Create and play the sequence that coordinates the intervals. self.pandaPace = Sequence(pandaPosInterval1, pandaHprInterval1, pandaPosInterval2, pandaHprInterval2, name="pandaPace") self.pandaPace.loop() # Disable the camera trackball controls. #self.disableMouse() # Load the environment model. self.environ = self.loader.loadModel("models/environment1") # Reparent the model to render. self.environ.reparentTo(self.render) # Apply scale and position transforms on the model. self.environ.setScale(0.25, 0.25, 0.25) self.environ.setPos(-8, 42, 0) self.boy = Actor("models/trex/trex", {"run":"models/trex/trex-run", "eat":"models/trex/trex-eat"}) self.boy.reparentTo(self.render) self.boy.setPos(0,0,0) self.boy.setScale(0.5) self.isMoving = False self.myAnimControl = self.boy.getAnimControl('run') base.camera.setPos(self.boy.getX(),self.boy.getY()+10,20) self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) self.cBoy = self.boy.attachNewNode(CollisionNode('cBoyNode')) self.cBoy.node().addSolid(CollisionSphere(0, 0, 3, 8.5)) #self.cBoy.show() #self.cPond = self.stall.attachNewNode(CollisionNode('cPond')) #self.cPond.node().addSolid(CollisionSphere(40, 0, 1, 70)) #self.cPond.show() # Add the spinCameraTask procedure to the task manager. #self.taskMgr.add(self.spinCameraTask,"asdsad") self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0} cs1 = CollisionSphere(0, 0, 0, 2) self.cnodePath1 = render.attachNewNode(CollisionNode('cnode1')) self.cnodePath1.node().addSolid(cs1) #self.cnodePath1.setCollideMask(BitMask32(0x10)) #self.cnodePath1.show() self.taskMgr.add(self.moveSphere1, "sfasdasf") cs2 = CollisionSphere(0, 0, 0, 1) self.cnodePath2 = render.attachNewNode(CollisionNode('cnode2')) self.cnodePath2.node().addSolid(cs2) #self.cnodePath2.reparentTo(self.render) #self.cnodePath2.node().setFromCollideMask(BitMask32.bit(0)) #self.cnodePath2.node().setIntoCollideMask(BitMask32.allOff()) #self.cnodePath2.show() self.taskMgr.add(self.moveSphere2, "sfasd") handler = CollisionHandlerEvent() handler.addInPattern('cnode1-into-cnode2') handler.addAgainPattern('cnode1-again-cnode2') handler.addOutPattern('cs1-out-cs2') self.accept('cnode1-into-cnode2', self.collide) #self.accept('cs1-out-cs2', self.collide) #self.accept('cnode1-again-cnode2', self.collide) self.traverser.addCollider(self.cnodePath1, handler) # Load and transform the panda actor. self.pandaActor = Actor("models/panda-model", {"walk": "models/panda-walk4"}) self.pandaActor.setScale(0.005, 0.005, 0.005) self.pandaActor.reparentTo(self.render) # Loop its animation. self.pandaActor.loop("walk") self.taskMgr.add(self.movePanda, "Sasdas") self.pandaActor2 = Actor("models/panda-model",{"walk": "models/panda-walk4"}) self.pandaActor2.setScale(0.003, 0.003, 0.003) self.pandaActor2.reparentTo(self.render) # Loop its animation. self.pandaActor2.loop("walk") self.taskMgr.add(self.movePanda2, "Sak") self.camera.setPos(0,0,0) self.camera.setHpr(90,0,0) self.cTrav1=CollisionTraverser() self.collisionHandler1 = CollisionHandlerQueue() self.cTrav1.addCollider(self.cBoy, self.collisionHandler1) self.taskMgr.add(self.boyMoveTask, "BoyMoveTask") #self.accept("v",self.switchView) self.accept("escape", sys.exit) self.accept("arrow_left", self.setKey, ["left",1]) self.accept("arrow_right", self.setKey, ["right",1]) self.accept("arrow_up", self.setKey, ["forward",1]) #self.accept("a", self.setKey, ["cam-left",1]) #self.accept("s", self.setKey, ["cam-right",1]) self.accept("arrow_left-up", self.setKey, ["left",0]) self.accept("arrow_right-up", self.setKey, ["right",0]) self.accept("arrow_up-up", self.setKey, ["forward",0]) #self.accept("a-up", self.setKey, ["cam-left",0]) #self.accept("s-up", self.setKey, ["cam-right",0]) self.cTrav2=CollisionTraverser() self.collisionHandler2 = CollisionHandlerQueue() self.cTrav2.addCollider(self.cBoy, self.collisionHandler2) # Define a procedure to move the camera. def spinCameraTask(self, task): angleDegrees = task.time * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.camera.setPos(0,0,50) self.camera.setHpr(0, -90, 0) return Task.cont def movePanda(self, task): angleDegrees = (task.time) * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.pandaActor.setPos(10 * sin(angleRadians), -10.0 * cos(angleRadians), 0) self.pandaActor.setHpr(90+angleDegrees, 0, 0) return Task.cont def movePanda2(self, task): angleDegrees = (task.time) * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.pandaActor2.setPos(10.0 * sin(angleRadians), 10.0 * cos(angleRadians), 0) self.pandaActor2.setHpr(-270-angleDegrees, 0, 0) return Task.cont def moveSphere2(self, task): angleDegrees = (task.time) * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.cnodePath2.setPos(10.0 * sin(angleRadians), 10.0 * cos(angleRadians), 1) self.cnodePath2.setHpr(90+angleDegrees, 0, 0) return Task.cont def moveSphere1(self, task): angleDegrees = (task.time) * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.cnodePath1.setPos(10 * sin(angleRadians), -10.0 * cos(angleRadians), 1) self.cnodePath1.setHpr(90+angleDegrees, 0, 0) return Task.cont def fly(self, task): angleDegrees = task.time * 6.0 angleRadians = angleDegrees * (pi / 180.0) x = self.pandaActor2.getX() y = self.pandaActor2.getY() p = self.pandaActor2.getH() self.pandaActor2.setPos(x, ((task.time)*(task.time))+20 * sin(angleRadians), 10.0 * sin(angleRadians)) self.cnodePath2.setPos(x, ((task.time)*(task.time))+20 * sin(angleRadians), 10.0 * sin(angleRadians)) self.pandaActor2.setHpr(p, -(angleDegrees*10), 0) return Task.cont def collide(self, entry): print "abc" #self.pandaActor2.setPos(0,0,2) self.taskMgr.remove("Sak") self.taskMgr.remove("sfasd") self.taskMgr.add(self.fly, "Sasopi") #self.pandaActor3 = Actor("models/panda-model", # {"walk": "models/panda-walk4"}) #self.pandaActor3.setScale(0.005, 0.005, 0.005) #self.pandaActor3.setPos(0, 0, 1) #self.camera.setPos(0,0,50) def setKey(self, key, value): self.keyMap[key] = value def boyMoveTask(self, task): base.camera.reparentTo(self.boy) base.camera.setPos(0,40,0) base.camera.lookAt(self.boy) if (self.keyMap["cam-left"]!=0): self.camera.setX(base.camera, -20 * globalClock.getDt()) if (self.keyMap["cam-right"]!=0): self.camera.setX(base.camera, +20 * globalClock.getDt()) self.startPos = self.boy.getPos() if (self.keyMap["left"]!=0): self.boy.setH(self.boy.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.boy.setH(self.boy.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.boy.setY(self.boy, -35 * globalClock.getDt()) if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0): if self.isMoving is False: self.boy.loop("run") self.isMoving = True else: if self.isMoving: self.boy.stop() self.boy.pose("walk",5) self.isMoving = False camvec = self.boy.getPos() - base.camera.getPos() camvec.setZ(20) camdist = camvec.length() camvec.normalize() if (camdist > 50): base.camera.setPos(base.camera.getPos() + camvec*(camdist-50)) camdist = 50.0 if (camdist < 25.0): base.camera.setPos(base.camera.getPos() - camvec*(25-camdist)) camdist = 25.0 self.cTrav1.traverse(render) self.collisionHandler1.sortEntries() if self.collisionHandler1.getNumEntries() == 0: self.startPos = self.boy.getPos() #self.boy.loop("eat") else: self.boy.setPos(self.startPos); #print self.collisionHandler1.getEntry(0) base.camera.setZ(self.boy.getZ() + 10)
class MousePicker(object): def __init__(self, pickTag="MyPickingTag", nodeName="pickRay", showCollisions=False): self.pickTag = pickTag self.nodeName = nodeName self.showCollisions = showCollisions def create(self): self.mPickerTraverser = CollisionTraverser() self.mCollisionQue = CollisionHandlerQueue() self.mPickRay = CollisionRay() self.mPickRay.setOrigin(base.camera.getPos(base.render)) self.mPickRay.setDirection(base.render.getRelativeVector(base.camera, Vec3(0, 1, 0))) # create our collison Node to hold the ray self.mPickNode = CollisionNode(self.nodeName) self.mPickNode.addSolid(self.mPickRay) # Attach that node to the camera since the ray will need to be positioned # relative to it, returns a new nodepath # well use the default geometry mask # this is inefficent but its for mouse picking only self.mPickNP = base.camera.attachNewNode(self.mPickNode) # we'll use what panda calls the "from" node. This is reall a silly convention # but from nodes are nodes that are active, while into nodes are usually passive environments # this isnt a hard rule, but following it usually reduces processing # Everything to be picked will use bit 1. This way if we were doing other # collision we could seperate it, we use bitmasks to determine what we check other objects against # if they dont have a bitmask for bit 1 well skip them! self.mPickNode.setFromCollideMask(BitMask32(1)) # Register the ray as something that can cause collisions self.mPickerTraverser.addCollider(self.mPickNP, self.mCollisionQue) # Setup 2D picker self.mPickerTraverser2D = CollisionTraverser() self.mCollisionQue2D = CollisionHandlerQueue() self.mPickNode2D = CollisionNode("2D PickNode") self.mPickNode2D.setFromCollideMask(BitMask32(1)) self.mPickNode2D.setIntoCollideMask(BitMask32.allOff()) self.mPick2DNP = base.camera2d.attachNewNode(self.mPickNode2D) self.mPickRay2D = CollisionRay() self.mPickNode2D.addSolid(self.mPickRay2D) self.mPickerTraverser2D.addCollider(self.mPick2DNP, self.mCollisionQue2D) if self.showCollisions: self.mPickerTraverser.showCollisions(base.render) self.mPickerTraverser2D.showCollisions(base.aspect2d) def mousePick(self, traverse=None, tag=None): # do we have a mouse if base.mouseWatcherNode.hasMouse() == False: return None, None traverse = traverse or base.render tag = tag or self.pickTag mpos = base.mouseWatcherNode.getMouse() # Set the position of the ray based on the mouse position self.mPickRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.mPickerTraverser.traverse(traverse) if self.mCollisionQue.getNumEntries() > 0: self.mCollisionQue.sortEntries() for entry in self.mCollisionQue.getEntries(): pickedObj = entry.getIntoNodePath() pickedObj = pickedObj.findNetTag(tag) if not pickedObj.isEmpty(): pos = entry.getSurfacePoint(base.render) return pickedObj, pos return None, None def mousePick2D(self, traverse=None, tag=None, all=False): # do we have a mouse if base.mouseWatcherNode.hasMouse() == False: return None, None traverse = traverse or base.render tag = tag or self.pickTag mpos = base.mouseWatcherNode.getMouse() self.mPickRay2D.setFromLens(base.cam2d.node(), mpos.getX(), mpos.getY()) self.mPickerTraverser2D.traverse(base.aspect2d) if self.mCollisionQue2D.getNumEntries() > 0: self.mCollisionQue2D.sortEntries() if all: return ( [ (entry.getIntoNodePath().findNetTag(tag), entry.getSurfacePoint(base.aspect2d)) for entry in self.mCollisionQue2D.getEntries() ], None, ) else: entry = self.mCollisionQue2D.getEntry(0) pickedObj = entry.getIntoNodePath() pickedObj = pickedObj.findNetTag(tag) if not pickedObj.isEmpty(): pos = entry.getSurfacePoint(base.aspect2d) return pickedObj, pos return None, None
class Player(GameObject, Walker, ArmedObject): def __init__(self): GameObject.__init__(self, Vec3(0, 0, 0), None, None, 100, 15, "player", 1, MASK_INTO_PLAYER) Walker.__init__(self) ArmedObject.__init__(self) self.weaponNP = self.actor light = PointLight("basic light") light.setColor(Vec4(1, 1, 1, 1)) light.setAttenuation((1, 0.01, 0.005)) self.lightNP = self.root.attachNewNode(light) self.lightNP.setZ(1) render.setLight(self.lightNP) self.collider.node().setFromCollideMask(MASK_WALLS | MASK_FROM_PLAYER) self.actor.setZ(self.height) base.camera.reparentTo(self.actor) base.camera.setPos(0, 0, 0) base.camera.setHpr(0, 0, 0) lens = base.camLens ratio = lens.getAspectRatio() lens.setFov(80 * ratio) lens.setNear(0.03) self.lastMousePos = Vec2(0, 0) self.mouseSpeedHori = 50.0 self.mouseSpeedVert = 30.0 self.mouseSensitivity = 1.0 self.healthLeft = -0.9 self.healthRight = 0.9 self.healthWidth = self.healthRight - self.healthLeft self.uiRoot = base.a2dBottomCenter.attachNewNode( PandaNode("player UI")) self.healthBar = loader.loadModel("UI/healthBar") self.healthBar.reparentTo(self.uiRoot) self.healthBar.setZ(0.05) self.healthBar.setX(self.healthLeft) self.healthBar.getChild(0).setScale(self.healthWidth / 6.0) self.weaponUIRoot = self.uiRoot.attachNewNode( PandaNode("player weapon UI")) self.weaponUIRoot.setPos(0, 0, 0.1) self.addWeapon(RapidShotgunWeapon(self.weaponUIRoot)) self.addWeapon(BlasterWeapon(self.weaponUIRoot)) self.weapons[0].setAvailable(True) self.setCurrentWeapon(0) self.updateHealthUI() self.inventory = [] self.updatingEffects = [] self.interactionSegment = CollisionSegment(0, 0, 0, 0, 1.5, 0) rayNode = CollisionNode("player interaction ray") rayNode.addSolid(self.interactionSegment) rayNode.setFromCollideMask(MASK_WALLS | MASK_FLOORS | MASK_INTO_ENEMY) rayNode.setIntoCollideMask(0) self.interactionSegmentNodePath = self.actor.attachNewNode(rayNode) #self.interactionSegmentNodePath.show() self.interactionSegmentQueue = CollisionHandlerQueue() self.interactionSegmentTraverser = CollisionTraverser() self.interactionSegmentTraverser.addCollider( self.interactionSegmentNodePath, self.interactionSegmentQueue) #self.hurtSound = loader.loadSfx("Sounds/FemaleDmgNoise.ogg") def update(self, keys, dt): GameObject.update(self, dt) self.walking = False quat = self.root.getQuat(render) forward = quat.getForward() right = quat.getRight() if keys["up"]: self.walking = True self.velocity += forward * self.acceleration * dt if keys["down"]: self.walking = True self.velocity -= forward * self.acceleration * dt if keys["left"]: self.walking = True self.velocity -= right * self.acceleration * dt if keys["right"]: self.walking = True self.velocity += right * self.acceleration * dt if self.walking: self.inControl = True mouseWatcher = base.mouseWatcherNode if mouseWatcher.hasMouse(): xSize = base.win.getXSize() ySize = base.win.getYSize() xPix = float(xSize % 2) / xSize yPix = float(ySize % 2) / ySize mousePos = Vec2(base.mouseWatcherNode.getMouse()) mousePos.addX(-xPix) mousePos.addY(-yPix) if abs(mousePos.x) < xPix: mousePos.x = 0 if abs(mousePos.y) < yPix: mousePos.y = 0 base.win.movePointer(0, xSize // 2, ySize // 2) else: mousePos = self.lastMousePos self.root.setH(self.root.getH() - mousePos.x * self.mouseSpeedHori * self.mouseSensitivity) self.actor.setP(self.actor.getP() + mousePos.y * self.mouseSpeedVert * self.mouseSensitivity) if self.currentWeapon is not None: if keys["shoot"]: self.startAttacking() else: self.endAttacking() [effect.update(self, dt) for effect in self.updatingEffects] [ effect.cleanup() for effect in self.updatingEffects if not effect.active ] self.updatingEffects = [ effect for effect in self.updatingEffects if effect.active ] def attackPerformed(self, weapon): ArmedObject.attackPerformed(self, weapon) def postTraversalUpdate(self, dt): Walker.update(self, dt) ArmedObject.update(self, dt) def alterHealth(self, dHealth, incomingImpulse, flinchValue, overcharge=False): GameObject.alterHealth(self, dHealth, incomingImpulse, flinchValue, overcharge) self.updateHealthUI() #self.hurtSound.play() def updateHealthUI(self): perc = self.health / self.maxHealth self.healthBar.setSx(perc) self.healthBar.setColorScale(1.0 - (perc - 0.5) / 0.5, min(1, perc / 0.5), 0, 1) #self.healthCounter.setText("{0:-.0f}".format(self.health)) #self.healthCounter.setColorScale(1.0 - (perc - 0.5)/0.5, min(1, perc/0.5), 0, 1) def scrollWeapons(self, direction): newIndex = (self.currentWeaponIndex + direction) % len(self.weapons) self.setCurrentWeapon(newIndex) def interact(self): self.interactionSegmentTraverser.traverse(render) if self.interactionSegmentQueue.getNumEntries() > 0: #print ("Hit something:") self.interactionSegmentQueue.sortEntries() rayHit = self.interactionSegmentQueue.getEntry(0) intoNP = rayHit.getIntoNodePath() if intoNP.hasPythonTag(TAG_OWNER): intoObj = intoNP.getPythonTag(TAG_OWNER) if intoObj is not None and hasattr(intoObj, "interact"): intoObj.interact(self) def addUpdatingEffect(self, effect): self.updatingEffects.append(effect) effect.start(self) def cleanup(self): if self.uiRoot is not None: self.uiRoot.removeNode() self.uiRoot = None self.healthBar = None self.weaponUIRoot = None if self.lightNP is not None: render.clearLight(self.lightNP) self.lightNP.removeNode() self.lightNP = None for effect in self.updatingEffects: effect.cleanup() self.updatingEffects = [] ArmedObject.cleanup(self) Walker.cleanup(self) GameObject.cleanup(self)
class ChessboardDemo(ShowBase): def __init__(self): # Initialize the ShowBase class from which we inherit, which will # create a window and set up everything we need for rendering into it. ShowBase.__init__(self) # This code puts the standard title and instruction text on screen self.title = OnscreenText(text="Panda3D: Tutorial - Mouse Picking", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1), pos=(0.8, -0.95), scale=.07) self.escapeEvent = OnscreenText(text="ESC: Quit", parent=base.a2dTopLeft, style=1, fg=(1, 1, 1, 1), pos=(0.06, -0.1), align=TextNode.ALeft, scale=.05) self.mouse1Event = OnscreenText( text="Left-click and drag: Pick up and drag piece", parent=base.a2dTopLeft, align=TextNode.ALeft, style=1, fg=(1, 1, 1, 1), pos=(0.06, -0.16), scale=.05) self.accept('escape', sys.exit) # Escape quits self.disableMouse() # Disble mouse camera control camera.setPosHpr(0, -12, 8, 0, -35, 0) # Set the camera self.setupLights() # Setup default lighting # Since we are using collision detection to do picking, we set it up like # any other collision detection system with a traverser and a handler self.picker = CollisionTraverser() # Make a traverser self.pq = CollisionHandlerQueue() # Make a handler # Make a collision node for our picker ray self.pickerNode = CollisionNode('mouseRay') # Attach that node to the camera since the ray will need to be positioned # relative to it self.pickerNP = camera.attachNewNode(self.pickerNode) # Everything to be picked will use bit 1. This way if we were doing other # collision we could separate it self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() # Make our ray # Add it to the collision node self.pickerNode.addSolid(self.pickerRay) # Register the ray as something that can cause collisions self.picker.addCollider(self.pickerNP, self.pq) # self.picker.showCollisions(render) # Now we create the chess board and its pieces # We will attach all of the squares to their own root. This way we can do the # collision pass just on the squares and save the time of checking the rest # of the scene self.squareRoot = render.attachNewNode("squareRoot") # For each square self.squares = [None for i in range(64)] self.pieces = [None for i in range(64)] for i in range(64): # Load, parent, color, and position the model (a single square # polygon) self.squares[i] = loader.loadModel("models/square") self.squares[i].reparentTo(self.squareRoot) self.squares[i].setPos(SquarePos(i)) self.squares[i].setColor(SquareColor(i)) # Set the model itself to be collideable with the ray. If this model was # any more complex than a single polygon, you should set up a collision # sphere around it instead. But for single polygons this works # fine. self.squares[i].find("**/polygon").node().setIntoCollideMask( BitMask32.bit(1)) # Set a tag on the square's node so we can look up what square this is # later during the collision pass self.squares[i].find("**/polygon").node().setTag('square', str(i)) # We will use this variable as a pointer to whatever piece is currently # in this square # The order of pieces on a chessboard from white's perspective. This list # contains the constructor functions for the piece classes defined # below pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook) for i in range(8, 16): # Load the white pawns self.pieces[i] = Pawn(i, WHITE) for i in range(48, 56): # load the black pawns self.pieces[i] = Pawn(i, PIECEBLACK) for i in range(8): # Load the special pieces for the front row and color them white self.pieces[i] = pieceOrder[i](i, WHITE) # Load the special pieces for the back row and color them black self.pieces[i + 56] = pieceOrder[i](i + 56, PIECEBLACK) # This will represent the index of the currently highlited square self.hiSq = False # This wil represent the index of the square where currently dragged piece # was grabbed from self.dragging = False # Start the task that handles the picking self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask') self.accept("mouse1", self.grabPiece) # left-click grabs a piece self.accept("mouse1-up", self.releasePiece) # releasing places it # This function swaps the positions of two pieces def swapPieces(self, fr, to): temp = self.pieces[fr] self.pieces[fr] = self.pieces[to] self.pieces[to] = temp if self.pieces[fr]: self.pieces[fr].square = fr self.pieces[fr].obj.setPos(SquarePos(fr)) if self.pieces[to]: self.pieces[to].square = to self.pieces[to].obj.setPos(SquarePos(to)) def mouseTask(self, task): # This task deals with the highlighting and dragging based on the mouse # First, clear the current highlight if self.hiSq is not False: self.squares[self.hiSq].setColor(SquareColor(self.hiSq)) self.hiSq = False # Check to see if we can access the mouse. We need it to do anything # else if self.mouseWatcherNode.hasMouse(): # get the mouse position mpos = self.mouseWatcherNode.getMouse() # Set the position of the ray based on the mouse position self.pickerRay.setFromLens(self.camNode, mpos.getX(), mpos.getY()) # If we are dragging something, set the position of the object # to be at the appropriate point over the plane of the board if self.dragging is not False: # Gets the point described by pickerRay.getOrigin(), which is relative to # camera, relative instead to render nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin()) # Same thing with the direction of the ray nearVec = render.getRelativeVector( camera, self.pickerRay.getDirection()) self.pieces[self.dragging].obj.setPos( PointAtZ(.5, nearPoint, nearVec)) # Do the actual collision pass (Do it only on the squares for # efficiency purposes) self.picker.traverse(self.squareRoot) if self.pq.getNumEntries() > 0: # if we have hit something, sort the hits so that the closest # is first, and highlight that node self.pq.sortEntries() i = int(self.pq.getEntry(0).getIntoNode().getTag('square')) # Set the highlight on the picked square self.squares[i].setColor(HIGHLIGHT) self.hiSq = i return Task.cont def grabPiece(self): # If a square is highlighted and it has a piece, set it to dragging # mode if self.hiSq is not False and self.pieces[self.hiSq]: self.dragging = self.hiSq self.hiSq = False def releasePiece(self): # Letting go of a piece. If we are not on a square, return it to its original # position. Otherwise, swap it with the piece in the new square # Make sure we really are dragging something if self.dragging is not False: # We have let go of the piece, but we are not on a square if self.hiSq is False: self.pieces[self.dragging].obj.setPos(SquarePos(self.dragging)) else: # Otherwise, swap the pieces self.swapPieces(self.dragging, self.hiSq) # We are no longer dragging anything self.dragging = False def setupLights(self): # This function sets up some default lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.8, .8, .8, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(LVector3(0, 45, -45)) directionalLight.setColor((0.2, 0.2, 0.2, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight))
class Viewfinder(DirectFrame): notify = directNotify.newCategory("Viewfinder") Ratio = 0.91 GoodRows = 13 BadRows = 4 RaySpreadX = 0.08 RaySpreadY = 0.06 ViewSizeX = (GoodRows - BadRows) * RaySpreadX ViewSizeY = (GoodRows - BadRows) * RaySpreadY def __init__(self, size): DirectFrame.__init__(self, parent=aspect2d, pos=(0, -1.0, 0), relief=None) image = loader.loadModel( "phase_4/models/minigames/photo_game_viewfinder.bam") self['image'] = image self['image_scale'] = (size, 1.0, size) self.screenSizeMult = size * Viewfinder.Ratio self.setTransparency(True) self.setDepthWrite(1) self.setDepthTest(1) self.initialiseoptions(Viewfinder) self.captureCam = NodePath(Camera("CaptureCamera")) self.captureCam.reparentTo(base.camera) self.captureLens = PerspectiveLens() self.captureCam.node().setLens(self.captureLens) self.focusTrav = CollisionTraverser('focusTrav') ray = CollisionRay() rayNode = CollisionNode('rayNode') rayNode.addSolid(ray) rayNode.setCollideMask(BitMask32(0)) rayNode.setFromCollideMask(CIGlobals.WallBitmask) self.focusRay = ray self.focusRayNode = self.captureCam.attachNewNode(rayNode) self.focusHandler = CollisionHandlerQueue() self.focusTrav.addCollider(self.focusRayNode, self.focusHandler) self.textureBuffer = base.win.makeTextureBuffer( "ViewFinderCapture", int(128 * 1.33), 128) self.displayRegion = self.textureBuffer.makeDisplayRegion() self.displayRegion.setCamera(self.captureCam) self.__updateRegions() taskMgr.add(self.__update, "viewfinderUpdate") def takePicture(self): return self.displayRegion.getScreenshot() def takePictureRaw(self): img = PNMImage() tex = self.takePicture() tex.store(img) ss = StringStream() img.write(ss, 'jpg') if 1: # Test it img2 = PNMImage() img2.read(ss) img2.write(Filename("test_viewfinder.jpg")) return ss.getData() def isInView(self, nodePath): """ Returns True if the `nodePath` is both in the bounds of the camera lens and not occluded by anything. """ if not nodePath or not isinstance(nodePath, RemoteCameraShyAvatar): return False nodePath = nodePath.avatar lensBounds = self.captureCam.node().getLens().makeBounds() bounds = nodePath.getBounds() bounds.xform(nodePath.getParent().getMat(self.captureCam)) inView = lensBounds.contains(bounds) if inView: # We have another step, make sure they're not occluded by another object. self.focusRayNode.lookAt(nodePath) self.focusTrav.traverse(render) if self.focusHandler.getNumEntries() > 0: self.focusHandler.sortEntries() collNP = self.focusHandler.getEntry(0).getIntoNodePath() parentNP = collNP.getParent().getPythonTag('player') # Make sure this is the same NodePath that was passed in. if parentNP == nodePath: return True return False def __updateRegions(self): self.screenSizeX = (base.a2dRight - base.a2dLeft) * self.screenSizeMult self.screenSizeY = (base.a2dTop - base.a2dBottom) * self.screenSizeMult self.captureFOV = ( Viewfinder.ViewSizeX / self.screenSizeX * CIGlobals.getSettingsMgr().getSetting("fpmgfov").getValue() * 0.5) self.captureLens.setFov(self.captureFOV) self.captureLens.setAspectRatio(1.33) def __update(self, task): self.__updateRegions() return task.cont def cleanup(self): taskMgr.remove("viewfinderUpdate") self.captureCam.removeNode() del self.captureCam del self.screenSizeX del self.screenSizeY del self.captureLens del self.captureFOV del self.screenSizeMult self.focusRayNode.removeNode() del self.focusRayNode del self.focusRay del self.focusTrav del self.focusHandler self.destroy()
class mode_head(): def __init__(self,base,Golog, folder_path = None, parent = None): # Set up basic attributes self.base = base self.golog = Golog self.bools = {'textboxes':True} self.buttons = dict() self.window_tasks = dict() self.bt = None self.mw = None self.listener = DirectObject() self.folder_path = folder_path #absolute path of golog folder '/path/to/golog/folder' if self.folder_path: self.file_path = os.path.abspath(self.folder_path + '/' + self.golog.label+ '.golog') autosave = True self.has_window = False self.parent = parent #for autosaving up to original golog self.reset = self.basic_reset self.garbage = [] #list of deleted math_data/graphics_data etc. #create a 2d rende self.render2d = NodePath('2d render') self.camera2D = self.render2d.attachNewNode(Camera('2d Camera')) self.camera2D.setDepthTest(False) self.camera2D.setDepthWrite(False) lens = OrthographicLens() lens.setFilmSize(2, 2) lens.setNearFar(-1000, 1000) self.camera2D.node().setLens(lens) # make a dictionary of mode_heads in the underlying golog if hasattr(self.golog,'mode_heads'): m = 0 while m in self.golog.mode_heads.keys(): m+=1 #get smallest unused mode_head index self.index = m self.label = self.golog.label+"_mode_head_"+str(self.index) self.golog.mode_heads[self.index] = self else: self.golog.mode_heads = dict() self.index = 0 self.label = self.golog.label+"_mode_head_"+ str(self.index) self.golog.mode_heads[self.index] = self ########## ### set up collision handling ### self.queue = CollisionHandlerQueue() ### set up selection tools self.create_list = [[],[]] #select nodes and add to create_list in order to create higher simplecies self.bools = {'selecter':False,'textboxes':True,'shift_clicked':False} #some bools that will be usefull self.dict = {'shift_pt':[None,None]} # set up mouse picker self.pickerNode = CollisionNode('mouseRay') self.pickerNP = self.golog.camera.attachNewNode(self.pickerNode) #attach collision node to camera self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.pickerNode.set_into_collide_mask(0) #so that collision rays don't collide into each other if there are two mode_heads self.golog.cTrav.addCollider(self.pickerNP,self.queue) #send collisions to self.queue # set up plane for picking self.planeNode = self.golog.render.attachNewNode("plane") self.planeNode.setTag("mode_head",self.label) # tag to say it belongs to this mode_head self.planeNode.setTag("mode_node", 'plane') self.planeFromObject = self.planeNode.attachNewNode(CollisionNode("planeColNode")) self.planeFromObject.node().addSolid(CollisionPlane(Plane(Vec3(0,-1,0),Point3(0,0,0)))) self.plane = self.planeFromObject.node().getSolid(0) ### # set up preview text self.textNP = self.render2d.attachNewNode(TextNode('text node')) self.textNP.setScale(.2) self.textNP.setPos(-1,0,0) self.textNP.show() #set up dragging info self.grabbed_dict = dict() self.drag_dict = dict() #a mapping from selected nodes to their original positions for dragging self.mouse_down_loc = (0,0,0) self.lowest_level = 3 def open_math_data(self,math_data): if math_data.type == 'golog': golog_dict = math_data() #calls the mathdata (which is a golog_dict) subgolog = golog_dict['golog'] subfolder_path = golog_dict['folder_path'] #### just to be safe, but probably not needed subgolog_folder_path = os.path.join(self.folder_path,'subgologs') if not os.path.exists(subgolog_folder_path): os.mkdir(subgolog_folder_path) #### folder_path = os.path.join(self.folder_path, *golog_dict['folder_path']) print(folder_path) controllable_golog = mode_head(self.base, subgolog, folder_path = folder_path, parent = self) window_manager.modeHeadToWindow(self.base, controllable_golog) if math_data.type == 'file': file_name, file_extension = os.path.splitext(math_data()[-1]) # if file_extension == '.txt': # tk_funcs.edit_txt(os.path.join(self.folder_path,*math_data())) # else: #prompt user to select a program tk_funcs.run_program('',os.path.join(self.folder_path,*math_data())) if math_data.type == 'latex': file_dict = math_data() tex_folder = os.path.join(os.path.abspath(self.folder_path),*file_dict['folder']) tex_file = os.path.join(os.path.abspath(self.folder_path),*file_dict['tex']) if 'pdf' in file_dict.keys(): pdf_file = os.path.join(self.folder_path, *file_dict['pdf']) elif os.path.exists(tex_file.split('.tex')[0]+'.pdf'): #if there is a pdf in the folder with the same name file_dict['pdf'] = file_dict['tex'] file_dict['pdf'][-1] = file_dict['pdf'][-1].split('.tex')[0]+'.pdf' #change extension to .pdf pdf_file = os.path.join(self.folder_path, *file_dict['pdf']) else: pdf_file = None tk_funcs.pdf_or_tex(pdf_file, tex_file) if math_data.type == 'weblink': open_new_tab(math_data()) def update_math_data(self,simplex, math_data_type, **kwargs): if autosave == True: self.save() if 'label' in kwargs: simplex.label = kwargs['label'] self.golog.Simplex_to_Graphics[simplex].textNP.node().setText(simplex.label) self.golog.text_preview_set(self.bools['textboxes']) if simplex.math_data.type != 'None': answer = tk_funcs.are_you_sure('are you sure you want to delete the current math_data?') if answer == 'yes': self.delete_math_data(simplex) else: return if math_data_type == 'None': simplex.math_data = hcat.Math_Data(type = 'None') if math_data_type == 'golog': #create a path for all subgologs, if it doesn't already exist subgolog_folder_path = os.path.join(self.folder_path,'subgologs') if not os.path.exists(subgolog_folder_path): os.mkdir(subgolog_folder_path) new_golog = golog.golog(self.base, label = kwargs['label']) #create a new golog #create a unique folder path list in subgolog_folder_path unique_path = tk_funcs.unique_path(subgolog_folder_path,[kwargs['label']]) new_folder_path = ['subgologs', *unique_path] os.mkdir(os.path.join(self.folder_path , *new_folder_path)) #make the directory as above #create a new golog save at new_folder_path/label.golog new_save_location = os.path.join(self.folder_path, *new_folder_path, kwargs['label']+'.golog') #new_save_location should be a subfolder of subgologs gexport(new_golog, new_save_location) #math data is a dictionary of the physical golog and it's relative save path list golog_dict = {'golog':new_golog, 'folder_path':new_folder_path} simplex.math_data = hcat.Math_Data(math_data = golog_dict, type = 'golog') if math_data_type == 'file': if not os.path.exists(os.path.join(self.folder_path,'files')): os.mkdir(os.path.join(self.folder_path,'files')) file_folder_path = ['files'] file_location = tk_funcs.ask_file_location() if not file_location: return #if user cancels file_name = os.path.split(file_location)[1] #file name with extension file_path = tk_funcs.unique_path(os.path.join(self.folder_path),[*file_folder_path, file_name]) #get a unique file path starting from the file_folder copyfile(file_location, os.path.join(self.folder_path,*file_path)) simplex.math_data = hcat.Math_Data(math_data = file_path, type = 'file') #? add handler for if user exits text editor #? make asynchronous if math_data_type == 'latex': #ensure latex folder exists if not os.path.exists(os.path.join(self.folder_path,'latex')): os.mkdir(os.path.join(self.folder_path,'latex')) # create a uniquely named folder in self.folder_path/latex/ based on simplex.label tex_folder_path = tk_funcs.unique_path(root = self.folder_path, path = ['latex',simplex.label]) os.mkdir(os.path.join(self.folder_path, *tex_folder_path)) #create a tex file in tex folder tex_file_path = [*tex_folder_path, simplex.label+'.tex'] # ask if want new or to load one location = tk_funcs.load_tex(self.folder_path) # if new, returns True and copies template tex file # if load, returns a path and copies the path into tex_file_path true_path = os.path.join(self.folder_path,*tex_file_path) if location == True: copyfile(os.path.abspath('./misc_data/config_files/template.tex'), true_path) # # open( true_path , 'w').close() if isinstance(location, str): copyfile(location, true_path) # make a file dictionary with just tex file in it file_dict = {'tex':tex_file_path, 'folder':tex_folder_path} simplex.math_data = hcat.Math_Data(math_data = file_dict, type = 'latex') if math_data_type == 'weblink': weblink = tk_funcs.ask_weblink() simplex.math_data = hcat.Math_Data(math_data = weblink, type = 'weblink') if math_data_type == 'text': #create a text file if not os.path.exists(os.path.join(self.folder_path,'files')): os.mkdir(os.path.join(self.folder_path,'files')) file_folder_path = ['files'] file_path = tk_funcs.unique_path(root = self.folder_path, path = ['files',simplex.label+'.txt' ]) with open(os.path.join(self.folder_path, *file_path),'w') as file: pass #create a math_data for it simplex.math_data = hcat.Math_Data(math_data = file_path, type = 'file') #save golog if autosave == True: self.save() return simplex.math_data def delete_math_data(self,simplex,**kwargs): simplex.math_data.delete(self.folder_path) simplex.math_data = hcat.Math_Data(type = 'None') def setup_window(self, windict): self.windict = windict for button in self.buttons.keys(): self.listener.accept(self.windict['bt'].prefix+button, self.buttons[button], extraArgs = [self.windict['mw']]) for window_task in self.window_tasks.keys(): base.taskMgr.add(self.window_tasks[window_task], window_task, extraArgs = [self.windict['mw']], appendTask = True) self.has_window = True def save(self, *ask): #if has a parent, save the parent. If not, save itself if not self.parent: #if doesn't have a parent mode_head, save parent #if we pass something to ask it will ask (this includes mousewatchers) if ask: save_location = tk_funcs.ask_file_location(initial_dir = self.folder_path) if not save_location: return #if user cancels print('saving to:\n'+save_location) gexport(self.golog, self.folder_path) else: gexport(self.golog, self.file_path) else: self.parent.save()# if parent has no mode_head, save itself #basic reset function which shuts off the listener and removes button bindings. Should only be called if no "reset" function exists def basic_reset(self,*args): self.buttons = dict() self.window_tasks = dict() self.listener.ignoreAll() #function to call before deleting the mode_head, for example when closing a window def clean(self): self.reset() #close window if self.has_window == True: if hasattr(mode_head,'windict'): if 'win' in mode_head.windict.keys(): self.base.closeWindow(mode_head.windict['win'], keepCamera = True, removeWindow = True) self.has_window = False del self.golog.mode_heads[self.index] del self.reset # function to return the only the relevant collision data from the mouseRay def get_relevant_entries(self, mw): # get list of entries by distance if not mw.node().hasMouse(): return mpos = mw.node().getMouse() self.pickerRay.setFromLens(self.golog.camNode,mpos.getX(),mpos.getY()) #mouse ray goes from camera through the 'lens plane' at position of mouse self.golog.cTrav.traverse(self.golog.render) self.queue.sortEntries() # get the first relevant node traversed by mouseRay #### ignore everything with a mode_head tag that is not defined by this mode_head for e in self.queue.getEntries(): if e.getIntoNodePath().getParent().hasTag("mode_head"): if e.getIntoNodePath().getParent().getTag("mode_head") == self.label: return (e.getIntoNodePath().getParent(), e.getIntoNodePath().getParent().getTag("mode_node"),e.getSurfacePoint(e.getIntoNodePath())) break else: entry = e break #return node create_list in the golog entryNP = entry.getIntoNodePath().getParent() if entryNP.hasTag('level'): return (entryNP, entryNP.getTag('level'),entryNP.getPos()) #function to 'pick up' a node by adding it to the dragged dictionary def pickup(self, mw): if not mw.node().hasMouse(): return (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) ### get position on plane for mouseloc mpos = mw.node().getMouse() self.pickerRay.setFromLens(self.golog.camNode,mpos.getX(),mpos.getY()) #mouse ray goes from camera through the 'lens plane' at position of mouse self.golog.cTrav.traverse(self.golog.render) self.queue.sortEntries() for e in self.queue.getEntries(): if e.getIntoNodePath().getParent().hasTag("mode_head"): if e.getIntoNodePath().getParent().getTag("mode_head") == self.label: if e.getIntoNodePath().getParent().getTag("mode_node") == 'plane': self.mouse_down_loc = e.getSurfacePoint(e.getIntoNodePath()) break #if selected node is in the drag_dict, use it to set a mouse location # if entryNP in self.drag_dict.keys(): self.mouse_down_loc = entryNP.getPos() if node_type in ['0','1']: self.grabbed_dict = {'graphics': self.golog.NP_to_Graphics[entryNP],'dragged':False, 'orig_pos': entryNP.getPos()} if node_type == 'plane': for node in self.create_list[0]: node.setColorScale(1,1,1,1) #turn white self.create_list = [[],[]] for node in self.drag_dict.keys(): node.setColorScale(1,1,1,1) self.drag_dict = dict() #drag dict is used for multi-dragging a = self.plane.distToPlane(self.golog.camera.getPos())/(2*self.golog.camera.node().getLens().getNear())# ratio for camera movement self.grabbed_dict = {'graphics':self.golog.camera, 'dragged':False, 'orig_pos': self.golog.camera.getPos(), 'mpos': LPoint3f(a*mpos.getX(),a*0,a*mpos.getY())} self.lowest_level = 3 #function to 'put down' a node, returns true if it's dragged something def putdown(self, mw): for node in self.drag_dict.keys(): self.drag_dict[node] = self.golog.NP_to_Graphics[node].graphics_kwargs['pos'] self.lowest_level = min(self.lowest_level, int(node.getTag('level'))) if 'dragged' in self.grabbed_dict.keys(): if self.grabbed_dict['dragged'] == True: self.grabbed_dict = dict() return True self.grabbed_dict = dict() #function to select a node and add a 1-simplex between 2 create_list 0-simplecies def select_for_creation(self, mw): if not mw.node().hasMouse(): return #remove selected for node in self.drag_dict.keys(): node.setColorScale(1,1,1,1) self.drag_dict = dict() self.lowest_level = 3 ### selection ### (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) if node_type == '0':# and set(create_list[1:]) = {[]}: if entryNP not in self.create_list[0]: #? don't just append, re-sort self.create_list[0].append(entryNP) entryNP.setColorScale(1,0,0,0) #turn red if len(self.create_list[0]) == 2: # NP -> graphics -> simplex faces = tuple([self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[faceNP]] for faceNP in self.create_list[0][-1:-3:-1]]) asked_list = tk_funcs.ask_math_data('1-Simplex') if not asked_list: #[label, math_data_type,] return simplex = self.golog.add(faces, label = asked_list[0]) #reversed create_list objects and creates a 1 - simplex from them self.update_math_data(simplex, asked_list[1], label = asked_list[0]) for node in self.create_list[0]: node.setColorScale(1,1,1,1) self.create_list[0] = [] #reset create_list #open math_data of simplex under mouse def mouse_open(self, mw): (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) # if spaced on a 0 simplex, open it's math data, or create it if node_type in ['0','1']: simplex = self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]] if not simplex.math_data(): asked_list = tk_funcs.ask_math_data(simplex.label) if not asked_list: return self.update_math_data(simplex, math_data_type = asked_list[1], label = asked_list[0]) #? make asynchronous else: self.open_math_data(simplex.math_data) # delete a simplex, prompt to delete the math_data and (recursively) it's supported simplecies def delete(self,mw): (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) if node_type in ['0','1']: #warning about deleting supported simplecies graphics = self.golog.NP_to_Graphics[entryNP] simplex = self.golog.Graphics_to_Simplex[graphics] if simplex.supports: answer = tk_funcs.are_you_sure(simplex.label+' still supports other simplecies. Are you sure you wish to delete?') if answer != 'yes': return self.delete_math_data(simplex) graphics._remove() #update the math_data of a simplex under the mouse def mouse_update(self, mw): (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) if node_type in ['0','1']: simplex = self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]] asked_list = tk_funcs.ask_math_data(simplex.label) if not asked_list: return self.update_math_data(simplex, math_data_type = asked_list[1], label = asked_list[0]) #create a simplex given a mouse position def create(self, mw): (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) if node_type == 'plane': for node in self.create_list[0]: node.setColorScale(1,1,1,1) #turn white self.create_list = [[],[]] asked_list = tk_funcs.ask_math_data('0-Simplex') if not asked_list: return #if canceled, do not create a simplex simplex = self.golog.add(0, pos = entry_pos, label = asked_list[0]) #create a simplex self.update_math_data(simplex, math_data_type = asked_list[1], label = asked_list[0]) #function which checks the drag dictionary and drags stuff def drag(self, mw): if self.grabbed_dict: #get mouse_loc mpos = mw.node().getMouse() self.pickerRay.setFromLens(self.golog.camNode,mpos.getX(),mpos.getY()) #mouse ray goes from camera through the 'lens plane' at position of mouse self.golog.cTrav.traverse(self.golog.render) self.queue.sortEntries() mouseloc = None for e in self.queue.getEntries(): if e.getIntoNodePath().getParent().getTag("mode_node") == 'plane': mouseloc = e.getSurfacePoint(e.getIntoNodePath()) break if not mouseloc:return self.bools['dragging'] = True # if there is something in the drag dict (for multiselect) if self.drag_dict: self.grabbed_dict['dragged'] = True #only drag lowest dim simplecies for node in self.drag_dict.keys(): if int(node.getTag('level')) == self.lowest_level: self.golog.NP_to_Graphics[node].update({'pos':self.drag_dict[node]+mouseloc-self.mouse_down_loc}) #if nothing is selected, drag the thing below you elif self.grabbed_dict['graphics'] != self.golog.camera: #radius of drag selection offset = mouseloc - self.grabbed_dict['graphics'].parent_pos_convolution() delta = offset - self.grabbed_dict['orig_pos'] norm = delta.getX()**2 +delta.getY()**2 +delta.getZ()**2 if self.grabbed_dict['dragged'] == True or norm > 1: self.grabbed_dict['dragged'] = True #if offset magnitude is greater than 1 or dragged == true, actually drag it if self.grabbed_dict['dragged'] == True: self.grabbed_dict['graphics'].update({'pos':offset}) elif self.grabbed_dict['graphics'] == self.golog.camera: a = self.plane.distToPlane(self.golog.camera.getPos())/(2*self.golog.camera.node().getLens().getNear())# ratio for camera movement self.golog.camera.setPos(self.grabbed_dict['orig_pos']-(a*mpos.getX(),0,a*mpos.getY())+self.grabbed_dict['mpos']) #send preview of math_data of simplex under the mouse def preview(self, mw): (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) if node_type == '0': simplex = self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]] elif node_type == '1': #? again consider what needs to be shown with 1-simplecies simplex = self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]] else: return # set preview up if self.has_window: if simplex.math_data.type == 'golog': self.windict['preview_dr'].setCamera(simplex.math_data()['golog'].camera) else: self.windict['preview_dr'].setCamera(self.camera2D) self.textNP.node().setText("label:\n" +simplex.label+"\n\n math data type:\n" + simplex.math_data.type) return def pprint(self,mw): (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) if node_type == '0': simplex = self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]] elif node_type == '1': #? again consider what needs to be shown with 1-simplecies simplex = self.golog.Graphics_to_Simplex[self.golog.NP_to_Graphics[entryNP]] else: return simplex.pprint() #tool for selecting multiple simplecies def multi_select(self,mw): if isinstance(mw, NodePath): entryNP = mw node_type = entryNP.getTag('level') else: return #reset select and create if node_type in ['0','1']: if entryNP in self.drag_dict.keys(): del self.drag_dict[entryNP] entryNP.setColorScale(1,1,1,1) self.lowest_level = min([*[int(node.getTag('level')) for node in self.drag_dict.keys()],3]) else: self.drag_dict[entryNP] = self.golog.NP_to_Graphics[entryNP].graphics_kwargs['pos'] entryNP.setColorScale(.5,.5,0,1) self.lowest_level = min(self.lowest_level, int(entryNP.getTag('level'))) def shift_box(self,mw): if None in self.dict['shift_pt']: self.dict['shift_pt'] = [None,None] return pt_1 = self.dict['shift_pt'][0] pt_2 = self.dict['shift_pt'][1] if sum([x**2 for x in list(pt_2-pt_1)]) <= 1: (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) self.multi_select(entryNP) #create vectors N = self.planeFromObject.node().getSolid(0).getNormal() x = [(pt_2-pt_1).getX(),0,0] z = [0,0,(pt_2-pt_1).getZ()] campos = list(self.golog.camera.getPos()) for simplex in self.golog.sSet.rawSimps: node = self.golog.Simplex_to_Graphics[simplex].node_list[0] P = list(node.getPos()) if t_int(pt_1,x,z,campos,P): self.multi_select(node) self.dict['shift_pt'] = [None,None] def consolidate(self, selected = False,sel_simp = None): #ask for label, or cancel G = self.golog # if a collection isn't provided, use the (multi-select) drag dictionary if not selected: selected = [G.Graphics_to_Simplex[G.NP_to_Graphics[node]] for node in self.drag_dict.keys()] if not selected: return #return if there was nothing passed, and nothing in the drag_dict for simp in selected: for face in simp.faces: if face not in selected: selected.append(face) # #? select a simplex to consolidate into # sel_simp = None # for simp in selected: # if simp.math_data.type == 'None': # sel_simp = simp #make a golog from selected new_golog = golog.golog(self.base, label ='test') def add(simplex): for face in simplex.faces: add(face) new_golog.add(simplex, pos = G.Simplex_to_Graphics[simplex].graphics_kwargs['pos']) for simplex in selected: add(simplex) #consolidate into 1 simplex if sel_simp: #consolidate into sel_simp subgolog_folder_path = os.path.join(self.folder_path,'subgologs') unique_path = tk_funcs.unique_path(subgolog_folder_path,[sel_simp.label]) new_folder_path = ['subgologs', *unique_path] sel_simp.math_data = hcat.Math_Data(math_data = {'golog':new_golog, 'folder_path':new_folder_path}, type = 'golog') #? remove simplexes and place at selected simplex location return sel_simp #create an entirely new simplex to put the golog into else: #? ask for label / cancel label = "test" subgolog_folder_path = os.path.join(self.folder_path,'subgologs') unique_path = tk_funcs.unique_path(subgolog_folder_path,[label]) new_folder_path = ['subgologs', *unique_path] #create a simplex with average position of things in golog avg = LPoint3f(*[sum([G.Simplex_to_Graphics[simplex].graphics_kwargs['pos'][i]/len(new_golog.sSet.simplecies[()]) for simplex in new_golog.sSet.simplecies[()]]) for i in range(3)]) s = self.golog.add(0, label ='test', math_data = hcat.Math_Data(math_data = {'golog':new_golog, 'folder_path':new_folder_path}, type = 'golog'), pos = LPoint3f(avg)) return s ########## BEGIN DEFINING MODES ########## #selection and creation mode def selection_and_creation(self, windict): def mouse1(mw): if not mw: return self.bools['shift_clicked'] = False self.pickup(mw) def shift_mouse1(mw): if not mw: return #on click, begin a rectagle dragging function (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) self.dict['shift_pt'][0] = entry_pos self.bools['shift_clicked'] = True def mouse1_up(mw): dropped_bool = self.putdown(mw) if self.bools['shift_clicked']: (entryNP, node_type, entry_pos) = self.get_relevant_entries(mw) self.dict['shift_pt'][1] = entry_pos self.shift_box(mw) self.bools['shift_clicked'] = False elif dropped_bool: pass else: self.select_for_creation(mw) def space(mw): if not mw: return self.mouse_open(mw) def u(mw): if not mw: return #? do a change not just update self.mouse_update(mw) def c(mw): self.consolidate() def p(mw): if not mw: return self.pprint(mw) def mouse3(mw): if not mw: return self.create(mw) def backspace(mw): if not mw: return self.delete(mw) def mouse_watch_task(mw,task): if not mw: return task.cont if not mw.node().hasMouse(): return task.cont self.drag(mw) self.preview(mw) return task.cont def wheel_up(mw): if not mw:return a = self.plane.distToPlane(self.golog.camera.getPos())/(2*self.golog.camera.node().getLens().getNear())# ratio for camera movement self.golog.camera.setPos( self.golog.camera.getPos() + (0,10,0) ) #fix for offset by storing a global camera - plane ratio def wheel_down(mw): if not mw:return self.golog.camera.setPos( self.golog.camera.getPos() - (0,10,0) ) def reset(*args): self.buttons = dict() self.window_task = dict() self.reset = self.basic_reset self.reset = reset self.buttons = {'mouse1':mouse1, 'mouse1-up':mouse1_up, 'mouse3':mouse3,'c':c, 'space':space, 'escape':self.reset, 's':self.save, 'u':u,'backspace':backspace, 'shift-mouse1':shift_mouse1,'p':p,'wheel_up':wheel_up, "wheel_down":wheel_down} self.window_tasks = {'mouse_watch_task':mouse_watch_task} self.setup_window(windict)
class Mouse(object): def __init__(self, base, oid_texture): self.base = base self.picking_texture = oid_texture self.picker = CollisionTraverser() self.pq = CollisionHandlerQueue() self.pickerNode = CollisionNode('mouseRay') self.pickerNP = self.base.cam.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask( CollisionNode.getDefaultCollideMask() | GeomNode.getDefaultCollideMask()) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.picker.addCollider(self.pickerNP, self.pq) #self.picker.showCollisions(render) if settings.mouse_over: taskMgr.add(self.mouse_task, 'mouse-task') self.over = None def find_over_ray(self): over = None if self.base.mouseWatcherNode.hasMouse(): mpos = self.base.mouseWatcherNode.getMouse() self.pickerRay.setFromLens(self.base.camNode, mpos.getX(), mpos.getY()) self.picker.traverse(render) if self.pq.getNumEntries() > 0: self.pq.sortEntries() np = self.pq.getEntry(0).getIntoNodePath().findNetPythonTag( 'owner') owner = np.getPythonTag('owner') over = owner np = self.pq.getEntry(0).getIntoNodePath().findNetPythonTag( 'patch') if np is not None: self.patch = np.getPythonTag('patch') else: self.patch = None return over def find_over_color(self): over = None if self.base.mouseWatcherNode.hasMouse(): mpos = self.base.mouseWatcherNode.getMouse() self.base.graphicsEngine.extract_texture_data( self.picking_texture, self.base.win.gsg) texture_peeker = self.picking_texture.peek() if texture_peeker is not None: x = (mpos.get_x() + 1) / 2 y = (mpos.get_y() + 1) / 2 value = LColor() texture_peeker.lookup(value, x, y) oid = color_to_int(value) if oid != 0: over = objectsDB.get_oid(oid) if over is None: print("Unknown oid", oid, value) return over def find_over(self): if settings.color_picking: over_color = self.find_over_color() else: over_color = None over_ray = self.find_over_ray() over = over_color if over_ray is not None: if over is None or over.distance_to_obs > over_ray.distance_to_obs: over = over_ray if hasattr(over, "primary") and over.primary is not None: over = over.primary return over def get_over(self): if settings.mouse_over: over = self.over else: over = self.find_over() return over def mouse_task(self, task): if self.base.mouseWatcherNode.hasMouse(): self.over = self.find_over() return Task.cont
class GameApp: def __init__(self): self.gameEventHandler = GameEventHandler(self) self.camLimits = ((-5, 5), (-6.5, 5), (1, 10)) self.gameReady = False self.hovered = None self.clicked = None self.modelToFigure = {} self.modelToField = {} self.modelToSeaField = {} self.modelToBuildingField = {} self.modelToBuilding = {} # self.highlightableObjects = render.attachNewNode('highlightables') self.setupColisionForHighlight() self.songMenu = None self.buildMenu = None def setupColisionForHighlight(self): # Since we are using collision detection to do picking, we set it up like # any other collision detection system with a traverser and a handler self.picker = CollisionTraverser() # Make a traverser self.pq = CollisionHandlerQueue() # Make a handler # Make a collision node for our picker ray self.pickerNode = CollisionNode('mouseRay') # Attach that node to the camera since the ray will need to be positioned # relative to it self.pickerNP = self.camera.attachNewNode(self.pickerNode) # Everything to be picked will use bit 1. This way if we were doing other # collision we could seperate it self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() # Make our ray # Add it to the collision node self.pickerNode.addSolid(self.pickerRay) # Register the ray as something that can cause collisions self.picker.addCollider(self.pickerNP, self.pq) def getCameraCoords(self): return self.camera.getPos() def setCameraCoords(self, x, y, z): self.camera.setPos(x, y, z) def getMouseCoords(self): if self.mouseWatcherNode.hasMouse(): return self.mouseWatcherNode.getMouse() return None def drawIsland(self, island, suppressRot=False): island.model.setPos(island.pos[0], island.pos[1], 0.001) island.model.setScale(0.05, 0.05, 0.05) island.model.reparentTo(self.render) for f in range(0, 6): circle = self.loader.loadModel('models/circle') pos = (island.fields[f].x, island.fields[f].y, 0.4) circle.setPos(pos) circle.setScale(0.4) circle.reparentTo(island.model) circle.setTag('clickable', 'true') cs = CollisionSphere(0, 0, 0, 1) cnodePath = circle.attachNewNode(CollisionNode('cnode')) cnodePath.node().addSolid(cs) island.fields[f].model = circle self.modelToField[circle.getKey()] = island.fields[f] for i in range(0, 3): buildingField = island.buildingFields[i] circle = self.loader.loadModel('models/circle') pos = (buildingField.x, buildingField.y, 0.1) circle.setPos(pos) circle.setScale(0.6) circle.reparentTo(island.model) circle.setTag('clickable', 'true') cs = CollisionSphere(0, 0, 0, 1) cnodePath = circle.attachNewNode(CollisionNode('cnode')) cnodePath.node().addSolid(cs) buildingField.model = circle self.modelToBuildingField[circle.getKey()] = buildingField # put the bay field circle = self.loader.loadModel('models/circle') pos = (island.bay.x, island.bay.y, 0.2) circle.setPos(pos) circle.setScale(0.6) circle.reparentTo(island.model) circle.setTag('clickable', 'true') cs = CollisionSphere(0, 0, 0, 1) cnodePath = circle.attachNewNode(CollisionNode('cnode')) cnodePath.node().addSolid(cs) island.bay.model = circle self.modelToSeaField[circle.getKey()] = island.bay degree = angle((0, 1), island.pos) * 180 / math.pi if island.pos[0] > 0: degree *= -1 if not suppressRot: island.model.setHpr(degree, 0, 0) def drawFigures(self): for player in self.game.players: for figure in player.figures: if hasattr(figure, 'model'): continue if type(figure) == Ship: field = figure.field figure.model = self.loader.loadModel('models/ship') figure.model.reparentTo(field.model) cs = CollisionSphere(1.5, 0, 1, 1.3) cnodePath = figure.model.attachNewNode( CollisionNode('cnode')) cnodePath.node().addSolid(cs) # cnodePath.show() cs = CollisionSphere(0, 0, 1.4, 1.3) cnodePath = figure.model.attachNewNode( CollisionNode('cnode')) cnodePath.node().addSolid(cs) # cnodePath.show() cs = CollisionSphere(-1.8, 0, 1, 1) cnodePath = figure.model.attachNewNode( CollisionNode('cnode')) cnodePath.node().addSolid(cs) # cnodePath.show() figure.model.setScale(1.4) figure.model.setHpr(90, 0, 0) # figure.model.setTag('highlightable', 'true') figure.model.setTag('clickable', 'true') self.modelToFigure[figure.model.getKey()] = figure else: field = figure.field figure.model = self.loader.loadModel('models/warrior100') figure.model.reparentTo(field.model) cs = CollisionSphere(0, -.35, 7, 1) cnodePath = figure.model.attachNewNode( CollisionNode('cnode')) cnodePath.node().addSolid(cs) figure.model.setScale(0.35) figure.model.setTag('highlightable', 'true') figure.model.setTag('clickable', 'true') self.modelToFigure[figure.model.getKey()] = figure col = 256 * int(player.color) # set figure title title = TextNode(str(figure.model.getKey()) + '_title') title.setText(type(figure).__name__) title.setCardColor(col, col, col, 1) title.setCardAsMargin(0.1, 0.1, 0.1, 0.1) title.setCardDecal(True) titleNode = self.render.attachNewNode(title) titleNode.reparentTo(figure.model) titleNode.setScale(3) titleNode.setPos(0, 3, 10) if type(figure) == Ship: titleNode.setScale(1.5) titleNode.setPos(-1.5, 0, 3) titleNode.setBillboardPointEye() def drawSeaways(self): for field in self.game.board.seawayFields: circle = self.loader.loadModel('models/circle') pos = (field.x, field.y, 0) circle.setPos(pos) circle.setScale(0.04) circle.setHpr(-90, 0, 0) circle.reparentTo(self.render) circle.setTag('clickable', 'true') cs = CollisionSphere(0, 0, 0, 1) cnodePath = circle.attachNewNode(CollisionNode('cnode')) cnodePath.node().addSolid(cs) field.model = circle self.modelToSeaField[circle.getKey()] = field def drawBuilding(self, building, field): model = self.loader.loadModel('models/house') # model.setScale(0.05) model.reparentTo(field.model) building.model = model self.modelToBuilding[model.getKey()] = building player = self.game.currentPlayer() model.setTag('clickable', 'true') cs = CollisionSphere(0, 0, 0, 2) cnodePath = model.attachNewNode(CollisionNode('cnode')) cnodePath.node().addSolid(cs) # cnodePath.show() col = 256 * int(player.color) # set building title title = TextNode(str(building.model.getKey()) + '_title') title.setText(building.building) title.setCardColor(col, col, col, 1) title.setCardAsMargin(0.1, 0.1, 0.1, 0.1) title.setCardDecal(True) titleNode = self.render.attachNewNode(title) titleNode.reparentTo(building.model) titleNode.setScale(1.5) titleNode.setPos(0, 0, 3) titleNode.setBillboardPointEye() def drawGame(self, game): if not self.gameReady: self.game = game # menu = OnscreenImage(image = 'textures/menu.png', pos = (1.53, 0, 0), scale=(0.35, 1, 1)) # menu.setTransparency(TransparencyAttrib.MAlpha) # setup the background of the board self.environ = self.loader.loadModel('models/plane') sea = self.loader.loadTexture('textures/sea.png') self.environ.setTexture(sea) self.environ.setPos(0, 1, 0) self.environ.setScale(1.1) sea.setWrapU(Texture.WM_repeat) sea.setWrapV(Texture.WM_repeat) self.environ.reparentTo(self.render) # setup camera self.camera.setPos(0, 0, 10) self.camera.setHpr(0, -70, 0) self.camLens.setNear(0.85) # setup lighting plight = PointLight('plight') plight.setColor(VBase4(1, 1, 1, 3)) plnp = self.render.attachNewNode(plight) plnp.setPos(10, 0, 10) self.render.setLight(plnp) ambientLight = AmbientLight('ambientLight') ambientLight.setColor(Vec4(0.25, 0.25, 0.25, .3)) ambientLightNP = self.render.attachNewNode(ambientLight) self.render.setLight(ambientLightNP) # place islands first = True for island in game.board.islands: island.drawable = True island.model = self.loader.loadModel('models/island2_104') self.drawIsland(island, first) first = False self.drawFigures() self.drawSeaways() self.turn = OnscreenText(text='Black\'s turn.', pos=(0.06, -0.1), align=TextNode.ALeft, parent=base.a2dTopLeft, scale=0.06) self.resources = OnscreenText(text='Resources: ', pos=(0.08, -0.2), align=TextNode.ALeft, parent=base.a2dTopLeft, scale=0.06) self.gameReady = True player = 'Black' if game.turn == 1: player = 'White' self.turn.setText(player + '\'s turn.') resourcesText = 'Resources: ' + \ str(self.game.currentPlayer().resources) self.resources.setText(resourcesText) if self.game.loosers != None: message = OnscreenText(text='End of the game', align=TextNode.ACenter, pos=(0, 0), scale=0.1) if self.game.loosers == 'black': message.setText('White wins!') elif self.game.loosers == 'white': message.setText('Black wins!') else: message.setText('Nobody wins!') def destroyGame(self): children = self.render.getChildren() for child in children: child.removeNode() def cameraSpeed(self, height, speedRange): # Figure out how 'wide' each range is leftSpan = self.camLimits[2][1] - self.camLimits[2][0] rightSpan = speedRange[1] - speedRange[0] # Convert the left range into a 0-1 range (float) valueScaled = float(height - self.camLimits[2][0]) / float(leftSpan) # Convert the 0-1 range into a value in the right range. return speedRange[0] + (valueScaled * rightSpan) def moveCamera(self): mousePos = self.getMouseCoords() if mousePos == None: return x, y = mousePos camX, camY, camZ = self.getCameraCoords() transformX, transformY = 0, 0 speed = self.cameraSpeed(camZ, (0.01, 0.2)) if x < -0.7 and y < -0.7: transformX -= speed transformY -= speed elif x > 0.7 and y < -0.7: transformX += speed transformY -= speed elif x < -0.7 and y > 0.7: transformX -= speed transformY += speed elif x > 0.7 and y > 0.7: transformX += speed transformY += speed else: if x < -0.7: transformX -= speed elif x > 0.7: transformX += speed if y < -0.7: transformY -= speed elif y > 0.7: transformY += speed newX = camX + transformX newY = camY + transformY if newX < self.camLimits[0][0] or newX > self.camLimits[0][1]: newX = camX if newY < self.camLimits[1][0] or newY > self.camLimits[1][1]: newY = camY self.setCameraCoords(newX, newY, camZ) def highlight(self): if self.mouseWatcherNode.hasMouse(): mPos = self.mouseWatcherNode.getMouse() # Set the position of the ray based on the mouse position self.pickerRay.setFromLens(self.camNode, mPos.getX(), mPos.getY()) self.picker.traverse(self.render) if self.pq.getNumEntries() > 0: # This is so we get the closest object. self.pq.sortEntries() pickedObj = self.pq.getEntry(0).getIntoNodePath() # pick the model and not the cnode pickedObj = pickedObj.findNetTag('clickable') if not pickedObj.isEmpty(): return pickedObj @staticmethod def boardingTransformations(figure, pos): figure.model.setScale(0.2) figure.model.setPos(1 + pos, 0, 1) @staticmethod def unboardingTransformations(figure): figure.model.setScale(0.35) figure.model.setPos(0, 0, 0) def drawSongsMenu(self, songs, field): if self.songMenu: return self.songMenu = [(OnscreenText(text='Choose song:', pos=(-0.7, -0.1), align=TextNode.ALeft, parent=base.a2dTopRight, scale=0.06), field)] i = 1 for song in songs: item = OnscreenText(text=str(i) + ') Song of ' + song, pos=(-0.7, -0.1 - i * 0.1), align=TextNode.ALeft, parent=base.a2dTopRight, scale=0.06) i += 1 self.songMenu.append((item, song)) def destroySongMenu(self): if self.songMenu: for item in self.songMenu: item[0].destroy() self.songMenu = None def drawBuildMenu(self, buildings, field): self.buildMenu = [(OnscreenText(text='Choose building:', pos=(-0.7, -0.1), align=TextNode.ALeft, parent=base.a2dTopRight, scale=0.06), field)] i = 1 for building in buildings: price = Building.buildingPrice(building) text = '{0}) {1} ({2})'.format(str(i), building, price) item = OnscreenText(text=text, pos=(-0.7, -0.1 - i * 0.1), align=TextNode.ALeft, parent=base.a2dTopRight, scale=0.06) i += 1 self.buildMenu.append((item, building)) def destroyBuildMenu(self): if self.buildMenu: for item in self.buildMenu: item[0].destroy() self.buildMenu = None def clickFigure(self, figure): print('figure') if type(figure) == Ship: ship = figure figure = self.clicked if isinstance(figure, Figure) and type(figure) != Ship: if figure.hasMoved: self.clicked = ship return if (figure.field.island == ship.field.island and figure.player == ship.player and None in ship.fields): figure.field.put(None) pos = 0 if ship.fields[0] == None: ship.fields[0] = figure else: ship.fields[1] = figure pos = 1 figure.field = ship figure.model.reparentTo(ship.model) self.boardingTransformations(figure, pos) figure.hasMoved = True if ship.player == self.game.currentPlayer(): self.clicked = ship else: if figure.player == self.game.currentPlayer(): self.clicked = figure def initiateBattle(self, blackTroops, whiteTroops): self.blackTroops = blackTroops self.whiteTroops = whiteTroops battle = self.game.newBattle() self.push(battle) self.gameEventHandler.ignoreAll() def clickField(self, field): print(self.clicked) if type(self.clicked) == Ship: return if self.clicked and isinstance(self.clicked, Figure): figure = self.clicked board = self.game.board if figure.hasMoved: return if type(figure.field) == Ship: if field in board.possibleMoves(figure.field): figure.field.removeFigure(figure) player = self.game.currentPlayer() battle = field.figure != None and field.figure.player != player whiteTroops = field.figure field.put(figure) figure.model.reparentTo(field.model) self.unboardingTransformations(figure) figure.hasMoved = True self.initiateBattle(figure, whiteTroops) if field in board.possibleMoves(self.clicked): initiateBattle = field.figure != None whiteTroops = field.figure figure.field.put(None) field.put(figure) figure.model.reparentTo(field.model) figure.hasMoved = True if initiateBattle: self.initiateBattle(figure, whiteTroops) if isinstance(self.clicked, Building): building = self.clicked player = self.game.currentPlayer() if not field.figure or field.figure.player != player: if field.island != building.field.island: return figure = None battle = field.figure != None and field.figure.player != player whiteTroops = field.figure if building.building == 'House': figure = self.game.giveBirthToPeasant(field) elif building.building == 'Barracks': figure = self.game.giveBirthToWarrior(field) if figure == None: return if figure: self.drawFigures() if battle: self.initiateBattle(figure, whiteTroops) else: print('Not enough resources!') def clickSeaField(self, field): if type(self.clicked) == Ship: figure = self.clicked if figure.hasMoved: return if field.figure != None: return if field in figure.field.linked: figure.field.put(None) field.put(figure) figure.model.reparentTo(field.model) figure.hasMoved = True if type(self.clicked) == Building: player = self.game.currentPlayer() building = self.clicked if building.building == 'Harbor': if building.field.island.bay != field: return player = self.game.currentPlayer() if not field.figure or field.figure.player != player: ship = self.game.buildShip(field) if ship: self.drawFigures() else: print('Not enough resources') def clickBuildingField(self, field): print("Gonna build, huh?") player = self.game.currentPlayer() print(self.game.possibleBuildings(field.island)) self.drawSongsMenu(self.game.possibleSongs(field.island), field) def handle(self, event, *args): print(event) if type(self.current()) != Game: return if event == 'wheel_up': x, y, z = self.getCameraCoords() if z > self.camLimits[2][0]: self.setCameraCoords(x, y, z - 1) elif event == 'wheel_down': x, y, z = self.getCameraCoords() if z < self.camLimits[2][1]: self.setCameraCoords(x, y, z + 1) elif event == 'enter': if self.game.loosers != None: self.pop() self.game.changeTurn() elif event == 'left_click': obj = self.highlight() if obj != None: key = obj.getKey() # if it's a figure if key in self.modelToFigure: figure = self.modelToFigure[key] self.clickFigure(figure) # if it's a figure field if key in self.modelToField: field = self.modelToField[key] self.clickField(field) # if it's a building field if key in self.modelToBuildingField: field = self.modelToBuildingField[key] self.clickBuildingField(field) # if it's a sea field if key in self.modelToSeaField: field = self.modelToSeaField[key] self.clickSeaField(field) # if it's a building if key in self.modelToBuilding: self.clicked = self.modelToBuilding[key] else: self.clicked = None if self.songMenu != None: if obj == None or obj.getKey() not in self.modelToBuildingField: self.destroySongMenu() elif event in [str(i) for i in range(1, 10)]: if self.songMenu: if self.songMenu[0][1] != self.game.board.islands[0]: song = self.songMenu[int(event)][1] buildings = self.game.buildings[song] self.drawBuildMenu(buildings, self.songMenu[0][1]) else: print('CHANGE OBJECTIVES!') self.destroySongMenu() return if self.buildMenu: building = self.buildMenu[int(event)][1] field = self.buildMenu[0][1] building = self.game.build(building, field) if building: self.drawBuilding(building, field) else: print('Not enough resources or field is taken!!>@') self.destroyBuildMenu() def hoverFigure(self, hovered): if self.hovered != None: reverseFactor = self.hovered.getScale()[0] reverseFactor *= REVERSE_HIGHLIGHT_SCALE self.hovered.setScale(reverseFactor) self.hovered = None if hovered != None: figure = self.modelToFigure[hovered.getKey()] if figure.player.color != str(self.current().turn): return self.hovered = hovered factor = HIGHLIGHT_SCALE * hovered.getScale()[0] hovered.setScale(factor)
class InputManager(DirectObject): def __init__(self, base, lookatpos, pggen, togglerotcenter=False): self.base = base self.originallookatpos = lookatpos # for backup self.lookatpos_pdv3 = Vec3(lookatpos[0], lookatpos[1], lookatpos[2]) self.camdist = (self.base.cam.getPos() - self.lookatpos_pdv3).length() self.pggen = pggen self.initviewdist = (self.base.cam.getPos() - self.lookatpos_pdv3).length() self.wheelscale_distance = 150 self.lastm1pos = None self.lastm2pos = None # toggle on the following part to explicitly show the rotation center self.togglerotcenter = togglerotcenter if self.togglerotcenter: self.rotatecenternp = self.base.p3dh.gensphere( pos=self.originallookatpos, radius=5, rgba=np.array([1, 1, 0, 1])) self.rotatecenternp.reparentTo(self.base.render) # for resetting self.original_cam_pdmat4 = Mat4(self.base.cam.getMat()) self.keymap = { "mouse1": False, "mouse2": False, "mouse3": False, "wheel_up": False, "wheel_down": False, "space": False, "w": False, "s": False, "a": False, "d": False, "g": False, "r": False } self.accept("mouse1", self.__setkeys, ["mouse1", True]) self.accept("mouse1-up", self.__setkeys, ["mouse1", False]) self.accept("mouse2", self.__setkeys, ["mouse2", True]) self.accept("mouse2-up", self.__setkeys, ["mouse2", False]) self.accept("mouse3", self.__setkeys, ["mouse3", True]) self.accept("mouse3-up", self.__setkeys, ["mouse3", False]) self.accept("wheel_up", self.__setkeys, ["wheel_up", True]) self.accept("wheel_down", self.__setkeys, ["wheel_down", True]) self.accept("space", self.__setkeys, ["space", True]) self.accept("space-up", self.__setkeys, ["space", False]) self.accept("w", self.__setkeys, ["w", True]) self.accept("w-up", self.__setkeys, ["w", False]) self.accept("s", self.__setkeys, ["s", True]) self.accept("s-up", self.__setkeys, ["s", False]) self.accept("a", self.__setkeys, ["a", True]) self.accept("a-up", self.__setkeys, ["a", False]) self.accept("d", self.__setkeys, ["d", True]) self.accept("d-up", self.__setkeys, ["d", False]) self.accept("g", self.__setkeys, ["g", True]) self.accept("g-up", self.__setkeys, ["g", False]) self.accept("r", self.__setkeys, ["r", True]) self.accept("r-up", self.__setkeys, ["r", False]) self.setup_interactiongeometries() def __setkeys(self, key, value): self.keymap[key] = value return def setup_interactiongeometries(self): """ set up collision rays, spheres, and planes for mouse manipulation :return: None author: weiwei date: 20161110 """ # create a trackball ray and set its bitmask to 8 # the trackball ray must be a subnode of cam since we will # transform the clicked point (in the view of the cam) to the world coordinate system # using the ray self.tracker_cn = CollisionNode("tracker") self.tracker_ray = CollisionRay() self.tracker_cn.addSolid(self.tracker_ray) self.tracker_cn.setFromCollideMask(BitMask32.bit(8)) self.tracker_cn.setIntoCollideMask(BitMask32.allOff()) self.tracker_np = self.base.cam.attachNewNode(self.tracker_cn) # create an inverted collision sphere and puts it into a collision node # its bitmask is set to 8, and it will be the only collidable object at bit 8 self.trackball_cn = CollisionNode("trackball") self.trackball_cn.addSolid( CollisionSphere(self.lookatpos_pdv3[0], self.lookatpos_pdv3[1], self.lookatpos_pdv3[2], self.camdist)) self.trackball_cn.setFromCollideMask(BitMask32.allOff()) self.trackball_cn.setIntoCollideMask(BitMask32.bit(8)) self.trackball_np = self.base.render.attachNewNode(self.trackball_cn) # self.trackball_np.show() # This creates a collision plane for mouse track self.trackplane_cn = CollisionNode("trackplane") # self.aimPlaneCN.addSolid(CollisionPlane(Plane(Vec3(0, 0, 1), self.lookatpos_pdv3))) # self.trackplane_cn.addSolid(CollisionBox(Point3(self.lookatpos_pdv3[0], self.lookatpos_pdv3[1], 0.1), 1e6, 1e6, 1e-6)) self.trackplane_cn.addSolid( CollisionPlane( Plane( Point3(self.base.cam.getMat().getRow3(2) - self.base.cam.getMat().getRow3(1)), Point3(self.lookatpos_pdv3[0], self.lookatpos_pdv3[1], 0.1)))) self.trackplane_cn.setFromCollideMask(BitMask32.allOff()) self.trackplane_cn.setIntoCollideMask(BitMask32.bit(8)) self.trackplane_np = self.base.render.attachNewNode(self.trackplane_cn) # self.trackplane_np.show() # creates a traverser to do collision testing self.ctrav = CollisionTraverser() # creates a queue type handler to receive the collision event info self.chandler = CollisionHandlerQueue() # register the ray as a collider with the traverser, # and register the handler queue as the handler to be used for the collisions. self.ctrav.addCollider(self.tracker_np, self.chandler) # create a pickerray self.picker_cn = CollisionNode('picker') self.picker_ray = CollisionRay() self.picker_cn.addSolid(self.picker_ray) self.picker_cn.setFromCollideMask(BitMask32.bit(7)) self.picker_cn.setIntoCollideMask(BitMask32.allOff()) self.picker_np = self.base.cam.attachNewNode(self.picker_cn) self.ctrav.addCollider(self.picker_np, self.chandler) def shift_trackballsphere(self, center=np.array([0, 0, 0])): self.camdist = (self.base.cam.getPos() - self.lookatpos_pdv3).length() self.trackball_cn.setSolid( 0, CollisionSphere(center[0], center[1], center[2], self.camdist)) def shift_trackplane(self): self.trackplane_cn.setSolid( 0, CollisionPlane( Plane( Point3(self.base.cam.getMat().getRow3(2) - self.base.cam.getMat().getRow3(1)), Point3(self.lookatpos_pdv3[0], self.lookatpos_pdv3[1], 0.1)))) def get_world_mouse1(self): """ 给et the position of mouse1 (clicked) using collision detection between a sphere and a ray :return: Vec3 or None author: weiwei date: 20161110 """ if self.base.mouseWatcherNode.hasMouse(): if self.keymap['mouse1']: # get the mouse position in the window mpos = self.base.mouseWatcherNode.getMouse() # sets the ray's origin at the camera and directs it to shoot through the mouse cursor self.tracker_ray.setFromLens(self.base.cam.node(), mpos.getX(), mpos.getY()) # performs the collision checking pass self.ctrav.traverse(self.trackball_np) if (self.chandler.getNumEntries() > 0): # Sort the handler entries from nearest to farthest self.chandler.sortEntries() entry = self.chandler.getEntry(0) colPoint = entry.getSurfacePoint(self.base.render) return colPoint return None def check_mouse1drag(self): """ this function uses a collision sphere to track the rotational mouse motion :return: author: weiwei date: 20200315 """ curm1pos = self.get_world_mouse1() if curm1pos is None: if self.lastm1pos is not None: self.lastm1pos = None return if self.lastm1pos is None: # first time click self.lastm1pos = curm1pos return curm1vec = Vec3(curm1pos - self.lookatpos_pdv3) lastm1vec = Vec3(self.lastm1pos - self.lookatpos_pdv3) curm1vec.normalize() lastm1vec.normalize() rotatevec = curm1vec.cross(lastm1vec) if rotatevec.length() > 1e-10: # avoid zero length rotateangle = curm1vec.signedAngleDeg(lastm1vec, rotatevec) rotateangle = rotateangle * self.camdist * 5 if rotateangle > .02 or rotateangle < -.02: rotmat = Mat4(self.base.cam.getMat()) posvec = Vec3(self.base.cam.getPos()) rotmat.setRow(3, Vec3(0, 0, 0)) self.base.cam.setMat(rotmat * Mat4.rotateMat(rotateangle, rotatevec)) self.base.cam.setPos(Mat3.rotateMat(rotateangle, rotatevec). \ xform(posvec - self.lookatpos_pdv3) + self.lookatpos_pdv3) self.lastm1pos = self.get_world_mouse1() self.shift_trackplane() def get_world_mouse2(self): if self.base.mouseWatcherNode.hasMouse(): if self.keymap['mouse2']: mpos = self.base.mouseWatcherNode.getMouse() self.tracker_ray.setFromLens(self.base.cam.node(), mpos.getX(), mpos.getY()) self.ctrav.traverse(self.trackplane_np) self.chandler.sortEntries() if (self.chandler.getNumEntries() > 0): entry = self.chandler.getEntry(0) colPoint = entry.getSurfacePoint(self.base.render) return colPoint return None def check_mouse2drag(self): """ :return: author: weiwei date: 20200313 """ curm2pos = self.get_world_mouse2() if curm2pos is None: if self.lastm2pos is not None: self.lastm2pos = None return if self.lastm2pos is None: # first time click self.lastm2pos = curm2pos return relm2vec = curm2pos - self.lastm2pos if relm2vec.length() > 1: self.base.cam.setPos(self.base.cam.getPos() - relm2vec) self.lookatpos_pdv3 = Vec3(self.lookatpos_pdv3 - relm2vec) newlookatpos = self.base.p3dh.pdv3_to_npv3(self.lookatpos_pdv3) if self.togglerotcenter: self.rotatecenternp.detachNode() self.rotatecenternp = self.base.p3dh.gensphere( pos=newlookatpos, radius=5, rgba=np.array([1, 1, 0, 1])) self.rotatecenternp.reparentTo(self.base.render) self.shift_trackballsphere(self.lookatpos_pdv3) self.last2mpos = curm2pos def get_world_mouse3(self): """ picker ray :return: author: weiwei date: 20200316 """ if self.base.mouseWatcherNode.hasMouse(): if self.keymap['mouse3']: mpos = self.base.mouseWatcherNode.getMouse() self.picker_ray.setFromLens(self.base.cam.node(), mpos.getX(), mpos.getY()) self.ctrav.traverse(self.base.render) if (self.chandler.getNumEntries() > 0): self.chandler.sortEntries() entry = self.chandler.getEntry(0) colPoint = entry.getSurfacePoint(self.base.render) return colPoint return None def check_mouse3click(self): """ :return: author: weiwei date: 20200316 """ curm3pos = self.get_world_mouse3() if curm3pos is None: return else: print(curm3pos) def check_mousewheel(self): """ zoom up or down the 3d view considering mouse action author: weiwei date: 2016, 20200313 :return: """ if self.keymap["wheel_up"] is True: self.keymap["wheel_up"] = False backward = self.base.cam.getPos() - self.lookatpos_pdv3 backward.normalize() newpos = self.base.cam.getPos( ) + backward * self.wheelscale_distance if newpos.length() < self.initviewdist * 20: self.base.cam.setPos(newpos[0], newpos[1], newpos[2]) self.shift_trackballsphere( self.trackball_cn.getSolid(0).getCenter()) if self.keymap["wheel_down"] is True: self.keymap["wheel_down"] = False forward = self.lookatpos_pdv3 - self.base.cam.getPos() if forward.length() < self.wheelscale_distance: return forward.normalize() newpos = self.base.cam.getPos( ) + forward * self.wheelscale_distance if newpos.length() > self.initviewdist * .05: self.base.cam.setPos(newpos[0], newpos[1], newpos[2]) self.shift_trackballsphere( self.trackball_cn.getSolid(0).getCenter()) def check_mouse1drag_trackball(self): """ This function uses the stereographic projection introduced in https://en.wikipedia.org/wiki/Stereographic_projection to track the rotational mouse motion Equations: [e, f] -> [x, y, z] = [2e/(1+e^2+f^2), 2f/(1+e^2+f^2), (-1+e^2+f^2)/(2+2e^2+2f^2)] :return: author: weiwei date: 20200315 """ def cvtvirtualtrackball(screenx, screeny, psec_squared=1 / 4): """ convert a screen point to virtual trackball coordinate psec indicates the size of the spherical section to be mapped to default radius = 1 :param screenx: :param screeny: :param psec_squared: :return: author: weiwei date: 20200315 """ screenpoint_squaredsum = screenx**2 + screeny**2 trackballx = 2 * psec_squared * screenx / (psec_squared + screenpoint_squaredsum) trackballz = 2 * psec_squared * screeny / (psec_squared + screenpoint_squaredsum) trackbally = -math.sqrt(1 - trackballx**2 - trackballz**2) returnvec = Vec3(trackballx, trackbally, trackballz) returnvec.normalize() return returnvec currentmouse = self.base.mouseWatcherNode.getMouse() curm1pos = [currentmouse.getX(), currentmouse.getY()] if curm1pos is None: if self.lastm1pos is not None: self.lastm1pos = None return if self.lastm1pos is None: # first time click self.lastm1pos = curm1pos return curm1vec_pdv3 = cvtvirtualtrackball(curm1pos[0], curm1pos[1]) lastm1vec_pdv3 = cvtvirtualtrackball(self.lastm1pos[0], self.lastm1pos[1]) rotatevec_pdv3 = curm1vec_pdv3.cross(lastm1vec_pdv3) rotateangle = curm1vec_pdv3.signedAngleDeg(lastm1vec_pdv3, rotatevec_pdv3) if rotateangle > .02 or rotateangle < -.02: rotateangle = rotateangle * 5 camrotmat_pd = self.base.cam.getMat().getUpper3() calibrated_camrotmat_pd = Mat3.rotateMat( rotateangle, camrotmat_pd.xformVec(rotatevec_pdv3)) posvec_pd = self.base.cam.getPos() self.base.cam.setMat(Mat4.identMat()) self.base.cam.setMat(camrotmat_pd * calibrated_camrotmat_pd) self.base.cam.setPos( calibrated_camrotmat_pd.xform(posvec_pd - self.lookatpos_pdv3) + self.lookatpos_pdv3) self.lastm1pos = curm1pos[:] def check_resetcamera(self): """ reset the rendering window to its initial viewpoint :return: author: weiwei date: 20200316 """ if self.keymap["r"] is True: self.keymap["r"] = False self.base.cam.setMat(self.original_cam_pdmat4) self.lookatpos_pdv3 = self.base.p3dh.npv3_to_pdv3( self.originallookatpos) # toggle on the following part to explicitly show the rotation center if self.togglerotcenter: self.rotatecenternp.detachNode() self.rotatecenternp = self.base.p3dh.gensphere( pos=self.originallookatpos, radius=5, rgba=np.array([1, 1, 0, 1])) self.rotatecenternp.reparentTo(self.base.render)
class Player(GameObject): def __init__(self, modelName, model_anims, max_health, speed, collider_name, base, pos, hpr=Vec3(0, 0, 0), scale=1.0): GameObject.__init__(self, modelName, model_anims, max_health, speed, collider_name, base, pos, hpr, scale) self.player_init() def player_init(self): self.base.pusher.addCollider(self.collider, self.actor) self.base.cTrav.addCollider(self.collider, self.base.pusher) self.collider.setPythonTag("player", self) self.score = 0 self.score_string = str(self.score) # self.base.camLens.setFov(150) #---------------------------------------------- # self.base.camLens.setFov(5) self.textObject = OnscreenText(text='Score:' + self.score_string, pos=(-1.15, -0.95), scale=0.1) self.ray = CollisionRay(0, 0, 0, 0, -1, 0) rayNode = CollisionNode("playerRay") rayNode.addSolid(self.ray) self.rayNodePath = self.actor.attachNewNode(rayNode) self.rayQueue = CollisionHandlerQueue() self.base.cTrav.addCollider(self.rayNodePath, self.rayQueue) # self.damagePerSecond = -5.0 self.beamModel = self.base.loader.loadModel("models/frowney") self.beamModel.reparentTo(self.actor) self.beamModel.setZ(10) self.beamModel.setLightOff() self.beamModel.hide() def move(self, movement_vector): anim_controller = self.actor.getAnimControl("walk") if not anim_controller.isPlaying(): self.actor.play("walk") self.actor.setPos(self.actor, movement_vector * self.speed) def stop(self): anim_controller = self.actor.getAnimControl("walk") anim_controller.stop() def change_health(self, dHealth): GameObject.change_health(self, dHealth) if self.health == 0: # imageOnject = OnscreenImage(image = "game_over.png") self.cleanup() sys.exit() def update_score(self): self.score_string = str(self.score) self.textObject.destroy() self.textObject = OnscreenText(text='Score:' + self.score_string, pos=(-1.15, -0.95), scale=0.1) def shoot(self): dt = globalClock.getDt() # print(self.rayQueue.getNumEntries()) # print(self.rayQueue) if self.rayQueue.getNumEntries() > 0: self.rayQueue.sortEntries() rayHit = self.rayQueue.getEntry(1) hitPos = rayHit.getSurfacePoint(self.base.render) # print(hitPos, "hitpos") # print(rayHit, "rayhit") # beamLength = (hitPos - self.actor.getPos()).length() # print("length: ", beamLength) hitNodePath = rayHit.getIntoNodePath() # print(hitNodePath) # print(hitNodePath.getPythonTag) # print(hitPos) # print(hitNodePath.getTag) # print(hitNodePath.hasPythonTag("enemy")) # print(rayHit.getFrom()) if hitNodePath.hasPythonTag("enemy"): # print("here") hitObject = hitNodePath.getPythonTag("enemy") hitObject.change_health(-1) # Find out how long the beam is, and scale the # beam-model accordingly. # print(self.actor.getPos()) beamLength = (hitPos - (self.actor.getPos())).length() self.beamModel.setSy(-beamLength) self.score += 1 self.update_score() self.beamModel.show() else: # If we're not shooting, don't show the beam-model. self.beamModel.hide()
class WalkingEnemy(Enemy): def __init__(self, pos): Enemy.__init__( self, pos, "Models/Misc/simpleEnemy", { "stand": "Models/Misc/simpleEnemy-stand", "walk": "Models/Misc/simpleEnemy-walk", "attack": "Models/Misc/simpleEnemy-attack", "die": "Models/Misc/simpleEnemy-die", "spawn": "Models/Misc/simpleEnemy-spawn" }, 3.0, 7.0, "walkingEnemy") self.attackDistance = 0.75 self.attackDelay = 0.3 self.attackDelayTimer = 0 self.attackWaitTimer = 0 self.acceleration = 100.0 mask = BitMask32() mask.setBit(2) self.collider.node().setIntoCollideMask(mask) self.attackSegment = CollisionSegment(0, 0, 0, 1, 0, 0) segmentNode = CollisionNode("enemyAttackSegment") segmentNode.addSolid(self.attackSegment) mask = BitMask32() mask.setBit(1) segmentNode.setFromCollideMask(mask) mask = BitMask32() segmentNode.setIntoCollideMask(mask) self.attackSegmentNodePath = render.attachNewNode(segmentNode) self.segmentQueue = CollisionHandlerQueue() base.cTrav.addCollider(self.attackSegmentNodePath, self.segmentQueue) self.attackDamage = -1 self.deathSound = loader.loadSfx("Sounds/enemyDie.ogg") self.attackSound = loader.loadSfx("Sounds/enemyAttack.ogg") self.yVector = Vec2(0, 1) self.actor.play("spawn") def runLogic(self, player, dt): spawnControl = self.actor.getAnimControl("spawn") if spawnControl is not None and spawnControl.isPlaying(): return vectorToPlayer = player.actor.getPos() - self.actor.getPos() vectorToPlayer2D = vectorToPlayer.getXy() distanceToPlayer = vectorToPlayer2D.length() vectorToPlayer2D.normalize() heading = self.yVector.signedAngleDeg(vectorToPlayer2D) self.attackSegment.setPointA(self.actor.getPos()) self.attackSegment.setPointB(self.actor.getPos() + self.actor.getQuat().getForward() * self.attackDistance) if distanceToPlayer > self.attackDistance * 0.9: attackControl = self.actor.getAnimControl("attack") if not attackControl.isPlaying(): self.walking = True vectorToPlayer.setZ(0) vectorToPlayer.normalize() self.velocity += vectorToPlayer * self.acceleration * dt self.attackWaitTimer = 0.2 self.attackDelayTimer = 0 else: self.walking = False self.velocity.set(0, 0, 0) if self.attackDelayTimer > 0: self.attackDelayTimer -= dt if self.attackDelayTimer <= 0: if self.segmentQueue.getNumEntries() > 0: self.segmentQueue.sortEntries() segmentHit = self.segmentQueue.getEntry(0) hitNodePath = segmentHit.getIntoNodePath() if hitNodePath.hasPythonTag("owner"): hitObject = hitNodePath.getPythonTag("owner") hitObject.alterHealth(self.attackDamage) self.attackWaitTimer = 1.0 elif self.attackWaitTimer > 0: self.attackWaitTimer -= dt if self.attackWaitTimer <= 0: self.attackWaitTimer = random.uniform(0.5, 0.7) self.attackDelayTimer = self.attackDelay self.actor.play("attack") self.attackSound.play() self.actor.setH(heading) def alterHealth(self, dHealth): Enemy.alterHealth(self, dHealth) self.updateHealthVisual() def updateHealthVisual(self): perc = self.health / self.maxHealth if perc < 0: perc = 0 self.actor.setColorScale(perc, perc, perc, 1) def cleanup(self): base.cTrav.removeCollider(self.attackSegmentNodePath) self.attackSegmentNodePath.removeNode() GameObject.cleanup(self)
class Physics: def __init__(self): self.rayCTrav = CollisionTraverser("collision traverser for ray tests") #self.pusher = PhysicsCollisionHandler() self.pusher = CollisionHandlerPusher() self.pusher.addInPattern('%fn-in-%in') self.pusher.addOutPattern('%fn-out-%in') self.pusher.addInPattern('%fn-in') self.pusher.addOutPattern('%fn-out') def startPhysics(self): #self.actorNode = ActorNode("playerPhysicsControler") #base.physicsMgr.attachPhysicalNode(self.actorNode) #self.actorNode.getPhysicsObject().setMass(self.player_mass) #self.mainNode = render.attachNewNode(self.actorNode) self.mainNode = render.attachNewNode("CharacterColliders") self.reparentTo(self.mainNode) charCollisions = self.mainNode.attachNewNode(CollisionNode(self.char_collision_name)) #charCollisions.node().addSolid(CollisionSphere(0, 0, self.player_height/4.0, self.player_height/4.0)) #charCollisions.node().addSolid(CollisionSphere(0, 0, self.player_height/4.0*3.05, self.player_height/4.0)) charCollisions.node().addSolid(CollisionSphere(0, 0, self.player_height/2.0, self.player_height/4.0)) charCollisions.node().setIntoCollideMask(BitMask32(0x80)) # 1000 0000 if self.show_collisions: charCollisions.show() self.pusher.addCollider(charCollisions, self.mainNode) base.cTrav.addCollider(charCollisions, self.pusher) charFFootCollisions = self.attachNewNode(CollisionNode("floor_ray")) charFFootCollisions.node().addSolid(CollisionRay(0, 0, 0.5, 0, 0, -1)) #charFFootCollisions.node().addSolid(CollisionSegment((0, 0, 0.2), (0, 0, -1))) charFFootCollisions.node().setIntoCollideMask(BitMask32.allOff()) charFFootCollisions.node().setFromCollideMask(BitMask32(0x7f)) # 0111 1111 if self.show_collisions: charFFootCollisions.show() self.floor_handler = CollisionHandlerFloor() self.floor_handler.addCollider(charFFootCollisions, self.mainNode) #self.floor_handler.setOffset(0) self.floor_handler.setMaxVelocity(5) base.cTrav.addCollider(charFFootCollisions, self.floor_handler) self.accept("{}-in".format(self.char_collision_name), self.checkCharCollisions) self.raytest_segment = CollisionSegment(0, 1) self.raytest_np = render.attachNewNode(CollisionNode("testRay")) self.raytest_np.node().addSolid(self.raytest_segment) self.raytest_np.node().setIntoCollideMask(BitMask32.allOff()) self.raytest_np.node().setFromCollideMask(BitMask32(0x7f)) # 0111 1111 if self.show_collisions: self.raytest_np.show() self.raytest_queue = CollisionHandlerQueue() self.rayCTrav.addCollider(self.raytest_np, self.raytest_queue) def stopPhysics(self): self.raytest_segment.removeNode() self.pusher.clearColliders() self.floor_handler.clearColliders() self.rayCTrav.clearColliders() def updatePlayerPos(self, speed, heading, dt): if heading is not None: self.mainNode.setH(camera, heading) self.mainNode.setP(0) self.mainNode.setR(0) self.mainNode.setFluidPos(self.mainNode, speed) self.doStep() def checkCharCollisions(self, args): self.doStep() def doStep(self): # do the step height check tmpNP = self.mainNode.attachNewNode("temporary") tmpNP.setPos(self.mainNode, 0, 0, -self.stepheight) pointA = self.mainNode.getPos(render) pointA.setZ(pointA.getZ() + self.player_height/1.8) pointB = tmpNP.getPos(render) if pointA == pointB: return char_step_collision = self.getFirstCollisionInLine(pointA, pointB) tmpNP.removeNode() if char_step_collision is not None: self.mainNode.setFluidZ(char_step_collision.getZ()) return True return False def getFirstCollisionInLine(self, pointA, pointB): """A simple raycast check which will return the first collision point as seen from point A towards pointB""" self.raytest_segment.setPointA(pointA) self.raytest_segment.setPointB(pointB) self.rayCTrav.traverse(render) self.raytest_queue.sortEntries() pos = None if self.raytest_queue.getNumEntries() > 0: pos = self.raytest_queue.getEntry(0).getSurfacePoint(render) return pos
class Player(GameObject): def __init__(self): GameObject.__init__( self, Vec3(0, 0, 0), "Models/PandaChan/act_p3d_chan", { "stand": "Models/PandaChan/a_p3d_chan_idle", "walk": "Models/PandaChan/a_p3d_chan_run" }, 5, 10, "player") self.actor.getChild(0).setH(180) mask = BitMask32() mask.setBit(1) self.collider.node().setIntoCollideMask(mask) mask = BitMask32() mask.setBit(1) self.collider.node().setFromCollideMask(mask) base.pusher.addCollider(self.collider, self.actor) base.cTrav.addCollider(self.collider, base.pusher) self.lastMousePos = Vec2(0, 0) self.groundPlane = Plane(Vec3(0, 0, 1), Vec3(0, 0, 0)) self.ray = CollisionRay(0, 0, 0, 0, 1, 0) rayNode = CollisionNode("playerRay") rayNode.addSolid(self.ray) mask = BitMask32() mask.setBit(2) rayNode.setFromCollideMask(mask) mask = BitMask32() rayNode.setIntoCollideMask(mask) self.rayNodePath = render.attachNewNode(rayNode) self.rayQueue = CollisionHandlerQueue() base.cTrav.addCollider(self.rayNodePath, self.rayQueue) self.beamModel = loader.loadModel("Models/Misc/bambooLaser") self.beamModel.reparentTo(self.actor) self.beamModel.setZ(1.5) self.beamModel.setLightOff() self.beamModel.hide() self.beamHitModel = loader.loadModel("Models/Misc/bambooLaserHit") self.beamHitModel.reparentTo(render) self.beamHitModel.setZ(1.5) self.beamHitModel.setLightOff() self.beamHitModel.hide() self.beamHitPulseRate = 0.15 self.beamHitTimer = 0 self.damagePerSecond = -5.0 self.score = 0 self.scoreUI = OnscreenText(text="0", pos=(-1.3, 0.825), mayChange=True, align=TextNode.ALeft) self.healthIcons = [] for i in range(self.maxHealth): icon = OnscreenImage(image="UI/health.png", pos=(-1.275 + i * 0.075, 0, 0.95), scale=0.04) icon.setTransparency(True) self.healthIcons.append(icon) self.damageTakenModel = loader.loadModel("Models/Misc/playerHit") self.damageTakenModel.setLightOff() self.damageTakenModel.setZ(1.0) self.damageTakenModel.reparentTo(self.actor) self.damageTakenModel.hide() self.damageTakenModelTimer = 0 self.damageTakenModelDuration = 0.15 self.laserSoundNoHit = loader.loadSfx("Sounds/laserNoHit.ogg") self.laserSoundNoHit.setLoop(True) self.laserSoundHit = loader.loadSfx("Sounds/laserHit.ogg") self.laserSoundHit.setLoop(True) self.beamHitLight = PointLight("beamHitLight") self.beamHitLight.setColor(Vec4(0.1, 1.0, 0.2, 1)) self.beamHitLight.setAttenuation((1.0, 0.1, 0.5)) self.beamHitLightNodePath = render.attachNewNode(self.beamHitLight) self.hurtSound = loader.loadSfx("Sounds/FemaleDmgNoise.ogg") self.yVector = Vec2(0, 1) self.actor.loop("stand") def update(self, keys, dt): GameObject.update(self, dt) self.walking = False if keys["up"]: self.walking = True self.velocity.addY(self.acceleration * dt) if keys["down"]: self.walking = True self.velocity.addY(-self.acceleration * dt) if keys["left"]: self.walking = True self.velocity.addX(-self.acceleration * dt) if keys["right"]: self.walking = True self.velocity.addX(self.acceleration * dt) if self.walking: standControl = self.actor.getAnimControl("stand") if standControl.isPlaying(): standControl.stop() walkControl = self.actor.getAnimControl("walk") if not walkControl.isPlaying(): self.actor.loop("walk") else: standControl = self.actor.getAnimControl("stand") if not standControl.isPlaying(): self.actor.stop("walk") self.actor.loop("stand") mouseWatcher = base.mouseWatcherNode if mouseWatcher.hasMouse(): mousePos = mouseWatcher.getMouse() else: mousePos = self.lastMousePos mousePos3D = Point3() nearPoint = Point3() farPoint = Point3() base.camLens.extrude(mousePos, nearPoint, farPoint) self.groundPlane.intersectsLine( mousePos3D, render.getRelativePoint(base.camera, nearPoint), render.getRelativePoint(base.camera, farPoint)) firingVector = Vec3(mousePos3D - self.actor.getPos()) firingVector2D = firingVector.getXy() firingVector2D.normalize() firingVector.normalize() heading = self.yVector.signedAngleDeg(firingVector2D) self.actor.setH(heading) self.beamHitTimer -= dt if self.beamHitTimer <= 0: self.beamHitTimer = self.beamHitPulseRate self.beamHitModel.setH(random.uniform(0.0, 360.0)) self.beamHitModel.setScale( math.sin(self.beamHitTimer * 3.142 / self.beamHitPulseRate) * 0.4 + 0.9) if keys["shoot"]: if self.rayQueue.getNumEntries() > 0: scoredHit = False self.rayQueue.sortEntries() rayHit = self.rayQueue.getEntry(0) hitPos = rayHit.getSurfacePoint(render) hitNodePath = rayHit.getIntoNodePath() if hitNodePath.hasPythonTag("owner"): hitObject = hitNodePath.getPythonTag("owner") if not isinstance(hitObject, TrapEnemy): hitObject.alterHealth(self.damagePerSecond * dt) scoredHit = True beamLength = (hitPos - self.actor.getPos()).length() self.beamModel.setSy(beamLength) self.beamModel.show() if scoredHit: if self.laserSoundNoHit.status() == AudioSound.PLAYING: self.laserSoundNoHit.stop() if self.laserSoundHit.status() != AudioSound.PLAYING: self.laserSoundHit.play() self.beamHitModel.show() self.beamHitModel.setPos(hitPos) self.beamHitLightNodePath.setPos(hitPos + Vec3(0, 0, 0.5)) if not render.hasLight(self.beamHitLightNodePath): render.setLight(self.beamHitLightNodePath) else: if self.laserSoundHit.status() == AudioSound.PLAYING: self.laserSoundHit.stop() if self.laserSoundNoHit.status() != AudioSound.PLAYING: self.laserSoundNoHit.play() if render.hasLight(self.beamHitLightNodePath): render.clearLight(self.beamHitLightNodePath) self.beamHitModel.hide() else: if render.hasLight(self.beamHitLightNodePath): render.clearLight(self.beamHitLightNodePath) self.beamModel.hide() self.beamHitModel.hide() if self.laserSoundNoHit.status() == AudioSound.PLAYING: self.laserSoundNoHit.stop() if self.laserSoundHit.status() == AudioSound.PLAYING: self.laserSoundHit.stop() if firingVector.length() > 0.001: self.ray.setOrigin(self.actor.getPos()) self.ray.setDirection(firingVector) self.lastMousePos = mousePos if self.damageTakenModelTimer > 0: self.damageTakenModelTimer -= dt self.damageTakenModel.setScale(2.0 - self.damageTakenModelTimer / self.damageTakenModelDuration) if self.damageTakenModelTimer <= 0: self.damageTakenModel.hide() def updateScore(self): self.scoreUI.setText(str(self.score)) def alterHealth(self, dHealth): GameObject.alterHealth(self, dHealth) self.updateHealthUI() self.damageTakenModel.show() self.damageTakenModel.setH(random.uniform(0.0, 360.0)) self.damageTakenModelTimer = self.damageTakenModelDuration self.hurtSound.play() def updateHealthUI(self): for index, icon in enumerate(self.healthIcons): if index < self.health: icon.show() else: icon.hide() def cleanup(self): self.scoreUI.removeNode() for icon in self.healthIcons: icon.removeNode() self.beamHitModel.removeNode() base.cTrav.removeCollider(self.rayNodePath) self.laserSoundHit.stop() self.laserSoundNoHit.stop() render.clearLight(self.beamHitLightNodePath) self.beamHitLightNodePath.removeNode() GameObject.cleanup(self)
class World(DirectObject): def __init__(self): #This code puts the standard title and instruction text on screen self.title = OnscreenText(text="Panda3D: Tutorial - Mouse Picking", style=1, fg=(1, 1, 1, 1), pos=(0.8, -0.95), scale=.07) self.escapeEvent = OnscreenText( text="ESC: Quit", style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.95), align=TextNode.ALeft, scale=.05) self.mouse1Event = OnscreenText( text="Left-click and drag: Pick up and drag piece", style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.90), align=TextNode.ALeft, scale=.05) self.accept('escape', sys.exit) #Escape quits base.disableMouse() #Disble mouse camera control camera.setPosHpr(0, -13.75, 6, 0, -25, 0) #Set the camera self.setupLights() #Setup default lighting #Since we are using collision detection to do picking, we set it up like #any other collision detection system with a traverser and a handler self.picker = CollisionTraverser() #Make a traverser self.pq = CollisionHandlerQueue() #Make a handler #Make a collision node for our picker ray self.pickerNode = CollisionNode('mouseRay') #Attach that node to the camera since the ray will need to be positioned #relative to it self.pickerNP = camera.attachNewNode(self.pickerNode) #Everything to be picked will use bit 1. This way if we were doing other #collision we could seperate it self.pickerNode.setFromCollideMask(BitMask32.bit(1)) self.pickerRay = CollisionRay() #Make our ray self.pickerNode.addSolid(self.pickerRay) #Add it to the collision node #Register the ray as something that can cause collisions self.picker.addCollider(self.pickerNP, self.pq) #self.picker.showCollisions(render) #Now we create the chess board and its pieces #We will attach all of the squares to their own root. This way we can do the #collision pass just on the sqaures and save the time of checking the rest #of the scene self.squareRoot = render.attachNewNode("squareRoot") #For each square self.squares = [None for i in range(64)] self.pieces = dict((i, None) for i in range(64)) #MOD for i in range(64): #Load, parent, color, and position the model (a single square polygon) self.squares[i] = loader.loadModel("models/square") self.squares[i].reparentTo(self.squareRoot) self.squares[i].setPos(SquarePos(i)) self.squares[i].setColor(SquareColor(i)) #Set the model itself to be collideable with the ray. If this model was #any more complex than a single polygon, you should set up a collision #sphere around it instead. But for single polygons this works fine. self.squares[i].find("**/polygon").node().setIntoCollideMask( BitMask32.bit(1)) #Set a tag on the square's node so we can look up what square this is #later during the collision pass self.squares[i].find("**/polygon").node().setTag('square', str(i)) #We will use this variable as a pointer to whatever piece is currently #in this square #The order of pieces on a chessboard from white's perspective. This list #contains the constructor functions for the piece classes defined below pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook) for i in range(8, 16): #Load the white pawns self.pieces[i] = Pawn(i, WHITE) for i in range(48, 56): #load the black pawns self.pieces[i] = Pawn(i, PIECEBLACK) for i in range(8): #Load the special pieces for the front row and color them white self.pieces[i] = pieceOrder[i](i, WHITE) #Load the special pieces for the back row and color them black self.pieces[i + 56] = pieceOrder[i](i + 56, PIECEBLACK) #This will represent the index of the currently highlited square self.hiSq = False #This wil represent the index of the square where currently dragged piece #was grabbed from self.dragging = False #Start the task that handles the picking self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask') self.accept("mouse1", self.grabPiece) #left-click grabs a piece self.accept("mouse1-up", self.releasePiece) #releasing places it #This function swaps the positions of two pieces def swapPieces(self, fr, to): temp = self.pieces[fr] self.pieces[fr] = self.pieces[to] self.pieces[to] = temp if self.pieces[fr]: self.pieces[fr].square = fr self.pieces[fr].obj.setPos(SquarePos(fr)) if self.pieces[to]: self.pieces[to].square = to self.pieces[to].obj.setPos(SquarePos(to)) def mouseTask(self, task): #This task deals with the highlighting and dragging based on the mouse #First, clear the current highlight if self.hiSq is not False: self.squares[self.hiSq].setColor(SquareColor(self.hiSq)) self.hiSq = False #Check to see if we can access the mouse. We need it to do anything else if base.mouseWatcherNode.hasMouse(): #get the mouse position mpos = base.mouseWatcherNode.getMouse() #Set the position of the ray based on the mouse position self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) #If we are dragging something, set the position of the object #to be at the appropriate point over the plane of the board if self.dragging is not False: #Gets the point described by pickerRay.getOrigin(), which is relative to #camera, relative instead to render nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin()) #Same thing with the direction of the ray nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection()) self.pieces[self.dragging].obj.setPos( PointAtZ(.5, nearPoint, nearVec)) #Do the actual collision pass (Do it only on the squares for #efficiency purposes) self.picker.traverse(self.squareRoot) if self.pq.getNumEntries() > 0: #if we have hit something, sort the hits so that the closest #is first, and highlight that node self.pq.sortEntries() i = int(self.pq.getEntry(0).getIntoNode().getTag('square')) #Set the highlight on the picked square self.squares[i].setColor(HIGHLIGHT) self.hiSq = i return Task.cont def grabPiece(self): #If a square is highlighted and it has a piece, set it to dragging mode if (self.hiSq is not False and self.pieces[self.hiSq]): self.dragging = self.hiSq self.hiSq = False def releasePiece(self): #Letting go of a piece. If we are not on a square, return it to its original #position. Otherwise, swap it with the piece in the new square if self.dragging is not False: #Make sure we really are dragging something #We have let go of the piece, but we are not on a square if self.hiSq is False: self.pieces[self.dragging].obj.setPos( SquarePos(self.dragging)) else: #Otherwise, swap the pieces self.swapPieces(self.dragging, self.hiSq) #We are no longer dragging anything self.dragging = False def setupLights(self): #This function sets up some default lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.8, .8, .8, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0, 45, -45)) directionalLight.setColor(Vec4(0.2, 0.2, 0.2, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight))
class Player(GameObject): def __init__(self): GameObject.__init__(self, Vec3(0, 0, 0), "Models/PandaChan/act_p3d_chan", { "stand" : "Models/PandaChan/a_p3d_chan_idle", "walk" : "Models/PandaChan/a_p3d_chan_run" }, 5, 10, "player") self.actor.getChild(0).setH(180) mask = BitMask32() mask.setBit(1) self.collider.node().setIntoCollideMask(mask) mask = BitMask32() mask.setBit(1) self.collider.node().setFromCollideMask(mask) base.pusher.addCollider(self.collider, self.actor) base.cTrav.addCollider(self.collider, base.pusher) self.lastMousePos = Vec2(0, 0) self.groundPlane = Plane(Vec3(0, 0, 1), Vec3(0, 0, 0)) self.ray = CollisionRay(0, 0, 0, 0, 1, 0) rayNode = CollisionNode("playerRay") rayNode.addSolid(self.ray) mask = BitMask32() mask.setBit(2) rayNode.setFromCollideMask(mask) mask = BitMask32() rayNode.setIntoCollideMask(mask) self.rayNodePath = render.attachNewNode(rayNode) self.rayQueue = CollisionHandlerQueue() base.cTrav.addCollider(self.rayNodePath, self.rayQueue) self.beamModel = loader.loadModel("Models/Misc/bambooLaser") self.beamModel.reparentTo(self.actor) self.beamModel.setZ(1.5) self.beamModel.setLightOff() self.beamModel.hide() self.damagePerSecond = -5.0 self.yVector = Vec2(0, 1) self.actor.loop("stand") def update(self, keys, dt): GameObject.update(self, dt) self.walking = False if keys["up"]: self.walking = True self.velocity.addY(self.acceleration*dt) if keys["down"]: self.walking = True self.velocity.addY(-self.acceleration*dt) if keys["left"]: self.walking = True self.velocity.addX(-self.acceleration*dt) if keys["right"]: self.walking = True self.velocity.addX(self.acceleration*dt) if self.walking: standControl = self.actor.getAnimControl("stand") if standControl.isPlaying(): standControl.stop() walkControl = self.actor.getAnimControl("walk") if not walkControl.isPlaying(): self.actor.loop("walk") else: standControl = self.actor.getAnimControl("stand") if not standControl.isPlaying(): self.actor.stop("walk") self.actor.loop("stand") mouseWatcher = base.mouseWatcherNode if mouseWatcher.hasMouse(): mousePos = mouseWatcher.getMouse() else: mousePos = self.lastMousePos mousePos3D = Point3() nearPoint = Point3() farPoint = Point3() base.camLens.extrude(mousePos, nearPoint, farPoint) self.groundPlane.intersectsLine(mousePos3D, render.getRelativePoint(base.camera, nearPoint), render.getRelativePoint(base.camera, farPoint)) firingVector = Vec3(mousePos3D - self.actor.getPos()) firingVector2D = firingVector.getXy() firingVector2D.normalize() firingVector.normalize() heading = self.yVector.signedAngleDeg(firingVector2D) self.actor.setH(heading) if keys["shoot"]: if self.rayQueue.getNumEntries() > 0: self.rayQueue.sortEntries() rayHit = self.rayQueue.getEntry(0) hitPos = rayHit.getSurfacePoint(render) hitNodePath = rayHit.getIntoNodePath() if hitNodePath.hasPythonTag("owner"): hitObject = hitNodePath.getPythonTag("owner") if not isinstance(hitObject, TrapEnemy): hitObject.alterHealth(self.damagePerSecond*dt) beamLength = (hitPos - self.actor.getPos()).length() self.beamModel.setSy(beamLength) self.beamModel.show() else: self.beamModel.hide() if firingVector.length() > 0.001: self.ray.setOrigin(self.actor.getPos()) self.ray.setDirection(firingVector) self.lastMousePos = mousePos def cleanup(self): base.cTrav.removeCollider(self.rayNodePath) GameObject.cleanup(self)
class Weapon(DirectObject): def __init__(self, _main, _name, _fireRate, _dmg=20,_mountSlot=0, weaponType="Pistol"): self.main = _main self.name = _name self.fireRate = _fireRate self.dmg = _dmg self.weaponType = weaponType self.mountSlot = _mountSlot self.muzzleFlash = loader.loadModel("muzzleflash") if weaponType == "Pistol": self.style = "OneHand" self.model = loader.loadModel("Pistol") self.muzzleFlash.setZ(0.65) self.muzzleFlash.setX(-0.04) self.muzzleFlash.setScale(0.25) self.muzzleFlash.find('**/+SequenceNode').node().setFrameRate(20) else: self.style = "TwoHand" self.model = loader.loadModel("MG") self.muzzleFlash.setZ(0.65) self.muzzleFlash.setX(0.08) self.muzzleFlash.setScale(0.3) self.muzzleFlash.find('**/+SequenceNode').node().setFrameRate(20) self.model.setY(2) self.muzzleFlash.reparentTo(self.model) self.muzzleFlash.find('**/+SequenceNode').node().stop() self.muzzleFlash.hide() # Load bullet model self.bullet = loader.loadModel("Bullet") self.bullet.setP(-90) self.bullet.setH(180) #self.bullet.setPos(0, 0.5, 0) # Control self.isFiring = False # Collision Stuff self.wepRay = None # Make weapon ray self.setupRay() self.model.show() def setAmmo(self): pass def setupRay(self): self.shootTraverser = CollisionTraverser() self.shootingQH = CollisionHandlerQueue() #self.shootingEH = CollisionHandlerEvent() #self.shootingEH.addInPattern('into-%in') # Create a collision Node shootNode = CollisionNode('WeaponRay') # set the nodes collision bitmask shootNode.setFromCollideMask(BitMask32.bit(1)) # create a collision segment (ray like) self.shootRay = CollisionSegment() shootNode.addSolid(self.shootRay) #self.pickerNP = self.main.player.model.attachNewNode(pickerNode) self.shootNP = render.attachNewNode(shootNode) #self.shootTraverser.addCollider(self.shootNP, self.shootingEH) self.shootTraverser.addCollider(self.shootNP, self.shootingQH) #self.shootNP.show() def doFire(self, _toPos=(0, 0, 0)): self.isFiring = True if self.weaponType == "Pistol": self.muzzleFlash.find('**/+SequenceNode').node().play(0, 1) else: self.muzzleFlash.find('**/+SequenceNode').node().loop(True) self.muzzleFlash.show() # For some reason the mouse ray end up at posZ -1 (which causes a problem when we make the enemy spheres smaller in radius) # so here for now.. ill make a quick fix. adjustedZ = (_toPos[0], _toPos[1], 0) self.shootRay.setPointA(self.main.player.model.getPos()) self.shootRay.setPointB(adjustedZ) fromPos = self.main.player.model.getPos() #self.model.getPos() #self.setProjectile(fromPos, adjustedZ)#_toPos) self.shootTraverser.traverse(self.main.enemyParent) if self.shootingQH.getNumEntries() > 0: self.shootingQH.sortEntries() enemyCol = self.shootingQH.getEntry(0).getIntoNodePath().node().getName() base.messenger.send("into-" + enemyCol, [self.dmg]) def stopFire(self): if self.weaponType == "Pistol" and \ self.muzzleFlash.find('**/+SequenceNode').node().isPlaying(): taskMgr.add(self.waitForFrame, "waitForFrame") return self.muzzleFlash.find('**/+SequenceNode').node().stop() self.muzzleFlash.hide() def waitForFrame(self, task): if self.muzzleFlash.find('**/+SequenceNode').node().isPlaying(): return task.cont self.muzzleFlash.find('**/+SequenceNode').node().stop() self.muzzleFlash.hide() def reload(self): pass def setProjectile(self, _from, _to): self.bullet.reparentTo(render)#self.model) # setup the projectile interval #self.bulletProjectile = ProjectileInterval(self.bullet, # startPos = Point3(_from), # duration = 1, # endPos = Point3(_to)) #self.bulletProjectile = self.bullet.posInterval(1.0, Point3(_to), startPos=Point3(_from)) #self.bulletProjectile = LerpPosInterval(self.bullet, 2.0, _to, _from) print "POSITIONS:" print _to print _from frm = render.getPos(self.main.player.model) print frm self.bulletProjectile = LerpPosInterval(self.bullet, 1.0, _to, _from) self.bulletProjectile.start()
class KlobWorld(ShowBase): def __init__(self): ShowBase.__init__(self) ## wp = WindowProperties(base.win.getProperties()) ## wp.setSize(1280,720) ## base.win.requestProperties(wp) base.setBackgroundColor(255,250,250) self.listAudio3d = [] self.allSounds() self.energyTime = 0 self.collHandQue = CollisionHandlerQueue() self.collHandQueEne = CollisionHandlerQueue() self.SPEED = .5 self.speedv = 4 base.cTrav = CollisionTraverser() self.bossLvl = False self.bossDead = False self.isMoving = False self.pause = True self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) self.currentLevel = "start" self.keyMap = {"left":0, "right":0, "forward":0, "backward":0, "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0, "fire-down":0, "p":0} ###Disable the default camera controls### base.disableMouse() self.pusher = CollisionHandlerPusher() base.cTrav.setRespectPrevTransform(True) #Uncomment to show collisions with environment #base.cTrav.showCollisions(render) self.setAcceptKeys() self.MainMenu() ## List to keep track of all actors added in each level ## to make it easier to cleanup level when destroyed self.crAct = [] self.extraElements = [] self.laserAmo = [] self.beamC = [] self.laserAmoCount = 0 self.enemyTimer = 0 self.gunAmmoCount = 0 self.loaded = [] self.bulletC = [] def allSounds(self): self.audio = Audio3DManager(self.sfxManagerList[0]) self.audio.attachListener(base.camera) self.heartBeat = base.loadMusic("sounds/heartbeat.wav") self.cheer = base.loadMusic("sounds/cheer.wav") self.intro = base.loadMusic("sounds/Mario.wav") self.bulletSound = base.loadMusic("sounds/gun_shot.wav") self.laserSound = base.loadMusic("sounds/gun_shot.wav") self.deadSound = base.loadMusic("sounds/pacman_death.wav") self.sound = self.audio.loadSfx("sounds/forest.wav") self.gust = base.loadMusic("sounds/gust.wav") self.siren = base.loadMusic("sounds/siren_2.wav") self.waterfallSound = self.audio.loadSfx("sounds/waterfall.wav") self.etSound = base.loadMusic("sounds/et-sound.wav") self.walking = base.loadMusic("sounds/running.wav") self.mainMenuMusic = base.loadMusic("sounds/intro.wav") self.rainforestMusic = self.loader.loadSfx("sounds/rainforest.wav") self.egyptMusic = self.loader.loadSfx("sounds/egypt.wav") self.asiaMusic = self.loader.loadSfx("sounds/asia.wav") self.newyorkMusic = self.loader.loadSfx("sounds/newyork.wav") self.mainMenuMusic.setLoop(True) self.rainforestMusic.setLoop(True) self.egyptMusic.setLoop(True) self.asiaMusic.setLoop(True) self.newyorkMusic.setLoop(True) self.gust.setLoop(True) self.sound.setLoop(True) self.siren.setLoop(True) self.walking.setVolume(5) self.heartBeat.setVolume(5) self.deadSound.setVolume(.5) self.laserSound.setVolume(.2) self.bulletSound.setVolume(.2) self.sound.setVolume(2) self.rainforestMusic.setVolume(.6) self.egyptMusic.setVolume(2) self.siren.setVolume(.3) def stopAllSounds(self): self.audio.detachSound(self.waterfallSound) self.audio.detachSound(self.sound) self.audio.detachSound(self.rainforestMusic) self.audio.detachSound(self.egyptMusic) self.audio.detachSound(self.newyorkMusic) self.intro.stop() self.bulletSound.stop() self.laserSound.stop() self.deadSound.stop() self.sound.stop() self.gust.stop() self.siren.stop() self.waterfallSound.stop() self.etSound.stop() self.walking.stop() self.mainMenuMusic.stop() self.rainforestMusic.stop() self.egyptMusic.stop() self.asiaMusic.stop() self.newyorkMusic.stop() def MainMenuLevels(self): if(self.currentLevel != "start"): self.destroyLevel() self.stopAllSounds() self.level1Btn = DirectButton( scale = (0.27,0.1,0.1), command = self.loadRainforestLevel, pos = Vec3(0, 0, 0.4), image = 'GUI/southamericabutton.png', relief = None) self.level2Btn = DirectButton( scale = (0.27,0.1,0.1), command = self.loadAfricaLevel, pos = Vec3(0, 0, 0.15), image = 'GUI/africabutton.png', relief = None) self.level3Btn = DirectButton( scale = (0.27,0.1,0.1), command = self.loadAsiaLevel, pos = Vec3(0, 0, -0.1), image = 'GUI/asiabutton.png', relief = None) self.level4Btn = DirectButton( scale = (0.27,0.1,0.1), command = self.loadNewYorkLevel, pos = Vec3(0, 0, -0.35), image = 'GUI/americabutton.png', relief = None) self.level2Btn.setTransparency(TransparencyAttrib.MAlpha) self.level3Btn.setTransparency(TransparencyAttrib.MAlpha) self.level4Btn.setTransparency(TransparencyAttrib.MAlpha) self.level1Btn.setTransparency(TransparencyAttrib.MAlpha) def destroyMainMenuLevels(self): self.level1Btn.destroy() self.level2Btn.destroy() self.level3Btn.destroy() self.level4Btn.destroy() self.mainMenuBtn = DirectButton( text="Main Menu", scale = (0.1,0.1,0.1), command = self.MainMenuLevels, pos = Vec3(0.8, 0, -0.9)) def MainMenu(self): if(self.currentLevel == "help"): self.destroyHelpMenu() elif(self.currentLevel != "start"): self.destroyLevel() self.mainMenuBtn.destroy() self.stopAllSounds() self.currentLevel="start" self.mainMenuImage = OnscreenImage("GUI/mainmenu.png",pos = Vec3(0, 0.0,-0.8), scale=(1.8, 0, 1.8)) self.mainMenuImage.reparentTo(aspect2d) self.mainMenuImage.setTransparency(1) self.mainMenuMusic.play() mapStart = loader.loadModel('GUI/button_maps.egg') self.startBtn = DirectButton(geom = (mapStart.find('**/start_but'), mapStart.find('**/start_but_click'), mapStart.find('**/start_but_roll'), mapStart.find('**/start_but_disabled')), relief = None, command = self.introScreen, scale = (0.7,0.7,0.7), pos = Vec3(0.6, 0, -0.35)) self.startBtn.setTransparency(TransparencyAttrib.MAlpha) mapHelp = loader.loadModel('GUI/helpbutton_maps.egg') self.helpBtn = DirectButton(geom = (mapHelp.find('**/help_but'), mapHelp.find('**/help_but_click'), mapHelp.find('**/help_but_roll'), mapHelp.find('**/help_but_disabled')), relief = None, command = self.HelpMenu, scale = (0.8,0.65,0.65), pos = Vec3(0.6, 0,-0.65)) self.helpBtn.setTransparency(TransparencyAttrib.MAlpha) def destroyMainMenu(self): self.startBtn.destroy() self.helpBtn.destroy() self.mainMenuImage.destroy() self.stopAllSounds() def HelpMenu(self): self.destroyMainMenu() self.currentLevel="help" self.helpMenuImage = OnscreenImage("GUI/helpmenu.png",pos = Vec3(0, 0.0,-0.8), scale=(1.8, 0, 1.8)) self.helpMenuImage.reparentTo(aspect2d) self.helpMenuImage.setTransparency(1) mapHelp = loader.loadModel('GUI/backbutton_maps.egg') self.backBtn = DirectButton(geom = (mapHelp.find('**/backBtn'), mapHelp.find('**/backBtn_click'), mapHelp.find('**/backBtn_roll'), mapHelp.find('**/backBtn_disabled')), relief = None, command = self.MainMenu, scale = (0.7,0.7,0.7), pos = Vec3(-1.4, 0, 0.8)) self.backBtn.setTransparency(TransparencyAttrib.MAlpha) ###...... #code missing. ### .... ##Records the state of the arrow keys### def setKey(self, key, value): if(self.pause is False): self.keyMap[key] = value if(self.keyMap["fire-down"] != 0 ): if( self.energy['value'] != 0 ): if(self.bossDead is False): self.beamC.append( self.loadLaser() ) self.laserAmo.append( self.laser() ) if(self.laserAmo): self.laserAmo[self.laserAmoCount].start() self.energy['value'] -= 3 self.laserAmoCount = self.laserAmoCount + 1 def loadEnviron(self, filename, scale): self.environ = self.loader.loadModel(filename) self.environ.setScale(scale) self.environ.reparentTo(self.render) self.environ.setPos(0, 0, 0) self.environ.setTag('wall','1') self.environ.setCollideMask(BitMask32(0x01)) alight = AmbientLight('alight') alight.setColor(VBase4(0.8, 0.8, 0.8, 1)) alnp = render.attachNewNode(alight) render.setLight(alnp) def loadAlien(self, point): ###Load alien actor### self.alien = Actor("models/alien/slugrocket-model", {"walk":"models/alien/slugrocket-anim"}) self.alien.reparentTo(render) self.alien.setScale(3) self.alien.setPos(point) self.alien.setPlayRate(1.2, "walk") self.alien.setBlend(frameBlend = True) self.dlight = DirectionalLight('my dlight') self.dlnp = render.attachNewNode(self.dlight) self.dlnp.reparentTo(base.camera) self.dlnp.lookAt(self.alien) self.dlight.setColor(VBase4(0.8, 0.8, 0.5, 1)) render.setLight(self.dlnp) base.camera.setPos(0,-10,2) base.camera.reparentTo(self.alien) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0,0,1000) self.camGroundRay.setDirection(0,0,-1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(BitMask32.bit(2)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) csAlien = CollisionSphere(0,0,0.6,0.6) cnodeAlienPath = self.alien.attachNewNode(CollisionNode('csAlien')) cnodeAlienPath.node().addSolid(csAlien) self.pusher.addCollider(cnodeAlienPath, self.alien) base.cTrav.addCollider(cnodeAlienPath, self.pusher) ### Uncomment the following comment to show ### the Collision Sphere on the alien ## cnodeAlienPath.show() self.health = DirectWaitBar(scale = 0.5, range = 100, value = 100, barColor = (0,1,0,1), pos = Vec3(0.75, 0, 0.9)) self.energy = DirectWaitBar(scale = 0.5, range = 100, value = 100, barColor = (1,1,0,1), pos = Vec3(-0.75, 0, 0.9)) self.energy.reparentTo(aspect2d) self.health.reparentTo(aspect2d) self.hud = OnscreenImage("GUI/hud.png",scale = Vec3(1.43, 1.0, 1.03),pos = Vec3(0, 0.0,0.045)) self.hud.reparentTo(aspect2d) self.hud.setTransparency(1) self.extraElements.append(self.energy) self.extraElements.append(self.health) self.extraElements.append(self.hud) def alienDie(self, currLvl): self.alien.stop() self.pause=True temp = NodePath(PandaNode("temp")) base.camera.reparentTo(self.floater) base.camera.setZ(base.camera.getZ()+1) base.camera.setY(base.camera.getY()-25) self.deadSound.play() fall = LerpHprInterval(nodePath=self.alien, duration=1.5, hpr=(self.alien.getH(),self.alien.getP(), self.alien.getR()-80)) fall.start() taskMgr.remove("moveTask") taskMgr.remove("laterFc") transition = Transitions(loader) transition.setFadeColor(0, 0, 0) self.dieImage = OnscreenImage("GUI/died.png",scale = Vec3(0.7, 0, 0.2),pos = Vec3(0, 0,-0.5)) self.dieImage.reparentTo(aspect2d) self.dieImage.setTransparency(1) if(self.currentLevel == "rainforest"): Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadRainforestLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start() elif(self.currentLevel == "africa"): Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadAfricaLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start() elif(self.currentLevel == "asia"): Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadAsiaLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start() elif(self.currentLevel == "newyork"): Sequence(Wait(2.0),Func(transition.fadeOut),Wait(2.0),Func(self.destroyLevel),Func(self.loadNewYorkLevel),Func(self.dieImage.destroy),Func(transition.fadeIn)).start() def collide(self, collEntry): collEntry.getFromNodePath().getParent().removeNode() def setAcceptKeys(self): ###Accept the control keys for movement and rotation### self.accept("escape", sys.exit) self.accept("p", self.setKey, ["p",1]) self.accept("arrow_up", self.setKey, ["forward",1]) self.accept("arrow_up-up", self.setKey, ["forward",0]) self.accept("arrow_down", self.setKey, ["backward", 1]) self.accept("arrow_down-up", self.setKey, ["backward", 0]) self.accept("arrow_left", self.setKey, ["left",1]) self.accept("arrow_left-up", self.setKey, ["left",0]) self.accept("arrow_right", self.setKey, ["right",1]) self.accept("arrow_right-up", self.setKey, ["right",0]) self.accept("a", self.setKey, ["cam-left",1]) self.accept("a-up", self.setKey, ["cam-left",0]) self.accept("s", self.setKey, ["cam-right",1]) self.accept("s-up", self.setKey, ["cam-right",0]) self.accept("z", self.setKey, ["cam-up",1]) self.accept("z-up", self.setKey, ["cam-up",0]) self.accept("x", self.setKey, ["cam-down", 1]) self.accept("x-up", self.setKey, ["cam-down", 0]) # Accept f to fire self.accept("f", self.setKey, ["fire-down",1]) self.accept("f-up", self.setKey, ["fire-down",0]) self.cTrav.traverse(render) #gun / laser code ommitted def getDistance(self, actor): self.vecAlien = Vec3(self.alien.getPos()) self.vecObj = Vec3(actor.getPos()) disVec = self.vecObj - self.vecAlien return disVec.length() def myFunction(self,task): self.walking.play() if(self.pause is False): for r in range(0, len(self.crAct)): self.crAct[r].setTarget(self.alien) self.bulletC.append( self.createBullet(self.crAct[r]) ) self.loaded.append( self.loadBullet( self.crAct[r]) ) self.loaded[self.gunAmmoCount].start() self.gunAmmoCount += 1 self.bulletSound.play() return task.again def bossLvlTask(self, dec, task): self.crAct[0].setAiPursue(self.alien) if(self.pause is False): self.deleteProjectiles() self.charcMoveKeys() startpos = self.alien.getPos() self.floater.setPos(self.alien.getPos()) self.floater.setZ(self.alien.getZ() + 2.0) base.camera.lookAt(self.floater) self.collHandQueEne.sortEntries() if(self.collHandQueEne.getNumEntries() > 0): entryb = self.collHandQueEne.getEntry(0) if( entryb.getIntoNodePath().getName() == "csAlien"): self.health['value'] -=5 if(self.bulletC): self.bulletC[self.gunAmmoCount-1].remove() self.bulletC.pop(self.gunAmmoCount-1) self.loaded.pop(self.gunAmmoCount-1) self.gunAmmoCount -= 1 if( self.health['value'] < 20 ): self.heartBeat.play() if(self.health['value'] == 0): self.alienDie(self.currentLevel) else: self.bulletC[self.gunAmmoCount-1].remove() self.bulletC.pop(self.gunAmmoCount-1) self.loaded.pop(self.gunAmmoCount-1) self.gunAmmoCount -= 1 self.collHandQue.sortEntries() if( self.collHandQue.getNumEntries() > 0 ): entry = self.collHandQue.getEntry(0) if( entry.getIntoNodePath().getName() == self.crAct[0].getCNP()): self.crAct[0].runAround(self.alien) self.crAct[0].setHitCount(1) self.crAct[0].decreaseHealth(dec) if( self.beamC): self.beamC[self.laserAmoCount-1].remove() self.beamC.pop(self.laserAmoCount-1) if(self.laserAmo): self.laserAmo.pop(self.laserAmoCount-1) self.laserAmoCount -= 1 if( self.crAct[0].getHealth()%4 == 0): self.crAct[0].jumpAway(self.alien) if( self.crAct[0].getHealth() == 0 ): ## print x.getDeaths() ## if( x.canRespawn() ): ## x.setDeaths(1) ## x.resetHitCount(0) ## x.setX(random.randint(0, 50)) ## x.setY(self.alien.getY()+15) ## else: self.crAct[0].cleanup() self.crAct[0].remove() self.crAct.pop(0) self.cutScene() if( self.crAct ): self.crAct[0].AIworld.update() if( self.keyMap["p"]!= 0): self.cutScene() return task.cont def move(self, task): ##ommmitted return task.cont def deleteProjectiles(self): ## if(self.pause is False): if(self.laserAmo): for i, x in enumerate(self.laserAmo): if( not x.isPlaying() ): self.beamC[i].remove() self.beamC.pop(i) self.laserAmo.pop(i) self.laserAmoCount = self.laserAmoCount -1 if(self.loaded): for i, x in enumerate(self.loaded): if(not x.isPlaying()): #self.crAct[i].setTarget(self.alien) self.bulletC[i].remove() self.bulletC.pop(i) self.loaded.pop(i) self.gunAmmoCount = self.gunAmmoCount -1 self.energyTime = self.energyTime + globalClock.getDt() if(self.energyTime > 2 ): if(self.energy['value'] != 100): self.energy['value'] +=5 self.energyTime = 0 def charcMoveKeys(self): if (self.keyMap["cam-left"]!=0): base.camera.setX(base.camera, -20 * globalClock.getDt()) if (self.keyMap["cam-right"]!=0): base.camera.setX(base.camera, +20 * globalClock.getDt()) if (self.keyMap["cam-up"]!=0): base.camera.setY(base.camera, -20 * globalClock.getDt()) if (self.keyMap["cam-down"]!=0): base.camera.setY(base.camera, +20 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.alien.setY(self.alien, 10 * globalClock.getDt()) if (self.keyMap["backward"]!=0): self.alien.setY(self.alien, -10 * globalClock.getDt()) if (self.keyMap["left"]!=0): self.alien.setH(self.alien.getH() + 40 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.alien.setH(self.alien.getH() - 40 * globalClock.getDt()) if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0) or (self.keyMap["backward"] != 0): if self.isMoving is False: self.alien.loop("walk") self.isMoving = True else: if self.isMoving: self.alien.stop() self.alien.pose("walk",5) self.isMoving = False def loadingScreen(self): self.intro.play() transition = Transitions(loader) transition.setFadeColor(0, 0, 0) text = TextNode('node name') dummy = NodePath(PandaNode("dummy")) black = OnscreenImage(image="GUI/black.png",pos=(0,0,0), scale=100) black.reparentTo(dummy) textNodePath = aspect2d.attachNewNode(text) textNodePath.reparentTo(aspect2d, 2) textNodePath.setScale(0.07) text.setTextColor(1, 1, 1, 1) if(self.currentLevel=="newyork"): Sequence(Func(transition.fadeOut),Func(black.reparentTo, aspect2d),Func(transition.fadeIn),Func(textNodePath.reparentTo,aspect2d, 10),Func(text.setText, "loading"),Wait(1.0),Func(text.setText, "loading."), Wait(1.0),Func(text.setText, "loading.."), Wait(1.0), Func(text.setText, "loading..."), Func(self.loadNextLevel),Wait(3.0),Func(transition.fadeIn),Func(textNodePath.remove), Func(black.destroy)).start() elif(self.currentLevel=="asia"): Sequence(Func(transition.fadeOut),Func(black.reparentTo, aspect2d),Func(transition.fadeIn),Func(textNodePath.reparentTo,aspect2d, 10),Func(text.setText, "loading"),Wait(1.0),Func(text.setText, "loading."), Wait(1.0),Func(text.setText, "loading.."), Wait(1.0), Func(text.setText, "loading..."), Func(self.loadNextLevel),Wait(3.0),Func(transition.fadeIn),Func(textNodePath.remove), Func(black.destroy)).start() else: Sequence(Func(transition.fadeOut),Func(black.reparentTo, aspect2d),Func(transition.fadeIn),Func(textNodePath.reparentTo,aspect2d, 10),Func(text.setText, "loading"),Wait(0.5),Func(text.setText, "loading."), Wait(0.5),Func(text.setText, "loading.."), Wait(0.5), Func(text.setText, "loading..."), Func(self.loadNextLevel),Wait(1.5),Func(transition.fadeIn),Func(textNodePath.remove), Func(black.destroy)).start() def cutScene(self): self.destroyLevel() self.stopAllSounds() self.cut = OnscreenImage("GUI/bossKilled.png",scale = Vec3(1.6, 0, 1.0),pos = Vec3(0, 0,0)) self.cut.reparentTo(aspect2d) self.cut.setTransparency(1) transition = Transitions(loader) transition.setFadeColor(0, 0, 0) self.cheer.play() if(self.currentLevel=="rainforest"): Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/map_11.png"), Wait(1.5),Func(self.cut.setImage, "GUI/map_12.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_13.png"), Wait(0.5),Func(self.cut.setImage,"GUI/map_14.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_15.png"), Wait(0.5),Func(self.cut.setImage,"GUI/map_16.png"),Wait(3.5),Func(self.cut.destroy), Func(transition.fadeOut), Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start() elif(self.currentLevel=="africa"): Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/map_21.png"), Wait(1.5),Func(self.cut.setImage, "GUI/map_22.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_23.png"), Wait(0.5),Func(self.cut.setImage,"GUI/map_24.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_25.png"), Wait(0.5),Func(self.cut.setImage,"GUI/map_26.png"), Wait(3.5),Func(self.cut.destroy), Func(transition.fadeOut),Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start() elif(self.currentLevel=="asia"): Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/map_31.png"), Wait(1.5),Func(self.cut.setImage, "GUI/map_32.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_33.png"), Wait(0.5),Func(self.cut.setImage,"GUI/map_34.png"),Wait(0.5),Func(self.cut.setImage,"GUI/map_35.png"), Wait(0.5),Func(self.cut.setImage,"GUI/map_36.png"),Wait(3.5),Func(self.cut.destroy), Func(transition.fadeOut),Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start() elif(self.currentLevel=="newyork"): Sequence(Wait(2.0),Func(transition.fadeOut),Wait(1.0),Func(transition.fadeIn),Func(self.cut.setImage,"GUI/win.png"), Wait(6.5),Func(self.cut.destroy), Func(transition.fadeOut),Func(self.loadingScreen), Wait(1.0),Func(transition.fadeIn)).start() def loadNextLevel(self): if(self.currentLevel=="start"): self.loadRainforestLevel() elif(self.currentLevel=="rainforest"): self.loadAfricaLevel() elif(self.currentLevel=="africa"): self.loadAsiaLevel() elif(self.currentLevel=="asia"): self.loadNewYorkLevel() else: self.MainMenu() def destroyLevel(self): self.mainMenuBtn.destroy() taskMgr.remove("moveTask") taskMgr.remove("bossTask") taskMgr.remove("myFunction") self.alien.cleanup() for enemy in self.crAct: enemy.cleanup() enemy.remove() self.alien.cleanup() self.alien.remove() for element in self.extraElements: element.removeNode() for beam in self.beamC: beam.removeNode() self.render.clearFog self.laserBeam2.removeNode() self.environ.removeNode() self.crAct[:] = [] self.extraElements[:] = [] self.laserAmo[:] =[] self.laserAmoCount = 0 def loadBossActor(self): self.bossLvl = True ###Load Ralph Boss actor### difficult = 10 taskMgr.remove("moveTask") taskMgr.remove("myFunction") self.health['value'] = 100 self.energy['value'] = 100 if(self.bossDead is False): self.bossImage = OnscreenImage("GUI/bossLoad.png",scale = Vec3(1.6, 0, 1.0),pos = Vec3(0, 0,0)) self.bossImage.reparentTo(aspect2d) self.bossImage.setTransparency(1) self.ralphBoss = EnemyActor(1,difficult,True) self.ralphBoss.enemy.setScale(2.0) self.crAct.append(self.ralphBoss) Sequence(Wait(3.0), Func(self.bossImage.destroy), Func(self.crAct[0].showHealthBar)).start() self.extraElements.append(self.crAct[0].bossHud) self.extraElements.append(self.crAct[0].health) self.crAct[0].setAiPursue(self.alien) self.pusher.addCollider(self.crAct[0].getFromObj(), self.crAct[0].enemy) base.cTrav.addCollider(self.crAct[0].getFromObj(), self.pusher) gunTex = loader.loadTexture('models/gun_tex.png') if(self.currentLevel == "rainforest"): dec = 5 self.ralphBoss.enemy.setPos(0,90,0) ralphTex = loader.loadTexture('models/ralph2rainforest.png') self.ralphBoss.enemy.setTexture(ralphTex, 1) self.ralphBoss.gunPos.setTexture(gunTex, 1) elif(self.currentLevel == "africa"): dec = 4 self.ralphBoss.enemy.setPos(-100,-90,0) ralphTex = loader.loadTexture('models/ralph2egypt.png') self.ralphBoss.enemy.setTexture(ralphTex, 1) self.ralphBoss.gunPos.setTexture(gunTex, 1) elif(self.currentLevel == "asia"): dec = 3 self.ralphBoss.enemy.setPos(0,0,0) ralphTex = loader.loadTexture('models/ralph2asia.png') self.ralphBoss.enemy.setTexture(ralphTex, 1) self.ralphBoss.gunPos.setTexture(gunTex, 1) elif(self.currentLevel == "newyork"): dec = 2 self.ralphBoss.enemy.setPos(120,10,0) taskMgr.add(self.bossLvlTask,"bossTask", extraArgs = [dec], appendTask=True) taskMgr.doMethodLater(1,self.myFunction,"myFunction") def loadRainforestLevel(self): self.keyMap = {"left":0, "right":0, "forward":0, "backward":0, "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0, "fire-down":0, "p":0} self.pause = False self.currentLevel = "rainforest" self.destroyIntro() difficulty = 2 self.bossLvl = False self.bossDead = False ###Load alien### startPos = Point3(0,0,0) self.loadAlien(startPos) self.rainforestMusic.play() ###Load the enemies### ralphTex = loader.loadTexture('models/ralph2rainforest.png') gunTex = loader.loadTexture('models/gun_tex.png') for i in range(0,2): enemy = EnemyActor(i, difficulty, False) enemy.enemy.setTexture(ralphTex, 1) enemy.gunPos.setTexture(gunTex, 1) enemy.setX(random.randint(-50,50)) enemy.setY(random.randint(-50,50)) enemy.setZ(0) self.crAct.append(enemy) self.crAct[i].setAiPursue(self.alien) self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy) base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher) taskMgr.add(self.move,"moveTask") taskMgr.doMethodLater(3,self.myFunction,"myFunction") self.loadLaser2() self.loadLaser() ###Load the environment### self.loadEnviron("models/south_america/rainforest", 5) self.plants = self.loader.loadModel("models/south_america/rainforest-nocollision") self.plants.reparentTo(self.render) self.plants.setScale(4) self.plants.setTwoSided(True) self.extraElements.append(self.plants) self.myFog = Fog("FOG") self.myFog.setColor(0.5,0.6,0.5) self.myFog.setExpDensity(0.005) render.setFog(self.myFog) self.audio.attachSoundToObject(self.sound, self.environ) self.audio.setSoundVelocityAuto(self.sound) self.audio.setListenerVelocityAuto() self.sound.play() def loadAfricaLevel(self): self.keyMap = {"left":0, "right":0, "forward":0, "backward":0, "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0, "fire-down":0, "p":0} self.pause = False self.currentLevel="africa" difficulty = 3 self.bossLvl = False self.bossDead = False ###Load alien### startPos = Point3(-130,-130,0) self.loadAlien(startPos) self.alien.setH(-40) ###Load the enemies### ralphTex = loader.loadTexture('models/ralph2egypt.png') gunTex = loader.loadTexture('models/gun_tex.png') for i in range(0,3): enemy = EnemyActor(i, difficulty, False) enemy.enemy.setTexture(ralphTex, 1) enemy.gunPos.setTexture(gunTex, 1) enemy.setX(random.randint(-170,-50)) enemy.setY(random.randint(-170,-50)) enemy.setZ(0) self.crAct.append(enemy) self.crAct[i].setAiPursue(self.alien) self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy) base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher) taskMgr.add(self.move,"moveTask") taskMgr.doMethodLater(3,self.myFunction,"myFunction") self.loadLaser2() self.loadLaser() ###Load environment### self.loadEnviron("models/africa/egypt", 7) self.egypt_nc = self.loader.loadModel("models/africa/egypt-nocollision") self.egypt_nc.reparentTo(self.render) self.egypt_nc.setPos(0,0,0) self.egypt_nc.setScale(7) self.extraElements.append(self.egypt_nc) self.sphinx = self.loader.loadModel("models/africa/sphinx") self.sphinx.setPos(0,80,0) self.sphinx.setH(180) self.sphinx.setScale(0.12) self.sphinx.reparentTo(self.render) self.extraElements.append(self.sphinx) cs = CollisionSphere(0,0,0,200) nodePath = self.sphinx.attachNewNode(CollisionNode('nodePath')) nodePath.node().addSolid(cs) self.gust.play() self.audio.attachSoundToObject(self.egyptMusic, self.environ) self.audio.setSoundVelocityAuto(self.egyptMusic) self.audio.setListenerVelocityAuto() self.egyptMusic.play() def loadAsiaLevel(self): self.keyMap = {"left":0, "right":0, "forward":0, "backward":0, "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0, "fire-down":0, "p":0} self.pause = False self.currentLevel = "asia" difficulty = 4 self.bossLvl = False self.bossDead = False ###Load alien### startPos = Point3(190,-140,0) self.loadAlien(startPos) ###Load the enemies### ralphTex = loader.loadTexture('models/ralph2asia.png') gunTex = loader.loadTexture('models/gun_tex.png') for i in range(0,4): enemy = EnemyActor(i, difficulty, False) enemy.enemy.setTexture(ralphTex, 1) enemy.gunPos.setTexture(gunTex, 1) enemy.setX(random.randint(0,100)) enemy.setY(random.randint(-150,-50)) enemy.setZ(0) self.crAct.append(enemy) self.crAct[i].setAiPursue(self.alien) self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy) base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher) taskMgr.add(self.move,"moveTask") taskMgr.doMethodLater(3,self.myFunction,"myFunction") self.loadLaser2() self.loadLaser() ###Load the environment### self.loadEnviron("models/asia/asia2", 5) self.asia_nc = self.loader.loadModel("models/asia/asia-nocollision") self.asia_nc.reparentTo(self.render) self.asia_nc.setPos(0,0,0) self.asia_nc.setScale(5) self.extraElements.append(self.asia_nc) self.myFog = Fog("FOG") self.myFog.setColor(0.8,0.8,0.8) self.myFog.setExpDensity(0.002) render.setFog(self.myFog) self.bonzai = self.loader.loadModel("models/asia/bonzai") self.bonzai.reparentTo(self.render) self.bonzai.setPos(170,20,0) self.bonzai.setScale(0.015) self.bonzai.setH(90) self.extraElements.append(self.bonzai) cs = CollisionSphere(0,0,200,200) nodePath = self.bonzai.attachNewNode(CollisionNode('nodePath')) nodePath.node().addSolid(cs) self.pusher.addCollider(nodePath, self.bonzai) self.waterfall = self.loader.loadModel("models/asia/waterFall") self.waterfall.reparentTo(self.render) self.waterfall.setPos(200,80,-.5) self.waterfall.setScale(0.25) self.waterfall.setH(180) self.extraElements.append(self.waterfall) cs = CollisionSphere(0,15,-5,130) nodePath = self.waterfall.attachNewNode(CollisionNode('nodePath')) nodePath.node().addSolid(cs) self.pusher.addCollider(nodePath, self.waterfall) self.waterfallSound.setLoop(True) self.audio.attachSoundToObject(self.waterfallSound,self.waterfall) self.audio.setSoundVelocityAuto(self.waterfallSound) self.audio.setListenerVelocityAuto() self.audio.setDistanceFactor(1.5) self.waterfallSound.play() self.tree1 = self.loader.loadModel("models/asia/bamboo") self.tree1.reparentTo(self.render) self.tree1.setPos(-50,-50,0) self.tree1.setScale(0.6,0.6,0.6) self.tree1.setBillboardAxis() self.extraElements.append(self.tree1) #Child bamboos scattered around placeholder = render.attachNewNode("Bamboo-Placeholder") placeholder.setPos(180,-40,0) placeholder.setScale(0.8) self.tree1.instanceTo(placeholder) self.extraElements.append(placeholder) placeholder = render.attachNewNode("Babmboo-Placeholder") placeholder.setPos(-20,-120,0) placeholder.setScale(1.0) self.tree1.instanceTo(placeholder) self.extraElements.append(placeholder) placeholder = render.attachNewNode("Bamboo-Placeholder") placeholder.setPos(-50,180,0) placeholder.setScale(1.0) self.tree1.instanceTo(placeholder) self.extraElements.append(placeholder) placeholder = render.attachNewNode("Bamboo-Placeholder") placeholder.setPos(-60,165,0) placeholder.setScale(0.6) self.tree1.instanceTo(placeholder) self.extraElements.append(placeholder) placeholder = render.attachNewNode("Bamboo-Placeholder") placeholder.setPos(-110,70,0) placeholder.setScale(1.0) self.tree1.instanceTo(placeholder) self.extraElements.append(placeholder) placeholder = render.attachNewNode("Bamboo-Placeholder") placeholder.setPos(-100,-50,0) placeholder.setScale(1.6) self.tree1.instanceTo(placeholder) self.extraElements.append(placeholder) self.asiaMusic.play() def loadNewYorkLevel(self): self.keyMap = {"left":0, "right":0, "forward":0, "backward":0, "cam-left":0, "cam-right":0, "cam-up":0, "cam-down":0, "fire-down":0,"p":0} self.pause = False self.currentLevel = "newyork" #self.destroyMainMenuLevels() difficulty = 5 ###Load alien### startPos = Point3(20,10,0) self.loadAlien(startPos) self.alien.setH(90) base.camera.setH(90) self.bossLvl = False self.bossDead = False ###Load the enemies### for i in range(0,5): enemy = EnemyActor(i, difficulty, False) enemy.setX(random.randint(-100,100)) enemy.setY(random.randint(8,12)) enemy.setZ(0) self.crAct.append(enemy) self.crAct[i].setAiPursue(self.alien) self.pusher.addCollider(self.crAct[i].getFromObj(), self.crAct[i].enemy) base.cTrav.addCollider(self.crAct[i].getFromObj(), self.pusher) taskMgr.add(self.move,"moveTask") taskMgr.doMethodLater(2,self.myFunction, "myFunction") self.loadLaser2() self.loadLaser() ###Load the environment### self.loadEnviron("models/america/newyork", 4) self.ny_nc = self.loader.loadModel("models/america/newyork-nocollision") self.ny_nc.reparentTo(self.render) self.ny_nc.setScale(4) self.extraElements.append(self.ny_nc) self.statue = self.loader.loadModel("models/america/statue") self.statue.reparentTo(self.render) self.statue.setPos(270,-100,13) self.statue.setScale(1) self.statue.setBillboardAxis() self.statue.setTwoSided(True) self.extraElements.append(self.statue) self.myFog = Fog("FOG") self.myFog.setColor(0.3,0.3,0.3) self.myFog.setExpDensity(0.005) render.setFog(self.myFog) self.siren.play() self.newyorkMusic.play()