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)
class Boule_feu(Arme): def __init__(self, parent): Arme.__init__(self, parent) # init du rayon de la mort self.ray = CollisionRay(0, 0, 0, 0, 1, 0) rayNode = CollisionNode("boule_feu") rayNode.addSolid(self.ray) mask = BitMask32() mask.setBit(2) rayNode.setFromCollideMask(mask) maskI = BitMask32() maskI.setBit(0) rayNode.setIntoCollideMask(maskI) self.rayNodePath = render.attachNewNode(rayNode) self.rayQueue = CollisionHandlerQueue() self.parent.base.cTrav.addCollider(self.rayNodePath, self.rayQueue) self.ray.setOrigin(12, 9, 7) self.ray.setDirection(self.parent.heros.actor.getPos() - self.parent.sorcier.obj.getPos()) self.rayNodePath.show() def update(self, keys, dt): self.ray.setDirection(self.parent.heros.actor.getPos() - self.parent.sorcier.obj.getPos()) if self.rayQueue.getNumEntries() > 0: self.rayQueue.sortEntries() rayHit = self.rayQueue.getEntry(0) hitPos = rayHit.getSurfacePoint(render) hitNodePath = rayHit.getIntoNodePath() print(hitNodePath)
def initHero(self): self.hero = loader.loadModel("charaRoot") self.hero.reparentTo(self.stage) model = base.gameData.heroModel self.heroArmature = Actor( "{}".format(model), { "idle": "{}-idle".format(model), "walk": "{}-run".format(model) }) self.heroArmature.reparentTo(self.hero) self.hero.setPos(self.startPos) cNode = CollisionNode('hero') cNode.addSolid(CollisionSphere(0, 0, 1.5, 1)) heroCollision = self.hero.attachNewNode(cNode) ######################################################### # heroCollision.show() self.pusher.addCollider( heroCollision, self.hero, base.drive.node()) base.cTrav.addCollider(heroCollision, self.pusher) heroGroundRay = CollisionRay() heroGroundRay.setOrigin(0, 0, 9) heroGroundRay.setDirection(0, 0, -1) heroGroundCol = CollisionNode('heroRay') heroGroundCol.addSolid(heroGroundRay) heroGroundCol.setFromCollideMask(CollideMask.bit(0)) heroGroundCol.setIntoCollideMask(CollideMask.allOff()) heroGroundColNp = self.hero.attachNewNode(heroGroundCol) ######################################################### # heroGroundColNp.show() base.cTrav.addCollider(heroGroundColNp, self.heroGroundHandler) self.controlCamera()
def raycast(self, origin, direction=(0,0,1), distance=inf, traverse_target=scene, ignore=list(), debug=False): self.position = origin self.look_at(self.position + direction) self._pickerNode.clearSolids() ray = CollisionRay() ray.setOrigin(Vec3(0,0,0)) ray.setDirection(Vec3(0,0,1)) self._pickerNode.addSolid(ray) if debug: temp = Entity(position=origin, model=Raycaster.line_model, scale=Vec3(1,1,min(distance,9999)), add_to_scene_entities=False) temp.look_at(self.position + direction) destroy(temp, 1/30) self._picker.traverse(traverse_target) if self._pq.get_num_entries() == 0: self.hit = HitInfo(hit=False, distance=distance) return self.hit ignore += tuple([e for e in scene.entities if not e.collision]) self._pq.sort_entries() self.entries = [ # filter out ignored entities e for e in self._pq.getEntries() if e.get_into_node_path().parent not in ignore and self.distance(self.world_position, Vec3(*e.get_surface_point(render))) <= distance ] if len(self.entries) == 0: self.hit = HitInfo(hit=False, distance=distance) return self.hit self.collision = self.entries[0] nP = self.collision.get_into_node_path().parent point = Vec3(*self.collision.get_surface_point(nP)) world_point = Vec3(*self.collision.get_surface_point(render)) hit_dist = self.distance(self.world_position, world_point) self.hit = HitInfo(hit=True, distance=distance) for e in scene.entities: if e == nP: # print('cast nP to Entity') self.hit.entity = e self.hit.point = point self.hit.world_point = world_point self.hit.distance = hit_dist self.hit.normal = Vec3(*self.collision.get_surface_normal(self.collision.get_into_node_path().parent).normalized()) self.hit.world_normal = Vec3(*self.collision.get_surface_normal(render).normalized()) return self.hit self.hit = HitInfo(hit=False, distance=distance) return self.hit
def colRay(parent, origin=(0,0,0.1), direction=(0,0,-1)): ray = CollisionRay() ray.setOrigin(origin) ray.setDirection(direction) col = CollisionNode(parent.getName()+"-ray") col.addSolid(ray) col.setIntoCollideMask(CollideMask.allOff()) colNode = parent.attachNewNode(col) handler = CollisionHandlerQueue() base.cTrav.addCollider(colNode, handler) #colNode.show() return handler
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)
class MouseCollision: def __init__(self, game): self.game = game self.c_trav = CollisionTraverser() self.mouse_groundHandler = CollisionHandlerQueue() self.mouse_ground_ray = CollisionRay() self.mouse_ground_col = CollisionNode('mouseRay') self.mouse_ground_ray.setOrigin(0, 0, 0) self.mouse_ground_ray.setDirection(0, -1, 0) self.mouse_ground_col.addSolid(self.mouse_ground_ray) self.mouse_ground_col.setFromCollideMask(CollideMask.bit(0)) self.mouse_ground_col.setIntoCollideMask(CollideMask.allOff()) self.mouse_ground_col_np = self.game.camera.attachNewNode( self.mouse_ground_col) self.c_trav.addCollider(self.mouse_ground_col_np, self.mouse_groundHandler) self.game.taskMgr.add(self.update, 'updateMouse') def update(self, task): if self.game.mouseWatcherNode.hasMouse(): if self.game.ship.model: mouse_pos = self.game.mouseWatcherNode.getMouse() self.mouse_ground_ray.setFromLens(self.game.camNode, mouse_pos.getX(), mouse_pos.getY()) near_point = render.getRelativePoint( self.game.camera, self.mouse_ground_ray.getOrigin()) near_vec = render.getRelativeVector( self.game.camera, self.mouse_ground_ray.getDirection()) self.game.ship.shipPoint.setPos( self.PointAtY(self.game.ship.model.getY(), near_point, near_vec)) return task.cont def PointAtY(self, y, point, vec): return point + vec * ((y - point.getY()) / vec.getY())
class PlayerObject(): def __init__(self, render, player): self.username = player.getUsername() self.isMoving = False self.render = render self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0} self.actor = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.actor.reparentTo(render) self.actor.setScale(0.2) self.actor.setPos(player.getX(), player.getY(), player.getZ()) self.actor.setH(player.getH()) self.cTrav = CollisionTraverser() self.GroundRay = CollisionRay() self.GroundRay.setOrigin(0,0,1000) self.GroundRay.setDirection(0,0,-1) self.GroundCol = CollisionNode('actorRay') self.GroundCol.addSolid(self.GroundRay) self.GroundCol.setFromCollideMask(BitMask32.bit(0)) self.GroundCol.setIntoCollideMask(BitMask32.allOff()) self.GroundColNp = self.actor.attachNewNode(self.GroundCol) self.GroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.GroundColNp, self.GroundHandler) # def getUsername(self): # return self.username def getActor(self): return self.actor def setPos(self, x, y, z): self.actor.setPos(x, y, z) def setH(self, h): self.actor.setH(h) def move(self, isActorMove): if isActorMove == "True": if self.isMoving is False: self.actor.loop("run") self.isMoving = True else: if self.isMoving: self.actor.stop() self.actor.pose("walk",5) self.isMoving = False
def setupCollisionRay(self, node, origin=(0, 0, 0), direction=(0, 0, 0), name=None): ray = CollisionRay() ray.setOrigin(origin) ray.setDirection(direction) col = CollisionNode(name) col.addSolid(ray) col.setFromCollideMask(CollideMask.bit(0)) col.setIntoCollideMask(CollideMask.allOff()) colNode = node.attachNewNode(col) queue = CollisionHandlerQueue() self.cTrav.addCollider(colNode, queue) return queue
class MouseCollision: def __init__(self, game): self.game = game self.c_trav = CollisionTraverser() self.mouse_groundHandler = CollisionHandlerQueue() self.mouse_ground_ray = CollisionRay() self.mouse_ground_col = CollisionNode('mouseRay') self.mouse_ground_ray.setOrigin(0, 0, 0) self.mouse_ground_ray.setDirection(0, -1, 0) self.mouse_ground_col.addSolid(self.mouse_ground_ray) self.mouse_ground_col.setFromCollideMask(CollideMask.bit(0)) self.mouse_ground_col.setIntoCollideMask(CollideMask.allOff()) self.mouse_ground_col_np = self.game.camera.attachNewNode(self.mouse_ground_col) self.c_trav.addCollider(self.mouse_ground_col_np, self.mouse_groundHandler) self.game.taskMgr.add(self.update, 'updateMouse') def update(self, task): if self.game.mouseWatcherNode.hasMouse(): if self.game.ship.model: mouse_pos = self.game.mouseWatcherNode.getMouse() self.mouse_ground_ray.setFromLens(self.game.camNode, mouse_pos.getX(), mouse_pos.getY()) near_point = render.getRelativePoint(self.game.camera, self.mouse_ground_ray.getOrigin()) near_vec = render.getRelativeVector(self.game.camera, self.mouse_ground_ray.getDirection()) self.game.ship.shipPoint.setPos(self.PointAtY(self.game.ship.model.getY(), near_point, near_vec)) return task.cont def PointAtY(self, y, point, vec): return point + vec * ((y - point.getY()) / vec.getY())
class PlayerInput(DirectObject): """ PlayerInput Class: Handels all inputs. """ def __init__(self): # Should make a method to get active players. self.activePlayer = ACTIVE_ACTORS['Player'].playerActor self.activePlayerSpeed = ACTIVE_ACTORS['Player'].playerSpeed # Set the control maps. self.controlMap = {"left": 0, "right": 0, "forward": 0, "backward": 0, "jump": 0, "wheel-in": 0, "wheel-out": 0} self.mousebtn = [0, 0, 0] # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) ### SETUP KEYBOARD ### # Setup the control [KEYS] for movement w,a,s,d. self.accept("escape", sys.exit) self.accept("w", self.setControl, ["forward", 1]) self.accept("a", self.setControl, ["left", 1]) self.accept("s", self.setControl, ["backward", 1]) self.accept("d", self.setControl, ["right", 1]) self.accept("space", self.setControl, ["jump", 1]) self.accept("w-up", self.setControl, ["forward", 0]) self.accept("a-up", self.setControl, ["left", 0]) self.accept("s-up", self.setControl, ["backward", 0]) self.accept("d-up", self.setControl, ["right", 0]) self.accept("space-up", self.setControl, ["jump", 0]) # Setup mouse [ZOOM]. self.accept("wheel_up", self.setControl, ["wheel-in", 1]) self.accept("wheel_down", self.setControl, ["wheel-out", 1]) # Add the "moveTask" taskMgr.add(self.move, "moveTask") # Game State Variable. self.isMoving = False ###> ### SETUP CAMERA ### # Reparent the -main- Camera to playerActor. base.camera.reparentTo(self.activePlayer) self.cameraTargetHeight = 6.0 self.cameraDistance = 30 self.cameraPitch = 10 base.disableMouse() # This should be used together with a right click function, for the camera rotate. Like in wow. WinProps = WindowProperties() # Hide the cursor. | This will change with the rightClick function. # Giving us the cursor when not rotating. If the player wants to rotate basic [KEYS] left/right can turn while cursor is active. WinProps.setCursorHidden(True) base.win.requestProperties(WinProps) #base.camera.setPos(self.activePlayer.getX(),self.activePlayer.getY()+10,2) # FROM THE ROAMING RALPH TUT> # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. #self.cTrav = CollisionTraverser() self.actorGroundRay = CollisionRay() self.actorGroundRay.setOrigin(0,0,1000) self.actorGroundRay.setDirection(0,0,-1) self.actorGroundCol = CollisionNode('actorRay') self.actorGroundCol.addSolid(self.actorGroundRay) self.actorGroundCol.setFromCollideMask(BitMask32.bit(0)) self.actorGroundCol.setIntoCollideMask(BitMask32.allOff()) self.actorGroundColNp = self.activePlayer.attachNewNode(self.actorGroundCol) self.actorGroundHandler = CollisionHandlerQueue() cTrav.addCollider(self.actorGroundColNp, self.actorGroundHandler) # We will detect anything obstructing the camera's view of the player self.cameraRay = CollisionSegment((0,0,self.cameraTargetHeight),(0,5,5)) self.cameraCol = CollisionNode('cameraRay') self.cameraCol.addSolid(self.cameraRay) self.cameraCol.setFromCollideMask(BitMask32.bit(0)) self.cameraCol.setIntoCollideMask(BitMask32.allOff()) self.cameraColNp = self.activePlayer.attachNewNode(self.cameraCol) self.cameraColHandler = CollisionHandlerQueue() cTrav.addCollider(self.cameraColNp, self.cameraColHandler) # Uncomment this line to see the collision rays self.actorGroundColNp.show() self.cameraColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring cTrav.showCollisions(render) ###> # Check the state of the KB. def setControl(self, key, value): self.controlMap[key] = value def move(self, task): self.actorPos = self.activePlayer.getPos() # Check if a-move key is pressed, if so move. # Forward. if (self.controlMap["forward"] != 0): self.activePlayer.setY(self.activePlayer, -self.activePlayerSpeed * globalClock.getDt()) # Backward. if (self.controlMap["backward"] != 0): self.activePlayer.setY(self.activePlayer, self.activePlayerSpeed * globalClock.getDt()) # Left. if (self.controlMap["left"] != 0): self.activePlayer.setX(self.activePlayer, self.activePlayerSpeed * globalClock.getDt()) # Right. if (self.controlMap["right"] != 0): self.activePlayer.setX(self.activePlayer, -self.activePlayerSpeed * globalClock.getDt()) if (self.controlMap["jump"] != 0): print "Jump now...!?" # Check for zooming and Do. if (self.controlMap["wheel-in"] != 0): self.cameraDistance -= 0.1 * self.cameraDistance if (self.cameraDistance < 5): self.cameraDistance = 5 self.controlMap["wheel-in"] = 0 elif (self.controlMap["wheel-out"] != 0): self.cameraDistance += 0.1 * self.cameraDistance if (self.cameraDistance > 250): self.cameraDistance = 250 self.controlMap["wheel-out"] = 0 # Make use of mouse, to turn. if base.mouseWatcherNode.hasMouse(): # get changes in mouse position md = base.win.getPointer(0) x = md.getX() y = md.getY() deltaX = md.getX() - 200 deltaY = md.getY() - 200 # reset mouse cursor position base.win.movePointer(0, 200, 200) # Mouse speed setting mouseSpeed = 0.3 # alter the actor yaw by an amount proportionate to deltaX self.activePlayer.setH(self.activePlayer.getH() - mouseSpeed* deltaX) # find the new camera pitch and clamp it to a reasonable range self.cameraPitch = self.cameraPitch + 0.1 * deltaY if (self.cameraPitch < -60): self.cameraPitch = -60 if (self.cameraPitch > 80): self.cameraPitch = 80 base.camera.setHpr(0,self.cameraPitch,0) # set the camera at around middle of the ship # We should pivot around here instead of the view target which is noticebly higher base.camera.setPos(0,0,self.cameraTargetHeight/2) # back the camera out to its proper distance base.camera.setY(base.camera,self.cameraDistance) # point the camera at the view target viewTarget = Point3(0,0,self.cameraTargetHeight) base.camera.lookAt(viewTarget) # reposition the end of the camera's obstruction ray trace self.cameraRay.setPointB(base.camera.getPos()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.controlMap["forward"]!=0) or (self.controlMap["left"]!=0) or (self.controlMap["right"]!=0): if self.isMoving is False: self.activePlayer.loop("run") self.isMoving = True else: if self.isMoving: self.activePlayer.stop() self.activePlayer.pose("walk",5) self.isMoving = False # Now check for collisions. cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.actorGroundHandler.getNumEntries()): entry = self.actorGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "ground"): self.activePlayer.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.activePlayer.setPos(self.actorPos) # Go through the BALL_DICT which is not a list and needs a new name :P # And find the ball being colided with. and then del. it for ball in BALL_LIST: if (len(entries)>0) and (entries[0].getIntoNode().getName() == str(ball)): print "Collide with ", entries[0].getIntoNode().getName() del BALL_LIST[ball] BALL_LIST[ball] = None # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.cameraColHandler.getNumEntries()): entry = self.cameraColHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(-y.getSurfacePoint(self.activePlayer).getY(), -x.getSurfacePoint(self.activePlayer).getY())) if (len(entries)>0): collisionPoint = entries[0].getSurfacePoint(self.activePlayer) collisionVec = ( viewTarget - collisionPoint) if ( collisionVec.lengthSquared() < self.cameraDistance * self.cameraDistance ): base.camera.setPos(collisionPoint) if (entries[0].getIntoNode().getName() == "ground"): base.camera.setZ(base.camera, 0.2) base.camera.setY(base.camera, 0.3) return task.cont
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 Usuario(object): ''' Usuario ''' def __init__(self): self.habilitado = False self.estaMovendo = False self.estaRodando = False self.timeIniMover = 0 self.timeIniRodar = 0 self.keyMap = { TECLA_esquerda: EVENT_up, TECLA_direita: EVENT_up, TECLA_frente: EVENT_up, TECLA_traz: EVENT_up } self.login = None self.senha = None self.nick = None self.vida_real = None self.vida_total = None self.mana_real = None self.mana_total = None self.forca = None self.velocidade = None self.velocidade_atack = None self.key = None self.addr = None self.login = None pandaFileModelo = get_path_modelo("ralph") self.__modelo = Actor(pandaFileModelo) self.__modelo.reparentTo(render) self.__modelo.setScale(SCALE_MODELOS) modeloStartPos = vinerWorld.mapa.modelo.find("**/start_point").getPos() self.set_pos(modeloStartPos) self.__setup_collision() def get_x(self): return self.__modelo.getX() def get_y(self): return self.__modelo.getY() def get_z(self): return self.__modelo.getZ() def get_h(self): return self.__modelo.getH() def get_pos(self): return self.__modelo.getPos() def set_x(self, x): self.__modelo.setX(x) def set_y(self, y): self.__modelo.setY(y) def set_z(self, z): self.__modelo.setZ(z) def set_h(self, h): self.__modelo.setH(h) def set_pos(self, pos): self.__modelo.setPos(pos) def get_dados(self): return [ self.key, self.nick, self.vida_real, self.vida_total, self.mana_real, self.mana_total, self.forca, self.velocidade, self.velocidade_atack, self.get_x(), self.get_y(), self.get_z(), self.get_h(), ] def stop_task_movimentacao(self): taskMgr.remove(self.key) def inicia_task_movimentacao(self): if self.key != "": taskMgr.add(self.__task_movimentacao, self.key, sort=1) def __setup_collision(self): #Colisao self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 5) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.__modelo.attachNewNode( self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) #Colisao def __task_movimentacao(self, task): dt = globalClock.getDt() startpos = self.__modelo.getPos() #rodar usuario if self.keyMap[TECLA_esquerda] == EVENT_down and self.keyMap[ TECLA_direita] == EVENT_up: if time.time() < self.timeIniRodar + 4: self.estaRodando = True self.__modelo.setH(self.__modelo, ((self.velocidade * 5) * dt)) else: h = self.get_h() vinerOnline.envia_pacote_todos( 1, ACAO_CLIENT_rodar, [self.key, TECLA_esquerda, EVENT_up, h]) self.estaRodando = False self.keyMap[TECLA_esquerda] = EVENT_up elif self.keyMap[TECLA_direita] == EVENT_down and self.keyMap[ TECLA_esquerda] == EVENT_up: if time.time() < self.timeIniRodar + 4: self.estaRodando = True self.__modelo.setH(self.__modelo, ((self.velocidade * 5) * dt) * -1) else: h = self.get_h() vinerOnline.envia_pacote_todos( 1, ACAO_CLIENT_rodar, [self.key, TECLA_direita, EVENT_up, h]) self.estaRodando = False self.keyMap[TECLA_direita] = EVENT_up elif self.estaRodando: self.estaRodando = False #rodar usuario #mover usuario if self.keyMap[TECLA_frente] == EVENT_down and self.keyMap[ TECLA_traz] == EVENT_up: if time.time() < self.timeIniMover + 4: self.estaMovendo = True self.__modelo.setY(self.__modelo, ((self.velocidade * 2) * dt) * -1) else: x = self.get_x() y = self.get_y() z = self.get_z() vinerOnline.envia_pacote_todos( 1, ACAO_CLIENT_mover, [self.key, TECLA_frente, EVENT_up, x, y, z]) self.estaMovendo = False self.keyMap[TECLA_frente] = EVENT_up elif self.keyMap[TECLA_traz] == EVENT_down and self.keyMap[ TECLA_frente] == EVENT_up: if time.time() < self.timeIniMover + 4: self.estaMovendo = True self.__modelo.setY(self.__modelo, (self.velocidade * dt)) else: x = self.get_x() y = self.get_y() z = self.get_z() vinerOnline.envia_pacote_todos( 1, ACAO_CLIENT_mover, [self.key, TECLA_traz, EVENT_up, x, y, z]) self.estaMovendo = False self.keyMap[TECLA_traz] = EVENT_up elif self.estaMovendo: self.estaMovendo = False #mover usuario #se esta moventdo trata colisao if self.estaMovendo: base.cTrav.traverse(render) if self.ralphGroundHandler.getNumEntries() == 1: entry = self.ralphGroundHandler.getEntry(0) if entry.getIntoNode().getName() == "terrain": self.__modelo.setZ(entry.getSurfacePoint(render).getZ()) else: self.__modelo.setPos(startpos) #se esta moventdo trata colisao return task.cont
class World(DirectObject): def __init__(self): #create Queue to hold the incoming chat #request the heartbeat so that the caht interface is being refreshed in order to get the message from other player self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0, "charge":0} base.win.setClearColor(Vec4(0,0,0,1)) self.cManager = ConnectionManager() self.cManager.startConnection() #------------------------------ #Chat Chat(self.cManager) #send dummy login info of the particular client #send first chat info #--------------------------------------- self.userName = username dummy_login ={'user_id' : self.userName, 'factionId': faction, 'password': '******'} self.cManager.sendRequest(Constants.RAND_STRING, dummy_login) chat = { 'userName' : self.userName, #username 'message' : '-------Login------' } self.cManager.sendRequest(Constants.CMSG_CHAT, chat) #-------------------------------------- #self.minimap = OnscreenImage(image="images/minimap.png", scale=(0.2,1,0.2), pos=(-1.1,0,0.8)) #frame = DirectFrame(text="Resource Bar", scale=0.001) resource_bar = DirectWaitBar(text="", value=35, range=100, pos=(0,0,0.9), barColor=(255,255,0,1), frameSize=(-0.3,0.3,0,0.03)) cp_bar = DirectWaitBar(text="", value=70, range=100, pos=(1.0,0,0.9), barColor=(0,0,255,1), frameSize=(-0.3,0.3,0,0.03), frameColor=(255,0,0,1)) # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0,0,0) # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos) nameplate = TextNode('textNode username_' + str(self.userName)) nameplate.setText(self.userName) npNodePath = self.ralph.attachNewNode(nameplate) npNodePath.setScale(0.8) npNodePath.setBillboardPointEye() #npNodePath.setPos(1.0,0,6.0) npNodePath.setZ(6.5) bar = DirectWaitBar(value=100, scale=1.0) bar.setColor(255,0,0) #bar.setBarRelief() bar.setZ(6.0) bar.setBillboardPointEye() bar.reparentTo(self.ralph) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation 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.accept("c", self.setKey, ["charge",1]) self.accept("c-up", self.setKey, ["charge",0]) taskMgr.add(self.move,"moveTask") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(),self.ralph.getY()+10,2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,1000) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) 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()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"]!=0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.ralph.setY(self.ralph, -25 * globalClock.getDt()) if (self.keyMap["charge"]!=0): self.ralph.setY(self.ralph, -250 * globalClock.getDt()) #ribbon = Ribbon(self.ralph, Vec4(1,1,1,1), 3, 10, 0.3) #ribbon.getRoot().setZ(2.0) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.keyMap["forward"]!=0) or (self.keyMap["charge"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk",5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.0): base.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) return task.cont
class Usuario(object): """ Usuario """ def __init__(self, dadosUsuario, principal=False): self.key = dadosUsuario["key"] self.nick = dadosUsuario["nick"] self.vida_real = float(dadosUsuario["vida_real"]) self.vida_total = float(dadosUsuario["vida_total"]) self.mana_real = float(dadosUsuario["mana_real"]) self.mana_total = float(dadosUsuario["mana_total"]) self.forca = float(dadosUsuario["forca"]) self.velocidade = float(dadosUsuario["velocidade"]) self.velocidade_atack = float(dadosUsuario["velocidade_atack"]) self.estaMovendo = False self.estaRodando = False self.__task_name = "Task Usuario - " + self.key self.keyMap = {TECLA_esquerda: EVENT_up, TECLA_direita: EVENT_up, TECLA_frente: EVENT_up, TECLA_traz: EVENT_up} pandaFileModelo = get_path_modelo("ralph") pandaFileAnimacaoRun = get_path_animacao("ralph-run") pandaFileAnimacaoWalk = get_path_animacao("ralph-walk") self.modelo = Actor(pandaFileModelo, {"run": pandaFileAnimacaoRun, "walk": pandaFileAnimacaoWalk}) self.modelo.reparentTo(render) self.modelo.setScale(SCALE_MODELOS) self.set_pos((float(dadosUsuario["x"]), float(dadosUsuario["y"]), float(dadosUsuario["z"]))) self.set_h(float(dadosUsuario["h"])) if not principal: self.text = Text( parent=self.modelo, pos=(0, 0, 5.5), scale=0.5, align="center", cor=COR_VERDE, text=self.nick ) self.text.billboardEffect() self.__setup_collision() taskMgr.add(self.__task_movimentacao, self.__task_name, sort=1) def get_x(self): return self.modelo.getX() def get_y(self): return self.modelo.getY() def get_z(self): return self.modelo.getZ() def get_h(self): return self.modelo.getH() def get_pos(self): return self.modelo.getPos() def set_x(self, x): self.modelo.setX(x) def set_y(self, y): self.modelo.setY(y) def set_z(self, z): self.modelo.setZ(z) def set_h(self, h): self.modelo.setH(h) def set_pos(self, pos): self.modelo.setPos(pos) def delete(self): taskMgr.remove(self.__task_name) self.modelo.delete() def __setup_collision(self): # Colisao self.cTrav = CollisionTraverser("usuarioTraverser") self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 5) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode("ralphRay") self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.modelo.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) # self.ralphGroundColNp.show() # self.cTrav.showCollisions(render) # Colisao def __task_movimentacao(self, task): dt = globalClock.getDt() startpos = self.modelo.getPos() # movimentos usuario modelo if self.keyMap[TECLA_esquerda] == EVENT_down and self.keyMap[TECLA_direita] == EVENT_up: self.modelo.setH(self.modelo, ((self.velocidade * 5) * dt)) if not self.estaRodando: self.estaRodando = True elif self.keyMap[TECLA_direita] == EVENT_down and self.keyMap[TECLA_esquerda] == EVENT_up: self.modelo.setH(self.modelo, ((self.velocidade * 5) * dt) * -1) if not self.estaRodando: self.estaRodando = True elif self.estaRodando: self.estaRodando = False if self.keyMap[TECLA_frente] == EVENT_down and self.keyMap[TECLA_traz] == EVENT_up: self.modelo.setY(self.modelo, ((self.velocidade * 2) * dt) * -1) if self.estaMovendo is False: self.modelo.loop("run") self.estaMovendo = True elif self.keyMap[TECLA_traz] == EVENT_down and self.keyMap[TECLA_frente] == EVENT_up: self.modelo.setY(self.modelo, (self.velocidade * dt)) if self.estaMovendo is False: self.modelo.loop("walk") self.estaMovendo = True elif self.estaMovendo: self.modelo.stop() self.modelo.pose("walk", 5) self.estaMovendo = False # movimentos usuario modelo if self.estaMovendo: self.cTrav.traverse(render) if self.ralphGroundHandler.getNumEntries() == 1: entry = self.ralphGroundHandler.getEntry(0) if entry.getIntoNode().getName() == "terrain": self.modelo.setZ(entry.getSurfacePoint(render).getZ()) else: self.modelo.setPos(startpos) return task.cont
class World(DirectObject): def __init__(self): self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0} base.win.setClearColor(Vec4(0,0,0,1)) # Post the instructions self.title = addTitle("Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.85, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.80, "[Up Arrow]: Run Ralph Forward") self.inst6 = addInstructions(0.70, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.65, "[S]: Rotate Camera Right") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0,0,0) # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() #self.addRalph(ralphStartPos) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation 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]) taskMgr.add(self.move,"moveTask") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) # Add some text ''' bk_text = "This is a test" textObject = OnscreenText(text = bk_text, pos = (0.95,-0.35), scale = 0.07,fg=(1,0.5,0.5,1),align=TextNode.ACenter,mayChange=1) ''' #MS: Adds a Roaming Ralph def addRalph(self, pos): ralphStartPos = pos self.ralph = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos) self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,1000) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) 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()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"]!=0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.ralph.setY(self.ralph, -25 * globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk",5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.0): base.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) return task.cont
class World(DirectObject): def skyBoxLoad(self): self.spaceSkyBox = load_model('skybox1.egg') self.spaceSkyBox.setScale(150) self.spaceSkyBox.setLightOff() self.spaceSkyBox.reparentTo(render) self.spaceSkyBox.setPos(0,0,-200) self.spaceSkyBox.setHpr(0,0,0) def loadEnviron(self): self.environ = load_model("secondWorld.egg") self.environ.reparentTo(render) self.environ.setPos(0,0,0) def loadPokemon(self): self.pikachu = load_model("pikachu.egg") self.pikachu.reparentTo(render) self.pikachu.setScale(1) # self.pikachu.setPos(0,0,1) # self.pikachu.place() self.Groudon = load_model("Groudon.egg") self.Groudon.reparentTo(render) self.Groudon.setPos(-50,0,0) # self.Groudon.place() def loadRalph(self): # Create the main character, Ralph basePath = r"../google_drive/ball/data/models/" ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor(basePath+"ralph",{"run":basePath+"ralph-run", "walk":basePath+"ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos) self.ralph.hide() def loadMusic(self, name="palette.mp3"): bgmusic = load_bgmusic(name) bgmusic.play() def keyControl(self): 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("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("w",self.setKey,["upward",1]) self.accept("w-up",self.setKey,["upward",0]) self.accept("s",self.setKey,["downward",1]) self.accept("s-up",self.setKey,["downward",0]) def displayInformation(self): self.title = addTitle("My Pokemon - Roam Mode") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[Arrow Keys]: Move") self.inst4 = addInstructions(0.85, "[w]: look up") self.inst4 = addInstructions(0.80, "[s]: look down") def __init__(self): self.keyMap = {"left":0, "right":0, "forward":0,"backward":0, "upward":0, "downward":0, "leftward":0,"rightward":0, "cam-left":0, "cam-right":0} # base.win.setClearColor(Vec4(0,0,0,1)) self.above = 3.0 # load sky box self.skyBoxLoad() # load environment self.loadEnviron() # load pokemon self.loadPokemon() # load ralph self.loadRalph() # load music self.loadMusic() self.displayInformation() self.keyControl() # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) taskMgr.add(self.move,"moveTask") taskMgr.add(self.setAbove,"setAbove") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(),self.ralph.getY(),2) self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,1000) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) def setAbove(self,task): if self.keyMap["upward"] == 1: self.above += 0.1 if self.keyMap["downward"] == 1: self.above -= 0.1 return task.cont #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"]!=0): self.ralph.setH(self.ralph.getH() + 113 * globalClock.getDt()) base.camera.setX(base.camera, +20 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - 113 * globalClock.getDt()) base.camera.setX(base.camera, -20 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.ralph.setY(self.ralph, -75 * globalClock.getDt()) if (self.keyMap["backward"] != 0): pass #self.ralph.setY(self.ralph, 75 * globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. 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.ralph.loop("run") self.isMoving = True else: if self.isMoving: #self.ralph.stop() #self.ralph.pose("walk",5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.0): base.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + self.above)#self.above) base.camera.lookAt(self.floater) return task.cont
class PandaPath(ShowBase): def __init__(self): # Set up the window, camera, etc. ShowBase.__init__(self) # Set the background color to black self.win.setClearColor((0, 0, 0, 1)) # This is used to store which keys are currently pressed. self.key_map = {"left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0} # Post the Instruction self.title = add_title("Panda 3D Demo") # Instructions self.inst1 = add_instructions(0.06, "[ESC]: Quit") self.inst2 = add_instructions(0.12, "[Left Arrow]: Rotate Left") self.inst3 = add_instructions(0.18, "[Right Arrow]: Rotate Ralph Right") self.inst4 = add_instructions(0.24, "[Up Arrow]: Run Ralph Forward") # self.inst6 = add_instructions(0.30, "[A]: Rotate Camera Left") # self.inst7 = add_instructions(0.36, "[S]: Rotate Camera Right") # Load the Environment Model self.environ = self.loader.loadModel(ENVIRONMENT) # Reparent the model to the render controller self.environ.reparentTo(render) # Apply scale and position transform on the model # self.environ.setScale(0.25, 0.25, 0.25) # self.environ.setPos(-8, 42, 0) # Create the Main Character # Load and transform the panda actor ralph_start_pos = self.environ.find("**/start_point").getPos() self.ralph = Actor(RALPH_ACTOR, RALPH_ACTIONS) # self.ralph.setScale(0.005, 0.005, 0.005) self.ralph.reparentTo(render) # Loop it's animation self.ralph.setScale(0.2) self.ralph.setPos(ralph_start_pos + (0, 0, 0.5)) # self.ralph.loop("walk") # Create a floater object, which floats 2 units above rlaph. We use this as a target for the camera to look at self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(self.ralph) # 2 Units above Ralph self.floater.setZ(2.0) # Configure the Camera # Add the spin camera taks procedure to the taks manager # self.taskMgr.add(self.spinCameraTask, "SpinCameraTask") # Accept certain control keys self.accept("escape", sys.exit) self.accept("arrow_left", self.set_key, ["left", True]) self.accept("arrow_right", self.set_key, ["right", True]) self.accept("arrow_up", self.set_key, ["forward", True]) self.accept("a", self.set_key, ["cam-left", True]) self.accept("s", self.set_key, ["cam-right", True]) self.accept("arrow_left-up", self.set_key, ["left", False]) self.accept("arrow_right-up", self.set_key, ["right", False]) self.accept("arrow_up-up", self.set_key, ["forward", False]) self.accept("a-up", self.set_key, ["cam-left", False]) self.accept("s-up", self.set_key, ["cam-right", False]) # Game States taskMgr.add(self.move, "moveTask") self.is_moving = False self.disableMouse() self.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 2) self.camera.lookAt(self.floater) """ Detect the height of hte terrain by creating a collision ray and casting it down towards the terrain. One ray will start above ralph's head and the other will start above the camera. A ray may hit the terrain, or it may hit a rock or a tree. If it hits the terrain we ca ndetect the height. If it hits anything else, we rule that the move is illegal. """ self.cTrav = CollisionTraverser() # Create a vector, it's location is at the top of ralph's head self.ralph_ground_ray = CollisionRay() self.ralph_ground_ray.setOrigin(0, 0, 9) # Top of ralph's head self.ralph_ground_ray.setDirection(0, 0, -1) # Points -Z axis # Create a Collision node self.ralph_ground_col = CollisionNode("ralph_ray") # Give the node a name self.ralph_ground_col.addSolid(self.ralph_ground_ray) # the vector from ralph's head to the ground is solid self.ralph_ground_col.setFromCollideMask(CollideMask.bit(0)) # ?? self.ralph_ground_col.setIntoCollideMask( CollideMask.allOff() ) # ?? This seems like it defines the behavior of ray self.ralph_ground_col_np = self.ralph.attachNewNode(self.ralph_ground_col) # Attach the ray to ralph self.ralph_ground_handler = ( CollisionHandlerQueue() ) # I think that when a collision occurs it sends through this self.cTrav.addCollider(self.ralph_ground_col_np, self.ralph_ground_handler) # Attach the collision """ Attach the a camera ray to the camera """ self.cam_ground_ray = CollisionRay() self.cam_ground_ray.setOrigin(0, 0, 9) self.cam_ground_ray.setDirection(0, 0, -1) self.cam_ground_col = CollisionNode("camera_ray") self.cam_ground_col.addSolid(self.cam_ground_ray) self.cam_ground_col.setFromCollideMask(CollideMask.bit(0)) self.cam_ground_col.setIntoCollideMask(CollideMask.allOff()) self.cam_ground_col_np = self.camera.attachNewNode(self.cam_ground_col) self.cam_ground_handler = CollisionHandlerQueue() self.cTrav.addCollider(self.cam_ground_col_np, self.cam_ground_handler) # Uncomment the following lines to view the rays self.ralph_ground_col_np.show() self.cam_ground_col_np.show() # Uncomment this line to show a visual representation of the Collision occuring self.cTrav.showCollisions(render) # Create some lighting ambient_light = AmbientLight("ambient_light") ambient_light.setColor((0.3, 0.3, 0.3, 1)) directional_light = DirectionalLight("directional_light") directional_light.setDirection((-5, -5, -5)) directional_light.setColor((1, 1, 1, 1)) directional_light.setSpecularColor((1, 1, 1, 1)) render.setLight(render.attachNewNode(ambient_light)) render.setLight(render.attachNewNode(directional_light)) # Add Cube X_OFFSET = 0 Y_OFFSET = -3 Z_OFFSET = 1 CUBE_SIZE = 2 x, y, z = ralph_start_pos x += X_OFFSET y += Y_OFFSET z += Z_OFFSET # make_cube(x, y, z, CUBE_SIZE) def set_key(self, key, value): self.key_map[key] = value def move(self, task): dt = globalClock.getDt() # print "DT: %f" % dt # ****: Movement # Get Ralph's position before we do anything to it start_pos = self.ralph.getPos() # User wants to turn if self.key_map["left"]: self.ralph.setH(self.ralph.getH() + 300 * dt) if self.key_map["right"]: self.ralph.setH(self.ralph.getH() - 300 * dt) # Perform a move forward if self.key_map["forward"]: self.ralph.setY(self.ralph, -25 * dt) # ****: Animation if self.key_map["forward"] or self.key_map["left"] or self.key_map["right"]: if not self.is_moving: self.ralph.loop("run") self.is_moving = True else: if self.is_moving: self.ralph.stop() self.ralph.pose("walk", 5) self.is_moving = False # ****: Camera Movement if self.key_map["cam-left"]: self.camera.setX(self.camera, -20 * dt) elif self.key_map["cam-right"]: self.camera.setX(self.camera, +20 * dt) # If the camera is too far from ralph, move it closer # If the camera is too close to ralph, move it farther camvec = self.ralph.getPos() - self.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if camdist > 10.0: self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if camdist < 5.0: self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist)) camdist - 5.0 # ****: Collision """ Normally, we would have to call traverse() to check for collisions. However, the class ShowBase that we inherit from has a task to do this for us If we assign a CollisionTraverser to self.cTrav Adjust ralph's Z coordinate. If ralph's ray hit terrain update his Z. If it hit anything else, or didn't hit anything put him back where he was last frame. """ entries = list(self.ralph_ground_handler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) # print "Entry count: %d" % len(entries) if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain": self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(start_pos) # Keep the camera at one foot above the terrain or two feet above ralph, whichever is greater entries = list(self.cam_ground_handler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain": self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if self.camera.getZ() < self.ralph.getZ() + 2.0: self.camera.setZ(self.ralph.getZ() + 2.0) """ The camera should look in rlaphs direction, but it should also try to stay horizontal so look at a floater which hovers above ralph's head """ self.camera.lookAt(self.floater) return task.cont
class World(ShowBase): def __init__(self): ShowBase.__init__(self) #PStatClient.connect() #self.lookPoint = NodePath(PandaNode("floater")) self.lookPoint = self.loader.loadModel("models/cone") self.lookPoint.reparentTo(render) self.menu = StartMenu(self) #self.bar = Bar() #self.messenger.toggleVerbose() #sys.exit() #pdb.set_trace() # Window change event handler #self.windowEventSetup() def setup(self): print("Init Levels...") self.initLevels() print("Init World...") self.initWorld("yard") print("Init Items...") self.initItems() print("Init Actors...") self.initActors() print("Init GUI ...") self.initGui() print("Init Lights...") self.initLights() print("Init Collisions...") self.initCollision() print("Init Tasks...") self.initTasks() print("Launching World") # Accept the control keys #self.accept("h", self.crono.start) def initItems(self): with open('items/items.json') as items_file: self.items = json.load(items_file) def initActors(self): self.player = Player(self, 20, 10, 10, 10, 10, 10) #app, hp, mana, strength, dexterity, vigor, magic): self.enemies = [] self.npcs = [] #Creating AI World self.AIworld = AIWorld(render) """self.foe1 = Enemy(self, 100, 50, 5, 2, "bug") #(self, app, hp, mana, speed, attackSpeed, name): self.nasgul = Enemy(self, 100, 50, 5, 2, "nasgul") self.npc1 = Npc(self, 100, 50, 5, 2, "guy2") self.npc2 = Npc(self, 100, 50, 5, 2, "ralph") self.enemies.append(self.foe1) self.enemies.append(self.nasgul) self.npcs.append(self.npc1) self.npcs.append(self.npc2)""" def initGui(self): # Load the models. self.inventory = Inventory(self) self.status = Status(self) self.skills = Skills(self) #self.statusBar = self.loader.loadModel("models/statusbar") ##self.statusBar.setDepthTest(True) #self.statusBar.setDepthWrite(True) # Reparent the model to render2d. #self.statusBar.reparentTo(self.render2d) #self.statusBar.setScale(0.15, 0.15, 0.15) #self.statusBar.setPos(-0.95, 0, 0.65) #self.crono = Crono(self) ##self.cursorpos = CursorPos(self) #self.playerpos = PlayerPos(self) #self.crono.draw(0.7, -0.85) #self.cursorpos.draw(0.0, -0.85) #self.playerpos.draw(-0.7, -0.85) self.accept("i", self.inventory.toggle) self.accept("c", self.status.toggle) self.accept("k", self.skills.toggle) def initTasks(self): #self.taskMgr.add(self.crono.task, "cronoTask") #self.taskMgr.add(self.cursorpos.task, "cursorposTask") ###self.taskMgr.add(self.playerpos.task, "playerposTask") self.taskMgr.add(self.checkCollision, "collisionTask") #self.taskMgr.add(self.player.update, "updateTask") self.taskMgr.add(self.player.move, "moveTask") self.taskMgr.add(self.player.updateCamera, "playerCameraTask",priority=1) """ #self.taskMgr.add(self.foe1.update, "bugTask",priority=1) #self.taskMgr.add(self.nasgul.update, "nasgulTask",priority=1) #self.taskMgr.add(self.npc1.update, "npc1Task",priority=1) #self.taskMgr.add(self.npc2.update, "npc2Task",priority=1) """ self.taskMgr.add(self.update, 'update') def initLights(self): # Create some lighting #self.environ.ls() #print(self.environ.findAllMatches("**/Spot")) ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(0.8, 0.8, 0.8, 0.65)) """ directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-10, -10, 5)) directionalLight.showFrustum() directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) dirnp = render.attachNewNode(directionalLight) dirnp.setPos(10, 0, 6) """ plight1 = PointLight('plight1') plight1.setColor(VBase4(1, 1, 1, 1)) plight1.showFrustum() #plight1.setShadowCaster(True) plnp1 = render.attachNewNode(plight1) plnp1.setPos(26.71, -33.2, 26) plight2 = PointLight('plight2') plight2.setColor(VBase4(1, 1, 1, 1)) plight2.showFrustum() plnp2 = render.attachNewNode(plight2) plnp2.setPos(-25, 25, 25) slight = Spotlight('slight') slight.setColor(VBase4(1, 1, 1, 1)) lens = PerspectiveLens() lens.setFilmSize(1, 1) # Or whatever is appropriate for your scene slight.setLens(lens) slight.setShadowCaster(True, 512, 512) slight.showFrustum() slnp = render.attachNewNode(slight) slnp.setPos(0, 0, 100) slnp.lookAt(Vec3(0,0,0)) render.setLight(slnp) render.setLight(plnp1) render.setLight(plnp2) #render.setLight(render.attachNewNode(ambientLight)) #render.setLight(dirnp) render.setShaderAuto() #render.setLight(render.attachNewNode(directionalLight)) """ self.light = render.attachNewNode(Spotlight("Spot")) self.light.node().setScene(render) self.light.node().setShadowCaster(True) self.light.node().showFrustum() self.light.node().getLens().setFov(40) self.light.node().getLens().setNearFar(10,100) render.setLight(self.light) """ def initLevels(self): with open('levels/levels.json') as levels_file: self.levels = json.load(levels_file) def initWorld(self, level): self.environ = self.loader.loadModel(self.levels["levels"][level]["model"]) #self.environ.setScale(20, 20, 20) #self.environ.setHpr(0, 0, 0) self.environ.setPos(0, 0, 0) self.playerStartPos = self.environ.find("**/startPos").getPos() # Reparent the model to render self.environ.reparentTo(render) #self.environ.ls() self.accept("q", self.changeMap) def destroyWorld(self): self.environ.detachNode() self.environ.removeNode() def changeMap(self):#, levelName): self.destroyWorld() self.initWorld("yard") def update(self, task): dt = globalClock.getDt() self.AIworld.update() return task.cont def setKey(self, key, value): self.keyMap[key] = value def windowEventSetup( self ): # accept the window event's self.accept( 'window-event', self.windowEventHandler) # create a window event yourself #messenger.send( 'window-event', [self.win] ) def windowEventHandler( self, window=None ): wp = window.getProperties() print("Window changed") print("X = %s" % wp.getXSize()) print("Y = %s" % wp.getYSize()) self.setResolution( wp.getXSize(), wp.getYSize() ) def setResolution( self, w, h ): wp = WindowProperties() wp.setSize( w, h ) if os.name == 'posix': self.openMainWindow() self.graphicsEngine.openWindows() self.win.requestProperties( wp ) # Define a procedure to move the camera. def spinCameraTask(self, task): angleDegrees = task.time * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.camera.setPos(40 * sin(angleRadians), -10.0 * cos(angleRadians), 3) self.camera.setHpr(angleDegrees, 0, 0) return Task.cont def initCollision(self): self.enemyGroundRay = [] self.enemyGroundCol = [] self.enemyGroundColNp = [] self.enemyGroundHandler = [] self.npcGroundRay = [] self.npcGroundCol = [] self.npcGroundColNp = [] self.npcGroundHandler = [] self.cTrav = CollisionTraverser() self.playerGroundRay = CollisionRay() self.playerGroundRay.setOrigin(0, 0, 9) self.playerGroundRay.setDirection(0, 0, -1) self.playerGroundCol = CollisionNode('playerRay') self.playerGroundCol.addSolid(self.playerGroundRay) self.playerGroundCol.setFromCollideMask(CollideMask.bit(0)) self.playerGroundCol.setIntoCollideMask(CollideMask.allOff()) self.playerGroundColNp = self.player.moveFloater.attachNewNode(self.playerGroundCol) self.playerGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.playerGroundColNp, self.playerGroundHandler) self.mouseGroundRay = CollisionRay() self.mouseGroundRay.setOrigin(0, 0, 9) self.mouseGroundRay.setDirection(0, 0, -1) self.mouseGroundCol = CollisionNode('mouseRay') self.mouseGroundCol.addSolid(self.mouseGroundRay) self.mouseGroundCol.setFromCollideMask(CollideMask.bit(0)) self.mouseGroundCol.setIntoCollideMask(CollideMask.allOff()) self.mouseGroundColNp = self.camera.attachNewNode(self.mouseGroundCol) self.mouseGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.mouseGroundColNp, self.mouseGroundHandler) # Uncomment this line to see the collision rays #self.playerGroundColNp.show() #self.mouseGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) i = 0 for enemy in self.enemies: self.enemyGroundRay.append(CollisionRay()) self.enemyGroundRay[i].setOrigin(0, 0, 9) self.enemyGroundRay[i].setDirection(0, 0, -1) self.enemyGroundCol.append(CollisionNode('%sRay' % enemy.name)) self.enemyGroundCol[i].addSolid(self.enemyGroundRay[i]) self.enemyGroundCol[i].setFromCollideMask(CollideMask.bit(0)) self.enemyGroundCol[i].setIntoCollideMask(CollideMask.allOff()) self.enemyGroundColNp.append(enemy.enemyActor.attachNewNode(self.enemyGroundCol[i])) self.enemyGroundHandler.append(CollisionHandlerQueue()) self.cTrav.addCollider(self.enemyGroundColNp[i], self.enemyGroundHandler[i]) #self.enemyGroundColNp.show() i += 1 i = 0 for npc in self.npcs: self.npcGroundRay.append(CollisionRay()) self.npcGroundRay[i].setOrigin(0, 0, 9) self.npcGroundRay[i].setDirection(0, 0, -1) self.npcGroundCol.append(CollisionNode('%sRay' % npc.name)) self.npcGroundCol[i].addSolid(self.npcGroundRay[i]) self.npcGroundCol[i].setFromCollideMask(CollideMask.bit(0)) self.npcGroundCol[i].setIntoCollideMask(CollideMask.allOff()) self.npcGroundColNp.append(npc.npcActor.attachNewNode(self.npcGroundCol[i])) self.npcGroundHandler.append(CollisionHandlerQueue()) self.cTrav.addCollider(self.npcGroundColNp[i], self.npcGroundHandler[i]) #self.npcGroundColNp.show() i += 1 def checkCollision(self, task): startpos = self.player.moveFloater.getPos() entries = list(self.playerGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) for entry in entries: if entry > 0 and entries[0].getIntoNode().getName() == "Ground": self.player.moveFloater.setZ(entry.getSurfacePoint(render).getZ()) else: self.player.moveFloater.setPos(startpos) if self.mouseWatcherNode.hasMouse(): mpos = self.mouseWatcherNode.getMouse() self.mouseGroundRay.setFromLens(self.camNode, mpos.getX(), mpos.getY()) nearPoint = render.getRelativePoint(self.camera, self.mouseGroundRay.getOrigin()) nearVec = render.getRelativeVector(self.camera, self.mouseGroundRay.getDirection()) try: self.lookPoint.setPos(PointAtZ(self.player.moveFloater.getZ(), nearPoint, nearVec)) except: pass i = 0 for enemy in self.enemies: startpos = enemy.enemyActor.getPos() entries = list(self.enemyGroundHandler[i].getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) for entry in entries: if entry > 0: # and entries[0].getIntoNode().getName() == "Ground": enemy.enemyActor.setZ(entry.getSurfacePoint(render).getZ()) else: enemy.enemyActor.setPos(startpos) i += 1 i = 0 for npc in self.npcs: startpos = npc.npcActor.getPos() entries = list(self.npcGroundHandler[i].getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) for entry in entries: if entry > 0: # and entries[0].getIntoNode().getName() == "Ground": npc.npcActor.setZ(entry.getSurfacePoint(render).getZ()) else: npc.npcActor.setPos(startpos) i += 1 return task.cont
class Collision(): def __init__(self,ui): self.ui = ui; # Find the collision node named wall_collide self.walls = self.ui.maze.find("**/wall_collide") self.walls.node().setIntoCollideMask(BitMask32.bit(0)) # CollisionNodes are usually invisible but can be shown. # self.walls.show() # We will now find the triggers for the holes and set their masks to 0 as # well. We also set their names to make them easier to identify during # collisions self.loseTriggers = [] for i in range(6): trigger = self.ui.maze.find("**/hole_collide" + str(i)) trigger.node().setIntoCollideMask(BitMask32.bit(0)) trigger.node().setName("loseTrigger") self.loseTriggers.append(trigger) # Uncomment this line to see the triggers # trigger.show() # Ground_collide is a single polygon on the same plane as the ground in the # maze. We will use a ray to collide with it so that we will know exactly # what height to put the ball at every frame. Since this is not something # that we want the ball itself to collide with, it has a different # bitmask. self.mazeGround = self.ui.maze.find("**/ground_collide") self.mazeGround.node().setIntoCollideMask(BitMask32.bit(1)) # Find the collison sphere for the ball which was created in the egg file # Notice that it has a from collision mask of bit 0, and an into collison # mask of no bits. This means that the ball can only cause collisions, not # be collided into self.ballSphere = self.ui.ball.find("**/ball") self.ballSphere.node().setFromCollideMask(BitMask32.bit(0)) self.ballSphere.node().setIntoCollideMask(BitMask32.allOff()) # No we create a ray to start above the ball and cast down. This is to # Determine the height the ball should be at and the angle the floor is # tilting. We could have used the sphere around the ball itself, but it # would not be as reliable self.ballGroundRay = CollisionRay() # Create the ray self.ballGroundRay.setOrigin(0,0,10) # Set its origin self.ballGroundRay.setDirection(0,0,-1) # And its direction # Collision solids go in CollisionNode self.ballGroundCol = CollisionNode('groundRay') # Create and name the node self.ballGroundCol.addSolid(self.ballGroundRay) # Add the ray self.ballGroundCol.setFromCollideMask(BitMask32.bit(1)) # Set its bitmasks self.ballGroundCol.setIntoCollideMask(BitMask32.allOff()) # Attach the node to the ballRoot so that the ray is relative to the ball # (it will always be 10 feet over the ball and point down) self.ballGroundColNp = self.ui.ballRoot.attachNewNode(self.ballGroundCol) # Uncomment this line to see the ray # self.ballGroundColNp.show() # Finally, we create a CollisionTraverser. CollisionTraversers are what # do the job of calculating collisions self.cTrav = CollisionTraverser() # Collision traverservs tell collision handlers about collisions, and then # the handler decides what to do with the information. We are using a # CollisionHandlerQueue, which simply creates a list of all of the # collisions in a given pass. There are more sophisticated handlers like # one that sends events and another that tries to keep collided objects # apart, but the results are often better with a simple queue self.cHandler = CollisionHandlerQueue() # Now we add the collision nodes that can create a collision to the # traverser. The traverser will compare these to all others nodes in the # scene. There is a limit of 32 CollisionNodes per traverser # We add the collider, and the handler to use as a pair self.cTrav.addCollider(self.ballSphere, self.cHandler) self.cTrav.addCollider(self.ballGroundColNp, self.cHandler)
class World(ShowBase): def __init__(self): # Load the default configuration.prc. This is recommended, as it # contains some important panda options loadPrcFile("../../Config/configuration.prc") ShowBase.__init__(self) # Create a new pipeline instance self.renderPipeline = RenderingPipeline(self) # Set the base path for the pipeline. This is required as we are in # a subdirectory self.renderPipeline.getMountManager().setBasePath("../../") # Also set the write path self.renderPipeline.getMountManager().setWritePath("../../Temp/") # Load the default settings self.renderPipeline.loadSettings("../../Config/pipeline.ini") # Now create the pipeline self.renderPipeline.create() # Add a directional light dPos = Vec3(40, 40, 15) dirLight = DirectionalLight() dirLight.setPos(dPos * 1000000.0) dirLight.setShadowMapResolution(1024) dirLight.setCastsShadows(True) dirLight.setColor(Vec3(8)) self.renderPipeline.addLight(dirLight) self.renderPipeline.setScatteringSource(dirLight) self.dirLight = dirLight self.keyMap = { "left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0 } base.win.setClearColor(Vec4(0, 0, 0, 1)) # Post the instructions self.title = addTitle( "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.85, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.80, "[Up Arrow]: Run Ralph Forward") self.inst6 = addInstructions(0.70, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.65, "[S]: Rotate Camera Right") # Set up the environment # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0, 0, 0) self.environ.find("**/wall").removeNode() # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", { "run": "models/ralph-run", "walk": "models/ralph-walk" }) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos) self.renderPipeline.setEffect(self.ralph, "Effects/Default/Default.effect", {"dynamic": True}) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation 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]) # NOTICE: It is important that your update tasks have a lower priority # than -10000 taskMgr.add(self.move, "moveTask", priority=-20000) self.accept("r", self.reloadShader) # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 1.2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 1000) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays # self.ralphGroundColNp.show() # self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring # self.cTrav.showCollisions(render) # Create some ocean self.water = ProjectedWaterGrid(self.renderPipeline) self.water.setWaterLevel(-3.0) # Create the skybox self.skybox = self.renderPipeline.getDefaultSkybox() self.skybox.reparentTo(render) self.prepareSRGB(render) self.reloadShader() self.renderPipeline.onSceneInitialized() # Add demo slider to move the sun position if self.renderPipeline.settings.displayOnscreenDebugger: self.renderPipeline.guiManager.demoSlider.node[ "command"] = self.setSunPos self.renderPipeline.guiManager.demoSlider.node["value"] = 50 def setSunPos(self): rawValue = self.renderPipeline.guiManager.demoSlider.node["value"] dPos = Vec3(100, 100, rawValue - 20) self.dirLight.setPos(dPos * 100000000.0) def reloadShader(self): self.renderPipeline.reloadShaders() # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value def prepareSRGB(self, np): """ Sets the correct texture format for all textures found in <np> """ for tex in np.findAllTextures(): baseFormat = tex.getFormat() if baseFormat == Texture.FRgb: tex.setFormat(Texture.FSrgb) elif baseFormat == Texture.FRgba: tex.setFormat(Texture.FSrgbAlpha) else: print "Unkown texture format:", baseFormat print "\tTexture:", tex # tex.setMinfilter(Texture.FTLinearMipmapLinear) # tex.setMagfilter(Texture.FTLinear) tex.setAnisotropicDegree(16) # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) 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()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"] != 0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"] != 0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"] != 0): self.ralph.setY(self.ralph, -25 * globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.keyMap["forward"] != 0) or (self.keyMap["left"] != 0) or (self.keyMap["right"] != 0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 7.0): base.camera.setPos(base.camera.getPos() + camvec * (camdist - 7)) camdist = 7.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.5): base.camera.setZ(self.ralph.getZ() + 2.5) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) return task.cont
class Game(ShowBase): def __init__(self): # Set up the window, camera, etc. ShowBase.__init__(self) # Set the background color to black self.win.setClearColor(BACKGROUND_COLOR) # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) # Create the main character playerStartPos = self.environ.find("**/start_point").getPos() self.player = Actor("models/player", {"run": "models/player-run", "walk": "models/player-walk"}) self.player.reparentTo(render) self.player.setScale(.2) self.player.setPos(playerStartPos + (0, 0, 0.5)) # Create a floater object, which floats 2 units above player. We # use this as a target for the camera to look at. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(self.player) self.floater.setZ(CAMERA_TARGET_HEIGHT_DELTA) self.first_person = False def key_dn(name): return lambda: self.setKey(name, True) def key_up(name): return lambda: self.setKey(name, False) def quit(): self.destroy() def toggle_first(): self.first_person = not self.first_person # Accept the control keys for movement and rotation key_map = [ # key command action help # --- ------- ------ ---- ("escape", "esc", lambda: quit(), '[ESC]: Quit'), ("arrow_left", 'left', key_dn("left"), "[Left Arrow]: Rotate Left"), ("arrow_left-up", 'left', key_up("left"), None), ("arrow_right", 'right', key_dn("right"), "[Right Arrow]: Rotate Right"), ("arrow_right-up", 'right', key_up("right"), None), ("arrow_up", 'forward', key_dn("forward"), "[Up Arrow]: Run Forward"), ("arrow_up-up", 'forward', key_up("forward"), None), ("arrow_down", 'backward', key_dn("backward"), "[Down Arrow]: Run Backward"), ("arrow_down-up", 'backward', key_up("backward"), None), ("a", 'cam-left', key_dn("cam-left"), "[A]: Rotate Camera Left"), ("a-up", 'cam-left', key_up("cam-left"), None), ("s", 'cam-right', key_dn("cam-right"), "[S]: Rotate Camera Right"), ("s-up", 'cam-right', key_up("cam-right"), None), ('f', 'first-pers', lambda: toggle_first(), '[F]: Toggle first-person'), ] self.keyMap = {} inst = Instructions() for key, command, action, description in key_map: if command: self.setKey(command, False) self.accept(key, action) if description: inst.add(description) taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera self.disableMouse() self.camera.setPos(self.player.getX(), self.player.getY() + 10, 2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above player's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.playerGroundRay = CollisionRay() self.playerGroundRay.setOrigin(0, 0, 9) self.playerGroundRay.setDirection(0, 0, -1) self.playerGroundCol = CollisionNode('playerRay') self.playerGroundCol.addSolid(self.playerGroundRay) self.playerGroundCol.setFromCollideMask(CollideMask.bit(0)) self.playerGroundCol.setIntoCollideMask(CollideMask.allOff()) self.playerGroundColNp = self.player.attachNewNode(self.playerGroundCol) self.playerGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.playerGroundColNp, self.playerGroundHandler) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0, 0, 9) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(CollideMask.bit(0)) self.camGroundCol.setIntoCollideMask(CollideMask.allOff()) self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays self.playerGroundColNp.show() self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection((-5, -5, -5)) directionalLight.setColor((1, 1, 1, 1)) directionalLight.setSpecularColor((1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # Get the time that elapsed since last frame. We multiply this with # the desired speed in order to find out with which distance to move # in order to achieve that desired speed. dt = globalClock.getDt() # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. if self.keyMap["cam-left"]: self.camera.setX(self.camera, -20 * dt) if self.keyMap["cam-right"]: self.camera.setX(self.camera, +20 * dt) # save player's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.player.getPos() # If a move-key is pressed, move player in the specified direction. if self.keyMap["left"]: self.player.setH(self.player.getH() + 300 * dt) if self.keyMap["right"]: self.player.setH(self.player.getH() - 300 * dt) if self.keyMap["forward"]: self.player.setY(self.player, -25 * dt) if self.keyMap["backward"]: self.player.setY(self.player, 25 * dt) # If player is moving, loop the run animation. # If he is standing still, stop the animation. if self.keyMap["forward"] or self.keyMap["backward"] or self.keyMap["left"] or self.keyMap["right"]: if self.isMoving is False: self.player.loop("run") self.isMoving = True else: if self.isMoving: self.player.stop() self.player.pose("walk", 5) self.isMoving = False # If the camera is too far from player, move it closer. # If the camera is too close to player, move it farther. if self.first_person: self.camera.setPos(self.player.getPos()) else: camvec = self.player.getPos() - self.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if camdist > CAMERA_DISTANCE_MAX: self.camera.setPos(self.camera.getPos() + camvec * (camdist - int(CAMERA_DISTANCE_MAX))) camdist = CAMERA_DISTANCE_MAX if camdist < CAMERA_DISTANCE_MIN: self.camera.setPos(self.camera.getPos() - camvec * (int(CAMERA_DISTANCE_MIN) - camdist)) camdist = CAMERA_DISTANCE_MIN # Normally, we would have to call traverse() to check for collisions. # However, the class ShowBase that we inherit from has a task to do # this for us, if we assign a CollisionTraverser to self.cTrav. self.cTrav.traverse(render) # Adjust player's Z coordinate. If player's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = list(self.playerGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain": self.player.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.player.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above player, whichever is greater. entries = list(self.camGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain": self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + CAMERA_POSITION_HEIGHT_DELTA_MIN) if self.camera.getZ() < self.player.getZ() + CAMERA_POSITION_HEIGHT_DELTA_MAX: self.camera.setZ(self.player.getZ() + CAMERA_POSITION_HEIGHT_DELTA_MAX) # The camera should look in player's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above player's head. self.camera.lookAt(self.floater) return task.cont
class World(DirectObject): def __init__(self): self.keyMap = {"left":0, "right":0, "forward":0, "back":0, "cam-left":0, "cam-right":0} self.flag1=0 self.flag2=0 self.flag3=0 self.flag4=0 self.count=0 self.health = 100 self.points = -5 self.flagd=1 self.player_points = 0 base.win.setClearColor(Vec4(0,0,0,1)) self.mySound=base.loader.loadSfx("sounds/trial.mp3") self.mySound.play() self.title = addTitle("Bumping Cars") #Full Screen props = WindowProperties.getDefault() w=base.pipe.getDisplayWidth() h=base.pipe.getDisplayHeight() props.setSize(w,h) props.setFullscreen(True) props.setCursorHidden(True) base.win.requestProperties(props) # Load World self.environ = loader.loadModel("models/world.egg") self.environ.reparentTo(render) self.environ.setPos(0,0,0) #Load Sky self.sky = loader.loadModel("models/clouds.egg") self.sky.reparentTo(render) self.sky.setPos(60,0,-450) # Create Player Car carStartPos = self.environ.find("**/start_point").getPos() self.car = Actor("models/carnsx") self.car.reparentTo(render) self.car.setScale(0.25) #self.car.place() self.car.setPos(carStartPos) # Create Enemy Car 1 enemyCarStartPos1 = (-108,-1,-.5) self.car1 = Actor("models/enemy_cars/monstercar/carmonster") self.car1.reparentTo(render) self.car1.setScale(0.25) #self.car1.place() self.car1.setPos(enemyCarStartPos1) # Create Enemy Car 2 enemyCarStartPos2 = (-104,-26,-.02) self.car2 = Actor("models/enemy_cars/yugo/yugo") self.car2.reparentTo(render) self.car2.setScale(0.15) #self.car2.place() self.car2.setPos(enemyCarStartPos2) # Create Enemy Car 3 enemyCarStartPos3 = (-111,-26,0) self.car3 = Actor("models/enemy_cars/truck/cartruck") self.car3.reparentTo(render) self.car3.setScale(0.25) #self.car3.place() self.car3.setPos(enemyCarStartPos3) # Create Enemy Car 4 enemyCarStartPos4 = (-111,-2,-.5) self.car4 = Actor("models/enemy_cars/truck/cartruck-purple") self.car4.reparentTo(render) self.car4.setScale(0.25) #self.car4.place() self.car4.setPos(enemyCarStartPos4) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation self.accept("escape", sys.exit) self.accept("a", self.setKey, ["cam-left",1]) self.accept("s", self.setKey, ["cam-right",1]) self.accept("arrow_up",self.setKey, ["forward",1]) self.accept("arrow_left",self.setKey, ["left",1]) self.accept("arrow_down",self.setKey, ["back",1]) self.accept("arrow_right",self.setKey, ["right",1]) self.accept("a-up", self.setKey, ["cam-left",0]) self.accept("s-up", self.setKey, ["cam-right",0]) self.accept("arrow_up-up",self.setKey, ["forward",0]) self.accept("arrow_left-up",self.setKey, ["left",0]) self.accept("arrow_right-up",self.setKey, ["right",0]) self.accept("arrow_down-up",self.setKey, ["back",0]) taskMgr.add(self.move,"moveTask") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.car.getX(),self.car.getY()+10,2) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) # AI self.AIworld = AIWorld(render) # AI Car 1 self.AIchar1 = AICharacter("car1",self.car1, 70, 0.1, 3) self.AIworld.addAiChar(self.AIchar1) self.AIbehaviors1 = self.AIchar1.getAiBehaviors() self.AIbehaviors1.pursue(self.car) # AI Car 2 self.AIchar2 = AICharacter("car2",self.car2, 180, 0.1, 1) self.AIworld.addAiChar(self.AIchar2) self.AIbehaviors2 = self.AIchar2.getAiBehaviors() self.AIbehaviors2.pursue(self.car4) # AI Car 3 self.AIchar3 = AICharacter("car3",self.car3, 70, 0.1, 3) self.AIworld.addAiChar(self.AIchar3) self.AIbehaviors3 = self.AIchar3.getAiBehaviors() self.AIbehaviors3.pursue(self.car) # AI Car 4 self.AIchar4 = AICharacter("car4",self.car4, 200, 0.5, 2) self.AIworld.addAiChar(self.AIchar4) self.AIbehaviors4 = self.AIchar4.getAiBehaviors() self.AIbehaviors4.pursue(self.car3) # Obstacle avoidance self.AIbehaviors1.obstacleAvoidance(1.0) self.AIworld.addObstacle(self.car2) self.AIworld.addObstacle(self.car3) self.AIworld.addObstacle(self.car4) self.AIbehaviors2.obstacleAvoidance(1.0) self.AIbehaviors3.obstacleAvoidance(1.0) self.AIbehaviors4.obstacleAvoidance(1.0) #AI World update taskMgr.add(self.AIUpdate,"AIUpdate") self.cTrav = CollisionTraverser() #self.cTrav.showCollisions(render) self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,1000) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.carGroundColNp = self.car.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.carGroundColNp, self.ralphGroundHandler) #car1 self.car1Ray = CollisionSphere(0,0,0,4) self.car1GroundCol = CollisionNode('car1Ray') self.car1GroundCol.addSolid(self.car1Ray) self.car1GroundCol.setFromCollideMask(BitMask32.bit(0)) self.car1GroundCol.setIntoCollideMask(BitMask32.allOff()) self.car1GroundColNp = self.car.attachNewNode(self.car1GroundCol) self.car1GroundHandler = CollisionHandlerQueue() #self.car1GroundColNp.show() self.cTrav.addCollider(self.car1GroundColNp, self.car1GroundHandler) cnodePath = self.car1.attachNewNode(CollisionNode('cnode1')) cnodePath.node().addSolid(self.car1Ray) #cnodePath.show() #car2 self.car2Ray = CollisionSphere(0,0,0,4) self.car2GroundCol = CollisionNode('car2Ray') self.car2GroundCol.addSolid(self.car2Ray) self.car2GroundCol.setFromCollideMask(BitMask32.bit(0)) self.car2GroundCol.setIntoCollideMask(BitMask32.allOff()) self.car2GroundColNp = self.car.attachNewNode(self.car2GroundCol) self.car2GroundHandler = CollisionHandlerQueue() #self.car2GroundColNp.show() self.cTrav.addCollider(self.car2GroundColNp, self.car2GroundHandler) cnodePath = self.car2.attachNewNode(CollisionNode('cnode2')) cnodePath.node().addSolid(self.car2Ray) #cnodePath.show() #car3 self.car3Ray = CollisionSphere(0,0,0,4) self.car3GroundCol = CollisionNode('car3Ray') self.car3GroundCol.addSolid(self.car3Ray) self.car3GroundCol.setFromCollideMask(BitMask32.bit(0)) self.car3GroundCol.setIntoCollideMask(BitMask32.allOff()) self.car3GroundColNp = self.car.attachNewNode(self.car3GroundCol) self.car3GroundHandler = CollisionHandlerQueue() #self.car3GroundColNp.show() self.cTrav.addCollider(self.car3GroundColNp, self.car3GroundHandler) cnodePath = self.car3.attachNewNode(CollisionNode('cnode3')) cnodePath.node().addSolid(self.car3Ray) #cnodePath.show() #car4 self.car4Ray = CollisionSphere(0,0,0,4) self.car4GroundCol = CollisionNode('car4Ray') self.car4GroundCol.addSolid(self.car4Ray) self.car4GroundCol.setFromCollideMask(BitMask32.bit(0)) self.car4GroundCol.setIntoCollideMask(BitMask32.allOff()) self.car4GroundColNp = self.car.attachNewNode(self.car4GroundCol) self.car4GroundHandler = CollisionHandlerQueue() #self.car4GroundColNp.show() self.cTrav.addCollider(self.car4GroundColNp, self.car4GroundHandler) cnodePath = self.car4.attachNewNode(CollisionNode('cnode4')) cnodePath.node().addSolid(self.car4Ray) #cnodePath.show() #camera 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) def onCollision(self, entry): print("123") def displayHealth(self): healthBar['scale'] = (self.health*0.01*BAR_WIDTH,0.2,0.2) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value def makezero4(self,task): self.flag4=0 def makezero3(self,task): self.flag3=0 #to update the AIWorld def AIUpdate(self,task): self.AIworld.update() return task.cont def makezero1(self,task): self.flag1=0 def makezero2(self,task): self.flag2=0 def move(self, task): if (self.flagd==1): self.points = self.points + globalClock.getDt() self.player_points = int(self.points) printPointObj(self.player_points) #print int(self.points) base.camera.lookAt(self.car) 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()) # save car's initial position so that we can restore it, # in case he falls off the map or runs into something. startposcar = self.car.getPos() # If a move-key is pressed, move the car in the specified direction. if (self.keyMap["left"]!=0): self.car.setH(self.car.getH() + 100 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.car.setH(self.car.getH() - 100 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.car.setY(self.car, -40 * globalClock.getDt()) if (self.keyMap["back"]!=0): self.car.setY(self.car, 40 * globalClock.getDt()) if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0) or (self.keyMap["back"]!=0): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.car.stop() self.isMoving = False # If the camera is too far from the car, move it closer. # If the camera is too close to the car, move it farther. camvec = self.car.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.car.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.car.setPos(startposcar) entries=[] for i in range(self.car1GroundHandler.getNumEntries()): entry = self.car1GroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "cnode1") and (self.flag1==0): #print "car1" self.flag1=1 self.health=self.health - 10 printHealthObj(self.health) print "car1" taskMgr.doMethodLater(5,self.makezero1,"flag1") entries=[] for i in range(self.car2GroundHandler.getNumEntries()): entry = self.car2GroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "cnode2") and (self.flag2==0): #print "car2" self.flag2=1 self.health=self.health - 10 printHealthObj(self.health) print "car2" taskMgr.doMethodLater(5,self.makezero2,"flag2") entries=[] for i in range(self.car3GroundHandler.getNumEntries()): entry = self.car3GroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "cnode3") and (self.flag3==0): #print "car3" self.flag3=1 self.health=self.health - 10 printHealthObj(self.health) print "car3" taskMgr.doMethodLater(5,self.makezero3,"flag3") entries=[] for i in range(self.car4GroundHandler.getNumEntries()): entry = self.car4GroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "cnode4") and (self.flag4==0): #print "car4" self.flag4=1 self.health=self.health - 10 printHealthObj(self.health) print "car4" taskMgr.doMethodLater(5,self.makezero4,"flag4") entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) if (base.camera.getZ() < self.car.getZ() + 2.0): base.camera.setZ(self.car.getZ() + 2.0) if self.health <= 0: self.flagd=0 frame=DirectFrame(image=r"end.jpg",frameSize=(-3, 3, -3, 3)) textObject1 = OnscreenText(text = 'You Died!', pos = (0, 0.7), scale = 0.22) textObject2 = OnscreenText(text = 'Press ESC to Exit', pos = (0,0.9), scale=0.1) b = DirectButton(text="Exit Game",scale=0.1,command = sys.exit) textObject3 = OnscreenText(text = 'Your Score: ' + str(self.player_points), pos = (-0.2, -0.9), scale = 0.22) self.floater.setPos(self.car.getPos()) self.floater.setZ(self.car.getZ() + 2.0) base.camera.lookAt(self.floater) self.displayHealth() return task.cont
class World(ShowBase): def __init__(self): # Load the default configuration.prc. This is recommended, as it # contains some important panda options loadPrcFile("../../Config/configuration.prc") ShowBase.__init__(self) # Create a new pipeline instance self.renderPipeline = RenderingPipeline(self) # Set the base path for the pipeline. This is required as we are in # a subdirectory self.renderPipeline.getMountManager().setBasePath("../../") # Also set the write path self.renderPipeline.getMountManager().setWritePath("../../Temp/") # Load the default settings self.renderPipeline.loadSettings("../../Config/pipeline.ini") # Now create the pipeline self.renderPipeline.create() # Add a directional light dPos = Vec3(40, 40, 15) dirLight = DirectionalLight() dirLight.setPos(dPos * 1000000.0) dirLight.setShadowMapResolution(1024) dirLight.setCastsShadows(True) dirLight.setColor(Vec3(8)) self.renderPipeline.addLight(dirLight) self.renderPipeline.setScatteringSource(dirLight) self.dirLight = dirLight self.keyMap = { "left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0} base.win.setClearColor(Vec4(0, 0, 0, 1)) # Post the instructions self.title = addTitle( "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.85, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.80, "[Up Arrow]: Run Ralph Forward") self.inst6 = addInstructions(0.70, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.65, "[S]: Rotate Camera Right") # Set up the environment # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0, 0, 0) self.environ.find("**/wall").removeNode() # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", {"run": "models/ralph-run", "walk": "models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos) self.renderPipeline.setEffect(self.ralph, "Effects/Default/Default.effect", { "dynamic": True }) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation 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]) # NOTICE: It is important that your update tasks have a lower priority # than -10000 taskMgr.add(self.move, "moveTask", priority=-20000) self.accept("r", self.reloadShader) # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 1.2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 1000) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays # self.ralphGroundColNp.show() # self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring # self.cTrav.showCollisions(render) # Create some ocean self.water = ProjectedWaterGrid(self.renderPipeline) self.water.setWaterLevel(-4.0) # Create the skybox self.skybox = self.renderPipeline.getDefaultSkybox() self.skybox.reparentTo(render) self.prepareSRGB(render) self.reloadShader() self.renderPipeline.onSceneInitialized() # Add demo slider to move the sun position if self.renderPipeline.settings.displayOnscreenDebugger: self.renderPipeline.guiManager.demoSlider.node[ "command"] = self.setSunPos self.renderPipeline.guiManager.demoSlider.node[ "value"] = 50 def setSunPos(self): rawValue = self.renderPipeline.guiManager.demoSlider.node["value"] dPos = Vec3(100, 100, rawValue - 20) self.dirLight.setPos(dPos * 100000000.0) def reloadShader(self): self.renderPipeline.reloadShaders() # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value def prepareSRGB(self, np): """ Sets the correct texture format for all textures found in <np> """ for tex in np.findAllTextures(): baseFormat = tex.getFormat() if baseFormat == Texture.FRgb: tex.setFormat(Texture.FSrgb) elif baseFormat == Texture.FRgba: tex.setFormat(Texture.FSrgbAlpha) else: print "Unkown texture format:", baseFormat print "\tTexture:", tex # tex.setMinfilter(Texture.FTLinearMipmapLinear) # tex.setMagfilter(Texture.FTLinear) tex.setAnisotropicDegree(16) # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) 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()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"] != 0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"] != 0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"] != 0): self.ralph.setY(self.ralph, -25 * globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.keyMap["forward"] != 0) or (self.keyMap["left"] != 0) or (self.keyMap["right"] != 0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 7.0): base.camera.setPos(base.camera.getPos() + camvec * (camdist - 7)) camdist = 7.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x, y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x, y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.5): base.camera.setZ(self.ralph.getZ() + 2.5) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) return task.cont
class PlayerObject(): def __init__(self, render, username, x, y, z, h): self.username = username self.isMoving = False self.render = render self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0} self.actor = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.actor.reparentTo(render) self.actor.setScale(0.2) self.actor.setPos(x, y, z) self.actor.setH(h) self.cTrav = CollisionTraverser() self.GroundRay = CollisionRay() self.GroundRay.setOrigin(0,0,1000) self.GroundRay.setDirection(0,0,-1) self.GroundCol = CollisionNode('actorRay') self.GroundCol.addSolid(self.GroundRay) self.GroundCol.setFromCollideMask(BitMask32.bit(0)) self.GroundCol.setIntoCollideMask(BitMask32.allOff()) self.GroundColNp = self.actor.attachNewNode(self.GroundCol) self.GroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.GroundColNp, self.GroundHandler) """ @Marvin Move moves the player around the map based on Must be called from a task to function properly Currently set up to take in random test data Non-random will have keys supplied from client input """ def move(self, key): actor = self.actor startpos = actor.getPos() if (key==0): actor.setH(actor.getH() + 300 * globalClock.getDt()) if (key==1): actor.setH(actor.getH() - 300 * globalClock.getDt()) if (key==2): actor.setY(actor, -25 * globalClock.getDt()) if (key==0) or (key==1) or (key==2): if self.isMoving is False: actor.loop("run") self.isMoving = True else: if self.isMoving: actor.stop() actor.pose("walk",5) self.isMoving = False self.cTrav.traverse(render) entries = [] for i in range(self.GroundHandler.getNumEntries()): entry = self.GroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.actor.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.actor.setPos(startpos) """
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 App(ShowBase): def __init__(self): ShowBase.__init__(self) base.disableMouse() #Carrega o terreno self.terrain = loadCharEnvir().loadEnvir() #Declaracao de variaveis self.isMoving = False self.getClick = 0 #Quantos objetos foram clicados self.clickedObj = None self.terrainSize = 1024 self.numLizards = 5 self.numMaleLizards = 0 self.numFemaleLizards = 0 #self.contChamGetMed = 0 #Contador para saber se atualiza o ponto medio #Carrega os lagartos iniciais self.lizards = [] for i in range(self.numLizards): randNum = random.randint(10,20) randNum2 = random.randint(10,20) lizard = loadCharEnvir().loadLizard(100 + (randNum+randNum2)*i,150 + (randNum+randNum2)*i,3) lizard.setTag("ID",str(i)) self.lizards.append(lizard) if (lizard.getTag("femaleOrMale") == "1"): self.numMaleLizards = self.numMaleLizards + 1 else: self.numFemaleLizards = self.numFemaleLizards + 1 #Calcula o ponto medio dos lagartos, tanto femeas quantos machos self.getMedianGenderPoints() #taskMgr.add(self.getCloserToMedian, "Aproxima os lagartos do ponto medio dos generos") #Adiciona as tasks e as funcoes de teclado e mouse self.taskMgr.add(self.updateTask, "update") self.keyboardSetup() #CAMERAS: #Faz a camera seguir o lagarto #self.followcam = FollowCam(self.camera, self.lizards[0]) #Faz a camera visualizar como um deus self.MoveCam = MoveCam(self.camera) #Ativa as colisoes self.setupMouseCollision() #Funcao que ajusta o angulo def clampAngle(self, angle): while angle < -180: angle = angle + 360 while angle > 180: angle = angle -360 return angle #Atribui um valor especifico para uma chave def keyboardSetup(self): self.keyMap = {"left":0, "right":0, "forward":0, "backward":0} self.accept("escape", sys.exit) 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("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("mouse1", self.leftMouseCommands) #Pode ser adicionado um drag aqui self.accept("mouse3", self.rightMouseCommands) #Funcao que calcula o ponto medio da densidade de lagartos de cada genero def getMedianGenderPoints(self): self.medianMalePoint = (0,0,0) self.medianFemalePoint = (0,0,0) #Calculo do somatorio dos pontos para cada genero for i in range(self.numLizards): if (self.lizards[i].getTag("femaleOrMale") == "1"): self.medianMalePoint = self.lizards[i].getPos() + self.medianMalePoint else: self.medianFemalePoint = self.lizards[i].getPos() + self.medianFemalePoint #Calculo do ponto medio de cada genero if (self.numMaleLizards != 0): self.medianMalePoint = (self.medianMalePoint[0]/self.numMaleLizards, self.medianMalePoint[1]/self.numMaleLizards, self.medianMalePoint[2]/self.numMaleLizards) if (self.numFemaleLizards != 0): self.medianFemalePoint = (self.medianFemalePoint[0]/self.numFemaleLizards, self.medianFemalePoint[1]/self.numFemaleLizards, self.medianFemalePoint[2]/self.numFemaleLizards) #===================================================================================== #NAO ESTA PRONTA // NAO FUNCIONA #Funcao que faz com que os lagartos, dependendo do genero, aproximem-se #===================================================================================== """ def getCloserToMedian(self, task): maleMedianPoint = render.attachNewNode("male median point") maleMedianPoint.setPos(self.medianMalePoint) femaleMedianPoint = render.attachNewNode("female median point") femaleMedianPoint.setPos(self.medianFemalePoint) for i in range(self.numLizards): #Se for macho, procura for femeas if (self.lizards[i].getTag("femaleOrMale") == 1): lizardAuxPoint = render.attachNewNode("ponto auxiliar para obter heading") lizardAuxPoint.setPos(self.lizards[i].getPos()) lizardAuxPoint.lookAt(femaleMedianPoint) self.lizards[i].setH(self.clampAngle(lizardAuxPoint.getH() + 180)) self.lizards[i].setPos(self.lizards[i], self.lizards[i].getRelativeVector(femaleMedianPoint, Vec3(0.1,-0.1,0))) print self.lizards[i].getRelativeVector(femaleMedianPoint, Vec3(0.1,-0.1,0)) #Respeitando os limites do terreno if (self.lizards[i].getX() < 0): self.lizards[i].setX(0) elif (self.lizards[i].getX() > self.terrainSize): self.lizards[i].setX(self.terrainSize) if (self.lizards[i].getY() < 0): self.lizards[i].setY(0) elif (self.lizards[i].getY() > self.terrainSize): self.lizards[i].setY(self.terrainSize) #Se for femea, procura por machos else: self.lizards[i].lookAt(maleMedianPoint) self.lizards[i].setPos(self.lizards[i], self.lizards[i].getRelativeVector(maleMedianPoint, Vec3(0.1,-0.1,0))) #Respeitando os limites do terreno if (self.lizards[i].getX() < 0): self.lizards[i].setX(0) elif (self.lizards[i].getX() > self.terrainSize): self.lizards[i].setX(self.terrainSize) if (self.lizards[i].getY() < 0): self.lizards[i].setY(0) elif (self.lizards[i].getY() > self.terrainSize): self.lizards[i].setY(self.terrainSize) #Faz uma atualizacao pra saber se deve atualizar o ponto medio self.contChamGetMed = self.contChamGetMed + 1 if (self.contChamGetMed == 1000): self.contChamGetMed = 0 self.getMedianGenderPoints() return task.cont""" #===================================================================================== #A ATRIBUICAO DO BOTAO DIREITO SERA COMPLETAMENTE REFEITA, E ESTA SERVE APENAS PARA ILUSTRAR A IDEIA #ESTA ATRIBUICAO ESTA ERRADA #===================================================================================== def rightMouseCommands(self): if self.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() if (self.clickedObj != None): self.moveCharacter(mpos.getX(), mpos.getY()) #FUNCAO PROVISORIA: #FALTA AJUSTAR - COMO FAZER PARA OPERAR AS ENTRADAS SEPARADAMENTE? def moveCharacter(self, posX, posY): self.mClickRay.setFromLens(self.camNode, posX, posY) self.mClicker.traverse(self.render) if (self.mCollisionQue.getNumEntries() > 0): self.mCollisionQue.sortEntries() entry = self.mCollisionQue.getEntry(0) self.target = render.attachNewNode("target point") self.target.setPos(2*self.clickedObj.getX() - entry.getSurfacePoint(render).getX(), 2*self.clickedObj.getY() - entry.getSurfacePoint(render).getY(), entry.getSurfacePoint(render).getZ()) self.finalPosY = self.target.getY() self.finalPosX = self.target.getX() finalHeading = render.attachNewNode("final heading") finalHeading.setPos(self.clickedObj.getPos()) finalHeading.lookAt(self.target.getPos()) self.Heading = finalHeading.getH() self.Heading = self.clampAngle(self.Heading) if (self.Heading-self.clickedObj.getH() > 150): turnTime = 4 else: if (self.Heading-self.clickedObj.getH() > 100): turnTime = 3 else: if (self.Heading-self.clickedObj.getH() > 50): turnTime = 2 else: if (self.Heading-self.clickedObj.getH() < -50): turnTime = 2 else: if (self.Heading-self.clickedObj.getH() < -100): turnTime = 3 else: if (self.Heading-self.clickedObj.getH() < -150): turnTime = 4 else: turnTime = 1 self.deltaSX = self.target.getX()-self.clickedObj.getX() self.deltaSY = self.target.getY()-self.clickedObj.getY() self.deltaS = sqrt((self.target.getY()-self.clickedObj.getY())*(self.target.getY()-self.clickedObj.getY()) + (self.target.getX()-self.clickedObj.getX())*(self.target.getX()-self.clickedObj.getX())) t = self.deltaS/3 changeHeading = self.clickedObj.hprInterval(turnTime, (self.Heading,0,0), (self.clickedObj.getH(),0,0)) changePos = self.clickedObj.posInterval(t, self.target.getPos(), self.clickedObj.getPos()) self.clickedObj.loop("walk", restart = 0) self.counter = 0 moveInterv = Sequence(changeHeading, Func(self.stopAnimation)) moveInterv.start() def stopAnimation(self): taskMgr.add(self.movingCharacter, "moving character") def movingCharacter(self,task): if self.counter < 130: self.clickedObj.setX(self.clickedObj.getX() - self.deltaSX/130) self.clickedObj.setY(self.clickedObj.getY() - self.deltaSY/130) self.counter = self.counter + 1 return task.cont else: self.clickedObj.stop() taskMgr.remove("moving character") #===================================================================================== #===================================================================================== #===================================================================================== #Atribui valor a uma chave def setKey(self, key, value): self.keyMap[key] = value #Atualiza o game def updateTask(self, task): self.updateLizard() return Task.cont #Funcao do botao esquerdo do mouse def leftMouseCommands(self): if self.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.mClickRay.setFromLens(self.camNode, mpos.getX(), mpos.getY()) self.mClicker.traverse(self.render) if (self.mCollisionQue.getNumEntries() > 0): self.mCollisionQue.sortEntries() entry = self.mCollisionQue.getEntry(0) clickedObject = entry.getIntoNodePath() clickedObject = clickedObject.findNetTag("clickable") if not clickedObject.isEmpty(): pos = entry.getSurfacePoint(self.render) self.getClick = 1 clickedObjectId = clickedObject.findNetTag("ID") self.clickedObjId = clickedObjectId #Procura o lagarto clicado for i in range(self.numLizards): if (self.lizards[i].getTag("ID") == self.clickedObjId.getTag("ID")): self.clickedObj = self.lizards[i] return else: #Zera se nao houverem objetos clicaveis proximos self.getClick = 0 #Define a colisao do mouse com objetos no terreno def setupMouseCollision(self): self.mClicker = CollisionTraverser() self.mCollisionQue = CollisionHandlerQueue() self.mClickRay = CollisionRay() self.mClickRay.setOrigin(self.camera.getPos(self.render)) self.mClickRay.setDirection(render.getRelativeVector(camera, Vec3(0,1,0))) self.mClickNode = CollisionNode('clickRay') self.mClickNode.addSolid(self.mClickRay) self.mClickNP = self.camera.attachNewNode(self.mClickNode) self.mClickNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.mClicker.addCollider(self.mClickNP, self.mCollisionQue) #Atualiza o personagem se algum botao foi pressionado #POSTERIORMENTE SERA RETIRADA - ESTA AQUI APENAS PARA DEBUG/EXEMPLIFICACAO def updateLizard(self): speedFactor = 3 if (self.getClick != 0): #Se o personagem esta se mexendo, rode a animacao #BUG - Se o jogador estiver pressionando o botao de andar enquanto muda de personagem, trava a animacao 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.clickedObj.loop("walk", restart = 0) self.isMoving = True else: if self.isMoving: self.clickedObj.stop() self.isMoving = False #if (self.clicked != None): if (self.keyMap["left"]!=0): self.clickedObj.setH(self.clickedObj.getH()+1) elif (self.keyMap["right"]!=0): self.clickedObj.setH(self.clickedObj.getH()-1) if (self.keyMap["forward"]!=0): self.clickedObj.setY(self.clickedObj, -speedFactor) elif (self.keyMap["backward"]!=0): self.clickedObj.setY(self.clickedObj, speedFactor) #Respeitando os limites do terreno if (self.clickedObj.getX() < 0): self.clickedObj.setX(0) elif (self.clickedObj.getX() > self.terrainSize): self.clickedObj.setX(self.terrainSize) if (self.clickedObj.getY() < 0): self.clickedObj.setY(0) elif (self.clickedObj.getY() > self.terrainSize): self.clickedObj.setY(self.terrainSize)
class App(ShowBase): def __init__(self): ShowBase.__init__(self) base.disableMouse() #Carrega o terreno self.terrain = loadCharEnvir().loadEnvir() #Declaracao de variaveis self.isMoving = False self.getClick = 0 #Quantos objetos foram clicados self.clickedObj = None self.terrainSize = 1024 self.numLizards = 5 self.numMaleLizards = 0 self.numFemaleLizards = 0 #self.contChamGetMed = 0 #Contador para saber se atualiza o ponto medio #Carrega os lagartos iniciais self.lizards = [] for i in range(self.numLizards): randNum = random.randint(10, 20) randNum2 = random.randint(10, 20) lizard = loadCharEnvir().loadLizard(100 + (randNum + randNum2) * i, 150 + (randNum + randNum2) * i, 3) lizard.setTag("ID", str(i)) self.lizards.append(lizard) if (lizard.getTag("femaleOrMale") == "1"): self.numMaleLizards = self.numMaleLizards + 1 else: self.numFemaleLizards = self.numFemaleLizards + 1 #Calcula o ponto medio dos lagartos, tanto femeas quantos machos self.getMedianGenderPoints() #taskMgr.add(self.getCloserToMedian, "Aproxima os lagartos do ponto medio dos generos") #Adiciona as tasks e as funcoes de teclado e mouse self.taskMgr.add(self.updateTask, "update") self.keyboardSetup() #CAMERAS: #Faz a camera seguir o lagarto #self.followcam = FollowCam(self.camera, self.lizards[0]) #Faz a camera visualizar como um deus self.MoveCam = MoveCam(self.camera) #Ativa as colisoes self.setupMouseCollision() #Funcao que ajusta o angulo def clampAngle(self, angle): while angle < -180: angle = angle + 360 while angle > 180: angle = angle - 360 return angle #Atribui um valor especifico para uma chave def keyboardSetup(self): self.keyMap = {"left": 0, "right": 0, "forward": 0, "backward": 0} self.accept("escape", sys.exit) 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("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("mouse1", self.leftMouseCommands) #Pode ser adicionado um drag aqui self.accept("mouse3", self.rightMouseCommands) #Funcao que calcula o ponto medio da densidade de lagartos de cada genero def getMedianGenderPoints(self): self.medianMalePoint = (0, 0, 0) self.medianFemalePoint = (0, 0, 0) #Calculo do somatorio dos pontos para cada genero for i in range(self.numLizards): if (self.lizards[i].getTag("femaleOrMale") == "1"): self.medianMalePoint = self.lizards[i].getPos( ) + self.medianMalePoint else: self.medianFemalePoint = self.lizards[i].getPos( ) + self.medianFemalePoint #Calculo do ponto medio de cada genero if (self.numMaleLizards != 0): self.medianMalePoint = (self.medianMalePoint[0] / self.numMaleLizards, self.medianMalePoint[1] / self.numMaleLizards, self.medianMalePoint[2] / self.numMaleLizards) if (self.numFemaleLizards != 0): self.medianFemalePoint = (self.medianFemalePoint[0] / self.numFemaleLizards, self.medianFemalePoint[1] / self.numFemaleLizards, self.medianFemalePoint[2] / self.numFemaleLizards) #===================================================================================== #NAO ESTA PRONTA // NAO FUNCIONA #Funcao que faz com que os lagartos, dependendo do genero, aproximem-se #===================================================================================== """ def getCloserToMedian(self, task): maleMedianPoint = render.attachNewNode("male median point") maleMedianPoint.setPos(self.medianMalePoint) femaleMedianPoint = render.attachNewNode("female median point") femaleMedianPoint.setPos(self.medianFemalePoint) for i in range(self.numLizards): #Se for macho, procura for femeas if (self.lizards[i].getTag("femaleOrMale") == 1): lizardAuxPoint = render.attachNewNode("ponto auxiliar para obter heading") lizardAuxPoint.setPos(self.lizards[i].getPos()) lizardAuxPoint.lookAt(femaleMedianPoint) self.lizards[i].setH(self.clampAngle(lizardAuxPoint.getH() + 180)) self.lizards[i].setPos(self.lizards[i], self.lizards[i].getRelativeVector(femaleMedianPoint, Vec3(0.1,-0.1,0))) print self.lizards[i].getRelativeVector(femaleMedianPoint, Vec3(0.1,-0.1,0)) #Respeitando os limites do terreno if (self.lizards[i].getX() < 0): self.lizards[i].setX(0) elif (self.lizards[i].getX() > self.terrainSize): self.lizards[i].setX(self.terrainSize) if (self.lizards[i].getY() < 0): self.lizards[i].setY(0) elif (self.lizards[i].getY() > self.terrainSize): self.lizards[i].setY(self.terrainSize) #Se for femea, procura por machos else: self.lizards[i].lookAt(maleMedianPoint) self.lizards[i].setPos(self.lizards[i], self.lizards[i].getRelativeVector(maleMedianPoint, Vec3(0.1,-0.1,0))) #Respeitando os limites do terreno if (self.lizards[i].getX() < 0): self.lizards[i].setX(0) elif (self.lizards[i].getX() > self.terrainSize): self.lizards[i].setX(self.terrainSize) if (self.lizards[i].getY() < 0): self.lizards[i].setY(0) elif (self.lizards[i].getY() > self.terrainSize): self.lizards[i].setY(self.terrainSize) #Faz uma atualizacao pra saber se deve atualizar o ponto medio self.contChamGetMed = self.contChamGetMed + 1 if (self.contChamGetMed == 1000): self.contChamGetMed = 0 self.getMedianGenderPoints() return task.cont""" #===================================================================================== #A ATRIBUICAO DO BOTAO DIREITO SERA COMPLETAMENTE REFEITA, E ESTA SERVE APENAS PARA ILUSTRAR A IDEIA #ESTA ATRIBUICAO ESTA ERRADA #===================================================================================== def rightMouseCommands(self): if self.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() if (self.clickedObj != None): self.moveCharacter(mpos.getX(), mpos.getY()) #FUNCAO PROVISORIA: #FALTA AJUSTAR - COMO FAZER PARA OPERAR AS ENTRADAS SEPARADAMENTE? def moveCharacter(self, posX, posY): self.mClickRay.setFromLens(self.camNode, posX, posY) self.mClicker.traverse(self.render) if (self.mCollisionQue.getNumEntries() > 0): self.mCollisionQue.sortEntries() entry = self.mCollisionQue.getEntry(0) self.target = render.attachNewNode("target point") self.target.setPos( 2 * self.clickedObj.getX() - entry.getSurfacePoint(render).getX(), 2 * self.clickedObj.getY() - entry.getSurfacePoint(render).getY(), entry.getSurfacePoint(render).getZ()) self.finalPosY = self.target.getY() self.finalPosX = self.target.getX() finalHeading = render.attachNewNode("final heading") finalHeading.setPos(self.clickedObj.getPos()) finalHeading.lookAt(self.target.getPos()) self.Heading = finalHeading.getH() self.Heading = self.clampAngle(self.Heading) if (self.Heading - self.clickedObj.getH() > 150): turnTime = 4 else: if (self.Heading - self.clickedObj.getH() > 100): turnTime = 3 else: if (self.Heading - self.clickedObj.getH() > 50): turnTime = 2 else: if (self.Heading - self.clickedObj.getH() < -50): turnTime = 2 else: if (self.Heading - self.clickedObj.getH() < -100): turnTime = 3 else: if (self.Heading - self.clickedObj.getH() < -150): turnTime = 4 else: turnTime = 1 self.deltaSX = self.target.getX() - self.clickedObj.getX() self.deltaSY = self.target.getY() - self.clickedObj.getY() self.deltaS = sqrt((self.target.getY() - self.clickedObj.getY()) * (self.target.getY() - self.clickedObj.getY()) + (self.target.getX() - self.clickedObj.getX()) * (self.target.getX() - self.clickedObj.getX())) t = self.deltaS / 3 changeHeading = self.clickedObj.hprInterval( turnTime, (self.Heading, 0, 0), (self.clickedObj.getH(), 0, 0)) changePos = self.clickedObj.posInterval(t, self.target.getPos(), self.clickedObj.getPos()) self.clickedObj.loop("walk", restart=0) self.counter = 0 moveInterv = Sequence(changeHeading, Func(self.stopAnimation)) moveInterv.start() def stopAnimation(self): taskMgr.add(self.movingCharacter, "moving character") def movingCharacter(self, task): if self.counter < 130: self.clickedObj.setX(self.clickedObj.getX() - self.deltaSX / 130) self.clickedObj.setY(self.clickedObj.getY() - self.deltaSY / 130) self.counter = self.counter + 1 return task.cont else: self.clickedObj.stop() taskMgr.remove("moving character") #===================================================================================== #===================================================================================== #===================================================================================== #Atribui valor a uma chave def setKey(self, key, value): self.keyMap[key] = value #Atualiza o game def updateTask(self, task): self.updateLizard() return Task.cont #Funcao do botao esquerdo do mouse def leftMouseCommands(self): if self.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.mClickRay.setFromLens(self.camNode, mpos.getX(), mpos.getY()) self.mClicker.traverse(self.render) if (self.mCollisionQue.getNumEntries() > 0): self.mCollisionQue.sortEntries() entry = self.mCollisionQue.getEntry(0) clickedObject = entry.getIntoNodePath() clickedObject = clickedObject.findNetTag("clickable") if not clickedObject.isEmpty(): pos = entry.getSurfacePoint(self.render) self.getClick = 1 clickedObjectId = clickedObject.findNetTag("ID") self.clickedObjId = clickedObjectId #Procura o lagarto clicado for i in range(self.numLizards): if (self.lizards[i].getTag("ID") == self.clickedObjId.getTag("ID")): self.clickedObj = self.lizards[i] return else: #Zera se nao houverem objetos clicaveis proximos self.getClick = 0 #Define a colisao do mouse com objetos no terreno def setupMouseCollision(self): self.mClicker = CollisionTraverser() self.mCollisionQue = CollisionHandlerQueue() self.mClickRay = CollisionRay() self.mClickRay.setOrigin(self.camera.getPos(self.render)) self.mClickRay.setDirection( render.getRelativeVector(camera, Vec3(0, 1, 0))) self.mClickNode = CollisionNode('clickRay') self.mClickNode.addSolid(self.mClickRay) self.mClickNP = self.camera.attachNewNode(self.mClickNode) self.mClickNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.mClicker.addCollider(self.mClickNP, self.mCollisionQue) #Atualiza o personagem se algum botao foi pressionado #POSTERIORMENTE SERA RETIRADA - ESTA AQUI APENAS PARA DEBUG/EXEMPLIFICACAO def updateLizard(self): speedFactor = 3 if (self.getClick != 0): #Se o personagem esta se mexendo, rode a animacao #BUG - Se o jogador estiver pressionando o botao de andar enquanto muda de personagem, trava a animacao 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.clickedObj.loop("walk", restart=0) self.isMoving = True else: if self.isMoving: self.clickedObj.stop() self.isMoving = False #if (self.clicked != None): if (self.keyMap["left"] != 0): self.clickedObj.setH(self.clickedObj.getH() + 1) elif (self.keyMap["right"] != 0): self.clickedObj.setH(self.clickedObj.getH() - 1) if (self.keyMap["forward"] != 0): self.clickedObj.setY(self.clickedObj, -speedFactor) elif (self.keyMap["backward"] != 0): self.clickedObj.setY(self.clickedObj, speedFactor) #Respeitando os limites do terreno if (self.clickedObj.getX() < 0): self.clickedObj.setX(0) elif (self.clickedObj.getX() > self.terrainSize): self.clickedObj.setX(self.terrainSize) if (self.clickedObj.getY() < 0): self.clickedObj.setY(0) elif (self.clickedObj.getY() > self.terrainSize): self.clickedObj.setY(self.terrainSize)
class World(DirectObject): def __init__(self): self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cWriter = ConnectionWriter(self.cManager, 0) host = "localhost" port = 9898 self.connection = self.cManager.openTCPClientConnection(host, port, 10000) #self.received = 1 #store a dictionary of active players with username player as key value pair #the dictionary also contain a special player named panda self.players = {} #for display the list on the screen self.temp = [] #store a dictionary of playerObject self.playerObjects = {} self.render = render self.loginSuccessful = False self.isMoving = False self.justStoping = False self.targetPlayer = None if self.connection: self.cReader.addConnection(self.connection) taskMgr.add(self.updateRoutine, 'updateRoutine') #taskMgr.doMethodLater(0.5, self.updateRoutine, 'updateRoutine') #taskMgr.add(self.updatePandaAttack, 'updatePandaAttack') #taskMgr.doMethodLater(3, self.updatePandaAttack, 'updatePandaAttack') self.loginRegister() #################Communication Method################ def loginRegister(self): print "1. Login" print "2. Register" userInput = str(raw_input("Enter 1 or 2: ")) if userInput == "1": self.login() elif userInput == "2": self.register(); else: print "Invalid input" self.loginRegister() def register(self): print "Please enter your username: "******"Please enter your password: "******"{} {} {}".format(REGISTER, username, password) self.sendRequest(msg) #define self.username to specify the username for this object def login(self): print "Please enter your username: "******"Please enter your password: "******"{} {} {}".format(LOGIN, self.username, password) self.sendRequest(msg) #user need to press esc key to logout def logout(self, x, y, z, h): print "logout called" player = self.players[self.username] msg = "{} {},{},{},{},{}".format(LOGOUT, self.username, player.getX(), player.getY(), player.getZ(), player.getH()) print msg self.sendRequest(msg) sys.exit() def updateMovement(self, isMove, x, y, z, h): #send code username,ismove,x,y,z,h to the server according to the protocol msg = "{} {},{},{},{},{},{}".format(UPDATE_PLAYER_MOVE, self.username, isMove, x, y, z, h) self.sendRequest(msg) def possibleAttackRequest(self, distance): msg = "{} {},{}".format(PANDA_ATTACK_REQUEST, self.username, distance) self.sendRequest(msg) def composeStringMessage(self, msg): myPyDatagram = PyDatagram() myPyDatagram.addString(msg) return myPyDatagram def retrieveStringMessage(self,datagram): myIterator = PyDatagramIterator(datagram) msg = myIterator.getString() #print msg, " received" return msg # def sendRequest(self): # if(self.received): # print "->Client request:" # # Send a request to the server # mylist = ["apple", "ball", "cat", "dog"] # # msg = random.choice(mylist) # request = self.composeStringMessage(msg) # ack = self.cWriter.send(request,self.connection) # print msg, " sent" # self.received = 0 def sendRequest(self, msg): request = self.composeStringMessage(msg) ack = self.cWriter.send(request,self.connection) #print msg, " sent" #self.received = 0 def receiveResponse(self): #print "<-Server response:" while self.cReader.dataAvailable(): datagram = NetDatagram() # Retrieve the contents of the datagram. if self.cReader.getData(datagram): msg = self.retrieveStringMessage(datagram) msgs = msg.split(' ') #print msgs[0] if msgs[0] == REGISTER_SUCCESSFUL: self.registerSuccessfulResponse() elif msgs[0] == USERNAME_EXIST: self.usernameExistResponse() elif msgs[0] == LOGIN_SUCCESSFUL: self.loginSuccessfulResponse(msgs[1]) elif msgs[0] == ADD_NEW_PLAYER: self.addNewPlayerResponse(msgs[1]) elif msgs[0] == LOGIN_FAIL: self.loginFailResponse() elif msgs[0] == LOGOUT: self.logoutResponse(msgs[1]) elif msgs[0] == UPDATE_PLAYER_MOVE_RESPONSE: self.updateMoveResponse(msgs[1]) elif msgs[0] == PANDA_ATTACK: self.pandaAttackResponse(msgs[1]) #self.received = 1 # def communicate(self): # #print "communicate" # #self.sendRequest() # self.receiveResponse() def updateRoutine(self,task): #self.communicate() self.receiveResponse() return task.again; def registerSuccessfulResponse(self): print "You have successfully registered. Please login to start the game." self.login() def usernameExistResponse(self): print "Username already exist. Please choose another username." self.register() #initail a dictionary of players def loginSuccessfulResponse(self, playerListMsg): actorsMsg = playerListMsg.split(":") #the dictionary also adds a special player named panda for aMsg in actorsMsg: elements = aMsg.split(",") actor = Player(elements[0], float(elements[1]), float(elements[2]), float(elements[3]), float(elements[4])) self.players[elements[0]] = actor print "login successful" #display other players' Ralph for username, value in self.players.iteritems(): if username == self.username: #display this player's Ralph self.showRalph(value) elif username != self.username and username != "panda": self.createActor(self.render, value) elif username == "panda": self.createPanda(self.render, value) else: pass self.loginSuccessful = True #add new player to the players dictionary def addNewPlayerResponse(self, msg): elements = msg.split(",") actor = Player(elements[0], float(elements[1]), float(elements[2]), float(elements[3]), float(elements[4])) self.players[elements[0]] = actor print "add new player: ", self.players[elements[0]].getUsername(), self.players[elements[0]].getX() self.createActor(self.render, actor) ###Line's Added### textMsg = elements[0]+" has logged in" self.notifyPlayer(textMsg) def loginFailResponse(self): print "Username and password does not match, please re-login or register." self.loginRegister() def logoutResponse(self, username): if username in self.players: del self.players[username] if username in self.playerObjects: playerObject = self.playerObjects[username] playerObject.getActor().delete() del self.playerObjects[username] #self.playerObjects print "{} logout".format(username) ###Lines Added### msg = username+" has logged out" self.notifyPlayer(msg) def notifyPlayer(self,msg): #label = DirectLabel(text=msg) label = OnscreenText(text=msg, style=1, fg=(1,1,1,1), pos=(1.3,-0.95), align=TextNode.ARight, scale = .07) taskMgr.doMethodLater(5, self.destroyLabel, 'destroyLabel', extraArgs=[label]) def destroyLabel(self,label): label.destroy() def updateMoveResponse(self, msg): if self.loginSuccessful: #msg contain username,isMoving,x,y,z,h msgs = msg.split(",") username = msgs[0] if username == self.username: #self already move, no need to update pass else: if username in self.playerObjects.keys(): player = self.players[username] player.setX(float(msgs[2])) player.setY(float(msgs[3])) player.setZ(float(msgs[4])) actor = self.playerObjects[username].getActor() actor.setPos(float(msgs[2]), float(msgs[3]), float(msgs[4])) actor.setH(float(msgs[5])) self.playerObjects[username].move(msgs[1]) def pandaAttackResponse(self, msg): #msg contain targetUsername #print "pan Att: ", msg #msgs = msg.split(",") targetUsername = msg targetPlayer = self.players[targetUsername] pandaActor = self.pandaObject.getActor() pandax = pandaActor.getX() panday = pandaActor.getY() pandaz = pandaActor.getZ() x = targetPlayer.getX() y = targetPlayer.getY() z = targetPlayer.getZ() distance = self.getDistance(pandax, panday, pandaz, x, y, z) if distance < PANDA_ATTACK_RANGE: if pandax > x and panday > y: self.pandaObject.setH(135) elif pandax > x and panday < y: self.pandaObject.setH(180) elif pandax < x and panday > y: self.pandaObject.setH(135) else: self.pandaObject.setH(90) #self.pandaObject.turn(180) self.pandaObject.move(x-0.5, y-0.5, z) panda = self.players["panda"] panda.setX(pandax); panda.setY(panday); panda.setZ(pandaz); #self.setTargetPlayer(msg) def setTargetPlayer(self, username): self.targetPlayer = self.players[username] def getTargetPlayer(self): return self.targetPlayer def createActor(self, render, actor): playerObject = PlayerObject(render, actor) self.playerObjects[actor.getUsername()] = playerObject # nameplate = TextNode('textNode username_' + str(actor.username)) # nameplate.setText(actor.username) # npNodePath = actor.actor.attachNewNode(nameplate) # npNodePath.setScale(1.0) # npNodePath.setBillboardPointEye() # npNodePath.setZ(8.0) def createPanda(self, render, actor): self.pandaObject = PandaObject(render, actor) def checkPossibleAttack(self, x, y, z): panda = self.players["panda"] pandax = panda.getX(); panday = panda.getY(); pandaz = panda.getZ(); distance = self.getDistance(pandax, panday, pandaz, x, y, z) if distance < PANDA_ATTACK_RANGE: self.possibleAttackRequest(distance) def getDistance(self, pandax, panday, pandaz, x, y, z): return math.sqrt( math.pow(pandax-x, 2) + math.pow(panday-y, 2) + math.pow(pandaz-z, 2) ) ################################################################# ################Ralph code ##################### def showRalph(self, player): # self.render = render self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0} base.win.setClearColor(Vec4(0,0,0,1)) # Post the instructions #self.title = addTitle("Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.85, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.80, "[Up Arrow]: Run Ralph Forward") self.inst6 = addInstructions(0.70, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.65, "[S]: Rotate Camera Right") self.inst8 = addInstructions(0.60, "[l] Show Players on the right corner") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0,0,0) # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) #self.ralph.setPos(ralphStartPos) self.ralph.setPos(player.getX(), player.getY(), player.getZ()) self.ralph.setH(player.getH()) ##################################### # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation #self.accept("escape", sys.exit) self.accept("escape", self.logout, [self.ralph.getX(), self.ralph.getY(), self.ralph.getZ(), self.ralph.getH()]) 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]) taskMgr.add(self.move,"moveTask") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(),self.ralph.getY()+10,2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,1000) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value '''method to show player list''' def showPlayers(self, set): for i in self.temp: i.destroy() self.temp = [] y=[] i = 0 while(i!=set.__len__()): y.append(0.95-(i*0.05)) i=i+1 i = 0 while(i!=y.__len__()): if set[i] == "panda": pass else: self.temp.append(OnscreenText(text=set[i], style=1, fg=(1,1,1,1), pos=(1.3, y[i]), align=TextNode.ARight, scale = .07)) i=i+1 # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): '''Call to Show player list''' x = self.players.keys() self.accept("l", self.showPlayers, [x]) ''' call end ''' # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) 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()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"]!=0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.ralph.setY(self.ralph, -25 * globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True self.justStoping = False else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk",5) self.isMoving = False self.justStoping = True #print self.ralph.getX(), self.ralph.getY(), self.ralph.getZ(), self.ralph.getH() if(self.isMoving or self.justStoping): self.updateMovement(self.isMoving, self.ralph.getX(), self.ralph.getY(), self.ralph.getZ(), self.ralph.getH()) #check if in panda attach range self.checkPossibleAttack(self.ralph.getX(), self.ralph.getY(), self.ralph.getZ()) player = self.players[self.username] player.setX(self.ralph.getX()) player.setY(self.ralph.getY()) player.setZ(self.ralph.getZ()) player.setH(self.ralph.getH()) self.justStoping = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.0): base.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) return task.cont
class Labryn(DirectObject): def keyControl(self): # get user input self.accept("escape", sys.exit) # ESC to quit self.accept("arrow_up",self.moveBallWrapper,["u"]) self.accept("arrow_down",self.moveBallWrapper,["d"]) self.accept("arrow_left",self.moveBallWrapper,["l"]) self.accept("arrow_right",self.moveBallWrapper,["r"]) self.accept("arrow_up_up",self.moveBallWrapper,[False]) self.accept("arrow_down_up",self.moveBallWrapper,[False]) self.accept("arrow_left_up",self.moveBallWrapper,[False]) self.accept("arrow_right_up",self.moveBallWrapper,[False]) self.accept("r", self.setCamera, [True]) self.accept("r-up", self.setCamera, [False]) def setCamera(self, spin): self.spin = spin def spinCamera(self, task): if self.spin == True: self.cameraSpinCount += 1 count = self.cameraSpinCount angleDegrees = count angleRadians = angleDegrees * (pi/ 180) camera.setPos(12*cos(-pi/2+angleRadians), 12*sin(-pi/2+angleRadians), 25) camera.setHpr(angleDegrees,-65,0) return Task.cont def initialize(self): self.loadBackground(_BGIMG) self.loadMyPokemon() base.disableMouse() camera.setPosHpr(0,-12,25,0,-65,0) self.arrowKeyPressed = False self.pokemonDirection = None # direction the ball is going self.jerkDirection = None self.spin = False self.cameraSpinCount = 0 self.jerk = (0,0,0) self.loadLabyrinth() self.keyControl() self.loadPokemonLevel1() self.light() self.loadBall() def loadBackground(self, imagePath): self.background = OnscreenImage(parent=render2dp, image=imagePath) base.cam2dp.node().getDisplayRegion(0).setSort(-20) def loadMyPokemon(self, pokes=['caterpie', 'charmander', 'geodude']): path = r"../google_drive/ball/data/img/myPoke" pokePath = path + r"/%s" %(pokes[0]) + r".png" poke = OnscreenImage(parent=aspect2d, image=pokePath, pos=(1,0,-0.8), scale=(0.16,1,0.12)) poke.setTransparency(TransparencyAttrib.MAlpha) def loadLabyrinth(self): self.MAZE = load_model("3.egg") self.MAZE.reparentTo(render) self.MAZE.setPos(0,0,0) self.MAZE.setHpr(90,0,0) def loadPokemonLevel1(self): self.pikachu = load_model("pikachu.egg") self.pikachu.reparentTo(render) self.pikachu.setScale(0.3) endPos = self.MAZE.find("**/end").getPos() self.pikachu.setPos(endPos) def light(self): ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) def loadBall(self): self.ballRoot = render.attachNewNode("ballRoot") self.ball = load_model("ball") self.ball.reparentTo(self.ballRoot) self.ball_tex = load_tex("pokeball.png") self.ball.setTexture(self.ball_tex,1) self.ball.setScale(0.8) # Find the collision sphere for the ball in egg. self.ballSphere = self.ball.find("**/ball") self.ballSphere.node().setFromCollideMask(BitMask32.bit(0)) self.ballSphere.node().setIntoCollideMask(BitMask32.allOff()) #self.ballSphere.show() # Now we create a ray to cast down at the ball. self.ballGroundRay = CollisionRay() self.ballGroundRay.setOrigin(0,0,10) self.ballGroundRay.setDirection(0,0,-1) # Collision solids go in CollisionNode self.ballGroundCol = CollisionNode('groundRay') self.ballGroundCol.addSolid(self.ballGroundRay) self.ballGroundCol.setFromCollideMask(BitMask32.bit(1)) self.ballGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ballGroundColNp = self.ballRoot.attachNewNode(self.ballGroundCol) # light ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.55, .55, .55, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0,0,-1)) directionalLight.setColor(Vec4(0.375,0.375,0.375,1)) directionalLight.setSpecularColor(Vec4(1,1,1,1)) self.ballRoot.setLight(render.attachNewNode(ambientLight)) self.ballRoot.setLight(render.attachNewNode(directionalLight)) # material to the ball m = Material() m.setSpecular(Vec4(1,1,1,1)) m.setShininess(96) self.ball.setMaterial(m,1) def __init__(self): self.initialize() self.WALLS = self.MAZE.find("**/Wall.004") self.WALLS.node().setIntoCollideMask(BitMask32.bit(0)) # collision with the ground. different bit mask #self.mazeGround = self.maze.find("**/ground_collide") #self.mazeGround.node().setIntoCollideMask(BitMask32.bit(1)) self.MAZEGROUND = self.MAZE.find("**/Cube.004") self.MAZEGROUND.node().setIntoCollideMask(BitMask32.bit(1)) # load the ball and attach it to the scene. # it is on a dummy node so that we can rotate the ball # without rotating the ray that will be attached to it # CollisionTraversers calculate collisions self.cTrav = CollisionTraverser() #self.cTrav.showCollisions(render) # self.cTrav.showCollisions(render) # A list collision handler queue self.cHandler = CollisionHandlerQueue() # add collision nodes to the traverse. # maximum nodes per traverser: 32 self.cTrav.addCollider(self.ballSphere,self.cHandler) self.cTrav.addCollider(self.ballGroundColNp,self.cHandler) # collision traversers have a built-in tool to visualize collisons # self.cTrav.showCollisions(render) self.start() def pokemonTurn(self, pokemon, direction): if direction == 'l' and self.pokemonDirection != 'l': pokemon.setH(-90) if direction == 'r' and self.pokemonDirection != 'r': pokemon.setH(90) if direction == 'd' and self.pokemonDirection != 'd': pokemon.setH(0) if direction == 'u' and self.pokemonDirection != 'u': pokemon.setH(180) def pokemonMove(self, pokemon, direction): self.pokemonTurn(pokemon, direction) if direction == 'l': newX = pokemon.getX() - _SPEED pokemon.setX(newX) elif direction == 'r': newX = pokemon.getX() + _SPEED pokemon.setX(newX) elif direction == 'u': newY = pokemon.getY() + _SPEED pokemon.setY(newY) elif direction == 'd': newY = pokemon.getY() - _SPEED pokemon.setY(newY) elif direction == "s": # stop pass def whereToGo(self, task): # this returns the direction pokemon should go # tell MAZE pokemon and ball's board position MAZE.setPokeCoord(self.pikachu.getX(), self.pikachu.getY()) MAZE.setBallCoord(self.ballRoot.getX(), self.ballRoot.getY()) # find out which direction to go direction = MAZE.getDecision() self.pokemonMove(self.pikachu,direction) return Task.cont def getInformation(self): # get information on the board pass def start(self): # maze model has a locator in it # self.ballRoot.show() startPos = self.MAZE.find("**/start").getPos() self.ballRoot.setPos(startPos) # set the ball in the pos self.ballV = Vec3(0,0,0) # initial velocity self.accelV = Vec3(0,0,0) # initial acceleration # for a traverser to work, need to call traverser.traverse() # base has a task that does this once a frame base.cTrav = self.cTrav # create the movement task, make sure its not already running taskMgr.remove("rollTask") taskMgr.add(self.spinCamera, "spinCamera") taskMgr.add(self.whereToGo, "whereToGo") taskMgr.add(lambda task: self.moveBall(task, self.jerkDirection), "moveBall") self.mainLoop = taskMgr.add(self.rollTask, "rollTask") self.mainLoop.last = 0 def moveBallWrapper(self, direction): if direction == False: self.arrowKeyPressed = False else: self.arrowKeyPressed = True self.jerkDirection = direction def moveBall(self, task, direction): if self.arrowKeyPressed == True: if direction == "u": self.jerk = Vec3(0,_JERK,0) elif direction == "d": self.jerk = Vec3(0,-_JERK,0) elif direction == "l": self.jerk = Vec3(-_JERK,0,0) elif direction == "r": self.jerk = Vec3(_JERK,0,0) return Task.cont # collision between ray and ground # info about the interaction is passed in colEntry def groundCollideHandler(self,colEntry): # set the ball to the appropriate Z for it to be on the ground newZ = colEntry.getSurfacePoint(render).getZ() self.ballRoot.setZ(newZ+.4) # up vector X normal vector norm = colEntry.getSurfaceNormal(render) accelSide = norm.cross(UP) self.accelV = norm.cross(accelSide) # collision between the ball and a wall def wallCollideHandler(self,colEntry): # some vectors needed to do the calculation norm = colEntry.getSurfaceNormal(render) * -1 norm.normalize() curSpeed = self.ballV.length() inVec = self.ballV/curSpeed velAngle = norm.dot(inVec) # angle of incidance hitDir = colEntry.getSurfacePoint(render) - self.ballRoot.getPos() hitDir.normalize() hitAngle = norm.dot(hitDir) # deal with collision cases if velAngle > 0 and hitAngle >.995: # standard reflection equation reflectVec = (norm * norm.dot(inVec*-1)*2) + inVec # makes velocity half of hitting dead-on self.ballV = reflectVec * (curSpeed * (((1-velAngle)*.5)+.5)) # a collision means the ball is already a little bit buried in # move it so exactly touching the wall disp = (colEntry.getSurfacePoint(render) - colEntry.getInteriorPoint(render)) newPos = self.ballRoot.getPos() + disp self.ballRoot.setPos(newPos) def rollTask(self,task): # standard technique for finding the amount of time # since the last frame dt = task.time - task.last task.last = task.time # If dt is large, then there is a HICCUP # ignore the frame if dt > .2: return Task.cont # dispatch which function to handle the collision based on name for i in range(self.cHandler.getNumEntries()): entry = self.cHandler.getEntry(i) name = entry.getIntoNode().getName() if name == "Wall.004": self.wallCollideHandler(entry) elif name=="Cube.004": self.groundCollideHandler(entry) # read the mouse position and tilt the maze accordingly self.accelV += self.jerk # move the ball, update the velocity based on accel self.ballV += self.accelV * dt * ACCELERATION # clamp the velocity to the max speed if self.ballV.lengthSquared() > MAX_SPEED_SQ: self.ballV.normalize() self.ballV *= MAX_SPEED # update the position self.ballRoot.setPos(self.ballRoot.getPos() + (self.ballV*dt)) # uses quaternion to rotate the ball prevRot = LRotationf(self.ball.getQuat()) axis = UP.cross(self.ballV) newRot = LRotationf(axis, 45.5 * dt * self.ballV.length()) self.ball.setQuat(prevRot * newRot) return Task.cont # continue the task
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) base.setBackgroundColor(0, 0, 0) self.accept("escape", sys.exit) # Escape quits self.disableMouse() camera.setPosHpr(0, 0, 0, 0, 0, 0) lens = PerspectiveLens() lens.setFov(90, 60) lens.setNear(0.01) lens.setFar(100000) self.cam.node().setLens(lens) self.ballSize = 0.025 self.cueLength = 0.2 # self.ballRoot = render.attachNewNode("ballRoot") # #self.ball = loader.loadModel("models/ball") # self.ball = loader.loadModel("models/ball_0_center.egg") # #self.ball = loader.loadModel("models/ball.dae") # self.ball.setScale(ballSize, ballSize, ballSize) # self.ball.reparentTo(self.ballRoot) # #print(self.ball.getBounds()) # #exit(1) # #self.ballSphere = self.ball.find("**/ball") # #print(self.ball.getScale()[0]) # cs = CollisionSphere(0, 0, 0, 1) # self.ballSphere = self.ball.attachNewNode(CollisionNode('ball')) # self.ballSphere.node().addSolid(cs) # self.ballSphere.node().setFromCollideMask(BitMask32.bit(0)) # self.ballSphere.node().setIntoCollideMask(BitMask32.bit(1)) self.sceneIndex = 0 self.planeInfo = PlaneScene(self.sceneIndex) self.planeScene = self.planeInfo.generateEggModel() self.planeScene.setTwoSided(True) self.planeScene.reparentTo(render) self.planeScene.hide() #get geometries from plane predictions planeTriangles, horizontalPlaneTriangles, self.gravityDirection = self.planeInfo.getPlaneTriangles( ) # add pool balls self.ballRoots = [] self.balls = [] self.ballSpheres = [] self.ballGroundRays = [] for ballIndex in xrange(3): ballRoot = render.attachNewNode("ballRoot_" + str(ballIndex)) ball = loader.loadModel("models/ball_" + str(ballIndex) + "_center.egg") ball.setScale(self.ballSize, self.ballSize, self.ballSize) cs = CollisionSphere(0, 0, 0, 1) ballSphere = ball.attachNewNode( CollisionNode('ball_' + str(ballIndex))) ballSphere.node().addSolid(cs) ballSphere.node().setFromCollideMask( BitMask32.bit(0) | BitMask32.bit(1) | BitMask32.bit(3) | BitMask32.bit(4)) ballSphere.node().setIntoCollideMask(BitMask32.bit(1)) ball.reparentTo(ballRoot) self.ballRoots.append(ballRoot) self.balls.append(ball) self.ballSpheres.append(ballSphere) ballGroundRay = CollisionRay() # Create the ray ballGroundRay.setOrigin(0, 0, 0) # Set its origin ballGroundRay.setDirection( self.gravityDirection[0], self.gravityDirection[1], self.gravityDirection[2]) # And its direction # Collision solids go in CollisionNode # Create and name the node ballGroundCol = CollisionNode('ball_ray_' + str(ballIndex)) ballGroundCol.addSolid(ballGroundRay) # Add the ray ballGroundCol.setFromCollideMask( BitMask32.bit(2)) # Set its bitmasks ballGroundCol.setIntoCollideMask(BitMask32.allOff()) # Attach the node to the ballRoot so that the ray is relative to the ball # (it will always be 10 feet over the ball and point down) ballGroundColNp = ballRoot.attachNewNode(ballGroundCol) self.ballGroundRays.append(ballGroundColNp) ballRoot.hide() continue # Finally, we create a CollisionTraverser. CollisionTraversers are what # do the job of walking the scene graph and calculating collisions. # For a traverser to actually do collisions, you need to call # traverser.traverse() on a part of the scene. Fortunately, ShowBase # has a task that does this for the entire scene once a frame. By # assigning it to self.cTrav, we designate that this is the one that # it should call traverse() on each frame. self.cTrav = CollisionTraverser() # Collision traversers tell collision handlers about collisions, and then # the handler decides what to do with the information. We are using a # CollisionHandlerQueue, which simply creates a list of all of the # collisions in a given pass. There are more sophisticated handlers like # one that sends events and another that tries to keep collided objects # apart, but the results are often better with a simple queue self.cHandler = CollisionHandlerQueue() # Now we add the collision nodes that can create a collision to the # traverser. The traverser will compare these to all others nodes in the # scene. There is a limit of 32 CollisionNodes per traverser # We add the collider, and the handler to use as a pair #self.cTrav.addCollider(self.ballSphere, self.cHandler) for ballSphere in self.ballSpheres: self.cTrav.addCollider(ballSphere, self.cHandler) continue for ballGroundRay in self.ballGroundRays: self.cTrav.addCollider(ballGroundRay, self.cHandler) continue #self.cTrav.addCollider(self.ballGroundColNp, self.cHandler) # Collision traversers have a built in tool to help visualize collisions. # Uncomment the next line to see it. #self.cTrav.showCollisions(render) # This section deals with lighting for the ball. Only the ball was lit # because the maze has static lighting pregenerated by the modeler ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.55, .55, .55, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(LVector3(0, 0, -1)) directionalLight.setColor((0.375, 0.375, 0.375, 1)) directionalLight.setSpecularColor((1, 1, 1, 1)) for ballRoot in self.ballRoots: ballRoot.setLight(render.attachNewNode(ambientLight)) ballRoot.setLight(render.attachNewNode(directionalLight)) continue # This section deals with adding a specular highlight to the ball to make # it look shiny. Normally, this is specified in the .egg file. m = Material() m.setSpecular((1, 1, 1, 1)) m.setShininess(96) for ball in self.balls: ball.setMaterial(m, 1) continue # self.original = False # if self.original: # camera.setPosHpr(0, 0, 25, 0, -90, 0) # self.maze = loader.loadModel("models/maze") # self.maze.reparentTo(render) # self.walls = self.maze.find("**/wall_collide") # self.walls.node().setIntoCollideMask(BitMask32.bit(0)) # self.walls.show() # pass # create collision entities from plane predictions self.triNPs = [] for triangleIndex, triangle in enumerate(planeTriangles): #print(triangleIndex) #for triangle in triangles: #print(triangle) tri = CollisionPolygon( Point3(triangle[0][0], triangle[0][1], triangle[0][2]), Point3(triangle[1][0], triangle[1][1], triangle[1][2]), Point3(triangle[2][0], triangle[2][1], triangle[2][2])) triNP = render.attachNewNode( CollisionNode('tri_' + str(triangleIndex))) triNP.node().setIntoCollideMask(BitMask32.bit(0)) triNP.node().addSolid(tri) self.triNPs.append(triNP) #triNP.show() continue # create special collision entities for horizontal planes so that balls can fall on one horizontal plane and bounce on it for triangleIndex, triangle in enumerate(horizontalPlaneTriangles): #print(triangleIndex) #for triangle in triangles: #print(triangle) tri = CollisionPolygon( Point3(triangle[0][0], triangle[0][1], triangle[0][2]), Point3(triangle[1][0], triangle[1][1], triangle[1][2]), Point3(triangle[2][0], triangle[2][1], triangle[2][2])) triNP = render.attachNewNode( CollisionNode('ground_' + str(triangleIndex))) triNP.node().setIntoCollideMask(BitMask32.bit(2)) triNP.node().addSolid(tri) self.triNPs.append(triNP) #triNP.show() continue # tri = CollisionPolygon(Point3(-1, 4, -1), Point3(2, 4, -1), Point3(2, 4, 2)) # triNP = render.attachNewNode(CollisionNode('tri')) # triNP.node().setIntoCollideMask(BitMask32.bit(0)) # triNP.node().addSolid(tri) # triNP.show() #self.planeScene.node().setIntoCollideMask(BitMask32.bit(0)) # roomRootNP = self.planeScene # roomRootNP.flattenLight() # mesh = BulletTriangleMesh() # polygons = roomRootNP.findAllMatches("**/+GeomNode") # # p0 = Point3(-10, 4, -10) # # p1 = Point3(-10, 4, 10) # # p2 = Point3(10, 4, 10) # # p3 = Point3(10, 4, -10) # # mesh.addTriangle(p0, p1, p2) # # mesh.addTriangle(p1, p2, p3) # print(polygons) # for polygon in polygons: # geom_node = polygon.node() # #geom_node.reparentTo(self.render) # #print(geom_node.getNumGeoms()) # ts = geom_node.getTransform() # #print(ts) # for geom in geom_node.getGeoms(): # mesh.addGeom(geom, ts) # continue # continue # #self.scene = roomRootNP # shape = BulletTriangleMeshShape(mesh, dynamic=False) # #shape = BulletPlaneShape(Vec3(0, 0, 1), 1) # room = BulletRigidBodyNode('scene') # room.addShape(shape) # #room.setLinearDamping(0.0) # #room.setFriction(0.0) # print(shape) # room.setDeactivationEnabled(False) # roomNP = render.attachNewNode(room) # roomNP.setPos(0, 0, 0) # roomNP.node().setIntoCollideMask(BitMask32.bit(0)) # self.world = BulletWorld() # self.world.setGravity(Vec3(0, 0, 0)) # self.world.attachRigidBody(roomNP.node()) #room.setRestitution(1) #self.roomNP = self.scene # create the cue self.cueRoot = render.attachNewNode("cueRoot") self.cue = loader.loadModel("models/cue_center.egg") self.cue.setScale(self.cueLength * 3, self.cueLength * 3, self.cueLength) self.cue.reparentTo(self.cueRoot) self.cuePos = (10, 0, 0) 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(2)) self.pickerNode.setIntoCollideMask(BitMask32.allOff()) 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.cTrav.addCollider(self.pickerNP, self.cHandler) self.accept("mouse1", self.hit) # left-click grabs a piece # create holes self.holeLength = 0.06 holePos, holeHpr = self.planeInfo.getHolePos() self.holeRoot = render.attachNewNode("holeRoot") #self.hole = loader.loadModel("models/hole_horizontal_center.egg") self.hole = loader.loadModel("models/hole_color.egg") #self.hole = loader.loadModel("models/billiards_hole_center.egg") self.hole.setScale(self.holeLength, self.holeLength, self.holeLength) self.hole.reparentTo(self.holeRoot) self.hole.setTwoSided(True) self.holeRoot.setPos(holePos[0], holePos[1], holePos[2]) self.holeRoot.setHpr(holeHpr[0], holeHpr[1], holeHpr[2]) #tex = loader.loadTexture('models/Black_Hole.jpg') #self.hole.setTexture(tex, 1) self.holeRoot.hide() ct = CollisionTube(0, 0, 0, 0, 0.001, 0, 0.5) self.holeTube = self.hole.attachNewNode(CollisionNode('hole')) self.holeTube.node().addSolid(ct) self.holeTube.node().setFromCollideMask(BitMask32.allOff()) self.holeTube.node().setIntoCollideMask(BitMask32.bit(4)) #self.holeTube.show() # create portals inPortalPos, inPortalHpr, outPortalPos, outPortalHpr, self.portalNormal = self.planeInfo.getPortalPos( ) self.portalLength = 0.06 self.inPortalRoot = render.attachNewNode("inPortalRoot") self.inPortal = loader.loadModel("models/portal_2_center.egg") self.inPortal.setScale(self.portalLength, self.portalLength, self.portalLength) self.inPortal.reparentTo(self.inPortalRoot) self.inPortalRoot.setPos(inPortalPos[0], inPortalPos[1], inPortalPos[2]) self.inPortalRoot.setHpr(inPortalHpr[0], inPortalHpr[1], inPortalHpr[2]) self.inPortalRoot.hide() ct = CollisionTube(0, 0, 0, 0, 0.001, 0, 1) self.inPortalTube = self.inPortal.attachNewNode( CollisionNode('portal_in')) self.inPortalTube.node().addSolid(ct) self.inPortalTube.node().setFromCollideMask(BitMask32.allOff()) self.inPortalTube.node().setIntoCollideMask(BitMask32.bit(3)) #self.inPortalTube.hide() self.outPortalRoot = render.attachNewNode("outPortalRoot") self.outPortal = loader.loadModel("models/portal_2_center.egg") self.outPortal.setScale(self.portalLength, self.portalLength, self.portalLength) self.outPortal.reparentTo(self.outPortalRoot) self.outPortalRoot.setPos(outPortalPos[0], outPortalPos[1], outPortalPos[2]) self.outPortalRoot.setHpr(outPortalHpr[0], outPortalHpr[1], outPortalHpr[2]) self.outPortalRoot.hide() ct = CollisionTube(0, 0, 0, 0, 0.001, 0, 1) self.outPortalTube = self.outPortal.attachNewNode( CollisionNode('portal_out')) self.outPortalTube.node().addSolid(ct) self.outPortalTube.node().setFromCollideMask(BitMask32.allOff()) self.outPortalTube.node().setIntoCollideMask(BitMask32.bit(3)) #self.outPortalTube.hide() #self.inPortalTube.show() #self.outPortalTube.show() #self.holeTube.show() #self.cTrav.addCollider(self.holeTube, self.cHandler) # create background image background_image = loader.loadTexture('dump/' + str(self.sceneIndex) + '_image.png') cm = CardMaker('background') cm.setHas3dUvs(True) info = np.load('dump/' + str(self.sceneIndex) + '_info.npy') #self.camera = getCameraFromInfo(self.info) depth = 10.0 sizeU = info[2] / info[0] * depth sizeV = info[6] / info[5] * depth cm.setFrame(Point3(-sizeU, depth, -sizeV), Point3(sizeU, depth, -sizeV), Point3(sizeU, depth, sizeV), Point3(-sizeU, depth, sizeV)) self.card = self.render.attachNewNode(cm.generate()) self.card.setTransparency(True) self.card.setTexture(background_image) self.card.hide() self.ballGroundMap = {} self.ballBouncing = np.full(len(self.balls), 3) self.started = False self.start() #self.hitIndex = -1 self.showing = 'parts' self.showingProgress = 0 partsScene = PartsScene(self.sceneIndex) self.planeNPs, self.planeCenters = partsScene.generateEggModel() return
class RoamingRalphDemo(ShowBase): def __init__(self): # Setup window size, title and so on load_prc_file_data( "", """ win-size 1600 900 window-title Render Pipeline - Roaming Ralph Demo """) if alt: ShowBase.__init__(self) self.render_pipeline = render_pipeline self.render_pipeline.create(self) else: # ------ Begin of render pipeline code (else case) ------ # Insert the pipeline path to the system path, this is required to be # able to import the pipeline classes #pipeline_path = "../../" # Just a special case for my development setup, so I don't accidentally # commit a wrong path. You can remove this in your own programs. #if not os.path.isfile(os.path.join(pipeline_path, "setup.py")): pipeline_path = "../tobsprRenderPipeline" sys.path.insert(0, pipeline_path) from rpcore import RenderPipeline, SpotLight self.render_pipeline = RenderPipeline() self.render_pipeline.create(self) # ------ End of render pipeline code, thats it! ------ # Set time of day self.render_pipeline.daytime_mgr.time = "7:40" # Use a special effect for rendering the scene, this is because the # roaming ralph model has no normals or valid materials self.render_pipeline.set_effect( render, "roaming_ralph_pipeline_scene-effect.yaml", {}, sort=250) self.keyMap = { "left": 0, "right": 0, "forward": 0, "backward": 0, "cam-left": 0, "cam-right": 0 } self.speed = 1.0 base.win.setClearColor(Vec4(0, 0, 0, 1)) # Post the instructions self.inst1 = addInstructions(0.95, "[ESC] Quit") self.inst4 = addInstructions(0.90, "[W] Run Ralph Forward") self.inst4 = addInstructions(0.85, "[S] Run Ralph Backward") self.inst2 = addInstructions(0.80, "[A] Rotate Ralph Left") self.inst3 = addInstructions(0.75, "[D] Rotate Ralph Right") self.inst6 = addInstructions(0.70, "[Left Arrow] Rotate Camera Left") self.inst7 = addInstructions(0.65, "[Right Arrow] Rotate Camera Right") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel( "roaming_ralph_pipeline_resources/world") self.environ.reparentTo(render) self.environ.setPos(0, 0, 0) # Remove wall nodes self.environ.find("**/wall").remove_node() # Create the main character, Ralph self.ralph = Actor( "roaming_ralph_pipeline_resources/ralph", { "run": "roaming_ralph_pipeline_resources/ralph-run", "walk": "roaming_ralph_pipeline_resources/ralph-walk" }) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(Vec3(-110.9, 29.4, 1.8)) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation self.accept("escape", sys.exit) self.accept("a", self.setKey, ["left", 1]) self.accept("d", self.setKey, ["right", 1]) self.accept("w", self.setKey, ["forward", 1]) self.accept("s", self.setKey, ["backward", 1]) self.accept("arrow_left", self.setKey, ["cam-left", 1]) self.accept("arrow_right", self.setKey, ["cam-right", 1]) self.accept("a-up", self.setKey, ["left", 0]) self.accept("d-up", self.setKey, ["right", 0]) self.accept("w-up", self.setKey, ["forward", 0]) self.accept("s-up", self.setKey, ["backward", 0]) self.accept("arrow_left-up", self.setKey, ["cam-left", 0]) self.accept("arrow_right-up", self.setKey, ["cam-right", 0]) self.accept("=", self.adjustSpeed, [0.25]) self.accept("+", self.adjustSpeed, [0.25]) self.accept("-", self.adjustSpeed, [-0.25]) taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX() + 10, self.ralph.getY() + 10, 2) base.camLens.setFov(80) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 1000) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Adjust movement speed def adjustSpeed(self, delta): newSpeed = self.speed + delta if 0 <= newSpeed <= 3: self.speed = newSpeed # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) 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()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"] != 0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) elif (self.keyMap["right"] != 0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"] != 0): self.ralph.setY(self.ralph, -25 * self.speed * globalClock.getDt()) elif (self.keyMap["backward"] != 0): self.ralph.setY(self.ralph, 25 * self.speed * globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.keyMap["forward"]!=0) or (self.keyMap["backward"]!=0) or \ (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.0): base.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) return task.cont
class RoamingRalphDemo(ShowBase): def __init__(self): # Set up the window, camera, etc. ShowBase.__init__(self) # Set the background color to black self.win.setClearColor((0, 0, 0, 1)) # Post the instructions self.title = addTitle( "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.06, "[ESC]: Quit") self.inst2 = addInstructions(0.12, "[Left trackpad]: Rotate Left") self.inst3 = addInstructions(0.18, "[Right trackpad]: Rotate Right") self.inst4 = addInstructions(0.24, "[Up trackpad]: Walk Forward") self.inst4 = addInstructions(0.30, "[Down trackpad]: Walk Backward") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) # Create the main character, Ralph self.vr = RoamingRalphVR() self.vr.init(msaa=4) self.ralph = render.attachNewNode('ralph') self.ralphStartPos = self.environ.find("**/start_point").getPos() self.vr.tracking_space.setPos(self.ralphStartPos) self.ralph.setPos(self.vr.hmd_anchor.getPos(render)) self.accept("escape", sys.exit) taskMgr.add(self.collision, "collisionTask") # Set up the camera self.disableMouse() # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 9) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(CollideMask.bit(0)) self.ralphGroundCol.setIntoCollideMask(CollideMask.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection((-5, -5, -5)) directionalLight.setColor((1, 1, 1, 1)) directionalLight.setSpecularColor((1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) # Grid checking and collision detection def collision(self, task): # Normally, we would have to call traverse() to check for collisions. # However, the class ShowBase that we inherit from has a task to do # this for us, if we assign a CollisionTraverser to self.cTrav. #self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = list(self.ralphGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName( ) == "terrain": self.vr.tracking_space.setZ( entries[0].getSurfacePoint(render).getZ()) else: self.vr.tracking_space.setPos(self.ralphStartPos) self.ralph.setPos(self.vr.hmd_anchor.getPos(render)) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. self.ralphStartPos = self.vr.tracking_space.getPos() return task.cont
class RoamingRalphDemo(ShowBase): def __init__(self): # Set up the window, camera, etc. ShowBase.__init__(self) # Set the background color to black self.win.setClearColor((0, 0, 0, 1)) # This is used to store which keys are currently pressed. self.keyMap = { "left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0} # Post the instructions self.title = addTitle( "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.06, "[ESC]: Quit") self.inst2 = addInstructions(0.12, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.18, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.24, "[Up Arrow]: Run Ralph Forward") self.inst6 = addInstructions(0.30, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.36, "[S]: Rotate Camera Right") self.dirText = addInstructions(0.42, "pos") self.anglesText = addInstructions(0.48, "angle") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. #self.environ = loader.loadModel("models/world") #self.environ.reparentTo(render) self.createArm() # Create the main character, Ralph #ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", {"run": "models/ralph-run", "walk": "models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) #self.ralph.setPos(ralphStartPos + (0, 0, 0.5)) # Create a floater object, which floats 2 units above ralph. We # use this as a target for the camera to look at. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(self.ralph) self.floater.setZ(2.0) # Accept the control keys for movement and rotation self.accept("escape", self.exitButton) self.accept("arrow_left", self.setKey, ["left", True]) self.accept("arrow_right", self.setKey, ["right", True]) self.accept("arrow_up", self.setKey, ["forward", True]) self.accept("a", self.setKey, ["cam-left", True]) self.accept("s", self.setKey, ["cam-right", True]) self.accept("arrow_left-up", self.setKey, ["left", False]) self.accept("arrow_right-up", self.setKey, ["right", False]) self.accept("arrow_up-up", self.setKey, ["forward", False]) self.accept("a-up", self.setKey, ["cam-left", False]) self.accept("s-up", self.setKey, ["cam-right", False]) taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera self.disableMouse() self.camera.setPos(15, 0, 3)#self.ralph.getX(), self.ralph.getY() + 10, 2) self.camera.setHpr(90, -5, 0) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 9) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(CollideMask.bit(0)) self.ralphGroundCol.setIntoCollideMask(CollideMask.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0, 0, 9) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(CollideMask.bit(0)) self.camGroundCol.setIntoCollideMask(CollideMask.allOff()) self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection((-5, -5, -5)) directionalLight.setColor((1, 1, 1, 1)) directionalLight.setSpecularColor((1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) def exitButton(self): servos.exit() __import__('sys').exit() def createArm(self): self.robotarm = Actor("models/robotarm") self.robotarm.reparentTo(render) self.robotarm.setPos(0,0,0) self.robotarm.setScale(.2) self.jointForearm = self.robotarm.controlJoint(None, "modelRoot", "forearm") self.jointBase = self.robotarm.controlJoint(None, "modelRoot", "base") taskMgr.add(self.monitorArm, "robot arm") inc = 15 self.accept("i", self.setForearm, [inc]) self.accept("u", self.setForearm, [-inc]) self.accept("j", self.setBase, [inc]) self.accept("k", self.setBase, [-inc]) def monitorArm(self, task): def clamp1(x): return min(1, max(-1, x)) direction = self.ralph.get_pos() - self.robotarm.get_pos() direction.z += 1 direction.normalize() # camera starts facing along x dec = math.asin(direction.x) cosdec = math.cos(dec) if cosdec > 1e-05: ra = math.asin(clamp1(direction.z / cosdec)) ra2 = math.acos(clamp1(direction.y / cosdec)) else: ra = ra2 = math.pi/2#float('nan') #print(cosdec, direction) #print(dec, ra, ra2, cosdec) if direction.z < 0: if ra2 < math.pi/2: ra2 = 0 else: ra2 = math.pi self.jointForearm.setH(-dec * 180/math.pi) self.jointBase.setP(ra2 * 180/math.pi) self.dirText.setText(str(direction)) self.anglesText.setText(str((dec, ra, ra2, cosdec))) a = self.jointForearm.getH() / 90.0 * 300 + 512 b = self.jointBase.getP() / 90.0 * 300 + 212 #print(a, b) baseID = 9 servos.setAngle({baseID:int(round(b)), (baseID+1):int(round(a))}) return task.again def monitorArmServos(self, task): baseID = 9 a = self.jointForearm.getH() / 90.0 * 300 + 512 b = self.jointBase.getP() / 90.0 * 300 + 212 #print(a, b) servos.setAngle({baseID:int(round(a)), (baseID+1):int(round(b))}) # frac = task.time - int(task.time) # if frac > .9 and frac < .99: #print(self.jointForearm.getH(), self.jointBase.getP()) return task.again def setForearm(self, inc): #self.jointForearm.setH(random.random()*180-90) self.jointForearm.setH(self.jointForearm.getH() + inc) def setBase(self, inc): #self.jointBase.setP(random.random()*180) self.jointBase.setP(self.jointBase.getP() + inc) # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # Get the time that elapsed since last frame. We multiply this with # the desired speed in order to find out with which distance to move # in order to achieve that desired speed. dt = globalClock.getDt() # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. if self.keyMap["cam-left"]: self.camera.setX(self.camera, -20 * dt) if self.keyMap["cam-right"]: self.camera.setX(self.camera, +20 * dt) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if self.keyMap["left"]: self.ralph.setH(self.ralph.getH() + 300 * dt) if self.keyMap["right"]: self.ralph.setH(self.ralph.getH() - 300 * dt) if self.keyMap["forward"]: self.ralph.setY(self.ralph, -25 * dt) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if self.keyMap["forward"] or self.keyMap["left"] or self.keyMap["right"]: if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. """camvec = self.ralph.getPos() - self.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if camdist > 10.0: self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if camdist < 5.0: self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Normally, we would have to call traverse() to check for collisions. # However, the class ShowBase that we inherit from has a task to do # this for us, if we assign a CollisionTraverser to self.cTrav. #self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = list(self.ralphGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain": self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = list(self.camGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain": self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if self.camera.getZ() < self.ralph.getZ() + 2.0: self.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.camera.lookAt(self.floater)""" return task.cont
class World(DirectObject): def __init__(self): self.itemID = 0 self.switchState = True self.iAktion = "E" self.altIPos = [0,0] self.switchCam = False self.kampf = Battle.Kampf() self.itemDa = False self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0} base.win.setClearColor(Vec4(0,0,0,1)) self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0,0,0) self.spieler = Players.Player(Actor("models/box.x")) self.spieler.actor.reparentTo(render) spielerStartPos = (-107.575, 26.6066, -0.490075) self.spieler.actor.setPos(spielerStartPos) self.textObjectSpieler = OnscreenText(text = self.spieler.name+": "+str(self.spieler.energie)+"/"+str(self.spieler.maxenergie)+" HP", pos = (-0.90, -0.98), scale = 0.07, fg = (1,0,0,1)) # Erstellt Gegner self.gegnerStartPos = ([(-39.1143569946,25.1781406403,-0.136657714844), (-102.375793457,-30.6321983337,0.0), (-56.927986145, -34.6329650879, -0.16748046875), (-79.6673126221,30.8231620789,2.89721679688), (-4.37648868561,30.5158863068,2.18450927734), (22.6527004242,4.99837779999,3.11364746094), (-23.8257598877,-7.87773084641,1.36920166016), (-80.6140823364,19.5769443512,4.70764160156), (-75.0773696899,-15.2991075516,6.24676513672) ]) gegnerPos = random.choice(self.gegnerStartPos) self.gegnerErstellen(gegnerPos) self.textObjectGegner = OnscreenText(text = str(self.gegner.name)+": "+str(self.gegner.energie)+"/"+str(self.gegner.maxenergie)+" HP", pos = (0.90, -0.98), scale = 0.07, fg = (1,0,0,1)) self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) self.item = None # Handling der Usereingaben für Bewegung 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("i", self.setKey, ["inventar",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.accept("e", self.iAktionsHandler,["e"]) self.accept("v", self.iAktionsHandler,["v"]) self.accept("w", self.iAktionsHandler,["w"]) taskMgr.add(self.move,"moveTask") taskMgr.add(self.erkenneKampf,"Kampferkennung") taskMgr.add(self.screentexts,"Screentexte") # Menü erstellen self.createMenu() # Kameraeinstellungen base.disableMouse() base.camera.setPos(self.spieler.actor.getX(),self.spieler.actor.getY()+10,2) self.collisionInit(); self.setAI() # Licht ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) # Hintergrund (Himmel) self.setupSkySphere() def iAktionsHandler(self,key): if key == "e": self.iAktion = "E" elif key == "w": self.iAktion = "W" elif key == "v": self.iAktion = "V" def collisionInit(self): # Kollisionserkennung, um auf dem Boden zu laufen. Der Collisionray # erkennt die Hoehe des Gelaendes und wenn ein Objekt da ist, wird # die Bewegung als illegal gewertet. self.cTrav = CollisionTraverser() self.spielerGroundRay = CollisionRay() self.spielerGroundRay.setOrigin(0,0,1000) self.spielerGroundRay.setDirection(0,0,-1) self.spielerGroundCol = CollisionNode('spielerRay') self.spielerGroundCol.addSolid(self.spielerGroundRay) self.spielerGroundCol.setFromCollideMask(BitMask32.bit(0)) self.spielerGroundCol.setIntoCollideMask(BitMask32.allOff()) self.spielerGroundColNp = self.spieler.actor.attachNewNode(self.spielerGroundCol) self.spielerGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.spielerGroundColNp, self.spielerGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) self.gegnerGroundRay = CollisionRay() self.gegnerGroundRay.setOrigin(0,0,1000) self.gegnerGroundRay.setDirection(0,0,-1) self.gegnerGroundCol = CollisionNode('gegnerRay') self.gegnerGroundCol.addSolid(self.gegnerGroundRay) self.gegnerGroundCol.setFromCollideMask(BitMask32.bit(0)) self.gegnerGroundCol.setIntoCollideMask(BitMask32.allOff()) self.gegnerGroundColNp = self.gegner.actor.attachNewNode(self.gegnerGroundCol) self.gegnerGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.gegnerGroundColNp, self.gegnerGroundHandler) def setupSkySphere(self): self.skysphere = loader.loadModel("models/LinearPinkSkySphere.bam") # Textur für den Himmel laden self.sky_tex = loader.loadTexture("Images/Sterne.jpg") # Himmel Textur konfigurieren self.skysphere.setTexture(self.sky_tex, 1) self.skysphere.setBin('background', 1) self.skysphere.setDepthWrite(0) self.skysphere.reparentTo(render) self.skysphere.setScale(40) taskMgr.add(self.skysphereTask, "SkySphere Task") def skysphereTask(self, task): self.skysphere.setPos(base.camera, 0, 0, 0) return task.cont def createMenu(self): self.createFrame() itemListe = self.spieler.inventar.anzeigen(1) standardpos = [0.18, 0.98, 0.83] self.buttonListe = [] beutelLabel = DirectLabel(text = itemListe[0][0], pos = (0.18, 0.98, 0.95), scale = 0.07, text_fg = (1,0,0,1), text_bg = (0, 50, 50, 1), textMayChange = 1) del itemListe [0][0] for zeile in range(4): for i in range(0,5): Button = DirectButton(text = itemListe [zeile] [i], pos = standardpos, scale = 0.07, text_fg = (1,0,0,1), text_bg = (0, 50, 50, 1), textMayChange = 1, extraArgs = [zeile,i], command = self.inventarAktion) self.buttonListe.append (Button) standardpos[0] += 0.25 standardpos[0] = 0.18 standardpos[2] -= 0.15 def createFrame(self): self.myFrame = DirectFrame(frameColor=(0, 50, 50, 0.5), frameSize=(-1, 1, -.7, 1), pos=(1, -1, 1)) def inventarAktion(self,zeile,spalte): if self.iAktion == "E": self.spieler.inventar.entfernen(1,[zeile,spalte]) self.myFrame.destroy() i = 0 for item in self.buttonListe: self.buttonListe [i].destroy() i += 1 del self.buttonListe[:] self.createMenu() elif self.iAktion == "W": self.altIPos = [zeile,spalte] elif self.iAktion == "V": self.spieler.inventar.verschieben(1,1,self.altIPos,[zeile,spalte]) self.myFrame.destroy() i = 0 for item in self.buttonListe: self.buttonListe [i].destroy() i += 1 del self.buttonListe[:] self.createMenu() # Erkennt den Status der Eingabe def setKey(self, key, value): self.keyMap[key] = value def screentexts(self,task): self.textObjectSpieler.destroy() self.textObjectSpieler = OnscreenText(text = self.spieler.name+": "+str(self.spieler.energie)+"/"+str(self.spieler.maxenergie)+" HP", pos = (-0.90, -0.98), scale = 0.07, fg = (1,0,0,1)) self.textObjectGegner.destroy() if self.kampf.active == True: self.textObjectGegner = OnscreenText(text = str(self.gegner.name)+": "+str(self.gegner.energie)+"/"+str(self.gegner.maxenergie)+" HP", pos = (0.90, -0.98), scale = 0.07, fg = (1,0,0,1)) else: self.textObjectGegner = OnscreenText(text = "Kein Gegner vorhanden", pos = (0.90, -0.98), scale = 0.07, fg = (1,0,0,1)) return Task.cont def camera(self): # cam-left Key: Kamera nach links # cam-right Key: Kamera nach rechts base.camera.lookAt(self.spieler.actor) 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()) # Wenn die Kamera zu weit weg ist, zoom heran. # Wenn die Kamera zu nah dran ist, zoom weg. camvec = self.spieler.actor.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # Haelt die Kamera einen Schritt über dem Boden # oder zwei Schritte ueber dem Spieler, je nachdem, was groesser ist. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) if (base.camera.getZ() < self.spieler.actor.getZ() + 2.0): base.camera.setZ(self.spieler.actor.getZ() + 2.0) # Die Kamera soll in die Richtung des Spielers gucken, aber auch # immer horizontal bleiben. self.floater.setPos(self.spieler.actor.getPos()) self.floater.setZ(self.spieler.actor.getZ() + 2.0) base.camera.lookAt(self.floater) def collisions(self,startpos): # Überprüfen auf Itemkollision if self.item <> None: if (self.item.actor.getX() - self.spieler.actor.getX() < 1 and self.item.actor.getY() - self.spieler.actor.getY() < 1 and self.item.actor.getZ() - self.spieler.actor.getZ() <1 and self.itemDa == True): self.itemDa = False self.item.actor.detachNode() self.spieler.inventar.einfuegen(self.item) self.myFrame.destroy() del self.buttonListe[:] self.createMenu() # Start der Kollisionserkennung self.cTrav.traverse(render) # Aendert die Z Koordinate des Spielers. Wenn er etwas trifft, bewegt # ihn entsprechend, wenn er nichts trifft, setzt die Koordinate # auf den Stand des letzten Frames self.dummyMethode(self.spielerGroundHandler, self.spieler.actor,startpos) def move(self,task): self.camera(); # Speichert die Startposition, damit der Spieler zurueckgesetzt # werden kann, sollte er irgendwo runterfallen startpos = self.spieler.actor.getPos() # Wenn einer der Move Keys gedrueckt wird, wird der Spieler # in die ensprechende Richtung bewegt if (self.keyMap["left"]!=0): self.spieler.actor.setH(self.spieler.actor.getH() + 150 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.spieler.actor.setH(self.spieler.actor.getH() - 150 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.spieler.actor.setY(self.spieler.actor, -12 * globalClock.getDt()) self.collisions(startpos); return Task.cont def gegnermove(self): # Zeit seit dem letzten Frame. Benötigt fuer # framerateunabhaengige Bewegung. elapsed = globalClock.getDt() startpos = self.gegner.actor.getPos() # Aendert die Z Koordinate des Gegners. Wenn er etwas trifft, bewegt # ihn entsprechend, wenn er nichts trifft, setzt die Koordinate # auf den Stand des letzten Frames self.cTrav.traverse(render) self.dummyMethode(self.gegnerGroundHandler, self.gegner.actor,startpos) self.gegner.actor.setP(0) if self.gegner.energie == 0: return Task.done else: return Task.cont def dummyMethode(self, handler, actor,startpos): entries = [] for i in range(handler.getNumEntries()): entry = handler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): actor.setZ(entries[0].getSurfacePoint(render).getZ()) else: actor.setPos(startpos) def setAI(self): # Erstellt die AI World self.AIworld = AIWorld(render) self.AIchar = AICharacter("gegner",self.gegner.actor, 100, 0.02, 1) self.AIworld.addAiChar(self.AIchar) self.AIbehaviors = self.AIchar.getAiBehaviors() self.AIbehaviors.wander(360, 0, 15, 1.0) #AI World update zum Tasknamager hinzufügen taskMgr.add(self.AIUpdate,"AIUpdate") # Update der AI World def AIUpdate(self,task): if self.kampf.active == False: self.AIworld.update() self.gegnermove() return Task.cont # Startet bei einem Abstand von 4 zwischen Spieler und Gegner einen Kampf def erkenneKampf(self,task): if (self.spieler.actor.getX() - self.gegner.actor.getX() < 4 and self.spieler.actor.getX() - self.gegner.actor.getX() > -4 and self.kampf.active == False): self.kampf.active = True self.startzeit = globalClock.getLongTime() if self.kampf.active == True: self.Kampf(self) if self.gegner.energie == 0: return Task.done else: return Task.cont def gegnerErstellen(self,pos): self.gegner = Monster.Goblin(Actor("models/box.x")) self.gegner.actor.reparentTo(render) self.gegner.actor.setPos(pos) self.gegnerAltPos = pos self.setAI() def gegnerTod(self): self.kampf.active = False itemPos = self.gegner.actor.getPos() self.gegner.actor.detachNode() self.item = Items.Axt() self.item.ID = self.itemID self.itemID += 1 self.itemDa = True self.item.actor.setScale(0.3) self.item.actor.reparentTo(render) self.item.actor.setPos(itemPos) gegnerNeuPos = random.choice(self.gegnerStartPos) while gegnerNeuPos == self.gegnerAltPos: gegnerNeuPos = random.choice(self.gegnerStartPos) self.gegnerErstellen(gegnerNeuPos) # Lässt Spieler und Gegner nach bestimmter Zeit Aktionen ausführen. Bei Tod des # Gegners wird ein neuer Gegner sowie ein Item generiert def Kampf(self,task): if ((int(globalClock.getLongTime()) - int(self.startzeit)) % 5 == 0 and self.kampf.active == True): erg = self.kampf.Kampf(self.spieler,self.gegner) self.spieler = erg[0] self.gegner = erg[1] self.startzeit -= 1 if self.spieler.energie == 0: sys.exit elif self.gegner.energie == 0: self.gegnerTod(); if self.startzeit <= 0: self.startzeit = globalClock.getLongTime()
def raycast(self, origin, direction=(0, 0, 1), distance=math.inf, traverse_target=scene, ignore=list(), debug=False): self.position = origin self.look_at(self.position + direction) self._pickerNode.clearSolids() # if thickness == (0,0): if distance == math.inf: ray = CollisionRay() ray.setOrigin(Vec3(0, 0, 0)) ray.setDirection(Vec3(0, 1, 0)) else: ray = CollisionSegment(Vec3(0, 0, 0), Vec3(0, distance, 0)) self._pickerNode.addSolid(ray) if debug: self._pickerNP.show() else: self._pickerNP.hide() self._picker.traverse(traverse_target) if self._pq.get_num_entries() == 0: self.hit = Hit(hit=False) return self.hit ignore += tuple([e for e in scene.entities if not e.collision]) self._pq.sort_entries() self.entries = [ # filter out ignored entities e for e in self._pq.getEntries() if e.get_into_node_path().parent not in ignore ] if len(self.entries) == 0: self.hit = Hit(hit=False) return self.hit self.collision = self.entries[0] nP = self.collision.get_into_node_path().parent point = self.collision.get_surface_point(nP) point = Vec3(point[0], point[2], point[1]) world_point = self.collision.get_surface_point(render) world_point = Vec3(world_point[0], world_point[2], world_point[1]) hit_dist = self.distance(self.world_position, world_point) if nP.name.endswith('.egg'): nP = nP.parent self.hit = Hit(hit=True) for e in scene.entities: if e == nP: # print('cast nP to Entity') self.hit.entity = e self.hit.point = point self.hit.world_point = world_point self.hit.distance = hit_dist normal = self.collision.get_surface_normal( self.collision.get_into_node_path().parent) self.hit.normal = (normal[0], normal[2], normal[1]) normal = self.collision.get_surface_normal(render) self.hit.world_normal = (normal[0], normal[2], normal[1]) return self.hit self.hit = Hit(hit=False) return self.hit
class Labryn(ShowBase): def setCamera(self, spin): # set camera spin state self.spin = spin def displayInformation(self): self.title = addTitle("Single Player") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[wasd]: Move") self.inst3 = addInstructions(0.85, "[q/e]: spin camera") self.inst4 = addInstructions(0.80, "[z/c]: zoom in/out") self.inst5 = addInstructions(0.75, "[shift]: hold and pan") self.inst6 = addInstructions(0.70, "[1/2/3]: use moves") self.inst7 = addInstructions(0.65, "[h]: hide instructions") self.insts = [self.title, self.inst1, self.inst2, self.inst3, self.inst4, self.inst5, self.inst6, self.inst7] def hideInstructions(self): if self.instStatus == "show": self.instStatus = "hide" groupHide(self.insts) else: # instructions are hidden self.instStatus = "show" groupShow(self.insts) def loadNextMusic(self, task): # random load background music if (self.music.status()!=self.music.PLAYING): # not playing self.musicCounter += 1 index = self.musicCounter % len(_BGMUSIC) self.music = load_bgmusic(_BGMUSIC[index]) self.music.play() return task.cont def spinCamera(self, task): # deal with spinning the camera # _FOCUS: focus point, changed by panning the camera # CAM_R: radius, changed by zooming # cameraSpinCount: amount of spinning, changed by spinning if self.spin == 1: # spin counter-clockwise self.cameraSpinCount += 1 angleDegrees = self.cameraSpinCount angleRadians = angleDegrees * (pi/ 180) self.CAM_RAD = angleRadians camera.setPos(_FOCUS[0]+self.CAM_R*cos(-pi/2+self.CAM_RAD), _FOCUS[1]+self.CAM_R*sin(-pi/2+self.CAM_RAD), (25.0/12)*self.CAM_R) camera.setHpr(angleDegrees,-65,0) elif self.spin == 2: # spin clockwise self.cameraSpinCount -= 1 angleDegrees = self.cameraSpinCount angleRadians = angleDegrees * (pi/ 180) self.CAM_RAD = angleRadians camera.setPos(_FOCUS[0]+self.CAM_R*cos(-pi/2+self.CAM_RAD), _FOCUS[1]+self.CAM_R*sin(-pi/2+self.CAM_RAD), (25.0/12)*self.CAM_R) camera.setHpr(angleDegrees,-65,0) elif self.spin == 3: # ZOOM IN not spin self.cameraZoomCount += 1 deltaR = self.cameraZoomCount * 0.1 new_R = 12-deltaR self.CAM_R = new_R camera.setPos(_FOCUS[0] + self.CAM_R*cos(-pi/2+self.CAM_RAD), _FOCUS[1] + self.CAM_R*sin(-pi/2+self.CAM_RAD), (25.0/12)*new_R) elif self.spin == 4: # ZOOM OUT self.cameraZoomCount -= 1 deltaR = self.cameraZoomCount * 0.1 new_R = 12-deltaR self.CAM_R = new_R camera.setPos(_FOCUS[0] + self.CAM_R*cos(-pi/2+self.CAM_RAD), _FOCUS[1] + self.CAM_R*sin(-pi/2+self.CAM_RAD), (25.0/12)*self.CAM_R) return Task.cont def takeRecord(self): def myCMP(aString, bString): a = float(aString.split(',')[0]) b = float(bString.split(',')[0]) return int(10*(a - b)) msg = "%.2f,%s\n" %(self.clock/100.0, time.ctime()) with open('record.txt') as f: data = f.readlines() # if has no previous data if len(data) == 0: data.append(msg) with open('record.txt','w') as f: f.writelines(data) else: data.append(msg) processedData = sorted(data, myCMP) with open('record.txt', 'w') as f: f.writelines(processedData) def printResults(self): addEndMessage(self.clock) with open('record.txt') as f: data = f.readlines() for i in xrange(0, len(data)): if i < 5: # only print the top 5 string = data[i] printRank(i, string) def checkForWin(self, task): if (checkWin(self.pikachu.getX(), self.pikachu.getY(), self.ballRoot.getX(), self.ballRoot.getY()) and self.gameOver == False): self.takeRecord() self.printResults() self.gameOver = True # if top 10, if top 1, print "WIN" # print previous best 10 results return Task.cont def pikachuBark(self, task): if self.distance < 3: if random.randint(1,200) == 1: # randomly bark dangerous sound if self.dangerous.status() != self.dangerous.PLAYING: self.dangerous.play() elif self.distance > 10: if random.randint(1,430) == 1: if self.safe.status() != self.safe.PLAYING: self.safe.play() return Task.cont def checkMouse(self, task): # get mouse position if base.mouseWatcherNode.hasMouse(): self.mouseX=base.mouseWatcherNode.getMouseX() self.mouseY=base.mouseWatcherNode.getMouseY() return Task.cont def dropRock(self): # when the user clicks, rock is dropped if self.pokeMoveChoice == 1: # selected Geodude result = MAZE.canDropRock(self.rockX, self.rockY) if result != False: # can place rock here MAZE.dropRock(result[0],result[1]) self.rock.setPos(self.rockX, self.rockY, 1) self.rockOnMaze = True self.pokeMoveChoice = None self.myPokeName.hide() self.myPokeName = None self.updateTwoD() self.playerCandyCount -= 1 def restart(self): sys.exit() def useFlame(self): # use flame to Pikachu -> cannot move self.onFire = True # on fire self.playerCandyCount -= 1 self.pokeStatus = 1 self.flame = ParticleEffect() self.flame.loadConfig("fireish.ptf") self.flame.setPos(self.pikachu.getPos()) self.flame.start(parent=render, renderParent=render) self.updateTwoD() def useStringShot(self): # use string shot -> speed goes down self.pokeStatus = 2 self.updateTwoD() def useThunder(self): self.onThunder = True self.pokeCandyCount -= 1 self.thunder = ParticleEffect() self.thunder.loadConfig("thunder.ptf") self.thunder.start(parent=render, renderParent=render) self.use.play() def placeRock(self, task): # rock moves with mouse cursor if self.pokeMoveChoice == 1: # selected Geodude dX,dY = ((self.mouseX-self.rockRefX), (self.mouseY-self.rockRefY)) self.rockX, self.rockY = MAZE.translateRockPosition(self.rockRefX, self.rockRefY, dX, dY) self.rock.show() self.rock.setPos(self.rockX, self.rockY, 1) self.updateTwoD() return Task.cont def placeRareCandy(self, task): # place rare candy with interval # needs to be improved if int(task.time) % 4 == 9 and self.candyOnBoard: self.candy.hide() self.candyOnBoard = False MAZE.clearCandy() if int(task.time) % 10 == 0 and (self.candyOnBoard == False): # every 10 seconds self.candy.setPos(MAZE.generateCandyPos()) self.candy.show() self.candyOnBoard = True return Task.cont def updateTwoD(self): # update player candy count self.playerCandyStatus.destroy() self.playerCandyStatus = candyStatus(0, self.playerCandyCount) self.pokeCandyStatus.destroy() self.pokeCandyStatus = candyStatus(1, self.pokeCandyCount) # update my pokes color if self.playerCandyCount == 0 : groupHide(self.myPokesBright) groupShow(self.myPokesDark) # update name if self.myPokeName != None: self.myPokeName.destroy() def clearRock(self): # clear rock self.rock.hide() self.rockOnMaze = False MAZE.clearRock() # clear it in 2D def clearFlame(self): # clear flame self.onFire = False self.flame.cleanup() self.pokeStatus = 0 self.pokeMoveChoice = None try: self.myPokeName.destroy() except: pass self.myPokeName = None def clearString(self): # clear string shot self.pokeStatus = 0 self.pokeMoveChoice = None try: self.myPokeName.destroy() except: pass self.myPokeName = None def clearThunder(self): self.onThunder = False try: self.thunder.cleanup() except: pass def timer(self, task): # deals with moves' lasting effects ############################################################## self.clock += 1 if self.rockOnMaze: # rock on maze self.rockCounter += 1 elif self.rockCounter != 1: # rock not on maze, counter not cleared self.rockCounter = 0 if self.onFire: self.fireCounter += 1 elif self.fireCounter != 1: self.fireCounter = 0 if self.pokeStatus == 2: # string shot self.stringCounter += 1 elif self.stringCounter != 1: self.stringCounter = 0 if self.onThunder: # thunderbolt self.thunderCounter += 1 elif self.thunderCounter != 1: self.thunderCounter = 0 if self.gameOver == True: # game is over self.gameOverCounter += 1 ################################################################## if self.rockCounter >= 100: self.clearRock() if self.fireCounter >= 80: self.clearFlame() if self.thunderCounter >= 150: self.clearThunder() if self.stringCounter >= 120: self.clearString() if self.gameOverCounter >= 800: # quit the game sys.exit() return Task.cont def usePokeMove(self, number): # use pokemon move if self.playerCandyCount > 0: # have more than one candy if number == 1 and self.rockOnMaze == False: if self.pokeMoveChoice == None: # no choice # set to center position centerx = base.win.getProperties().getXSize()/2 centery = base.win.getProperties().getYSize()/2 base.win.movePointer(0,centerx,centery) self.pokeMoveChoice = 1 # placeRock called here self.rockRefX, self.rockRefY = 0,0 self.rock.show() self.rock.setPos(0,0,1) elif self.pokeMoveChoice != 1: pass else: # self.pokeMoveChoice is already 1, cancel the choice self.pokeMoveChoice = None self.clearRock() # clear rock elif number == 2: if self.pokeMoveChoice == None: self.pokeMoveChoice = 2 self.useFlame() elif self.pokeMoveChoice != 2: pass else: self.pokeMoveChoice = None elif number == 3: if self.pokeMoveChoice == None: self.pokeMoveChoice = 3 self.useStringShot() elif self.pokeMoveChoice != 3: pass else: # already 3 self.pokeMoveChoice = None if self.pokeMoveChoice == None: # no choice if self.myPokeName != None: # there is a name on board self.myPokeName.destroy() # kill it else: # no name pass else: # there is a choice if self.myPokeName != None: self.myPokeName.destroy() self.myPokeName = writePokeName(self.pokeMoveChoice) def loadRareCandy(self): # load rare candy (a box) # needs to be improved self.candy = Model_Load.loadRareCandy() self.candy.reparentTo(render) self.candy.setScale(0.1) self.candy.hide() def eatRareCandy(self, task): # check who eats candy if self.candyOnBoard: # candy on board if checkEat(self.ballRoot.getX(), self.ballRoot.getY(), self.candy.getX(), self.candy.getY()): # ball eats self.candy.hide() # eaten self.candyOnBoard = False if self.playerCandyCount < 3: self.playerCandyCount += 1 groupShow(self.myPokesBright) MAZE.clearCandy() elif checkEatPika(self.pikachu.getX(), self.pikachu.getY(), self.candy.getX(), self.candy.getY()): self.candy.hide() self.candyOnBoard = False if self.pokeCandyCount < 3: self.pokeCandyCount += 1 MAZE.clearCandy() return Task.cont def setFocus(self, changing): # set focus of the camera while panning self.changingFocus = changing if changing == True: # Just Pressed self.referenceX, self.referenceY = self.mouseX, self.mouseY else: # cursor moves up self.referenceX, self.referenceY = None, None def resetView(self): # reset the view to default self.CAM_R, self.CAM_RAD = 12, 0 self.cameraSpinCount, self.cameraZoomCount = 0, 0 # _FOCUS = [0,0,0] does not work WHY??? _FOCUS[0], _FOCUS[1], _FOCUS[2] = 0,0,0 self.changingFocus = False self.referenceX, self.referenceY = None, None camera.setPos(_FOCUS[0], _FOCUS[1]-self.CAM_R, 25) camera.setHpr(0, -65, 0) def changeFocus(self, task): # change focus with displacement of mouse cursor if (self.changingFocus == True and self.mouseX != None and self.mouseY != None ): dX, dY = ((self.mouseX - self.referenceX)*0.1, (self.mouseY - self.referenceY)*0.1) _FOCUS[0] += dX _FOCUS[1] += dY camera.setPos(_FOCUS[0] + self.CAM_R*cos(-pi/2+self.CAM_RAD), _FOCUS[1] + self.CAM_R*sin(-pi/2+self.CAM_RAD), (25.0/12)*self.CAM_R) return Task.cont def thunderbolt(self, task): if self.onThunder == True: self.thunder.setPos(self.ballRoot.getPos()) return Task.cont def displayClock(self, task): msg = "Time: %.2f" %(self.clock/100.0) if self.clockMSG == None: self.clockMSG = OnscreenText(text=msg, style=1, fg=(1,1,1,1), pos=(1.3, .95), align=TextNode.ALeft, scale = .05) else: self.clockMSG.destroy() self.clockMSG = OnscreenText(text=msg, style=1, fg=(1,1,1,1), pos=(1.3, .95), align=TextNode.ALeft, scale = .05) return task.cont def initialize(self): taskMgr.stop() self.musicCounter, self.clock = 0, 0 self.gameOverCounter = 0 self.clockMSG = None self.music = load_bgmusic(_BGMUSIC[0]) self.background = loadBackground() base.cam2dp.node().getDisplayRegion(0).setSort(-20) self.candyOnBoard = False self.playerCandyCount, self.pokeCandyCount = 0, 0 self.gameOver = False self.displayInformation() self.instStatus = "show" ######################Rare Candy############################### pokes=['caterpie', 'charmander', 'geodude'] self.myPokesDark = loadMyPokemon_Dark(pokes) # my pokemons self.myPokesBright = loadMyPokemon_Bright() groupHide(self.myPokesBright) self.loadRareCandy() # load rare candy ######################Camera Initialization#################### self.CAM_R, self.CAM_RAD = 12, 0 camera.setPos(_FOCUS[0],_FOCUS[1]-12,_FOCUS[2]+25) camera.setHpr(0, -65, 0) self.cameraSpinCount, self.cameraZoomCount = 0, 0 self.changingFocus = False self.spin = 0 #######################ICONS################################### self.myIcon = loadMyIcon() self.pokeIcon = loadPokeIcon() self.playerCandyStatus = candyStatus(0, self.playerCandyCount) self.pokeCandyStatus = candyStatus(1, self.pokeCandyCount) self.rareCandyImage = loadRareCandyImage() self.pokeRareCandyImage = loadRareCandyImage(pos=(-.3,0,-.75)) #######################FLAMES################################## base.enableParticles() self.fireCounter = 0 self.onFire = False #######################STRINGSHOT############################# self.stringCounter = 0 #######################THUNDER################################ self.thunderCounter = 0 #######################SOUND################################## self.dangerous = load_sound("pikachu_d.wav") self.safe = load_sound("pikachu_s1.wav") self.use = load_sound("pikachu_u.wav") #######################"GLOBALS"############################## self.speedCounter = 0 self.onThunder = False self.direction = 's' self.myDirection = ['zx', 'zy'] self.rockCounter = 0 self.rockX, self.rockY = None, None self.rockOnMaze = False self.pokeMoveChoice = None self.myPokeName = None self.arrowKeyPressed = False self.pokemonDirection = 'd' self.mouseX, self.mouseY = None, None # direction the ball is going self.jerkDirection = None base.disableMouse() self.jerk = Vec3(0,0,0) self.MAZE = Model_Load.loadLabyrinth() Control.keyControl(self) self.loadPokemonLevel1() self.light() self.loadBall() self.pokeStatus = 0 # 0 is normal, 1 is burned, 2 is slow-speed ########################################ROCK################### self.rock = Model_Load.loadRock() self.rock.reparentTo(render) self.rock.hide() # Do not show, but load beforehand for performance def loadPokemonLevel1(self): self.pikachu = load_model("pikachu.egg") self.pikachu.reparentTo(render) self.pikachu.setScale(0.3) endPos = self.MAZE.find("**/end").getPos() self.pikachu.setPos(endPos) def light(self): ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) def loadBall(self): self.ballRoot = render.attachNewNode("ballRoot") self.ball = load_model("ball") self.ball.reparentTo(self.ballRoot) self.ball_tex = load_tex("pokeball.png") self.ball.setTexture(self.ball_tex,1) self.ball.setScale(0.8) # Find the collision sphere for the ball in egg. self.ballSphere = self.ball.find("**/ball") self.ballSphere.node().setFromCollideMask(BitMask32.bit(0)) self.ballSphere.node().setIntoCollideMask(BitMask32.allOff()) #self.ballSphere.show() # Now we create a ray to cast down at the ball. self.ballGroundRay = CollisionRay() self.ballGroundRay.setOrigin(0,0,10) self.ballGroundRay.setDirection(0,0,-1) # Collision solids go in CollisionNode self.ballGroundCol = CollisionNode('groundRay') self.ballGroundCol.addSolid(self.ballGroundRay) self.ballGroundCol.setFromCollideMask(BitMask32.bit(1)) self.ballGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ballGroundColNp = self.ballRoot.attachNewNode(self.ballGroundCol) # light ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.55, .55, .55, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0,0,-1)) directionalLight.setColor(Vec4(0.375,0.375,0.375,1)) directionalLight.setSpecularColor(Vec4(1,1,1,1)) self.ballRoot.setLight(render.attachNewNode(ambientLight)) self.ballRoot.setLight(render.attachNewNode(directionalLight)) # material to the ball m = Material() m.setSpecular(Vec4(1,1,1,1)) m.setShininess(96) self.ball.setMaterial(m,1) def __init__(self): self.initialize() self.WALLS = self.MAZE.find("**/Wall.004") self.WALLS.node().setIntoCollideMask(BitMask32.bit(0)) # collision with the ground. different bit mask #self.mazeGround = self.maze.find("**/ground_collide") #self.mazeGround.node().setIntoCollideMask(BitMask32.bit(1)) self.MAZEGROUND = self.MAZE.find("**/Cube.004") self.MAZEGROUND.node().setIntoCollideMask(BitMask32.bit(1)) # add collision to the rock cs = CollisionSphere(0, 0, 0, 0.5) self.cnodePath = self.rock.attachNewNode(CollisionNode('cnode')) self.cnodePath.node().addSolid(cs) self.cnodePath.node().setIntoCollideMask(BitMask32.bit(0)) # CollisionTraversers calculate collisions self.cTrav = CollisionTraverser() #self.cTrav.showCollisions(render) #self.cTrav.showCollisions(render) # A list collision handler queue self.cHandler = CollisionHandlerQueue() # add collision nodes to the traverse. # maximum nodes per traverser: 32 self.cTrav.addCollider(self.ballSphere,self.cHandler) self.cTrav.addCollider(self.ballGroundColNp,self.cHandler) self.cTrav.addCollider(self.cnodePath, self.cHandler) # collision traversers have a built-in tool to visualize collisons #self.cTrav.showCollisions(render) self.start() def pokemonTurn(self, pokemon, direction): if direction == 'l' and self.pokemonDirection != 'l': self.pokemonDirection = 'l' pokemon.setH(-90) if direction == 'r' and self.pokemonDirection != 'r': self.pokemonDirection = 'r' pokemon.setH(90) if direction == 'd' and self.pokemonDirection != 'd': self.pokemonDirection = 'd' pokemon.setH(0) if direction == 'u' and self.pokemonDirection != 'u': self.pokemonDirection = 'u' pokemon.setH(180) def pokemonMove(self, pokemon, direction): self.pokemonTurn(pokemon, direction) if self.pokeStatus == 0: speed = _SPEED elif self.pokeStatus == 1: speed = 0 else: # self.pokeStatus == 2 speed = _SPEED/2.0 if direction == 'l': newX = pokemon.getX() - speed pokemon.setX(newX) elif direction == 'r': newX = pokemon.getX() + speed pokemon.setX(newX) elif direction == 'u': newY = pokemon.getY() + speed pokemon.setY(newY) elif direction == 'd': newY = pokemon.getY() - speed pokemon.setY(newY) elif direction == "s": # stop pass def whereToGo(self, task): # this returns the direction pokemon should go # tell MAZE pokemon and ball's board position self.pokemonMove(self.pikachu, self.direction) MAZE.setPokeCoord(self.pikachu.getX(), self.pikachu.getY(), self.pokemonDirection) MAZE.setBallCoord(self.ballRoot.getX(), self.ballRoot.getY()) MAZE.sendInformation(self.myDirection, self.rockOnMaze, self.onThunder, self.playerCandyCount, self.pokeCandyCount, self.distance) # find out which direction to go self.direction = MAZE.getDecision() self.pokemonMove(self.pikachu,self.direction) return Task.cont def whatToDo(self, task): # determines when to use thunder if self.pokeCandyCount > 0: # Pikachu has candies decision = MAZE.useThunderDecision() if decision == True: self.useThunder() return Task.cont def getInformation(self, task): # get information on the board self.speedCounter += 1 # sample every other call to avoid if self.speedCounter % 2 == 0: dX = self.ballRoot.getX() - self.oldPos[0] dY = self.ballRoot.getY() - self.oldPos[1] if dX < 0 : # print "going left" self.myDirection[0] = 'l' elif abs(dX) < _EPSILON: # print "not moving horiz" self.myDirection[0] = 'zx' else: # print "going right" self.myDirection[0] = 'r' if dY < 0 : # print "going down" self.myDirection[1] = 'd' elif abs(dY) < _EPSILON: # print "not moving verti" self.myDirection[1] = 'zy' else: # print "going up" self.myDirection[1] = 'u' self.oldPos = self.ballRoot.getPos() # calculate distance self.distance = MAZE.getDistance() return Task.cont def start(self): # maze model has a locator in it # self.ballRoot.show() self.startPos = self.MAZE.find("**/start").getPos() self.oldPos = self.MAZE.find("**/start").getPos() self.ballRoot.setPos(self.startPos) # set the ball in the pos self.ballV = Vec3(0,0,0) # initial velocity self.accelV = Vec3(0,0,0) # initial acceleration # for a traverser to work, need to call traverser.traverse() # base has a task that does this once a frame base.cTrav = self.cTrav # create the movement task, make sure its not already running taskMgr.remove("rollTask") taskMgr.add(self.placeRock, "placeRock") taskMgr.add(self.displayClock, "displayClock") taskMgr.add(self.timer, "timer") taskMgr.add(self.loadNextMusic, "loadNextMusic") taskMgr.add(self.getInformation, "getInformation") taskMgr.add(self.eatRareCandy, "eatRareCandy") taskMgr.add(self.placeRareCandy, "placeRareCandy") taskMgr.add(self.checkMouse, "checkMouse") taskMgr.add(self.spinCamera, "spinCamera") taskMgr.add(self.changeFocus, "changeFocus") taskMgr.add(self.whereToGo, "whereToGo") taskMgr.add(self.whatToDo, "whatToDo") taskMgr.add(self.moveBall, "moveBall") taskMgr.add(self.thunderbolt, "thunderbolt") taskMgr.add(self.checkForWin, "checkForWin") taskMgr.add(self.pikachuBark, "pikachuBark") self.mainLoop = taskMgr.add(self.rollTask, "rollTask") self.mainLoop.last = 0 def moveBallWrapper(self, direction): # wrapper for moving the ball # needs to be improved if direction == False: self.arrowKeyPressed = False else: self.arrowKeyPressed = True self.jerkDirection = direction def moveBall(self, task): # move the ball # a key press changes the jerk direction = self.jerkDirection if self.arrowKeyPressed == True and self.onThunder == False: if direction == "u": self.jerk = Vec3(0,_JERK,0) elif direction == "d": self.jerk = Vec3(0,-_JERK,0) elif direction == "l": self.jerk = Vec3(-_JERK,0,0) elif direction == "r": self.jerk = Vec3(_JERK,0,0) elif self.onThunder == True: self.jerk = self.jerk return Task.cont # collision between ray and ground # info about the interaction is passed in colEntry def groundCollideHandler(self,colEntry): # set the ball to the appropriate Z for it to be on the ground newZ = colEntry.getSurfacePoint(render).getZ() self.ballRoot.setZ(newZ+.4) # up vector X normal vector norm = colEntry.getSurfaceNormal(render) accelSide = norm.cross(UP) self.accelV = norm.cross(accelSide) # collision between the ball and a wall def wallCollideHandler(self,colEntry): # some vectors needed to do the calculation norm = colEntry.getSurfaceNormal(render) * -1 norm.normalize() curSpeed = self.ballV.length() inVec = self.ballV/curSpeed velAngle = norm.dot(inVec) # angle of incidance hitDir = colEntry.getSurfacePoint(render) - self.ballRoot.getPos() hitDir.normalize() hitAngle = norm.dot(hitDir) # deal with collision cases if velAngle > 0 and hitAngle >.995: # standard reflection equation reflectVec = (norm * norm.dot(inVec*-1)*2) + inVec # makes velocity half of hitting dead-on self.ballV = reflectVec * (curSpeed * (((1-velAngle)*.5)+.5)) # a collision means the ball is already a little bit buried in # move it so exactly touching the wall disp = (colEntry.getSurfacePoint(render) - colEntry.getInteriorPoint(render)) newPos = self.ballRoot.getPos() + disp self.ballRoot.setPos(newPos) def rollTask(self,task): # standard technique for finding the amount of time # since the last frame dt = task.time - task.last task.last = task.time # If dt is large, then there is a HICCUP # ignore the frame if dt > .2: return Task.cont # dispatch which function to handle the collision based on name for i in range(self.cHandler.getNumEntries()): entry = self.cHandler.getEntry(i) name = entry.getIntoNode().getName() if name == "Wall.004": self.wallCollideHandler(entry) elif name=="Cube.004": self.groundCollideHandler(entry) else: if self.rockOnMaze == True: self.wallCollideHandler(entry) self.accelV += self.jerk # move the ball, update the velocity based on accel self.ballV += self.accelV * dt * ACCELERATION # clamp the velocity to the max speed if self.ballV.lengthSquared() > MAX_SPEED_SQ: self.ballV.normalize() self.ballV *= MAX_SPEED # update the position self.ballRoot.setPos(self.ballRoot.getPos() + (self.ballV*dt)) # uses quaternion to rotate the ball prevRot = LRotationf(self.ball.getQuat()) axis = UP.cross(self.ballV) newRot = LRotationf(axis, 45.5 * dt * self.ballV.length()) self.ball.setQuat(prevRot * newRot) return Task.cont # continue the task
class Collision(): def __init__(self, ui): self.ui = ui # Most times, you want collisions to be tested against invisible geometry # rather than every polygon. This is because testing against every polygon # in the scene is usually too slow. You can have simplified or approximate # geometry for the solids and still get good results. # # Sometimes you'll want to create and position your own collision solids in # code, but it's often easier to have them built automatically. This can be # done by adding special tags into an egg file. Check maze.egg and ball.egg # and look for lines starting with <Collide>. The part is brackets tells # Panda exactly what to do. Polyset means to use the polygons in that group # as solids, while Sphere tells panda to make a collision sphere around them # Keep means to keep the polygons in the group as visable geometry (good # for the ball, not for the triggers), and descend means to make sure that # the settings are applied to any subgroups. # # Once we have the collision tags in the models, we can get to them using # NodePath's find command # Find the collision node named wall_collide self.walls = self.ui.maze.find("**/wall_collide") # Collision objects are sorted using BitMasks. BitMasks are ordinary numbers # with extra methods for working with them as binary bits. Every collision # solid has both a from mask and an into mask. Before Panda tests two # objects, it checks to make sure that the from and into collision masks # have at least one bit in common. That way things that shouldn't interact # won't. Normal model nodes have collision masks as well. By default they # are set to bit 20. If you want to collide against actual visable polygons, # set a from collide mask to include bit 20 # # For this example, we will make everything we want the ball to collide with # include bit 0 self.walls.node().setIntoCollideMask(BitMask32.bit(0)) # CollisionNodes are usually invisible but can be shown. Uncomment the next # line to see the collision walls # self.walls.show() # We will now find the triggers for the holes and set their masks to 0 as # well. We also set their names to make them easier to identify during # collisions self.loseTriggers = [] for i in range(6): trigger = self.ui.maze.find("**/hole_collide" + str(i)) trigger.node().setIntoCollideMask(BitMask32.bit(0)) trigger.node().setName("loseTrigger") self.loseTriggers.append(trigger) # Uncomment this line to see the triggers # trigger.show() # Ground_collide is a single polygon on the same plane as the ground in the # maze. We will use a ray to collide with it so that we will know exactly # what height to put the ball at every frame. Since this is not something # that we want the ball itself to collide with, it has a different # bitmask. self.mazeGround = self.ui.maze.find("**/ground_collide") self.mazeGround.node().setIntoCollideMask(BitMask32.bit(1)) # Find the collison sphere for the ball which was created in the egg file # Notice that it has a from collision mask of bit 0, and an into collison # mask of no bits. This means that the ball can only cause collisions, not # be collided into self.ballSphere = self.ui.ball.find("**/ball") self.ballSphere.node().setFromCollideMask(BitMask32.bit(0)) self.ballSphere.node().setIntoCollideMask(BitMask32.allOff()) # No we create a ray to start above the ball and cast down. This is to # Determine the height the ball should be at and the angle the floor is # tilting. We could have used the sphere around the ball itself, but it # would not be as reliable self.ballGroundRay = CollisionRay() # Create the ray self.ballGroundRay.setOrigin(0, 0, 10) # Set its origin self.ballGroundRay.setDirection(0, 0, -1) # And its direction # Collision solids go in CollisionNode self.ballGroundCol = CollisionNode( 'groundRay') # Create and name the node self.ballGroundCol.addSolid(self.ballGroundRay) # Add the ray self.ballGroundCol.setFromCollideMask( BitMask32.bit(1)) # Set its bitmasks self.ballGroundCol.setIntoCollideMask(BitMask32.allOff()) # Attach the node to the ballRoot so that the ray is relative to the ball # (it will always be 10 feet over the ball and point down) self.ballGroundColNp = self.ui.ballRoot.attachNewNode( self.ballGroundCol) # Uncomment this line to see the ray # self.ballGroundColNp.show() # Finally, we create a CollisionTraverser. CollisionTraversers are what # do the job of calculating collisions self.cTrav = CollisionTraverser() # Collision traverservs tell collision handlers about collisions, and then # the handler decides what to do with the information. We are using a # CollisionHandlerQueue, which simply creates a list of all of the # collisions in a given pass. There are more sophisticated handlers like # one that sends events and another that tries to keep collided objects # apart, but the results are often better with a simple queue self.cHandler = CollisionHandlerQueue() # Now we add the collision nodes that can create a collision to the # traverser. The traverser will compare these to all others nodes in the # scene. There is a limit of 32 CollisionNodes per traverser # We add the collider, and the handler to use as a pair self.cTrav.addCollider(self.ballSphere, self.cHandler) self.cTrav.addCollider(self.ballGroundColNp, self.cHandler)
class RoamingRalphDemo(ShowBase): def __init__(self): # Set up the window, camera, etc. ShowBase.__init__(self) base.render.setAttrib(LightRampAttrib.makeHdr0()) # Configure depth pre-pass prepass_pass = lionrender.DepthScenePass() # Configure scene pass scene_fb_props = FrameBufferProperties() scene_fb_props.set_rgb_color(True) scene_fb_props.set_rgba_bits(8, 8, 8, 0) scene_fb_props.set_depth_bits(32) scene_pass = lionrender.ScenePass( frame_buffer_properties=scene_fb_props, clear_color=LColor(0.53, 0.80, 0.92, 1), share_depth_with=prepass_pass) scene_pass.node_path.set_depth_write(False) # Configure post processing filter_pass = lionrender.FilterPass(fragment_path='shaders/fsq.frag') filter_pass.node_path.set_shader_input('inputTexture', scene_pass.output) # Enable FXAA fxaa_pass = lionrender.FxaaFilterPass() fxaa_pass.node_path.set_shader_input('inputTexture', filter_pass.output) # Output result fxaa_pass.output_to(render2d) # This is used to store which keys are currently pressed. self.keyMap = { "left": 0, "right": 0, "forward": 0, "backward": 0, "cam-left": 0, "cam-right": 0, } # Post the instructions self.title = addTitle( "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.06, "[ESC]: Quit") self.inst2 = addInstructions(0.12, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.18, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.24, "[Up Arrow]: Run Ralph Forward") self.inst5 = addInstructions(0.30, "[Down Arrow]: Walk Ralph Backward") self.inst6 = addInstructions(0.36, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.42, "[S]: Rotate Camera Right") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) # We do not have a skybox, so we will just use a sky blue background color self.setBackgroundColor(0.53, 0.80, 0.92, 1) # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", { "run": "models/ralph-run", "walk": "models/ralph-walk" }) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos + (0, 0, 1.5)) # Create a floater object, which floats 2 units above ralph. We # use this as a target for the camera to look at. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(self.ralph) self.floater.setZ(2.0) # Accept the control keys for movement and rotation self.accept("escape", sys.exit) self.accept("arrow_left", self.setKey, ["left", True]) self.accept("arrow_right", self.setKey, ["right", True]) self.accept("arrow_up", self.setKey, ["forward", True]) self.accept("arrow_down", self.setKey, ["backward", True]) self.accept("a", self.setKey, ["cam-left", True]) self.accept("s", self.setKey, ["cam-right", True]) self.accept("arrow_left-up", self.setKey, ["left", False]) self.accept("arrow_right-up", self.setKey, ["right", False]) self.accept("arrow_up-up", self.setKey, ["forward", False]) self.accept("arrow_down-up", self.setKey, ["backward", False]) self.accept("a-up", self.setKey, ["cam-left", False]) self.accept("s-up", self.setKey, ["cam-right", False]) self.accept("v", self.toggleCards) taskMgr.add(self.move, "moveTask") # Set up the camera self.disableMouse() self.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 2) self.cTrav = CollisionTraverser() # Use a CollisionHandlerPusher to handle collisions between Ralph and # the environment. Ralph is added as a "from" object which will be # "pushed" out of the environment if he walks into obstacles. # # Ralph is composed of two spheres, one around the torso and one # around the head. They are slightly oversized since we want Ralph to # keep some distance from obstacles. self.ralphCol = CollisionNode('ralph') self.ralphCol.addSolid(CollisionSphere(center=(0, 0, 2), radius=1.5)) self.ralphCol.addSolid( CollisionSphere(center=(0, -0.25, 4), radius=1.5)) self.ralphCol.setFromCollideMask(CollideMask.bit(0)) self.ralphCol.setIntoCollideMask(CollideMask.allOff()) self.ralphColNp = self.ralph.attachNewNode(self.ralphCol) self.ralphPusher = CollisionHandlerPusher() self.ralphPusher.horizontal = True # Note that we need to add ralph both to the pusher and to the # traverser; the pusher needs to know which node to push back when a # collision occurs! self.ralphPusher.addCollider(self.ralphColNp, self.ralph) self.cTrav.addCollider(self.ralphColNp, self.ralphPusher) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 9) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(CollideMask.bit(0)) self.ralphGroundCol.setIntoCollideMask(CollideMask.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0, 0, 9) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(CollideMask.bit(0)) self.camGroundCol.setIntoCollideMask(CollideMask.allOff()) self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection((-5, -5, -5)) directionalLight.setColor((1, 1, 1, 1)) directionalLight.setSpecularColor((1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) # Clean up texture attributes for texture in self.render.find_all_textures(): texture.set_format(Texture.F_srgb) # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # Get the time that elapsed since last frame. We multiply this with # the desired speed in order to find out with which distance to move # in order to achieve that desired speed. dt = globalClock.getDt() # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. if self.keyMap["cam-left"]: self.camera.setX(self.camera, -20 * dt) if self.keyMap["cam-right"]: self.camera.setX(self.camera, +20 * dt) # If a move-key is pressed, move ralph in the specified direction. if self.keyMap["left"]: self.ralph.setH(self.ralph.getH() + 300 * dt) if self.keyMap["right"]: self.ralph.setH(self.ralph.getH() - 300 * dt) if self.keyMap["forward"]: self.ralph.setY(self.ralph, -20 * dt) if self.keyMap["backward"]: self.ralph.setY(self.ralph, +10 * dt) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. currentAnim = self.ralph.getCurrentAnim() if self.keyMap["forward"]: if currentAnim != "run": self.ralph.loop("run") elif self.keyMap["backward"]: # Play the walk animation backwards. if currentAnim != "walk": self.ralph.loop("walk") self.ralph.setPlayRate(-1.0, "walk") elif self.keyMap["left"] or self.keyMap["right"]: if currentAnim != "walk": self.ralph.loop("walk") self.ralph.setPlayRate(1.0, "walk") else: if currentAnim is not None: self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - self.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if camdist > 10.0: self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if camdist < 5.0: self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Normally, we would have to call traverse() to check for collisions. # However, the class ShowBase that we inherit from has a task to do # this for us, if we assign a CollisionTraverser to self.cTrav. #self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z entries = list(self.ralphGroundHandler.entries) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) for entry in entries: if entry.getIntoNode().getName() == "terrain": self.ralph.setZ(entry.getSurfacePoint(render).getZ()) # Keep the camera at one unit above the terrain, # or two units above ralph, whichever is greater. entries = list(self.camGroundHandler.entries) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) for entry in entries: if entry.getIntoNode().getName() == "terrain": self.camera.setZ(entry.getSurfacePoint(render).getZ() + 1.5) if self.camera.getZ() < self.ralph.getZ() + 2.0: self.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.camera.lookAt(self.floater) return task.cont def toggleCards(self): self.bufferViewer.toggleEnable()
class World(DirectObject): global bk_text bk_text = ' ' def __init__(self): global speed global maxspeed self.keyMap = {"left":0, "right":0, "forward":0, "accelerate":0, "decelerate":0, "cam-left":0, "cam-right":0} base.win.setClearColor(Vec4(0,0,0,1)) # Post the instructions self.title = addTitle("HW2: Roaming Ralph Modified (Walking on the Moon) with friends") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[A]: Rotate Ralph Left") self.inst3 = addInstructions(0.85, "[D]: Rotate Ralph Right") self.inst4 = addInstructions(0.80, "[W]: Move Ralph Forward") self.inst5 = addInstructions(0.75, "[P]: Increase Ralph Velocity (Run)") self.inst6 = addInstructions(0.70, "[O]: Decrease Ralph Velocity (Walk)") self.inst7 = addInstructions(0.60, "[Left Arrow]: Rotate Camera Left") self.inst8 = addInstructions(0.55, "[Right Arrow]: Rotate Camera Right") # Set up the environment self.environ = loader.loadModel("models/square") self.environ.reparentTo(render) self.environ.setPos(0,0,0) self.environ.setScale(100,100,1) self.moon_tex = loader.loadTexture("models/moon_1k_tex.jpg") self.environ.setTexture(self.moon_tex, 1) # Create the main character, Ralph if(v ==[0]): print(model) self.ralph = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.ralph.setScale(.2) elif(v == [1]): print(model) self.ralph = Actor("models/panda-model", {"walk": "models/panda-walk4"}) speed = 100 maxspeed =10000 self.ralph.setScale(0.0001, 0.00015, 0.0005) self.ralph.setScale(.002) self.ralph.setPlayRate(100.0, "models/panda-walk4") speed = 100 maxspeed =10000 self.ralph.setScale(.0035) else: print(model) self.ralph = Actor("models/GroundRoamer.egg") self.ralph.setScale(.15) self.ralph.setHpr(180,0,0) self.Groundroamer_texture = loader.loadTexture("models/Groundroamer.tif") self.ralph.setTexture(self.Groundroamer_texture) self.ralph.reparentTo(render) self.ralph.setPos(0,0,0) #creates Earth self.earth = Actor("models/planet_sphere.egg.pz") self.earth.reparentTo(render) self.earth.setScale(6.0) self.earth.setPos(40,25,6) self.earth_texture = loader.loadTexture("models/earth_1k_tex.jpg") self.earth.setTexture(self.earth_texture) #creates Mercury self.mercury = Actor("models/planet_sphere.egg.pz") self.mercury.reparentTo(render) self.mercury.setScale(2.0) self.mercury.setPos(-40,-25,2) self.mercury_texture = loader.loadTexture("models/mercury_1k_tex.jpg") self.mercury.setTexture(self.mercury_texture) #creates Venus self.venus = Actor("models/planet_sphere.egg.pz") self.venus.reparentTo(render) self.venus.setScale(4.0) self.venus.setPos(40,-30,4) self.venus_texture = loader.loadTexture("models/venus_1k_tex.jpg") self.venus.setTexture(self.venus_texture) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation self.accept("escape", sys.exit) self.accept("a", self.setKey, ["left",1]) self.accept("d", self.setKey, ["right",1]) self.accept("w", self.setKey, ["forward",1]) self.accept("s", self.setKey, ["backward",1]) self.accept("arrow_left", self.setKey, ["cam-left",1]) self.accept("arrow_right", self.setKey, ["cam-right",1]) self.accept("a-up", self.setKey, ["left",0]) self.accept("d-up", self.setKey, ["right",0]) self.accept("w-up", self.setKey, ["forward",0]) self.accept("arrow_left-up", self.setKey, ["cam-left",0]) self.accept("arrow_right-up", self.setKey, ["cam-right",0]) self.accept("p", self.setKey, ["accelerate",1]) self.accept("o", self.setKey, ["decelerate",1]) self.accept("p-up", self.setKey, ["accelerate",0]) self.accept("o-up", self.setKey, ["decelerate",0]) taskMgr.add(self.move,"moveTask") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(),self.ralph.getY()+10,2) self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 9) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(CollideMask.bit(0)) self.ralphGroundCol.setIntoCollideMask(CollideMask.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0, 0, 9) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(CollideMask.bit(0)) self.camGroundCol.setIntoCollideMask(CollideMask.allOff()) #self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() #self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) 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()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # pring the inital position #print startpos global speed global maxspeed # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"]!=0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"]!=0): if (v == [2]): self.ralph.setY(self.ralph, speed * globalClock.getDt()) else: self.ralph.setY(self.ralph, -speed * globalClock.getDt()) if (self.keyMap["accelerate"]!=0): speed += 100 if (speed > maxspeed): speed = maxspeed elif (self.keyMap["decelerate"]!=0): speed -= 1 if (speed < 10.0): speed = 10.0 # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) or (self.keyMap["right"]!=0): if self.isMoving is False: self.ralph.loop("walk") self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk",5) self.isMoving = False speed = 10.0 # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) return task.cont
class World(DirectObject): def __init__(self): self.keyMap = {"left":0, "right":0, "forward":0, "backward":0} base.win.setClearColor(Vec4(0,0,0,1)) # number of collectibles self.numObjects = 10; # print the number of objects printNumObj(self.numObjects) # Post the instructions self.title = addTitle("Roaming Ralph (Edited by Adam Gressen)") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[A]: Rotate Ralph Left") self.inst3 = addInstructions(0.85, "[D]: Rotate Ralph Right") self.inst4 = addInstructions(0.80, "[W]: Run Ralph Forward") self.inst5 = addInstructions(0.75, "[S]: Run Ralph Backward") self.inst6 = addInstructions(0.70, "[Space]: Run, Ralph, Run") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0,0,0) # Timer to increment in the move task self.time = 0 # Get bounds of environment min, max = self.environ.getTightBounds() self.mapSize = max-min # Create the main character, Ralph self.ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(self.ralphStartPos) # ralph's health self.health = 100 # ralph's stamina self.stamina = 100 # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation self.accept("escape", sys.exit) # these don't work well in combination with the space bar 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("arrow_down", self.setKey, ["backward",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("arrow_down-up", self.setKey, ["backward",0]) self.accept("space", self.runRalph, [True]) self.accept("space-up", self.runRalph, [False]) self.accept("a", self.setKey, ["left",1]) self.accept("d", self.setKey, ["right",1]) self.accept("w", self.setKey, ["forward",1]) self.accept("s", self.setKey, ["backward",1]) self.accept("a-up", self.setKey, ["left",0]) self.accept("d-up", self.setKey, ["right",0]) self.accept("w-up", self.setKey, ["forward",0]) self.accept("s-up", self.setKey, ["backward",0]) # Game state variables self.isMoving = False self.isRunning = False # Set up the camera base.disableMouse() #base.camera.setPos(self.ralph.getX(),self.ralph.getY()+10,2) base.camera.setPos(0, 0, 0) base.camera.reparentTo(self.ralph) base.camera.setPos(0, 40, 2) base.camera.lookAt(self.ralph) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. base.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,300) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) # camera ground collision handler self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0,0,300) self.camGroundRay.setDirection(0,0,-1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(BitMask32.bit(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Place the health items self.placeHealthItems() # Place the collectibles self.placeCollectibles() # Uncomment this line to show a visual representation of the # collisions occuring #base.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) taskMgr.add(self.move,"moveTask") taskMgr.doMethodLater(0.5, self.healthDec, "healthTask") # reinitialize all necessary parts of the game def restart(self): self.numObjects = 10 printNumObj(self.numObjects) self.ralph.setPos(self.ralphStartPos) self.health = 100 self.stamina = 100 self.time = 0 base.camera.setPos(0, 0, 0) base.camera.reparentTo(self.ralph) base.camera.setPos(0, 40, 2) base.camera.lookAt(self.ralph) self.placeHealthItems() self.placeCollectibles() taskMgr.add(self.move,"moveTask") taskMgr.doMethodLater(0.5, self.healthDec, "healthTask") # Display ralph's health def displayHealth(self): healthBar['scale'] = (self.health*0.01*BAR_WIDTH,0.2,0.2) # Display ralph's stamina def displayStamina(self): sprintBar['scale'] = (self.stamina*0.01*BAR_WIDTH,0.2,0.2) # Allow ralph to collect the health items def collectHealthItems(self, entry): # refill ralph's health self.health = 100 # reposition the collectible self.placeItem(entry.getIntoNodePath().getParent()) def collectCollectibles(self, entry): # remove the collectible entry.getIntoNodePath().getParent().removeNode() # update the number of objects self.numObjects -= 1 printNumObj(self.numObjects) # Places an item randomly on the map def placeItem(self, item): # Add ground collision detector to the health item self.collectGroundRay = CollisionRay() self.collectGroundRay.setOrigin(0,0,300) self.collectGroundRay.setDirection(0,0,-1) self.collectGroundCol = CollisionNode('colRay') self.collectGroundCol.addSolid(self.collectGroundRay) self.collectGroundCol.setFromCollideMask(BitMask32.bit(0)) self.collectGroundCol.setIntoCollideMask(BitMask32.allOff()) self.collectGroundColNp = item.attachNewNode(self.collectGroundCol) self.collectGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.collectGroundColNp, self.collectGroundHandler) placed = False; while placed == False: # re-randomize position item.setPos(-random.randint(0,140),-random.randint(0,40),0) base.cTrav.traverse(render) # Get Z position from terrain collision entries = [] for j in range(self.collectGroundHandler.getNumEntries()): entry = self.collectGroundHandler.getEntry(j) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): item.setZ(entries[0].getSurfacePoint(render).getZ()+1) placed = True # remove placement collider self.collectGroundColNp.removeNode() def placeHealthItems(self): self.placeholder = render.attachNewNode("HealthItem-Placeholder") self.placeholder.setPos(0,0,0) # Add the health items to the placeholder node for i in range(5): # Load in the health item model self.healthy = loader.loadModel("models/sphere") self.healthy.setPos(0,0,0) self.healthy.reparentTo(self.placeholder) self.placeItem(self.healthy) # Add spherical collision detection healthSphere = CollisionSphere(0,0,0,1) sphereNode = CollisionNode('healthSphere') sphereNode.addSolid(healthSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.healthy.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) def placeCollectibles(self): self.placeCol = render.attachNewNode("Collectible-Placeholder") self.placeCol.setPos(0,0,0) # Add the health items to the placeCol node for i in range(self.numObjects): # Load in the health item model self.collect = loader.loadModel("models/jack") self.collect.setPos(0,0,0) self.collect.reparentTo(self.placeCol) self.placeItem(self.collect) # Add spherical collision detection colSphere = CollisionSphere(0,0,0,1) sphereNode = CollisionNode('colSphere') sphereNode.addSolid(colSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.collect.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Makes ralph's health decrease over time def healthDec(self, task): if (self.health <= 0): self.die() elif (self.numObjects != 0): self.health -= 1 print self.health return task.again else: return task.done # Make ralph's stamina regenerate def staminaReg(self, task): if (self.stamina >= 100): self.stamina = 100 return task.done else: self.stamina += 1 task.setDelay(1) return task.again # Make ralph run def runRalph(self, arg): self.isRunning = arg # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): if self.numObjects != 0: # print the time self.time += globalClock.getDt() timeText['text'] = str(self.time) else: self.die() # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # calculate ralph's speed if (self.isRunning and self.stamina > 0): taskMgr.remove("staminaTask") ralphSpeed = 45 self.stamina -= 0.5 else: taskMgr.doMethodLater(5, self.staminaReg, "staminaTask") ralphSpeed = 25 # If a move-key is pressed, move ralph in the specified direction. # and rotate the camera to remain behind ralph if (self.keyMap["left"]!=0): self.ralph.setH(self.ralph.getH() + 100 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - 100 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.ralph.setY(self.ralph, -ralphSpeed * globalClock.getDt()) if (self.keyMap["backward"]!=0): self.ralph.setY(self.ralph, ralphSpeed *globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. 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.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk",5) self.isMoving = False # so the following line is unnecessary base.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) #base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+5) elif (len(entries)>0) and (entries[0].getIntoNode().getName() == "healthSphere"): self.collectHealthItems(entries[0]) elif (len(entries)>0) and (entries[0].getIntoNode().getName() == "colSphere"): self.collectCollectibles(entries[0]) else: self.ralph.setPos(startpos) # Keep the camera above the terrain entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): modZ = entries[0].getSurfacePoint(render).getZ() base.camera.setZ(20.0+modZ+(modZ-self.ralph.getZ())) self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ()+2.0) base.camera.lookAt(self.floater) self.displayHealth() self.displayStamina() return task.cont # Restart or End? def die(self): # end all running tasks taskMgr.remove("moveTask") taskMgr.remove("healthTask") # open the file f = open('scores.txt', 'r') # current name, time, and collected items score n = f.readline() t = f.readline() c = f.readline() # close the file f.close() # number of collected collectibles colObj = 10 - self.numObjects # enter new high score if int(c) < colObj or (int(c) == colObj and float(t) > self.time): self.label = DirectLabel(text="New High Score! Enter Your Name:", scale=.05, pos=(0,0,0.2)) self.entry = DirectEntry(text="", scale=.05, initialText="", numLines=1, focus=1, pos=(-0.25,0,0), command=self.submitScore) else: # display high score self.highscore = OkDialog(dialogName="highscoreDialog", text="Current High Score:\n\nName: " + n + "Time: " + t + "Items Collected: " + c, command=self.showDialog) def showDialog(self, arg): # cleanup highscore dialog self.highscore.cleanup() # display restart or exit dialog self.dialog = YesNoDialog(dialogName="endDialog", text="Would you like to play again?", command=self.endResult) def submitScore(self, name): f = open('scores.txt', 'w') # add new high score value = name + '\n' + str(self.time) + '\n' + str(10 - self.numObjects) f.write(value) f.close() self.entry.remove() self.label.remove() self.dialog = YesNoDialog(dialogName="endDialog", text="Would you like to play again?", command=self.endResult) # Handle the dialog result def endResult(self, arg): if (arg): # cleanup the dialog box self.dialog.cleanup() # restart the game self.restart() else: sys.exit()
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()
class World(DirectObject): def __init__(self): self.startvar = 0 self.startdialog = YesNoDialog(dialogName="START GAME", text="START GAME", command=self.endbox) self.timepass = model() self.timepass1 = model1() self.keyMap = {"left": 0, "right": 0, "forward": 0, "backward": 0} base.win.setClearColor(Vec4(0, 0, 0, 1)) # number of collectibles self.numObjects = 0 #music self.backmusic = base.loader.loadSfx("sounds/tales.mp3") self.backmusic.setLoop(True) self.backmusic.setVolume(0.2) self.backmusic.play() self.skatemusic = base.loader.loadSfx("sounds/skate.mp3") self.skatemusic.setVolume(.65) self.skatemusic.setLoop(True) self.bombmusic = base.loader.loadSfx("sounds/bomb.mp3") self.bombmusic.setVolume(.85) self.springmusic = base.loader.loadSfx("sounds/spring.mp3") self.springmusic.setVolume(.65) self.springmusic.setLoop(True) self.colmusic = base.loader.loadSfx("sounds/collect.mp3") self.colmusic.setVolume(.65) # print the number of objects printNumObj(self.numObjects) # Post the instructions # self.title = addTitle("Roaming Ralph (Edited by Adam Gressen)") # self.inst1 = addInstructions(0.95, "[ESC]: Quit") # self.inst2 = addInstructions(0.90, "[A]: Rotate Ralph Left") # self.inst3 = addInstructions(0.85, "[D]: Rotate Ralph Right") # self.inst4 = addInstructions(0.80, "[W]: Run Ralph Forward") # self.inst5 = addInstructions(0.75, "[S]: Run Ralph Backward") # self.inst6 = addInstructions(0.70, "[Space]: Run, Ralph, Run") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0, 0, 0) # Timer to increment in the move task self.time = 0 # Get bounds of environment min, max = self.environ.getTightBounds() self.mapSize = max - min # Create the main character, Ralph self.ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor( "models/ralph", { "run": "models/ralph-run", "jump": "models/ralph-jump", "walk": "models/ralph-walk" }) self.ralph.reparentTo(render) self.ralph.setScale(.30) self.ralph.setPos(self.ralphStartPos) #skate self.skate = loader.loadModel("models/Skateboard") self.skate.reparentTo(render) self.skate.setScale(.02) self.skate.setPos(-random.randint(38, 50), -random.randint(15, 37), -0.015) # ralph's health self.health = 100 #spring self.spring = loader.loadModel("models/spring") self.spring.reparentTo(render) self.spring.setScale(.8) self.spring.setPos(-random.randint(72, 78), -random.randint(10, 15), 6.715) # ralph's stamina self.stamina = 100 # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation self.accept("escape", sys.exit) # these don't work well in combination with the space bar 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("arrow_down", self.setKey, ["backward", 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("arrow_down-up", self.setKey, ["backward", 0]) self.accept("a", self.setKey, ["left", 1]) self.accept("d", self.setKey, ["right", 1]) self.accept("w", self.setKey, ["forward", 1]) self.accept("s", self.setKey, ["backward", 1]) self.accept("a-up", self.setKey, ["left", 0]) self.accept("d-up", self.setKey, ["right", 0]) self.accept("w-up", self.setKey, ["forward", 0]) self.accept("s-up", self.setKey, ["backward", 0]) # Game state variables self.isMoving = False self.isRunning = False self.onboard = 0 self.boardtime = 0 self.onspring = 0 self.isjumping = False # Set up the camera base.disableMouse() #base.camera.setPos(self.ralph.getX(),self.ralph.getY()+10,2) base.camera.setPos(0, 0, 0) base.camera.reparentTo(self.ralph) base.camera.setPos(0, 40, 2) base.camera.lookAt(self.ralph) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. base.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 300) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) # camera ground collision handler self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0, 0, 300) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(BitMask32.bit(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Place the health items self.placeHealthItems() # Place the collectibles self.placeCollectibles() # Place the bomb self.placebombItems() # Uncomment this line to show a visual representation of the # collisions occuring #base.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) #print self.startvar taskMgr.add(self.move, "moveTask") #taskMgr.doMethodLater(0.5, self.healthDec, "healthTask") # Display ralph's health def displayHealth(self): healthBar['scale'] = (self.health * 0.01 * BAR_WIDTH, 0.2, 0.2) # Display ralph's stamina def displayStamina(self): sprintBar['scale'] = (self.stamina * 0.01 * BAR_WIDTH, 0.2, 0.2) # Allow ralph to collect the health items def collectHealthItems(self, entry): # refill ralph's health self.colmusic.play() if (self.health < 100): self.health = self.health + 15.5 # reposition the collectible self.placeItem(entry.getIntoNodePath().getParent()) def collectCollectibles(self, entry): # remove the collectible #entry.getIntoNodePath().getParent().removeNode() self.colmusic.play() self.placeItem(entry.getIntoNodePath().getParent()) # update the number of objects self.numObjects += 1 #self.tot=10-self.numObjects printNumObj(self.numObjects) def blastbomb(self): # remove the collectible #self.placeItem(entry.getIntoNodePath().getParent()) # blast self.fire = loader.loadModel("models/fire") self.fire.reparentTo(render) self.fire.setScale(.01) self.fire.setHpr(0, -90, 0) self.bombmusic.play() self.backmusic.stop() self.fire.setPos(self.ralph.getPos()) self.die() # Places an item randomly on the map def placeItem(self, item): # Add ground collision detector to the health item self.collectGroundRay = CollisionRay() self.collectGroundRay.setOrigin(0, 0, 300) self.collectGroundRay.setDirection(0, 0, -1) self.collectGroundCol = CollisionNode('colRay') self.collectGroundCol.addSolid(self.collectGroundRay) self.collectGroundCol.setFromCollideMask(BitMask32.bit(0)) self.collectGroundCol.setIntoCollideMask(BitMask32.allOff()) self.collectGroundColNp = item.attachNewNode(self.collectGroundCol) self.collectGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.collectGroundColNp, self.collectGroundHandler) placed = False while placed == False: # re-randomize position item.setPos(-random.randint(-40, 140), -random.randint(-40, 40), 0) base.cTrav.traverse(render) # Get Z position from terrain collision entries = [] for j in range(self.collectGroundHandler.getNumEntries()): entry = self.collectGroundHandler.getEntry(j) entries.append(entry) entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): item.setZ(entries[0].getSurfacePoint(render).getZ() + 1) placed = True # remove placement collider self.collectGroundColNp.removeNode() def placeHealthItems(self): self.placeholder = render.attachNewNode("HealthItem-Placeholder") self.placeholder.setPos(0, 0, 0) # Add the health items to the placeholder node for i in range(5): # Load in the health item model self.healthy = loader.loadModel("models/sphere") self.healthy.setPos(0, 0, 0) self.healthy.setScale(.4) self.healthy.reparentTo(self.placeholder) self.placeItem(self.healthy) # Add spherical collision detection healthSphere = CollisionSphere(0, 0, 0, 1.4) sphereNode = CollisionNode('healthSphere') sphereNode.addSolid(healthSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.healthy.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) #bomb def placebombItems(self): self.placebomb = render.attachNewNode("bomb-Placeholder") self.placebomb.setPos(0, 0, 0) # Add the bomb items to the placeholder node for i in range(30): # Load in the health item model self.bomby = loader.loadModel("models/bomb") self.bomby.setPos(0, 0, 0) self.bomby.setScale(.4) self.bomby.reparentTo(self.placebomb) self.placeItem(self.bomby) # Add spherical collision detection bombSphere = CollisionSphere(0, 0, 0, 1.4) sphereNode = CollisionNode('bombSphere') sphereNode.addSolid(bombSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.bomby.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) #blue def placeCollectibles(self): self.placeCol = render.attachNewNode("Collectible-Placeholder") self.placeCol.setPos(0, 0, 0) # Add the health items to the placeCol node for i in range(50): # Load in the health item model self.collect = loader.loadModel("models/jack") self.collect.setPos(0, 0, 0) self.collect.setScale(.4) self.collect.reparentTo(self.placeCol) self.placeItem(self.collect) # Add spherical collision detection colSphere = CollisionSphere(0, 0, 0, 1.4) sphereNode = CollisionNode('colSphere') sphereNode.addSolid(colSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.collect.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Makes ralph's health decrease over time # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): #print self.ralph.getPos() self.time += globalClock.getDt() timeText['text'] = str(self.time) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. # and rotate the camera to remain behind ralph if (self.keyMap["left"] != 0) and (self.onboard == 0): self.ralph.setH(self.ralph.getH() + 100 * globalClock.getDt()) if (self.keyMap["right"] != 0) and (self.onboard == 0): self.ralph.setH(self.ralph.getH() - 100 * globalClock.getDt()) if (self.keyMap["forward"] != 0) and (self.onboard == 0): self.ralph.setY(self.ralph, -45 * globalClock.getDt()) if (self.keyMap["backward"] != 0) and (self.onboard == 0): self.ralph.setY(self.ralph, 45 * globalClock.getDt()) if (self.keyMap["forward"] != 0) and (self.onboard == 0) and (self.onspring > 0): self.ralph.setY(self.ralph, -65 * globalClock.getDt()) if (self.keyMap["backward"] != 0) and (self.onboard == 0) and (self.onspring > 0): self.ralph.setY(self.ralph, +65 * globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.isMoving): if (self.health <= 0): self.ralph.setPos(10000, 10000, 1000) self.ralph.stop() self.blastbomb() else: self.health -= .07 if ((self.keyMap["forward"] != 0) or (self.keyMap["left"] != 0) or (self.keyMap["right"] != 0) or (self.keyMap["backward"] != 0)) and (self.onboard == 0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving and (self.onspring == 0): self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False #skate if (math.fabs(self.skate.getX() - self.ralph.getX()) < 2) and (math.fabs(self.skate.getY() - self.ralph.getY()) < 5) and (self.onspring == 0) and (self.onboard == 0): self.onboard = 1 self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False self.isjumping = False self.skatemusic.play() if (self.onboard == 1): if (self.keyMap["left"] != 0): self.ralph.setH(self.ralph.getH() + 60 * globalClock.getDt()) self.skate.setH(self.ralph.getH()) if (self.keyMap["right"] != 0): self.ralph.setH(self.ralph.getH() - 60 * globalClock.getDt()) self.skate.setH(self.ralph.getH()) if (self.keyMap["forward"] != 0): self.ralph.setY(self.ralph, -100 * globalClock.getDt()) self.skate.setY(self.ralph.getY()) self.skate.setZ(self.ralph.getZ()) self.skate.setX(self.ralph.getX()) if (self.keyMap["backward"] != 0): self.ralph.setY(self.ralph, 100 * globalClock.getDt()) self.skate.setY(self.ralph.getY()) self.skate.setZ(self.ralph.getZ()) self.skate.setX(self.ralph.getX()) self.boardtime = self.boardtime + 1 #self.ralph.stop() #self.ralph.pose("walk",5) #print self.onboard if (self.boardtime == 1000): self.onboard = 0 self.boardtime = 0 self.skate.setPos(-random.randint(72, 78), -random.randint(10, 15), 6.715) self.skatemusic.stop() #spring #spring if (math.fabs(self.spring.getX() - self.ralph.getX()) < 2) and (math.fabs(self.spring.getY() - self.ralph.getY()) < 2) and (self.onboard == 0) and (self.onspring == 0): self.onspring = 500 self.springmusic.play() self.spring.setPos(-random.randint(38, 50), -random.randint(15, 37), -0.015) if (self.onspring > 0): self.onspring = self.onspring - 1 #print self.onspring if (self.isjumping is False): self.ralph.loop("jump") self.isjumping = True else: #print self.ralph.getX() if self.isjumping: if ((self.keyMap["forward"] != 0) or (self.keyMap["left"] != 0) or (self.keyMap["right"] != 0)): self.ralph.loop("run") self.isMoving = True else: self.ralph.stop() self.ralph.pose("walk", 5) self.isjumping = False self.onspring = 0 self.springmusic.stop() # so the following line is unnecessary base.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) #base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+5) elif (len(entries) > 0) and (entries[0].getIntoNode().getName() == "healthSphere"): self.collectHealthItems(entries[0]) elif (len(entries) > 0) and (entries[0].getIntoNode().getName() == "colSphere"): self.collectCollectibles(entries[0]) elif (len(entries) > 0) and (entries[0].getIntoNode().getName() == "bombSphere"): self.blastbomb() else: self.ralph.setPos(startpos) # Keep the camera above the terrain entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): modZ = entries[0].getSurfacePoint(render).getZ() base.camera.setZ(10.0 + modZ + (modZ - self.ralph.getZ())) self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) self.displayHealth() return task.cont # End def die(self): # end all running tasks self.ralph.setPos(10000, 10000, 10000) taskMgr.remove("moveTask") taskMgr.remove("healthTask") self.ralph.stop() self.skatemusic.stop() self.springmusic.stop() self.backmusic.stop() colObj = self.numObjects myscore = str(colObj) self.highscore = OkDialog(dialogName="highscoreDialog", text="Your Score: " + myscore, command=self.endResult) # Handle the dialog result def endResult(self, arg): sys.exit() def endbox(self, arg): if (arg): self.startvar = 1 self.startdialog.cleanup() # restart the game #self.restart() else: sys.exit()
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 Labryn(DirectObject): def setCamera(self, spin): self.spin = spin def spinCamera(self, task): if self.spin == 1: # spin counter-clockwise self.cameraSpinCount += 1 angleDegrees = self.cameraSpinCount angleRadians = angleDegrees * (pi/ 180) self.CAM_RAD = angleRadians camera.setPos(_FOCUS[0]+self.CAM_R*cos(-pi/2+self.CAM_RAD), _FOCUS[1]+self.CAM_R*sin(-pi/2+self.CAM_RAD), (25.0/12)*self.CAM_R) camera.setHpr(angleDegrees,-65,0) elif self.spin == 2: # spin clockwise self.cameraSpinCount -= 1 angleDegrees = self.cameraSpinCount angleRadians = angleDegrees * (pi/ 180) self.CAM_RAD = angleRadians camera.setPos(_FOCUS[0]+self.CAM_R*cos(-pi/2+self.CAM_RAD), _FOCUS[1]+self.CAM_R*sin(-pi/2+self.CAM_RAD), (25.0/12)*self.CAM_R) camera.setHpr(angleDegrees,-65,0) elif self.spin == 3: # ZOOM IN not spin self.cameraZoomCount += 1 deltaR = self.cameraZoomCount * 0.1 new_R = 12-deltaR self.CAM_R = new_R camera.setPos(_FOCUS[0] + self.CAM_R*cos(-pi/2+self.CAM_RAD), _FOCUS[1] + self.CAM_R*sin(-pi/2+self.CAM_RAD), (25.0/12)*new_R) elif self.spin == 4: # ZOOM OUT self.cameraZoomCount -= 1 deltaR = self.cameraZoomCount * 0.1 new_R = 12-deltaR self.CAM_R = new_R camera.setPos(_FOCUS[0] + self.CAM_R*cos(-pi/2+self.CAM_RAD), _FOCUS[1] + self.CAM_R*sin(-pi/2+self.CAM_RAD), (25.0/12)*self.CAM_R) return Task.cont def checkMouse(self, task): if base.mouseWatcherNode.hasMouse(): self.mouseX=base.mouseWatcherNode.getMouseX() self.mouseY=base.mouseWatcherNode.getMouseY() return Task.cont def dropRock(self): if self.pokeMoveChoice == 1: # selected Geodude result = MAZE.canDropRock(self.rockX, self.rockY) if result != False: # can place rock here MAZE.dropRock(result[0],result[1]) self.rock.setPos(self.rockX, self.rockY, 1) self.rockOnMaze = True self.pokeMoveChoice = None self.myPokeName.hide() self.myPokeName = None self.updateTwoD() self.playerCandyCount -= 1 def useFlame(self): self.onFire = True # on fire self.playerCandyCount -= 1 self.pokeStatus = 1 self.flame = ParticleEffect() self.flame.loadConfig("fireish.ptf") self.flame.setPos(self.pikachu.getPos()) self.flame.start(parent=render, renderParent=render) self.updateTwoD() def useStringShot(self): self.pokeStatus = 2 self.updateTwoD() def placeRock(self, task): if self.pokeMoveChoice == 1: # selected Geodude dX,dY = ((self.mouseX-self.rockRefX), (self.mouseY-self.rockRefY)) self.rockX, self.rockY = MAZE.translateRockPosition(self.rockRefX, self.rockRefY, dX, dY) self.rock.show() self.rock.setPos(self.rockX, self.rockY, 1) self.updateTwoD() return Task.cont def placeRareCandy(self, task): if int(task.time) % 4 == 9 and self.candyOnBoard: self.candy.hide() self.candyOnBoard = False if int(task.time) % 10 == 0 and (self.candyOnBoard == False): # every 10 seconds self.candy.setPos(MAZE.generateCandyPos()) self.candy.show() self.candyOnBoard = True return Task.cont def updateTwoD(self): # update player candy count self.playerCandyStatus.destroy() self.playerCandyStatus = candyStatus(0, self.playerCandyCount) # update pikachu candy count # TODO # update my pokes color if self.playerCandyCount == 0 : groupHide(self.myPokesBright) groupShow(self.myPokesDark) # update name if self.myPokeName != None: self.myPokeName.destroy() def clearRock(self): self.rock.hide() self.rockOnMaze = False MAZE.clearRock() # clear it in 2D def clearFlame(self): self.onFire = False self.flame.cleanup() self.pokeStatus = 0 self.pokeMoveChoice = None try: self.myPokeName.destroy() except: pass self.myPokeName = None def clearString(self): self.pokeStatus = 0 self.pokeMoveChoice = None try: self.myPokeName.destroy() except: pass self.myPokeName = None def timer(self, task): # deals with moves' lasting effects ############################################################## if self.rockOnMaze: # rock on maze self.rockCounter += 1 elif self.rockCounter != 1: # rock not on maze, counter not cleared self.rockCounter = 0 if self.onFire: self.fireCounter += 1 elif self.fireCounter != 1: self.fireCounter = 0 if self.pokeStatus == 2: # string shot self.stringCounter += 1 elif self.stringCounter != 1: self.stringCounter = 0 ################################################################## if self.rockCounter == 500: self.clearRock() if self.fireCounter == 80: self.clearFlame() if self.stringCounter == 120: self.clearString() return Task.cont def usePokeMove(self, number): if self.playerCandyCount > 0: # have more than one candy if number == 1 and self.rockOnMaze == False: if self.pokeMoveChoice != 1: # NONE or other # set to center position centerx = base.win.getProperties().getXSize()/2 centery = base.win.getProperties().getYSize()/2 base.win.movePointer(0,centerx,centery) self.pokeMoveChoice = 1 # placeRock called here self.rockRefX, self.rockRefY = 0,0 self.rock.show() self.rock.setPos(0,0,1) else: # already 1 self.pokeMoveChoice = None self.clearRock() # clear rock elif number == 2: if self.pokeMoveChoice != 2: self.pokeMoveChoice = 2 self.useFlame() else: self.pokeMoveChoice = None elif number == 3: if self.pokeMoveChoice != 3: self.pokeMoveChoice = 3 self.useStringShot() else: self.pokeMoveChoice = None if self.pokeMoveChoice == None: # no choice if self.myPokeName != None: # there is a name on board self.myPokeName.destroy() # kill it else: # no name pass else: # there is a choice if self.myPokeName != None: self.myPokeName.destroy() self.myPokeName = Two_D.writePokeName(self.pokeMoveChoice) def loadRareCandy(self): self.candy = Model_Load.loadRareCandy() self.candy.reparentTo(render) self.candy.setScale(0.1) self.candy.hide() def eatRareCandy(self, task): if self.candyOnBoard: # candy on board if checkEat(self.ballRoot.getX(), self.ballRoot.getY(), self.candy.getX(), self.candy.getY()): # ball eats self.candy.hide() # eaten self.candyOnBoard = False self.playerCandyCount += 1 # self.playerCandyStatus.destroy() # self.playerCandyStatus = candyStatus(0, # self.playerCandyCount) # update print "BALL EATS CANDY" groupShow(self.myPokesBright) elif checkEat(self.pikachu.getX(), self.pikachu.getY(), self.candy.getX(), self.candy.getY()): self.candy.hide() self.candyOnBoard = False self.pokemonCandyCount += 1 return Task.cont def setFocus(self, changing): self.changingFocus = changing if changing == True: # Just Pressed self.referenceX, self.referenceY = self.mouseX, self.mouseY else: # cursor moves up self.referenceX, self.referenceY = None, None def resetView(self): self.CAM_R, self.CAM_RAD = 12, 0 self.cameraSpinCount, self.cameraZoomCount = 0, 0 # _FOCUS = [0,0,0] does not work WHY??? _FOCUS[0], _FOCUS[1], _FOCUS[2] = 0,0,0 self.changingFocus = False self.referenceX, self.referenceY = None, None camera.setPos(_FOCUS[0], _FOCUS[1]-self.CAM_R, 25) camera.setHpr(0, -65, 0) def changeFocus(self, task): if (self.changingFocus == True and self.mouseX != None and self.mouseY != None ): dX, dY = ((self.mouseX - self.referenceX)*0.1, (self.mouseY - self.referenceY)*0.1) _FOCUS[0] += dX _FOCUS[1] += dY camera.setPos(_FOCUS[0] + self.CAM_R*cos(-pi/2+self.CAM_RAD), _FOCUS[1] + self.CAM_R*sin(-pi/2+self.CAM_RAD), (25.0/12)*self.CAM_R) return Task.cont def initialize(self): #bgmusic = load_bgmusic("palette.mp3") #bgmusic.play() self.background = Two_D.loadBackground() base.cam2dp.node().getDisplayRegion(0).setSort(-20) self.candyOnBoard = False self.playerCandyCount, self.pokemonCandyCount = 2, 0 ######################Rare Candy############################### pokes=['caterpie', 'charmander', 'geodude'] self.myPokesDark = Two_D.loadMyPokemon_Dark(pokes) # my pokemons self.myPokesBright = Two_D.loadMyPokemon_Bright() groupHide(self.myPokesBright) self.loadRareCandy() # load rare candy ######################Camera Initialization#################### self.CAM_R, self.CAM_RAD = 12, 0 camera.setPos(_FOCUS[0],_FOCUS[1]-12,_FOCUS[2]+25) camera.setHpr(0, -65, 0) self.cameraSpinCount, self.cameraZoomCount = 0, 0 self.changingFocus = False self.spin = 0 #######################ICONS################################### self.myIcon = Two_D.loadMyIcon() self.pokeIcon = Two_D.loadPokeIcon() self.playerCandyStatus = candyStatus(0, self.playerCandyCount) #######################FLAMES################################## base.enableParticles() self.fireCounter = 0 self.onFire = False #######################STRINGSHOT############################# self.stringCounter = 0 #######################GLOBALS################################# self.i = 0 self.myDirection = ['zx', 'zy'] self.rockCounter = 0 self.rockX, self.rockY = None, None self.rockOnMaze = False self.pokeMoveChoice = None self.myPokeName = None self.arrowKeyPressed = False self.pokemonDirection = 'd' self.mouseX, self.mouseY = None, None # direction the ball is going self.jerkDirection = None base.disableMouse() self.jerk = (0,0,0) self.MAZE = Model_Load.loadLabyrinth() Control.keyControl(self) self.loadPokemonLevel1() self.light() self.loadBall() self.pokeStatus = 0 # 0 is normal, 1 is burned, 2 is slow-speed ########################################ROCK################### self.rock = Model_Load.loadRock() self.rock.reparentTo(render) self.rock.hide() # Do not show, but load beforehand for performance def loadPokemonLevel1(self): self.pikachu = load_model("pikachu.egg") self.pikachu.reparentTo(render) self.pikachu.setScale(0.3) endPos = self.MAZE.find("**/end").getPos() self.pikachu.setPos(endPos) def light(self): ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) def loadBall(self): self.ballRoot = render.attachNewNode("ballRoot") self.ball = load_model("ball") self.ball.reparentTo(self.ballRoot) self.ball_tex = load_tex("pokeball.png") self.ball.setTexture(self.ball_tex,1) self.ball.setScale(0.8) # Find the collision sphere for the ball in egg. self.ballSphere = self.ball.find("**/ball") self.ballSphere.node().setFromCollideMask(BitMask32.bit(0)) self.ballSphere.node().setIntoCollideMask(BitMask32.allOff()) #self.ballSphere.show() # Now we create a ray to cast down at the ball. self.ballGroundRay = CollisionRay() self.ballGroundRay.setOrigin(0,0,10) self.ballGroundRay.setDirection(0,0,-1) # Collision solids go in CollisionNode self.ballGroundCol = CollisionNode('groundRay') self.ballGroundCol.addSolid(self.ballGroundRay) self.ballGroundCol.setFromCollideMask(BitMask32.bit(1)) self.ballGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ballGroundColNp = self.ballRoot.attachNewNode(self.ballGroundCol) # light ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.55, .55, .55, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0,0,-1)) directionalLight.setColor(Vec4(0.375,0.375,0.375,1)) directionalLight.setSpecularColor(Vec4(1,1,1,1)) self.ballRoot.setLight(render.attachNewNode(ambientLight)) self.ballRoot.setLight(render.attachNewNode(directionalLight)) # material to the ball m = Material() m.setSpecular(Vec4(1,1,1,1)) m.setShininess(96) self.ball.setMaterial(m,1) def __init__(self): self.initialize() self.WALLS = self.MAZE.find("**/Wall.004") self.WALLS.node().setIntoCollideMask(BitMask32.bit(0)) # collision with the ground. different bit mask #self.mazeGround = self.maze.find("**/ground_collide") #self.mazeGround.node().setIntoCollideMask(BitMask32.bit(1)) self.MAZEGROUND = self.MAZE.find("**/Cube.004") self.MAZEGROUND.node().setIntoCollideMask(BitMask32.bit(1)) # add collision to the rock cs = CollisionSphere(0, 0, 0, 0.5) self.cnodePath = self.rock.attachNewNode(CollisionNode('cnode')) self.cnodePath.node().addSolid(cs) self.cnodePath.show() self.cnodePath.node().setIntoCollideMask(BitMask32.bit(0)) # load the ball and attach it to the scene. # it is on a dummy node so that we can rotate the ball # without rotating the ray that will be attached to it # CollisionTraversers calculate collisions self.cTrav = CollisionTraverser() #self.cTrav.showCollisions(render) #self.cTrav.showCollisions(render) # A list collision handler queue self.cHandler = CollisionHandlerQueue() # add collision nodes to the traverse. # maximum nodes per traverser: 32 self.cTrav.addCollider(self.ballSphere,self.cHandler) self.cTrav.addCollider(self.ballGroundColNp,self.cHandler) self.cTrav.addCollider(self.cnodePath, self.cHandler) # collision traversers have a built-in tool to visualize collisons #self.cTrav.showCollisions(render) self.start() def pokemonTurn(self, pokemon, direction): if direction == 'l' and self.pokemonDirection != 'l': self.pokemonDirection = 'l' pokemon.setH(-90) if direction == 'r' and self.pokemonDirection != 'r': self.pokemonDirection = 'r' pokemon.setH(90) if direction == 'd' and self.pokemonDirection != 'd': self.pokemonDirection = 'd' pokemon.setH(0) if direction == 'u' and self.pokemonDirection != 'u': self.pokemonDirection = 'u' pokemon.setH(180) def pokemonMove(self, pokemon, direction): self.pokemonTurn(pokemon, direction) if self.pokeStatus == 0: speed = _SPEED elif self.pokeStatus == 1: speed = 0 else: # self.pokeStatus == 2 speed = _SPEED/2.0 if direction == 'l': newX = pokemon.getX() - speed pokemon.setX(newX) elif direction == 'r': newX = pokemon.getX() + speed pokemon.setX(newX) elif direction == 'u': newY = pokemon.getY() + speed pokemon.setY(newY) elif direction == 'd': newY = pokemon.getY() - speed pokemon.setY(newY) elif direction == "s": # stop pass def whereToGo(self, task): # this returns the direction pokemon should go # tell MAZE pokemon and ball's board position print self.myDirection MAZE.setPokeCoord(self.pikachu.getX(), self.pikachu.getY(), self.pokemonDirection) MAZE.setBallCoord(self.ballRoot.getX(), self.ballRoot.getY()) # find out which direction to go direction = MAZE.getDecision() self.pokemonMove(self.pikachu,direction) return Task.cont def getInformation(self, task): # get information on the board # TODO self.i += 1 # sample every other call to avoid if self.i % 2 == 0: dX = self.ballRoot.getX() - self.oldPos[0] dY = self.ballRoot.getY() - self.oldPos[1] if dX < 0 : # print "going left" self.myDirection[0] = 'l' elif abs(dX) < _EPSILON: # print "not moving horiz" self.myDirection[0] = 'zx' else: # print "going right" self.myDirection[0] = 'r' if dY < 0 : # print "going down" self.myDirection[1] = 'd' elif abs(dY) < _EPSILON: # print "not moving verti" self.myDirection[1] = 'zy' else: # print "going up" self.myDirection[1] = 'u' self.oldPos = self.ballRoot.getPos() return Task.cont def start(self): # maze model has a locator in it # self.ballRoot.show() self.startPos = self.MAZE.find("**/start").getPos() self.oldPos = self.MAZE.find("**/start").getPos() self.ballRoot.setPos(self.startPos) # set the ball in the pos self.ballV = Vec3(0,0,0) # initial velocity self.accelV = Vec3(0,0,0) # initial acceleration # for a traverser to work, need to call traverser.traverse() # base has a task that does this once a frame base.cTrav = self.cTrav # create the movement task, make sure its not already running taskMgr.remove("rollTask") taskMgr.add(self.placeRock, "placeRock") taskMgr.add(self.timer, "timer") taskMgr.add(self.getInformation, "getInformation") taskMgr.add(self.eatRareCandy, "eatRareCandy") taskMgr.add(self.placeRareCandy, "placeRareCandy") taskMgr.add(self.checkMouse, "checkMouse") taskMgr.add(self.spinCamera, "spinCamera") taskMgr.add(self.changeFocus, "changeFocus") taskMgr.add(self.whereToGo, "whereToGo") # taskMgr.add(lambda task: self.moveBall(task, self.jerkDirection), # "moveBall") taskMgr.add(self.moveBall, "moveBall") self.mainLoop = taskMgr.add(self.rollTask, "rollTask") self.mainLoop.last = 0 def moveBallWrapper(self, direction): if direction == False: self.arrowKeyPressed = False else: self.arrowKeyPressed = True self.jerkDirection = direction def moveBall(self, task): direction = self.jerkDirection if self.arrowKeyPressed == True: if direction == "u": self.jerk = Vec3(0,_JERK,0) elif direction == "d": self.jerk = Vec3(0,-_JERK,0) elif direction == "l": self.jerk = Vec3(-_JERK,0,0) elif direction == "r": self.jerk = Vec3(_JERK,0,0) return Task.cont """ def moveBall(self, task, direction): if self.arrowKeyPressed == True: if direction == "u": self.jerk = Vec3(0,_JERK,0) elif direction == "d": self.jerk = Vec3(0,-_JERK,0) elif direction == "l": self.jerk = Vec3(-_JERK,0,0) elif direction == "r": self.jerk = Vec3(_JERK,0,0) return Task.cont """ # collision between ray and ground # info about the interaction is passed in colEntry def groundCollideHandler(self,colEntry): # set the ball to the appropriate Z for it to be on the ground newZ = colEntry.getSurfacePoint(render).getZ() self.ballRoot.setZ(newZ+.4) # up vector X normal vector norm = colEntry.getSurfaceNormal(render) accelSide = norm.cross(UP) self.accelV = norm.cross(accelSide) # collision between the ball and a wall def wallCollideHandler(self,colEntry): # some vectors needed to do the calculation norm = colEntry.getSurfaceNormal(render) * -1 norm.normalize() curSpeed = self.ballV.length() inVec = self.ballV/curSpeed velAngle = norm.dot(inVec) # angle of incidance hitDir = colEntry.getSurfacePoint(render) - self.ballRoot.getPos() hitDir.normalize() hitAngle = norm.dot(hitDir) # deal with collision cases if velAngle > 0 and hitAngle >.995: # standard reflection equation reflectVec = (norm * norm.dot(inVec*-1)*2) + inVec # makes velocity half of hitting dead-on self.ballV = reflectVec * (curSpeed * (((1-velAngle)*.5)+.5)) # a collision means the ball is already a little bit buried in # move it so exactly touching the wall disp = (colEntry.getSurfacePoint(render) - colEntry.getInteriorPoint(render)) newPos = self.ballRoot.getPos() + disp self.ballRoot.setPos(newPos) def rollTask(self,task): # standard technique for finding the amount of time # since the last frame dt = task.time - task.last task.last = task.time # If dt is large, then there is a HICCUP # ignore the frame if dt > .2: return Task.cont # dispatch which function to handle the collision based on name for i in range(self.cHandler.getNumEntries()): entry = self.cHandler.getEntry(i) name = entry.getIntoNode().getName() if name == "Wall.004": self.wallCollideHandler(entry) elif name=="Cube.004": self.groundCollideHandler(entry) else: if self.rockOnMaze == True: self.wallCollideHandler(entry) self.accelV += self.jerk # move the ball, update the velocity based on accel self.ballV += self.accelV * dt * ACCELERATION # clamp the velocity to the max speed if self.ballV.lengthSquared() > MAX_SPEED_SQ: self.ballV.normalize() self.ballV *= MAX_SPEED # update the position self.ballRoot.setPos(self.ballRoot.getPos() + (self.ballV*dt)) # uses quaternion to rotate the ball prevRot = LRotationf(self.ball.getQuat()) axis = UP.cross(self.ballV) newRot = LRotationf(axis, 45.5 * dt * self.ballV.length()) self.ball.setQuat(prevRot * newRot) return Task.cont # continue the task
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 RoamingPenguinDemo(ShowBase): def __init__(self): # Set up the window, camera, etc. ShowBase.__init__(self) # This is used to store which keys are currently pressed. self.keyMap = { "left": 0, "right": 0, "forward": 0, "backward": 0, "cam-left": 0, "cam-right": 0, } ########################################################################### self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) # We do not have a skybox, so we will just use a sky blue background color #self.setBackgroundColor(0.53, 0.80, 0.92, 1) self.setBackgroundColor(.1, .1, .1, 1) # Create the main character, person #personStartPos = self.environ.find("**/start_point").getPos() #self.person = Actor("models/panda", # {"run": "models/panda-walk", # "walk": "models/panda-walk"}) person2StartPos = self.environ.find("**/start_point").getPos() self.person2 = Actor("models/passenger_penguin", {"run": "models/passenger_penguin", "walk": "models/passenger_penguin"}) self.person2.reparentTo(render) self.person2.setScale(.1) self.person2.setPos(person2StartPos + (px, py, 1)) person3StartPos = self.environ.find("**/start_point").getPos() self.person3 = Actor("models/MagicBunny", {"run": "models/MagicBunny", "walk": "models/MagicBunny"}) #px = random.randint(-1,1) #py = random.randint(-1,1) self.person3.reparentTo(render) self.person3.setScale(.04) #self.person.setPos(personStartPos + (0, 0, 2)) self.person3.setPos(person3StartPos + (px/1.5+3, py/2, 0)) personStartPos = self.environ.find("**/start_point").getPos() self.person = Actor("models/panda", {"run": "models/panda-walk", "walk": "models/panda-walk"}) self.person.reparentTo(render) self.person.setScale(.1) self.person.setPos(personStartPos + (0, 0, 1.5)) self.person.loop("run") arenaStartPos = self.environ.find("**/start_point").getPos() self.arena = Actor("models/FarmHouse") self.arena.reparentTo(render) self.arena.setScale(.1) self.arena.setPos(arenaStartPos + (-1, 0, 0)) arena2StartPos = self.environ.find("**/start_point").getPos() self.arena2 = Actor("models/fence") self.arena2.reparentTo(render) self.arena2.setScale(5.9) self.arena.setPos(arenaStartPos + (px, py-12, 1)) self.arena2.setPos(arenaStartPos + (8, 5, -1)) arena2StartPos = self.environ.find("**/start_point").getPos() self.arena3 = Actor("models/gate") self.arena3.reparentTo(render) self.arena3.setScale(.01) self.arena3.setPos(arenaStartPos + (px/2+random.randint(12,15), py/2, -1)) self.arena4 = Actor("models/FarmHouse") self.arena4.reparentTo(render) self.arena4.setScale(.1) self.arena4.setPos(arenaStartPos + (px/3-random.randint(18,22), py/3, -1)) self.arena5 = Actor("models/gate") self.arena5.reparentTo(render) self.arena5.setScale(.008) self.arena5.setPos(arenaStartPos + (px/1.2-9, py/1.2, -1)) ##################################################################################################################################### base.enableParticles() self.t = loader.loadModel("teapot") # for the particle enhancer self.t.setScale(10) self.t.setPos(-10, -20, -1) self.t.reparentTo(render) #self.setupLights() self.p = ParticleEffect() self.p.setScale(1000) self.loadParticleConfig('smoke.ptf') # looks like a storm at night self.p.setScale(20) #################################################3 # Create a floater object, which floats 2 units above person. We # use this as a target for the camera to look at. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(self.person) self.floater.setZ(2.0) # Accept the control keys for movement and rotation taskMgr.add(self.move, "moveTask") # Set up the camera self.disableMouse() self.camera.setPos(self.person.getX(), self.person.getY() + 10, 2) self.cTrav = CollisionTraverser() self.personCol = CollisionNode('person') self.personCol.addSolid(CollisionSphere(center=(0, 0, 2), radius=1.5)) self.personCol.addSolid(CollisionSphere(center=(0, -0.25, 4), radius=1.5)) self.personCol.setFromCollideMask(CollideMask.bit(0)) self.personCol.setIntoCollideMask(CollideMask.allOff()) self.personColNp = self.person.attachNewNode(self.personCol) self.personPusher = CollisionHandlerPusher() self.personPusher.horizontal = True self.personPusher.addCollider(self.personColNp, self.person) self.cTrav.addCollider(self.personColNp, self.personPusher) self.personGroundRay = CollisionRay() self.personGroundRay.setOrigin(0, 0, 9) self.personGroundRay.setDirection(0, 0, -1) self.personGroundCol = CollisionNode('personRay') self.personGroundCol.addSolid(self.personGroundRay) self.personGroundCol.setFromCollideMask(CollideMask.bit(0)) self.personGroundCol.setIntoCollideMask(CollideMask.allOff()) self.personGroundColNp = self.person.attachNewNode(self.personGroundCol) self.personGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.personGroundColNp, self.personGroundHandler) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0, 0, 9) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(CollideMask.bit(0)) self.camGroundCol.setIntoCollideMask(CollideMask.allOff()) self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.3, .3, .3, .2)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection((-5, -5, -5)) directionalLight.setColor((.2, .2, .2, 1)) directionalLight.setSpecularColor((.1, .1, .1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) def loadParticleConfig(self, filename): # Start of the code from steam.ptf self.p.cleanup() self.p = ParticleEffect() self.p.loadConfig(Filename(filename)) self.p.start(self.t) self.p.setPos(3.000, 0.000, 2.250) # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value def move(self, task): dt = globalClock.getDt() #z = abs(py) self.person.setX(self.person, 4 * dt) self.person.setX(self.person, -4 * dt) ## this is how the Panda finds his friend if px < 0 : #if self.person.getPos() - self.person2.getPos() < (0, 0, 0) : if self.person.getY() - self.person2.getY() < 6 : #self.person.getPos(personStartPos + (0, py, 1.5)) self.person.setY(self.person, 0 * dt) self.person.stop() self.person.pose("walk", 5) self.isMoving = False else: self.person.setY(self.person, py * dt) self.person.setX(self.person, px * dt) self.person.setH(self.person, px/(abs(px)+6)* dt) else: if self.person.getY() - self.person2.getY() < 6 : #self.person.getPos(personStartPos + (0, py, 1.5)) self.person.setY(self.person, 0 * dt) self.person.stop() self.person.pose("walk", 5) self.isMoving = False else: self.person.setY(self.person, py * dt) self.person.setX(self.person, px * dt) self.person.setH(self.person, px/(abs(px)+6)* dt) if self.keyMap["cam-left"]: self.camera.setX(self.camera, -20 * dt) if self.keyMap["cam-right"]: self.camera.setX(self.camera, +20 * dt) camvec = self.person.getPos() - self.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if camdist > 10.0: self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if camdist < 5.0: self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 entries = list(self.personGroundHandler.entries) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) for entry in entries: if entry.getIntoNode().getName() == "terrain": self.person.setZ(entry.getSurfacePoint(render).getZ()) entries = list(self.camGroundHandler.entries) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) for entry in entries: if entry.getIntoNode().getName() == "terrain": self.camera.setZ(entry.getSurfacePoint(render).getZ() + 3.5) if self.camera.getZ() < self.person.getZ() + 4.0: self.camera.setZ(self.person.getZ() + 4.0) self.camera.lookAt(self.floater) return task.cont
class World(DirectObject): def __init__(self): ## Add the default values to the dictionary. self.keyMap = {"left":0, "right":0, "forward":0, \ "boost":0, "strafeL":0, "strafeR":0, \ "cam-left":0, "cam-right":0} base.win.setClearColor(Vec4(0, 0, 0, 1)) self.jump = False self.jumped = False # Post the instructions self.title = addTitle( "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.85, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.80, "[Up Arrow]: Run Ralph Forward") self.inst6 = addInstructions(0.70, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.65, "[D]: Rotate Camera Right") self.inst8 = addInstructions(0.60, "[B]: Ralph Boost") self.inst9 = addInstructions(0.55, "[V]: Strafe Left") self.inst10 = addInstructions(0.50, "[N]: Strafe Right") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0, 0, 0) ## Stops the sound as soon as the world renders ## Note:Sound won't play very long becasue the game takes seconds to compile and load ## Remove loading screen after world is rendered and ready to go. loadingText.cleanup() mySound.stop() # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", { "run": "models/ralph-run", "walk": "models/ralph-walk" }) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation 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("d", self.setKey, ["cam-right", 1]) self.accept("b", self.setKey, ["boost", 1]) self.accept("v", self.setKey, ["strafeL", 1]) self.accept("n", self.setKey, ["strafeR", 1]) ## -up to signify what happens when you let go of the key self.accept("b-up", self.setKey, ["boost", 0]) self.accept("v-up", self.setKey, ["strafeL", 0]) self.accept("n-up", self.setKey, ["strafeR", 0]) 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("d-up", self.setKey, ["cam-right", 0]) taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 1000) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value def setZ(self, task): x = self.ralph.getX() y = self.ralph.getY() z = self.ralph.getZ() self.ralph.setPos(x, y, 0) self.jumped = False # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) if (self.keyMap["cam-left"] != 0): base.camera.setX(base.camera, -50 * globalClock.getDt()) # Increased camera rotation speed to match rotation speed of Ralph if (self.keyMap["cam-right"] != 0): base.camera.setX(base.camera, +50 * globalClock.getDt()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"] != 0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"] != 0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"] != 0): self.ralph.setY(self.ralph, -25 * globalClock.getDt()) ## What to do if b was pressed? if (self.keyMap["boost"] != 0): self.jump = True # What to do if n is pressed # Ralph will strafe right. If b is also pressed, Ralph will strafe to the right quicker if (self.keyMap["strafeR"] != 0): self.ralph.setX(self.ralph, -25 * globalClock.getDt()) if (self.keyMap["strafeL"] != 0): self.ralph.setX(self.ralph, 25 * globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. # Function to make Ralph jump up the y-axis and fall back down # when 'j' is released ## Add boost, strafeL, and strafeR to the animation alteration conditions here. if (self.keyMap["forward"]!=0) or (self.keyMap["left"]!=0) \ or (self.keyMap["right"]!=0) or (self.keyMap["boost"]!=0) \ or (self.keyMap["strafeL"]!=0) or (self.keyMap["strafeR"]!=0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): if self.jump is True: self.ralph.setZ(entries[0].getSurfacePoint(render).getZ() + 1) self.jumped = True self.jump = False else: if self.jumped is True: taskMgr.doMethodLater(0.1, self.setZ, 'setZ') else: self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.0): base.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) return task.cont
class RoamingRalphDemo(CosmoniumBase): def get_local_position(self): return base.camera.get_pos() def create_terrain_appearance(self): self.terrain_appearance.set_shadow(self.shadow_caster) def create_terrain_heightmap(self): self.heightmap = PatchedHeightmap('heightmap', self.noise_size, self.height_scale, self.size, self.size, True, ShaderHeightmapPatchFactory(self.noise)) def create_terrain_biome(self): self.biome = PatchedHeightmap('biome', self.biome_size, 1.0, self.size, self.size, False, ShaderHeightmapPatchFactory(self.biome_noise)) def create_terrain_shader(self): # control4 = HeightColorMap('colormap', # [ # ColormapLayer(0.00, top=LRGBColor(0, 0.1, 0.24)), # ColormapLayer(0.40, top=LRGBColor(0, 0.1, 0.24)), # ColormapLayer(0.49, top=LRGBColor(0, 0.6, 0.6)), # ColormapLayer(0.50, bottom=LRGBColor(0.9, 0.8, 0.6), top=LRGBColor(0.5, 0.4, 0.3)), # ColormapLayer(0.80, top=LRGBColor(0.2, 0.3, 0.1)), # ColormapLayer(0.90, top=LRGBColor(0.7, 0.6, 0.4)), # ColormapLayer(1.00, bottom=LRGBColor(1, 1, 1), top=LRGBColor(1, 1, 1)), # ]) appearance = DetailMap(self.terrain_control, self.heightmap, create_normals=True) data_source = [HeightmapDataSource(self.heightmap, PatchedGpuTextureSource, filtering=HeightmapDataSource.F_none), HeightmapDataSource(self.biome, PatchedGpuTextureSource, filtering=HeightmapDataSource.F_none), TextureDictionaryDataSource(self.terrain_appearance, TextureDictionaryDataSource.F_hash)] if settings.allow_tesselation: tesselation_control = ConstantTesselationControl(invert_v=False) else: tesselation_control = None if self.fog is not None: after_effects = [Fog(**self.fog)] else: after_effects = None self.terrain_shader = BasicShader(appearance=appearance, tesselation_control=tesselation_control, geometry_control=DisplacementGeometryControl(self.heightmap), data_source=data_source, after_effects=after_effects) def create_tile(self, x, y): self.terrain_shape.add_root_patch(x, y) def create_terrain(self): self.tile_factory = TileFactory(self.tile_density, self.size, self.has_water, self.water) self.terrain_shape = TiledShape(self.tile_factory, self.size, self.max_lod, lod_control=VertexSizeMaxDistancePatchLodControl(self.max_distance, self.max_vertex_size)) self.create_terrain_heightmap() self.create_terrain_biome() self.create_terrain_appearance() self.create_terrain_shader() self.terrain = HeightmapSurface( 'surface', 0, self.terrain_shape, self.heightmap, self.biome, self.terrain_appearance, self.terrain_shader, self.size, clickable=False, average=True) self.terrain.set_parent(self) self.terrain.create_instance() def toggle_water(self): if not self.has_water: return self.water.visible = not self.water.visible self.terrain_shape.check_settings() def get_height(self, position): height = self.terrain.get_height(position) if self.has_water and self.water.visible and height < self.water.level: height = self.water.level return height #Used by populator def get_height_patch(self, patch, u, v): height = self.terrain.get_height_patch(patch, u, v) if self.has_water and self.water.visible and height < self.water.level: height = self.water.level return height def skybox_init(self): skynode = base.cam.attachNewNode('skybox') self.skybox = loader.loadModel('ralph-data/models/rgbCube') self.skybox.reparentTo(skynode) self.skybox.setTextureOff(1) self.skybox.setShaderOff(1) self.skybox.setTwoSided(True) # make big enough to cover whole terrain, else there'll be problems with the water reflections self.skybox.setScale(1.5* self.size) self.skybox.setBin('background', 1) self.skybox.setDepthWrite(False) self.skybox.setDepthTest(False) self.skybox.setLightOff(1) self.skybox.setShaderOff(1) self.skybox.setFogOff(1) #self.skybox.setColor(.55, .65, .95, 1.0) self.skybox_color = LColor(pow(0.5, 1/2.2), pow(0.6, 1/2.2), pow(0.7, 1/2.2), 1.0) self.skybox.setColor(self.skybox_color) def objects_density_for_patch(self, patch): scale = 1 << patch.lod return int(self.objects_density / scale + 1.0) def create_populator(self): if settings.allow_instancing: TerrainPopulator = GpuTerrainPopulator else: TerrainPopulator = CpuTerrainPopulator self.rock_collection = TerrainPopulator(RockFactory(self), self.objects_density_for_patch, self.objects_density, RandomObjectPlacer(self)) self.tree_collection = TerrainPopulator(TreeFactory(self), self.objects_density_for_patch, self.objects_density, RandomObjectPlacer(self)) self.object_collection = MultiTerrainPopulator() self.object_collection.add_populator(self.rock_collection) self.object_collection.add_populator(self.tree_collection) def set_light_angle(self, angle): self.light_angle = angle self.light_quat.setFromAxisAngleRad(angle * pi / 180, LVector3.forward()) self.light_dir = self.light_quat.xform(LVector3.up()) cosA = self.light_dir.dot(LVector3.up()) self.vector_to_star = self.light_dir if self.shadow_caster is not None: self.shadow_caster.set_direction(-self.light_dir) if self.directionalLight is not None: self.directionalLight.setDirection(-self.light_dir) if cosA >= 0: coef = sqrt(cosA) self.light_color = (1, coef, coef, 1) self.directionalLight.setColor(self.light_color) self.skybox.setColor(self.skybox_color * cosA) else: self.light_color = (1, 0, 0, 1) self.directionalLight.setColor(self.light_color) self.skybox.setColor(self.skybox_color * 0) self.update() def update(self): self.object_collection.update_instance() self.terrain.update_instance(None, None) def apply_instance(self, instance): pass def create_instance_delayed(self): pass def get_apparent_radius(self): return 0 def get_name(self): return "terrain" def is_emissive(self): return False def __init__(self): CosmoniumBase.__init__(self) config = RalphConfigParser() (self.noise, self.biome_noise, self.terrain_control, self.terrain_appearance, self.water, self.fog) = config.load_and_parse('ralph-data/ralph.yaml') self.tile_density = 64 self.default_size = 128 self.max_vertex_size = 64 self.max_lod = 10 self.size = 128 * 8 self.max_distance = 1.001 * self.size * sqrt(2) self.noise_size = 512 self.biome_size = 128 self.noise_scale = 0.5 * self.size / self.default_size self.objects_density = int(25 * (1.0 * self.size / self.default_size) * (1.0 * self.size / self.default_size)) self.objects_density = 250 self.height_scale = 100 * 5.0 self.has_water = True self.fullscreen = False self.shadow_caster = None self.light_angle = None self.light_dir = LVector3.up() self.vector_to_star = self.light_dir self.light_quat = LQuaternion() self.light_color = (1.0, 1.0, 1.0, 1.0) self.directionalLight = None self.shadow_size = self.default_size / 8 self.shadow_box_length = self.height_scale self.observer = RalphCamera(self.cam, self.camLens) self.observer.init() self.distance_to_obs = float('inf') self.height_under = 0.0 self.scene_position = LVector3() self.scene_scale_factor = 1 self.scene_orientation = LQuaternion() #Size of an edge seen from 4 units above self.edge_apparent_size = (1.0 * self.size / self.tile_density) / (4.0 * self.observer.pixel_size) print("Apparent size:", self.edge_apparent_size) self.win.setClearColor((135.0/255, 206.0/255, 235.0/255, 1)) # This is used to store which keys are currently pressed. self.keyMap = { "left": 0, "right": 0, "forward": 0, "backward": 0, "cam-left": 0, "cam-right": 0, "cam-up": 0, "cam-down": 0, "sun-left": 0, "sun-right": 0, "turbo": 0} # Set up the environment # # Create some lighting self.vector_to_obs = base.cam.get_pos() self.vector_to_obs.normalize() if True: self.shadow_caster = ShadowCaster(1024) self.shadow_caster.create() self.shadow_caster.set_lens(self.shadow_size, -self.shadow_box_length / 2.0, self.shadow_box_length / 2.0, -self.light_dir) self.shadow_caster.set_pos(self.light_dir * self.shadow_box_length / 2.0) self.shadow_caster.bias = 0.1 else: self.shadow_caster = None self.ambientLight = AmbientLight("ambientLight") self.ambientLight.setColor((settings.global_ambient, settings.global_ambient, settings.global_ambient, 1)) self.directionalLight = DirectionalLight("directionalLight") self.directionalLight.setDirection(-self.light_dir) self.directionalLight.setColor(self.light_color) self.directionalLight.setSpecularColor(self.light_color) render.setLight(render.attachNewNode(self.ambientLight)) render.setLight(render.attachNewNode(self.directionalLight)) render.setShaderAuto() base.setFrameRateMeter(True) self.create_terrain() self.create_populator() self.terrain_shape.set_populator(self.object_collection) self.create_tile(0, 0) self.skybox_init() self.set_light_angle(45) # Create the main character, Ralph ralphStartPos = LPoint3() self.ralph = Actor("ralph-data/models/ralph", {"run": "ralph-data/models/ralph-run", "walk": "ralph-data/models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos + (0, 0, 0.5)) self.ralph_shape = InstanceShape(self.ralph) self.ralph_shape.parent = self self.ralph_shape.set_owner(self) self.ralph_shape.create_instance() self.ralph_appearance = ModelAppearance(self.ralph) self.ralph_appearance.set_shadow(self.shadow_caster) self.ralph_shader = BasicShader() self.ralph_appearance.bake() self.ralph_appearance.apply(self.ralph_shape, self.ralph_shader) self.ralph_shader.apply(self.ralph_shape, self.ralph_appearance) self.ralph_shader.update(self.ralph_shape, self.ralph_appearance) # Create a floater object, which floats 2 units above ralph. We # use this as a target for the camera to look at. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(self.ralph) self.floater.setZ(2.0) # Accept the control keys for movement and rotation self.accept("escape", sys.exit) self.accept("control-q", sys.exit) self.accept("arrow_left", self.setKey, ["left", True]) self.accept("arrow_right", self.setKey, ["right", True]) self.accept("arrow_up", self.setKey, ["forward", True]) self.accept("arrow_down", self.setKey, ["backward", True]) self.accept("shift", self.setKey, ["turbo", True]) self.accept("a", self.setKey, ["cam-left", True], direct=True) self.accept("s", self.setKey, ["cam-right", True], direct=True) self.accept("u", self.setKey, ["cam-up", True], direct=True) self.accept("u-up", self.setKey, ["cam-up", False]) self.accept("d", self.setKey, ["cam-down", True], direct=True) self.accept("d-up", self.setKey, ["cam-down", False]) self.accept("o", self.setKey, ["sun-left", True], direct=True) self.accept("o-up", self.setKey, ["sun-left", False]) self.accept("p", self.setKey, ["sun-right", True], direct=True) self.accept("p-up", self.setKey, ["sun-right", False]) self.accept("arrow_left-up", self.setKey, ["left", False]) self.accept("arrow_right-up", self.setKey, ["right", False]) self.accept("arrow_up-up", self.setKey, ["forward", False]) self.accept("arrow_down-up", self.setKey, ["backward", False]) self.accept("shift-up", self.setKey, ["turbo", False]) self.accept("a-up", self.setKey, ["cam-left", False]) self.accept("s-up", self.setKey, ["cam-right", False]) self.accept("w", self.toggle_water) self.accept("h", self.print_debug) self.accept("f2", self.connect_pstats) self.accept("f3", self.toggle_filled_wireframe) self.accept("shift-f3", self.toggle_wireframe) self.accept("f5", self.bufferViewer.toggleEnable) self.accept("f8", self.terrain_shape.dump_tree) self.accept('alt-enter', self.toggle_fullscreen) taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera self.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 2) self.camera_height = 2.0 render.set_shader_input("camera", self.camera.get_pos()) self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 9) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(CollideMask.bit(0)) self.ralphGroundCol.setIntoCollideMask(CollideMask.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) #self.terrain_shape.test_lod(LPoint3d(*self.ralph.getPos()), self.distance_to_obs, self.pixel_size, self.terrain_appearance) #self.terrain_shape.update_lod(LPoint3d(*self.ralph.getPos()), self.distance_to_obs, self.pixel_size, self.terrain_appearance) #self.terrain.shape_updated() self.terrain.update_instance(LPoint3d(*self.ralph.getPos()), None) # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # Get the time that elapsed since last frame. We multiply this with # the desired speed in order to find out with which distance to move # in order to achieve that desired speed. dt = globalClock.getDt() # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. if self.keyMap["cam-left"]: self.camera.setX(self.camera, -20 * dt) if self.keyMap["cam-right"]: self.camera.setX(self.camera, +20 * dt) if self.keyMap["cam-up"]: self.camera_height *= (1 + 2 * dt) if self.keyMap["cam-down"]: self.camera_height *= (1 - 2 * dt) if self.camera_height < 1.0: self.camera_height = 1.0 if self.keyMap["sun-left"]: self.set_light_angle(self.light_angle + 30 * dt) if self.keyMap["sun-right"]: self.set_light_angle(self.light_angle - 30 * dt) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. delta = 25 if self.keyMap["turbo"]: delta *= 10 if self.keyMap["left"]: self.ralph.setH(self.ralph.getH() + 300 * dt) if self.keyMap["right"]: self.ralph.setH(self.ralph.getH() - 300 * dt) if self.keyMap["forward"]: self.ralph.setY(self.ralph, -delta * dt) if self.keyMap["backward"]: self.ralph.setY(self.ralph, delta * dt) #self.limit_pos(self.ralph) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if self.keyMap["forward"] or self.keyMap["backward"] or self.keyMap["left"] or self.keyMap["right"]: if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - self.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if camdist > 10.0: self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if camdist < 5.0: self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Normally, we would have to call traverse() to check for collisions. # However, the class ShowBase that we inherit from has a task to do # this for us, if we assign a CollisionTraverser to self.cTrav. self.cTrav.traverse(render) if False: # Adjust ralph's Z coordinate. If ralph's ray hit anything, put # him back where he was last frame. entries = list(self.ralphGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0: self.ralph.setPos(startpos) ralph_height = self.get_height(self.ralph.getPos()) self.ralph.setZ(ralph_height) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. camera_height = self.get_height(self.camera.getPos()) + 1.0 if camera_height < ralph_height + self.camera_height: self.camera.setZ(ralph_height + self.camera_height) else: self.camera.setZ(camera_height) #self.limit_pos(self.camera) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.camera.lookAt(self.floater) #self.shadow_caster.set_pos(self.ralph.get_pos()) self.shadow_caster.set_pos(self.ralph.get_pos() - camvec * camdist + camvec * self.shadow_size / 2) render.set_shader_input("camera", self.camera.get_pos()) self.vector_to_obs = base.cam.get_pos() self.vector_to_obs.normalize() if self.isMoving: #self.terrain_shape.test_lod(LPoint3d(*self.ralph.getPos()), self.distance_to_obs, self.pixel_size, self.terrain_appearance) pass#self.terrain_shape.update_lod(LPoint3d(*self.ralph.getPos()), self.distance_to_obs, self.pixel_size, self.terrain_appearance) self.object_collection.update_instance() self.terrain.update_instance(LPoint3d(*self.ralph.getPos()), None) return task.cont def print_debug(self): print("Height:", self.get_height(self.ralph.getPos()), self.terrain.get_height(self.ralph.getPos())) print("Ralph:", self.ralph.get_pos()) print("Camera:", base.camera.get_pos())
class World(DirectObject): def __init__(self): #Let's start the Music mySound = base.loader.loadSfx("music/music.mp3") mySound.setLoopCount(0) #And Keep it On Loop mySound.play() base.setFrameRateMeter(True) #Shows the FrameRate in The Top Corner self.walking = Vec3() self.isMoving = False self.dest = None base.win.setClearColor(Vec4(0,0,0,1)) self.keyMap = {"left":0, "right":0, "forward":0, "backward":0} base.win.setClearColor(Vec4(0,0,0,1)) #Here is the number of collectibles in the game self.rare = 1; self.vasenum = 10; self.coinnum = 30; self.silvernum = 5; self.chestnum = 2; #Here is the Obstacles in the game self.rocknum = 500; #Here is the Score self.score = 0; #Here is the total Number of Objects to collect self.numObjects = self.rare + self.vasenum + self.coinnum + self.silvernum + self.chestnum # print the number of objects printNumObj(self.score) # Post the instructions self.title = addTitle("Mighty Mountain") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[A]: Rotate Ralph Left") self.inst3 = addInstructions(0.85, "[D]: Rotate Ralph Right") self.inst4 = addInstructions(0.80, "[W]: Run Ralph Forward") self.inst5 = addInstructions(0.75, "[S]: Run Ralph Backward") self.inst6 = addInstructions(0.70, "[Space]: Run, Ralph, Run") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0,0,0) # Timer to increment in the move task self.time = 0 # Get bounds of environment min, max = self.environ.getTightBounds() self.mapSize = max-min # Create the main character, Ralph self.ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", {"run":"models/ralph-run", "walk":"models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(self.ralphStartPos) # ralph's stamina self.stamina = 200 # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation self.accept("escape", self.endgame) # these don't work well in combination with the space bar 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("arrow_down", self.setKey, ["backward",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("arrow_down-up", self.setKey, ["backward",0]) self.accept("space", self.runRalph, [True]) self.accept("space-up", self.runRalph, [False]) self.accept("a", self.setKey, ["left",1]) self.accept("d", self.setKey, ["right",1]) self.accept("w", self.setKey, ["forward",1]) self.accept("s", self.setKey, ["backward",1]) self.accept("a-up", self.setKey, ["left",0]) self.accept("d-up", self.setKey, ["right",0]) self.accept("w-up", self.setKey, ["forward",0]) self.accept("s-up", self.setKey, ["backward",0]) # Game state variables self.isMoving = False self.isRunning = False # Set up the camera base.disableMouse() #base.camera.setPos(self.ralph.getX(),self.ralph.getY()+10,2) base.camera.setPos(0, 0, 0) base.camera.reparentTo(self.ralph) base.camera.setPos(0, 40, 2) base.camera.lookAt(self.ralph) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. base.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,300) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) # camera ground collision handler self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0,0,300) self.camGroundRay.setDirection(0,0,-1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(BitMask32.bit(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Place the collectibles self.placeCollectibles() #Platinum self.placeVases() self.placeCoins() self.placeSilver() self.placeGold() self.placeChests() #Place the obstacles self.placeRocks() #Cactus # Uncomment this line to show a visual representation of the # collisions occuring #base.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) taskMgr.add(self.move,"moveTask") #Reinitialize all necessary parts of the game def restart(self): #self.numObjects = 10 self.score = 0 printNumObj(self.score) self.ralph.setPos(self.ralphStartPos) self.stamina = 200 self.time = 0 base.camera.setPos(0, 0, 0) base.camera.reparentTo(self.ralph) base.camera.setPos(0, 40, 2) base.camera.lookAt(self.ralph) # Place the collectibles self.placeCollectibles() #Platinum self.placeVases() self.placeCoins() self.placeSilver() self.placeGold() self.placeChests() #Place the obstacles self.placeRocks() #Total number of obstacles self.numObjects = self.rare + self.vasenum + self.coinnum + self.silvernum + self.chestnum taskMgr.add(self.move,"moveTask") # Display ralph's stamina def displayStamina(self): sprintBar['scale'] = (self.stamina*0.01*BAR_WIDTH,0.2,0.2) #Collects the item and modifies score def collectCollectibles(self, entry): #Platinum #Remove the collectible entry.getIntoNodePath().getParent().removeNode() # Update the number of objects self.score = self.score * self.numObjects + 500 self.numObjects = self.numObjects - 1 printNumObj(self.score) def collectVase(self, entry): # Remove the collectible entry.getIntoNodePath().getParent().removeNode() # Update the number of objects self.score = self.score + 10 self.numObjects = self.numObjects - 1 printNumObj(self.score) def collectCoins(self, entry): # Remove the collectible entry.getIntoNodePath().getParent().removeNode() # Update the number of objects self.score = self.score + 1 printNumObj(self.score) self.numObjects = self.numObjects - 1 def collectSilver(self, entry): # Remove the collectible entry.getIntoNodePath().getParent().removeNode() # Update the number of objects self.score = self.score + 20 printNumObj(self.score) self.numObjects = self.numObjects - 1 def collectGold(self, entry): # Remove the collectible entry.getIntoNodePath().getParent().removeNode() # Update the number of objects self.score = self.score + 30 printNumObj(self.score) self.numObjects = self.numObjects - 1 def collectChest(self, entry): # Remove the collectible entry.getIntoNodePath().getParent().removeNode() # Update the number of objects self.score = self.score + 100 printNumObj(self.score) self.numObjects = self.numObjects - 1 #Unique function which handles collisions with a deduction obstacles. def deductRocks(self, entry): # Remove the collectible entry.getIntoNodePath().getParent().removeNode() # Update the number of objects if self.score > 500: randomnum = random.randint(1,2) if randomnum == 1: self.score = self.score - 100 #Removes Score if randomnum == 2: self.score = self.score + 100 #Removes Score if self.score < 500: self.score = self.score - 100 randomnum = random.randint(1,2) if randomnum == 1: result =buttonbox(msg='A kind wizard wishes to help you on your quest? Trust him?', title='Alert!', choices=("Yes", "No")) if result == "Yes": othernum = random.randint(1,100) othernum = othernum * self.score + self.numObjects #Y = MX + B if othernum > 1000: msgbox("Good choice! Add 1,000 Points to your Score!") self.score = self.score + 1000 if othernum < 1000: msgbox("The wizard tricked you!He stole 100 Points!") self.score = self.score - 100 printNumObj(self.score) # Places an item randomly on the map def placeItem(self, item): # Add ground collision detector to the health item self.collectGroundRay = CollisionRay() self.collectGroundRay.setOrigin(0,0,300) self.collectGroundRay.setDirection(0,0,-1) self.collectGroundCol = CollisionNode('colRay') self.collectGroundCol.addSolid(self.collectGroundRay) self.collectGroundCol.setFromCollideMask(BitMask32.bit(0)) self.collectGroundCol.setIntoCollideMask(BitMask32.allOff()) self.collectGroundColNp = item.attachNewNode(self.collectGroundCol) self.collectGroundHandler = CollisionHandlerQueue() base.cTrav.addCollider(self.collectGroundColNp, self.collectGroundHandler) placed = False; while placed == False: # re-randomize position item.setPos(-random.randint(0,140),-random.randint(0,40),0) base.cTrav.traverse(render) # Get Z position from terrain collision entries = [] for j in range(self.collectGroundHandler.getNumEntries()): entry = self.collectGroundHandler.getEntry(j) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): item.setZ(entries[0].getSurfacePoint(render).getZ()+1) placed = True # remove placement collider self.collectGroundColNp.removeNode() #Places all obstacles on map. def placeCollectibles(self): self.placeCol = render.attachNewNode("Collectible-Placeholder") self.placeCol.setPos(0,0,0) # Add the health items to the placeCol node for i in range(self.rare): # Load in the health item model self.collect = loader.loadModel("models/moneyBag") self.collect.setPos(0,0,0) self.collect.reparentTo(self.placeCol) self.placeItem(self.collect) # Add spherical collision detection colSphere = CollisionSphere(0,0,0,1) sphereNode = CollisionNode('colSphere') sphereNode.addSolid(colSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.collect.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) def placeVases(self): self.placeV = render.attachNewNode("Collectible-Placeholder") self.placeV.setPos(0,0,0) # Add the health items to the placeCol node for i in range(self.vasenum): # Load in the health item model self.collect = loader.loadModel("models/jar.egg") self.collect.setPos(0,0,0) self.collect.reparentTo(self.placeV) self.placeItem(self.collect) # Add spherical collision detection vaseSphere = CollisionSphere(0,0,0,1) sphereNode = CollisionNode('vaseSphere') sphereNode.addSolid(vaseSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.collect.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) def placeCoins(self): self.placeC = render.attachNewNode("Collectible-Placeholder") self.placeC.setPos(0,0,0) # Add the health items to the placeCol node for i in range(self.coinnum): # Load in the health item model self.collect = loader.loadModel("models/Cookie.egg") self.collect.setPos(0,0,0) self.collect.reparentTo(self.placeC) self.placeItem(self.collect) # Add spherical collision detection coinSphere = CollisionSphere(0,0,0,1) sphereNode = CollisionNode('coinSphere') sphereNode.addSolid(coinSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.collect.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) def placeSilver(self): self.placeS = render.attachNewNode("Collectible-Placeholder") self.placeS.setPos(0,0,0) # Add the health items to the placeCol node for i in range(self.silvernum): # Load in the health item model self.collect = loader.loadModel("models/Anvil.egg") self.collect.setPos(0,0,0) self.collect.reparentTo(self.placeS) self.placeItem(self.collect) # Add spherical collision detection silverSphere = CollisionSphere(0,0,0,1) sphereNode = CollisionNode('silverSphere') sphereNode.addSolid(silverSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.collect.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) def placeGold(self): self.placeG = render.attachNewNode("Collectible-Placeholder") self.placeG.setPos(0,0,0) # Add the health items to the placeCol node for i in range(self.silvernum): # Load in the health item model self.collect = loader.loadModel("models/key.egg") self.collect.setPos(0,0,0) self.collect.reparentTo(self.placeS) self.placeItem(self.collect) # Add spherical collision detection goldSphere = CollisionSphere(0,0,0,1) sphereNode = CollisionNode('goldSphere') sphereNode.addSolid(goldSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.collect.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) def placeChests(self): self.placeCh = render.attachNewNode("Collectible-Placeholder") self.placeCh.setPos(0,0,0) # Add the health items to the placeCol node for i in range(self.chestnum): # Load in the health item model self.collect = loader.loadModel("models/Keg.a2c.cr.egg") self.collect.setPos(0,0,0) self.collect.reparentTo(self.placeCh) self.placeItem(self.collect) # Add spherical collision detection chestSphere = CollisionSphere(0,0,0,1) sphereNode = CollisionNode('chestSphere') sphereNode.addSolid(chestSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.collect.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) def placeRocks(self): self.placeR = render.attachNewNode("Collectible-Placeholder") self.placeR.setPos(0,0,0) # Add the health items to the placeCol node for i in range(self.rocknum): # Load in the health item model self.collect = loader.loadModel("models/smallcactus.egg") self.collect.setScale(0.2) self.collect.setPos(0,0,0) self.collect.reparentTo(self.placeR) self.placeItem(self.collect) # Add spherical collision detection rockSphere = CollisionSphere(0,0,0,1) sphereNode = CollisionNode('rockSphere') sphereNode.addSolid(rockSphere) sphereNode.setFromCollideMask(BitMask32.allOff()) sphereNode.setIntoCollideMask(BitMask32.bit(0)) sphereNp = self.collect.attachNewNode(sphereNode) sphereColHandler = CollisionHandlerQueue() base.cTrav.addCollider(sphereNp, sphereColHandler) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Makes ralph's health decrease over time # Make ralph's stamina regenerate def staminaReg(self, task): if (self.stamina >= 200): self.stamina = 200 return task.done else: self.stamina += 1 task.setDelay(1) return task.again # Make ralph run def runRalph(self, arg): self.isRunning = arg # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): if self.score < 0: self.die() if self.numObjects == 0: self.endgame() randomnum1 = random.randint(1,1000) randomnum2 = randomnum1 * self.numObjects + self.score if randomnum1 == 1000: result =buttonbox(msg='An odd villager wishes to help you on your quest? Trust him?', title='Alert!', choices=("Yes", "No")) if result == "Yes": if randomnum2 > 20000: msgbox("The villager grants you 4,000 Points!") self.score = self.score + 4000 if randomnum2 < 20000: msgbox("The villager betrays you! He steal 200 points!") self.score = self.score - 200 # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # calculate ralph's speed if (self.isRunning and self.stamina > 0): taskMgr.remove("staminaTask") ralphSpeed = 45 self.stamina -= 0.5 else: taskMgr.doMethodLater(5, self.staminaReg, "staminaTask") ralphSpeed = 25 # If a move-key is pressed, move ralph in the specified direction. # and rotate the camera to remain behind ralph if (self.keyMap["left"]!=0): self.ralph.setH(self.ralph.getH() + 100 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - 100 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.ralph.setY(self.ralph, -ralphSpeed * globalClock.getDt()) if (self.keyMap["backward"]!=0): self.ralph.setY(self.ralph, ralphSpeed *globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. 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.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk",5) self.isMoving = False # so the following line is unnecessary base.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) #base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+5) #Adds all the items to the map and handles if they get hit. elif (len(entries)>0) and (entries[0].getIntoNode().getName() == "colSphere"): self.collectCollectibles(entries[0]) elif (len(entries)>0) and (entries[0].getIntoNode().getName() == "vaseSphere"): self.collectVase(entries[0]) elif (len(entries)>0) and (entries[0].getIntoNode().getName() == "coinSphere"): self.collectCoins(entries[0]) elif (len(entries)>0) and (entries[0].getIntoNode().getName() == "silverSphere"): self.collectSilver(entries[0]) elif (len(entries)>0) and (entries[0].getIntoNode().getName() == "goldSphere"): self.collectGold(entries[0]) elif (len(entries)>0) and (entries[0].getIntoNode().getName() == "chestSphere"): self.collectChest(entries[0]) elif (len(entries)>0) and (entries[0].getIntoNode().getName() == "rockSphere"): self.deductRocks(entries[0]) else: self.ralph.setPos(startpos) # Keep the camera above the terrain entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): modZ = entries[0].getSurfacePoint(render).getZ() base.camera.setZ(20.0+modZ+(modZ-self.ralph.getZ())) self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ()+2.0) base.camera.lookAt(self.floater) self.displayStamina() return task.cont #If the user collects all items and/or ends the game through Escape. def endgame(self): # end all running tasks taskMgr.remove("moveTask") taskMgr.remove("healthTask") # Open database connection and inserts data. conn = MySQLdb.connect("sql5.freemysqlhosting.net","sql5106009","DFxbmhVkvG","sql5106009") cursor = conn.cursor() cursor.execute("INSERT INTO scores (score, username) VALUES (%s, %s)", (self.score, name)) conn.commit() time.sleep(5) #Error without this... #Some text self.label = DirectLabel(text="End Game!", scale=.05, pos=(0,0,0.2)) self.entry = DirectEntry(text="", scale=.05, initialText="", numLines=1, focus=1, pos=(-0.25,0,0)) #Display high score self.highscore = OkDialog(dialogName="highscoreDialog", text="Your High Score:\n\nName: " + name + "Score: " + str(self.score), command=sys.exit()) # Restart or End? def die(self): # end all running tasks taskMgr.remove("moveTask") taskMgr.remove("healthTask") # Open database connection conn = MySQLdb.connect("sql5.freemysqlhosting.net","sql5106009","DFxbmhVkvG","sql5106009") cursor = conn.cursor() cursor.execute("INSERT INTO scores (score, username) VALUES (%s, %s)", (self.score, name)) conn.commit() time.sleep(5) self.label = DirectLabel(text="Game over!", scale=.05, pos=(0,0,0.2)) self.entry = DirectEntry(text="", scale=.05, initialText="", numLines=1, focus=1, pos=(-0.25,0,0)) #Display high score self.highscore = OkDialog(dialogName="highscoreDialog", text="Your High Score:\n\nName: " + name + " " + "Score: " + str(self.score), command=self.showDialog) def showDialog(self, arg): # cleanup highscore dialog self.highscore.cleanup() # display restart or exit dialog self.dialog = YesNoDialog(dialogName="endDialog", text="Would you like to continue?", command=self.endResult) # Handle the dialog result def endResult(self, arg): if (arg): # cleanup the dialog box self.dialog.cleanup() # restart the game self.restart() else: sys.exit()
class World(DirectObject): def __init__(self): # This code puts the standard title and instruction text on screen self.title = OnscreenText(text="Ball in Maze", style=1, fg=(1, 1, 1, 1), pos=(0.7, -0.95), scale=.07) self.instructions = OnscreenText(text="Press Esc to exit.", pos=(-1.3, .95), fg=(1, 1, 1, 1), align=TextNode.ALeft, scale=.05) base.setBackgroundColor(0, 0, 0) self.central_msg = OnscreenText(text="", pos=(0, 0), fg=(1, 1, 0, 1), scale=.1) self.central_msg.hide() self.accept("escape", sys.exit) # Escape quits base.disableMouse() # Disable mouse-based camera control camera.setPosHpr(0, 0, 25, 0, -90, 0) # Place the camera # Load the maze and place it in the scene self.maze = loader.loadModel("models/maze") self.maze.reparentTo(render) # Most times, you want collisions to be tested against invisible geometry # rather than every polygon. This is because testing against every polygon # in the scene is usually too slow. You can have simplified or approximate # geometry for the solids and still get good results. # # Sometimes you'll want to create and position your own collision solids in # code, but it's often easier to have them built automatically. This can be # done by adding special tags into an egg file. Check maze.egg and ball.egg # and look for lines starting with <Collide>. The part is brackets tells # Panda exactly what to do. Polyset means to use the polygons in that group # as solids, while Sphere tells panda to make a collision sphere around them # Keep means to keep the polygons in the group as visable geometry (good # for the ball, not for the triggers), and descend means to make sure that # the settings are applied to any subgroups. # # Once we have the collision tags in the models, we can get to them using # NodePath's find command # Find the collision node named wall_collide self.walls = self.maze.find("**/wall_collide") # Collision objects are sorted using BitMasks. BitMasks are ordinary numbers # with extra methods for working with them as binary bits. Every collision # solid has both a from mask and an into mask. Before Panda tests two # objects, it checks to make sure that the from and into collision masks # have at least one bit in common. That way things that shouldn't interact # won't. Normal model nodes have collision masks as well. By default they # are set to bit 20. If you want to collide against actual visable polygons, # set a from collide mask to include bit 20 # # For this example, we will make everything we want the ball to collide with # include bit 0 self.walls.node().setIntoCollideMask(BitMask32.bit(0)) # CollisionNodes are usually invisible but can be shown. Uncomment the next # line to see the collision walls # self.walls.show() # We will now find the triggers for the holes and set their masks to 0 as # well. We also set their names to make them easier to identify during # collisions self.loseTriggers = [] for i in range(6): trigger = self.maze.find("**/hole_collide" + str(i)) trigger.node().setIntoCollideMask(BitMask32.bit(0)) trigger.node().setName("loseTrigger") self.loseTriggers.append(trigger) # Uncomment this line to see the triggers # trigger.show() # Ground_collide is a single polygon on the same plane as the ground in the # maze. We will use a ray to collide with it so that we will know exactly # what height to put the ball at every frame. Since this is not something # that we want the ball itself to collide with, it has a different # bitmask. self.mazeGround = self.maze.find("**/ground_collide") self.mazeGround.node().setIntoCollideMask(BitMask32.bit(1)) # Load the ball and attach it to the scene # It is on a root dummy node so that we can rotate the ball itself without # rotating the ray that will be attached to it self.ballRoot = render.attachNewNode("ballRoot") self.ball = loader.loadModel("models/ball") self.ball.reparentTo(self.ballRoot) # Find the collison sphere for the ball which was created in the egg file # Notice that it has a from collision mask of bit 0, and an into collison # mask of no bits. This means that the ball can only cause collisions, not # be collided into self.ballSphere = self.ball.find("**/ball") self.ballSphere.node().setFromCollideMask(BitMask32.bit(0)) self.ballSphere.node().setIntoCollideMask(BitMask32.allOff()) # No we create a ray to start above the ball and cast down. This is to # Determine the height the ball should be at and the angle the floor is # tilting. We could have used the sphere around the ball itself, but it # would not be as reliable self.ballGroundRay = CollisionRay() # Create the ray self.ballGroundRay.setOrigin(0, 0, 10) # Set its origin self.ballGroundRay.setDirection(0, 0, -1) # And its direction # Collision solids go in CollisionNode self.ballGroundCol = CollisionNode( 'groundRay') # Create and name the node self.ballGroundCol.addSolid(self.ballGroundRay) # Add the ray self.ballGroundCol.setFromCollideMask( BitMask32.bit(1)) # Set its bitmasks self.ballGroundCol.setIntoCollideMask(BitMask32.allOff()) # Attach the node to the ballRoot so that the ray is relative to the ball # (it will always be 10 feet over the ball and point down) self.ballGroundColNp = self.ballRoot.attachNewNode(self.ballGroundCol) # Uncomment this line to see the ray # self.ballGroundColNp.show() # Finally, we create a CollisionTraverser. CollisionTraversers are what # do the job of calculating collisions self.cTrav = CollisionTraverser() # Collision traverservs tell collision handlers about collisions, and then # the handler decides what to do with the information. We are using a # CollisionHandlerQueue, which simply creates a list of all of the # collisions in a given pass. There are more sophisticated handlers like # one that sends events and another that tries to keep collided objects # apart, but the results are often better with a simple queue self.cHandler = CollisionHandlerQueue() # Now we add the collision nodes that can create a collision to the # traverser. The traverser will compare these to all others nodes in the # scene. There is a limit of 32 CollisionNodes per traverser # We add the collider, and the handler to use as a pair self.cTrav.addCollider(self.ballSphere, self.cHandler) self.cTrav.addCollider(self.ballGroundColNp, self.cHandler) # Collision traversers have a built in tool to help visualize collisions. # Uncomment the next line to see it. # self.cTrav.showCollisions(render) # This section deals with lighting for the ball. Only the ball was lit # because the maze has static lighting pregenerated by the modeler ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.55, .55, .55, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0, 0, -1)) directionalLight.setColor(Vec4(0.375, 0.375, 0.375, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) self.ballRoot.setLight(render.attachNewNode(ambientLight)) self.ballRoot.setLight(render.attachNewNode(directionalLight)) # This section deals with adding a specular highlight to the ball to make # it look shiny m = Material() m.setSpecular(Vec4(1, 1, 1, 1)) m.setShininess(96) self.ball.setMaterial(m, 1) # Finally, we call start for more initialization self.start() def start(self): # The maze model also has a locator in it for where to start the ball # To access it we use the find command startPos = self.maze.find("**/start").getPos() self.ballRoot.setPos(startPos) # Set the ball in the starting position self.ballV = Vec3(0, 0, 0) # Initial velocity is 0 self.accelV = Vec3(0, 0, 0) # Initial acceleration is 0 # For a traverser to actually do collisions, you need to call # traverser.traverse() on a part of the scene. Fortunatly, base has a # task that does this for the entire scene once a frame. This sets up our # traverser as the one to be called automatically base.cTrav = self.cTrav # Create the movement task, but first make sure it is not already running taskMgr.remove("rollTask") self.mainLoop = taskMgr.add(self.rollTask, "rollTask") self.mainLoop.last = 0 # This function handles the collision between the ray and the ground # Information about the interaction is passed in colEntry def groundCollideHandler(self, colEntry): # Set the ball to the appropriate Z value for it to be exactly on the ground newZ = colEntry.getSurfacePoint(render).getZ() self.ballRoot.setZ(newZ + .4) # Find the acceleration direction. First the surface normal is crossed with # the up vector to get a vector perpendicular to the slope norm = colEntry.getSurfaceNormal(render) accelSide = norm.cross(UP) # Then that vector is crossed with the surface normal to get a vector that # points down the slope. By getting the acceleration in 3D like this rather # than in 2D, we reduce the amount of error per-frame, reducing jitter self.accelV = norm.cross(accelSide) # This function handles the collision between the ball and a wall def wallCollideHandler(self, colEntry): # First we calculate some numbers we need to do a reflection norm = colEntry.getSurfaceNormal(render) * -1 # The normal of the wall curSpeed = self.ballV.length() # The current speed inVec = self.ballV / curSpeed # The direction of travel velAngle = norm.dot(inVec) # Angle of incidance hitDir = colEntry.getSurfacePoint(render) - self.ballRoot.getPos() hitDir.normalize() hitAngle = norm.dot( hitDir) # The angle between the ball and the normal # Ignore the collision if the ball is either moving away from the wall # already (so that we don't accidentally send it back into the wall) # and ignore it if the collision isn't dead-on (to avoid getting caught on # corners) if velAngle > 0 and hitAngle > .995: # Standard reflection equation reflectVec = (norm * norm.dot(inVec * -1) * 2) + inVec # This makes the velocity half of what it was if the hit was dead-on # and nearly exactly what it was if this is a glancing blow self.ballV = reflectVec * (curSpeed * (((1 - velAngle) * .5) + .5)) # Since we have a collision, the ball is already a little bit buried in # the wall. This calculates a vector needed to move it so that it is # exactly touching the wall disp = (colEntry.getSurfacePoint(render) - colEntry.getInteriorPoint(render)) newPos = self.ballRoot.getPos() + disp self.ballRoot.setPos(newPos) # This is the task that deals with making everything interactive def rollTask(self, task): # Standard technique for finding the amount of time since the last frame dt = task.time - task.last task.last = task.time # If dt is large, then there has been a # hiccup that could cause the ball # to leave the field if this functions runs, so ignore the frame if dt > .2: return Task.cont # The collision handler collects the collisions. We dispatch which function # to handle the collision based on the name of what was collided into for i in range(self.cHandler.getNumEntries()): entry = self.cHandler.getEntry(i) name = entry.getIntoNode().getName() if name == "wall_collide": self.wallCollideHandler(entry) elif name == "ground_collide": self.groundCollideHandler(entry) elif name == "loseTrigger": self.loseGame(entry) # Read the mouse position and tilt the maze accordingly if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() # get the mouse position self.maze.setP(mpos.getY() * -10) self.maze.setR(mpos.getX() * 10) # Finally, we move the ball # Update the velocity based on acceleration self.ballV += self.accelV * dt * ACCEL # Clamp the velocity to the maximum speed if self.ballV.lengthSquared() > MAX_SPEED_SQ: self.ballV.normalize() self.ballV *= MAX_SPEED # Update the position based on the velocity self.ballRoot.setPos(self.ballRoot.getPos() + (self.ballV * dt)) # This block of code rotates the ball. It uses something called a quaternion # to rotate the ball around an arbitrary axis. That axis perpendicular to # the balls rotation, and the amount has to do with the size of the ball # This is multiplied on the previous rotation to incrimentally turn it. prevRot = LRotationf(self.ball.getQuat()) axis = UP.cross(self.ballV) newRot = LRotationf(axis, 45.5 * dt * self.ballV.length()) self.ball.setQuat(prevRot * newRot) return Task.cont # Continue the task indefinitely def show_message(self, message=''): if message: self.central_msg.setText(message) self.central_msg.show() else: self.central_msg.hide() # If the ball hits a hole trigger, then it should fall in the hole. # This is faked rather than dealing with the actual physics of it. def loseGame(self, entry): # The triggers are set up so that the center of the ball should move to the # collision point to be in the hole toPos = entry.getInteriorPoint(render) taskMgr.remove('rollTask') # Stop the maze task # Move the ball into the hole over a short sequence of time. Then wait a # second and call start to reset the game Sequence( Parallel( LerpFunc(self.ballRoot.setX, fromData=self.ballRoot.getX(), toData=toPos.getX(), duration=.1), LerpFunc(self.ballRoot.setY, fromData=self.ballRoot.getY(), toData=toPos.getY(), duration=.1), LerpFunc(self.ballRoot.setZ, fromData=self.ballRoot.getZ(), toData=self.ballRoot.getZ() - .9, duration=.2)), Func(self.show_message, "Try Again!"), Wait(1), Func(self.show_message, ""), Func(self.start)).start()
class Game(DirectObject): def __init__(self, model): self.model = model base.setBackgroundColor(0.1, 0.1, 0.8, 1) base.setFrameRateMeter(True) base.cam.setPos(0, -20, 4) base.cam.lookAt(0, 0, 0) # Light alight = AmbientLight('ambientLight') alight.setColor(Vec4(0.5, 0.5, 0.5, 1)) alightNP = render.attachNewNode(alight) dlight = DirectionalLight('directionalLight') dlight.setDirection(Vec3(1, 1, -1)) dlight.setColor(Vec4(0.7, 0.7, 0.7, 1)) dlightNP = render.attachNewNode(dlight) render.clearLight() render.setLight(alightNP) render.setLight(dlightNP) # Input self.accept('escape', self.doExit) self.accept('r', self.doReset) self.accept('f1', self.toggleWireframe) self.accept('f2', self.toggleTexture) self.accept('f3', self.toggleDebug) self.accept('f5', self.doScreenshot) inputState.watchWithModifiers('forward', 'w') inputState.watchWithModifiers('left', 'a') inputState.watchWithModifiers('reverse', 's') inputState.watchWithModifiers('right', 'd') inputState.watchWithModifiers('turnLeft', 'q') inputState.watchWithModifiers('turnRight', 'e') # Task taskMgr.add(self.update, 'updateWorld') # Physics self.setup() # _____HANDLER_____ def doExit(self): self.cleanup() sys.exit(1) def doReset(self): self.cleanup() self.setup() def toggleWireframe(self): base.toggleWireframe() def toggleTexture(self): base.toggleTexture() def toggleDebug(self): if self.debugNP.isHidden(): self.debugNP.show() else: self.debugNP.hide() def doScreenshot(self): base.screenshot('Bullet') # ____TASK___ def calculate_moves(self): self.y = self.model.predict(self.x) self.moves = self.y > 0 # 0.5 def processInput(self, dt): engineForce = 0.0 brakeForce = 0.0 if self.moves[0]: #inputState.isSet('forward'): engineForce = 1000.0 brakeForce = 0.0 if not self.moves[0]: #inputState.isSet('reverse'): engineForce = 0.0 brakeForce = 100.0 if self.moves[1]: #inputState.isSet('turnLeft'): self.steering += dt * self.steeringIncrement self.steering = min(self.steering, self.steeringClamp) if not self.moves[1]: #inputState.isSet('turnRight'): self.steering -= dt * self.steeringIncrement self.steering = max(self.steering, -self.steeringClamp) """ if inputState.isSet('forward'): engineForce = 1000.0 brakeForce = 0.0 if inputState.isSet('reverse'): engineForce = 0.0 brakeForce = 100.0 if inputState.isSet('turnLeft'): self.steering += dt * self.steeringIncrement self.steering = min(self.steering, self.steeringClamp) if inputState.isSet('turnRight'): self.steering -= dt * self.steeringIncrement self.steering = max(self.steering, -self.steeringClamp) """ # Apply steering to front wheels self.vehicle.setSteeringValue(self.steering, 0) self.vehicle.setSteeringValue(self.steering, 1) # Apply engine and brake to rear wheels self.vehicle.applyEngineForce(engineForce, 2) self.vehicle.applyEngineForce(engineForce, 3) self.vehicle.setBrake(brakeForce, 2) self.vehicle.setBrake(brakeForce, 3) def raycast(self): """pFrom = render.getRelativePoint(self.yugoNP,Point3(0,0,0))#Point3(0,0,0) pFrom -= Point3(0,0,pFrom[2]) pRel = render.getRelativePoint(base.cam,self.yugoNP.getPos()) # FIXME THIS IS IT!! get rid of z component pRel -= Point3(0,0,pRel[2]) p45 = Point3(pRel[0] - pRel[1], pRel[1] + pRel[0],0) pn45 = Point3(pRel[0] + pRel[1], pRel[1] - pRel[0],0) #print(render.getRelativePoint(self.yugoNP,Point3(0,0,0))) #print(dir(self.yugoNP)) pTo = [pFrom + pn45, pFrom + pRel, pFrom + p45]#[pFrom + Vec3(-10,10,0)*999,pFrom + Vec3(0,10,0)*999,pFrom + Vec3(10,10,0)*999]# FIXME should be relative to front of car, getting cloe! #self.yugoNP.getPosDelta()*99999]#[Point3(-10,10,0) * 99999,Point3(0,10,0) * 99999,Point3(10,10,0) * 99999] #self.ray = CollisionRay(0,0,0,100,0,0) result = [self.world.rayTestClosest(pFrom,pt) for pt in pTo] #print(dir(self.yugoNP)) #print(result.getHitPos()) return tuple([res.getHitPos().length() for res in result]) """#queue = CollisionHandlerQueue() #traverser.addCollider(fromObject, queue) #traverser.traverse(render) #queue.sortEntries() #for entry in queue.getEntries(): #print(entry) #print(result.getHitPos()) #if result.getNode() != None: #print(self.yugoNP.getPos(result.getNode())) #print(self.cTrav) self.cTrav.traverse(render) entries = list(self.colHandler.getEntries()) entries.sort(key=lambda y: y.getSurfacePoint(render).getY()) #for entry in entries: print(entry.getFromNodePath().getName()) if entries: # and len(result) > 1: for r in entries: if r.getIntoNodePath().getName( ) == 'Box' and r.getFromNodePath().getName() in [ 'ray%d' % i for i in range(3) ]: self.ray_col_vec_dict[ r.getFromNodePath().getName()].append( numpy.linalg.norm( list(r.getSurfacePoint( r.getFromNodePath()))[:-1])) self.ray_col_vec_dict = { k: (min(self.ray_col_vec_dict[k]) if len(self.ray_col_vec_dict[k]) >= 1 else 10000) for k in self.ray_col_vec_dict } self.x = numpy.array(list(self.ray_col_vec_dict.values())) #return entries def update(self, task): dt = globalClock.getDt() self.raycast() self.calculate_moves() self.ray_col_vec_dict = {k: [] for k in self.ray_col_vec_dict} self.processInput(dt) self.world.doPhysics(dt, 10, 0.008) #print(dir(result[1])) #print(numpy.linalg.norm(list(result[1].getSurfacePoint(result[1].getFromNodePath()))[:-1])) #base.camera.setPos(0,-40,10) #print self.vehicle.getWheel(0).getRaycastInfo().isInContact() #print self.vehicle.getWheel(0).getRaycastInfo().getContactPointWs() #print self.vehicle.getChassis().isKinematic() return task.cont def cleanup(self): self.world = None self.worldNP.removeNode() def setup(self): self.worldNP = render.attachNewNode('World') # World self.debugNP = self.worldNP.attachNewNode(BulletDebugNode('Debug')) self.debugNP.show() self.world = BulletWorld() self.world.setGravity(Vec3(0, 0, -9.81)) self.world.setDebugNode(self.debugNP.node()) #terrain = GeoMipTerrain("mySimpleTerrain") #terrain.setHeightfield("./models/heightfield_2.png") #terrain.getRoot().reparentTo(self.worldNP)#render) #terrain.generate() # Plane shape = BulletPlaneShape(Vec3(0, 0, 1), 0) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Ground')) np.node().addShape(shape) np.setPos(0, 0, -1) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Track')) np.node().setMass(5000.0) np.setPos(3, 0, 10) np.setCollideMask(BitMask32.allOn()) #(0x0f)) #self.track = BulletVehicle(self.world, np.node()) #self.track.setCoordinateSystem(ZUp) self.track_np = loader.loadModel('models/race_track.egg') self.track_np.setScale(100) self.track_np.reparentTo(np) self.track_np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) self.track_np = np #self.track_np.show() # Chassis shape = BulletBoxShape(Vec3(0.6, 1.4, 0.5)) ts = TransformState.makePos(Point3(0, 0, 0.5)) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Vehicle')) np.node().addShape(shape, ts) np.setPos(0, 0, 1) np.node().setMass(800.0) np.node().setDeactivationEnabled(False) self.world.attachRigidBody(np.node()) #np.node().setCcdSweptSphereRadius(1.0) #np.node().setCcdMotionThreshold(1e-7) self.cTrav = CollisionTraverser() # Vehicle self.vehicle = BulletVehicle(self.world, np.node()) self.vehicle.setCoordinateSystem(ZUp) self.yugoNP = loader.loadModel('models/yugo/yugo.egg') self.yugoNP.reparentTo(np) self.colHandler = CollisionHandlerQueue() self.ray_col_np = {} self.ray_col_vec_dict = {} for ray_dir in range(-1, 2): # populate collision rays self.ray = CollisionRay() self.ray.setOrigin(ray_dir, 0.5, 0.5) self.ray.setDirection(ray_dir, 1, 0) self.ray_col = CollisionNode('ray%d' % (ray_dir + 1)) self.ray_col.addSolid(self.ray) self.ray_col.setFromCollideMask( BitMask32.allOn()) #(0x0f))#CollideMask.bit(0) #self.ray_col.setIntoCollideMask(CollideMask.allOff()) self.ray_col_np['ray%d' % (ray_dir + 1)] = self.yugoNP.attachNewNode( self.ray_col) self.cTrav.addCollider(self.ray_col_np['ray%d' % (ray_dir + 1)], self.colHandler) self.ray_col_np['ray%d' % (ray_dir + 1)].show() self.ray_col_vec_dict['ray%d' % (ray_dir + 1)] = [] self.world.attachVehicle(self.vehicle) self.cTrav.showCollisions(render) # FIXME base.camera.reparentTo(self.yugoNP) # Right front wheel np = loader.loadModel('models/yugo/yugotireR.egg') np.reparentTo(self.worldNP) self.addWheel(Point3(0.70, 1.05, 0.3), True, np) # Left front wheel np = loader.loadModel('models/yugo/yugotireL.egg') np.reparentTo(self.worldNP) self.addWheel(Point3(-0.70, 1.05, 0.3), True, np) # Right rear wheel np = loader.loadModel('models/yugo/yugotireR.egg') np.reparentTo(self.worldNP) self.addWheel(Point3(0.70, -1.05, 0.3), False, np) # Left rear wheel np = loader.loadModel('models/yugo/yugotireL.egg') np.reparentTo(self.worldNP) self.addWheel(Point3(-0.70, -1.05, 0.3), False, np) # Steering info self.steering = 0.0 # degree self.steeringClamp = 45.0 # degree self.steeringIncrement = 120.0 # degree per second # Box for i, j in [(0, 8), (-3, 5), (6, -5), (8, 3), (-4, -4)]: shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5)) # https://discourse.panda3d.org/t/wall-collision-help/23606 np = self.worldNP.attachNewNode(BulletRigidBodyNode('Box')) np.node().setMass(1.0) np.node().addShape(shape) np.setPos(i, j, 2) np.setCollideMask(BitMask32.allOn()) #(0x0f)) self.world.attachRigidBody(np.node()) self.boxNP = np #self.colHandler2 = CollisionHandlerQueue() visualNP = loader.loadModel('models/box.egg') visualNP.reparentTo(self.boxNP) #self.cTrav.addCollider(self.boxNP,self.colHandler) """ aNode = CollisionNode("TheRay") self.ray = CollisionRay() self.ray.setOrigin( self.yugoNP.getPos() ) self.ray.setDirection( Vec3(0, 10, 0) ) #self.ray.show() aNodePath = self.yugoNP.attachNewNode( CollisionNode("TheRay") ) aNodePath.node().addSolid(self.ray) aNodePath.show() """ #aNode.addSolid(self.ray) #self.ray = CollisionRay(0,0,0,10,0,0) #self.ray.reparentTo(self.yugoNP) #self.rayColl = CollisionNode('PlayerRay') #self.rayColl.addSolid(self.ray) #self.playerRayNode = self.yugoNP.attachNewNode( self.rayColl ) #self.playerRayNode.show() #base.myTraverser.addCollider (self.playerRayNode, base.floor) #base.floor.addCollider( self.playerRayNode, self.yugoNP) """ MyEvent=CollisionHandlerFloor() MyEvent.setReach(100) MyEvent.setOffset(15.0) aNode = CollisionNode("TheRay") ray = CollisionRay() ray.setOrigin( self.boxNP.getPos() ) ray.setDirection( Vec3(10, 0, 0) ) aNode.addSolid(ray) aNodePath = MyModel.attachNewNode( aNode ) Collision = ( aNode, "TheRay" ) Collision[0].setFromCollideMask( BitMask32.bit( 1 ) ) """ def addWheel(self, pos, front, np): wheel = self.vehicle.createWheel() wheel.setNode(np.node()) wheel.setChassisConnectionPointCs(pos) wheel.setFrontWheel(front) wheel.setWheelDirectionCs(Vec3(0, 0, -1)) wheel.setWheelAxleCs(Vec3(1, 0, 0)) wheel.setWheelRadius(0.25) wheel.setMaxSuspensionTravelCm(40.0) wheel.setSuspensionStiffness(40.0) wheel.setWheelsDampingRelaxation(2.3) wheel.setWheelsDampingCompression(4.4) wheel.setFrictionSlip(100.0) wheel.setRollInfluence(0.1)
class World(ShowBase): def skyBoxLoad(self): self.spaceSkyBox = load_model('skybox1.egg') self.spaceSkyBox.setScale(150) self.spaceSkyBox.setLightOff() self.spaceSkyBox.reparentTo(render) self.spaceSkyBox.setPos(0,0,-200) self.spaceSkyBox.setHpr(0,0,0) def loadEnviron(self): self.environ = load_model("secondWorld.egg") self.environ.reparentTo(render) self.environ.setPos(0,0,0) def Hooh(self): """ hooh """ self.hoohActor = Actor("anim2hooh.egg", {"wing":"anim-Anim0.egg"}) self.hoohActor.reparentTo(render) self.hoohActor.loop("wing") self.hoohActor.setPos(self.ralphStartPos[0], self.ralphStartPos[1]+100, self.ralphStartPos[2]+100) self.hoohActor.setPlayRate(4.0,"wing") self.hoohActor.setHpr(180,90,0) start = Point3(self.ralphStartPos[0], self.ralphStartPos[1]+95, self.ralphStartPos[2]+100) end = Point3(self.ralphStartPos[0], self.ralphStartPos[1]-100, self.ralphStartPos[2]+100) turnHpr1 = Point3(180,90,0) turnHpr2 = Point3(0,90,0) hoohPosInt1 = self.hoohActor.posInterval(5.0, start, startPos = end) hoohPosInt2 = self.hoohActor.posInterval(5.0, end, startPos = start) hoohHprInt1 = self.hoohActor.hprInterval(1.0, turnHpr2, startHpr=turnHpr1) hoohHprInt2 = self.hoohActor.hprInterval(1.0, turnHpr1, startHpr=turnHpr2) self.hoohFly = Sequence(hoohPosInt1, hoohHprInt1, hoohPosInt2, hoohHprInt2, name="hoohFly") self.hoohFly.loop() def gold(self, task): _GOLD_PARTICLES.setPos(self.hoohActor.getPos()) return task.cont def loadPokemon(self): """ Pikachu """ self.pikachu = load_model("pikachu.egg") self.pikachu.reparentTo(render) self.pikachu.setPos(_PIKACHU_POS) self.pikachu.setHpr(_PIKACHU_HPR) """ Groudon """ self.Groudon = load_model("Groudon.egg") self.Groudon.reparentTo(render) self.Groudon.setPos(_GROUDON_POS) self.Groudon.setHpr(_GROUDON_HPR) """ Bulbasaur """ self.bulbasaur = load_model("bulbasaur.egg") self.bulbasaur.reparentTo(render) self.bulbasaur.setPos(_BULBASAUR_POS) self.bulbasaur.setHpr(_BULBASAUR_HPR) """ hooh """ self.Hooh() """ Pichu """ self.pichu = load_model("pichu.egg") self.pichu.reparentTo(render) self.pichu.setPos(_PICHU_POS) self.pichu.setHpr(_PICHU_HPR) """ Charmander """ self.charmander = load_model("char.egg") self.charmander.reparentTo(render) self.charmander.setPos(_CHARMANDER_POS) self.charmander.setHpr(_CHARMANDER_HPR) """ charizard """ self.charizard = load_model("charizard.egg") self.charizard.reparentTo(render) self.charizard.setPos(_CHARIZARD_POS) self.charizard.setHpr(_CHARIZARD_HPR) """ blastoise """ self.blastoise = load_model("blastoise.egg") self.blastoise.reparentTo(render) self.blastoise.setPos(_BLASTOISE_POS) self.blastoise.setHpr(_BLASTOISE_HPR) """ Squirtle """ self.squirtle = load_model("squirtle.egg") self.squirtle.reparentTo(render) self.squirtle.setPos(_SQUIRTLE_POS) self.squirtle.setHpr(_SQUIRTLE_HPR) """ Dragonite """ self.dragonite = load_model("dragonite.egg") self.dragonite.reparentTo(render) self.dragonite.setPos(_DRAGONITE_POS) self.dragonite.setHpr(_DRAGONITE_HPR) _FLAME.setPos(_FLAME_POS) _FLAME.setScale(0.1) _FLAME.start(parent=render, renderParent=render) """ venusaur """ self.venusaur = load_model("venusaur.egg") self.venusaur.reparentTo(render) self.venusaur.setPos(_VENUSAUR_POS) self.venusaur.setHpr(_VENUSAUR_HPR) def loadRalph(self): # Create the main character, Ralph basePath = r"../google_drive/ball/data/models/" self.ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor(basePath+"ralph",{"run":basePath+"ralph-run", "walk":basePath+"ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(self.ralphStartPos) self.ralph.hide() def loadNextMusic(self, task): # random load background music if (self.music.status()!=self.music.PLAYING): # not playing self.musicCounter += 1 index = self.musicCounter % len(_BGMUSIC) self.music = load_bgmusic(_BGMUSIC[index]) self.music.play() return task.cont def keyControl(self): 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("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("w",self.setKey,["upward",1]) self.accept("w-up",self.setKey,["upward",0]) self.accept("s",self.setKey,["downward",1]) self.accept("s-up",self.setKey,["downward",0]) self.accept("t", self.toggleMusic) self.accept("u", self.changeVolume, ['u']) self.accept("d", self.changeVolume, ['d']) self.accept("h", self.hideInstructions) def changeVolume(self, direction): if direction == 'u' and self.volume < 1: self.volume += 0.05 else: # direction == 'd' if self.volume > 0: self.volume -= 0.05 self.music.setVolume(self.volume) def toggleMusic(self): self.music.stop() self.musicCounter += 1 # increment the counter by index = self.musicCounter % len(_BGMUSIC) self.music = load_bgmusic(_BGMUSIC[index]) self.music.play() def displayInformation(self): self.title = addTitle("My Pokemon - Roam Mode") self.inst1 = addInstructions(0.95, "[ESC]: Quit") self.inst2 = addInstructions(0.90, "[Arrow Keys]: Move") self.inst3 = addInstructions(0.85, "[w]: look up") self.inst4 = addInstructions(0.80, "[s]: look down") self.inst5 = addInstructions(0.75, "[t]: toggle next song") self.inst6 = addInstructions(0.70, "[u]: volume up") self.inst7 = addInstructions(0.65, "[d]: volume down") self.inst8 = addInstructions(0.60, "[h]: hide/show instructions") self.insts = [self.title, self.inst1, self.inst2, self.inst3, self.inst4, self.inst5, self.inst6, self.inst7, self.inst8] def hideInstructions(self): if self.instStatus == "show": self.instStatus = "hide" groupHide(self.insts) else: # instructions are hidden self.instStatus = "show" groupShow(self.insts) def __init__(self): base.enableParticles() self.keyMap = {"left":0, "right":0, "forward":0,"backward":0, "upward":0, "downward":0, "leftward":0,"rightward":0, "cam-left":0, "cam-right":0} _GOLD_PARTICLES.start(parent=render, renderParent=render) _GOLD_PARTICLES.setScale(200) self.instStatus = "show" self.musicCounter = 0 self.music = load_bgmusic(_BGMUSIC[0]) # self.music.play() self.volume = 0 self.music.setVolume(self.volume) base.win.setClearColor(Vec4(0,0,0,1)) self.above = 3.0 # load environment self.loadEnviron() # load ralph self.loadRalph() # load sky box self.skyBoxLoad() # load pokemon self.loadPokemon() self.displayInformation() self.keyControl() # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) taskMgr.add(self.move,"moveTask") taskMgr.add(self.setAbove,"setAbove") taskMgr.add(self.loadNextMusic, "loadRandomMusic") taskMgr.add(self.gold, "gold") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(),self.ralph.getY(),2) self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0,0,1000) self.ralphGroundRay.setDirection(0,0,-1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) def setAbove(self,task): if self.keyMap["upward"] == 1: self.above += 0.1 if self.keyMap["downward"] == 1: self.above -= 0.1 return task.cont #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"]!=0): self.ralph.setH(self.ralph.getH() + 113 * globalClock.getDt()) base.camera.setX(base.camera, +20 * globalClock.getDt()) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - 113 * globalClock.getDt()) base.camera.setX(base.camera, -20 * globalClock.getDt()) if (self.keyMap["forward"]!=0): self.ralph.setY(self.ralph, -75 * globalClock.getDt()) if (self.keyMap["backward"] != 0): pass #self.ralph.setY(self.ralph, 75 * globalClock.getDt()) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. 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.ralph.loop("run") self.isMoving = True else: if self.isMoving: #self.ralph.stop() #self.ralph.pose("walk",5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.0): base.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + self.above)#self.above) base.camera.lookAt(self.floater) return task.cont
class World(DirectObject): def __init__(self): # This code puts the standard title and instruction text on screen self.title = OnscreenText(text="Panda3D: Tutorial - Collision Detection", style=1, fg=(1,1,1,1), pos=(0.7,-0.95), scale = .07) self.instructions = OnscreenText(text="Mouse pointer tilts the board", pos = (-1.3, .95), fg=(1,1,1,1), align = TextNode.ALeft, scale = .05) self.accept("escape", sys.exit) # Escape quits base.disableMouse() # Disable mouse-based camera control camera.setPosHpr(0, 0, 25, 0, -90, 0) # Place the camera # Load the maze and place it in the scene self.maze = loader.loadModel("models/maze") self.maze.reparentTo(render) # Most times, you want collisions to be tested against invisible geometry # rather than every polygon. This is because testing against every polygon # in the scene is usually too slow. You can have simplified or approximate # geometry for the solids and still get good results. # # Sometimes you'll want to create and position your own collision solids in # code, but it's often easier to have them built automatically. This can be # done by adding special tags into an egg file. Check maze.egg and ball.egg # and look for lines starting with <Collide>. The part is brackets tells # Panda exactly what to do. Polyset means to use the polygons in that group # as solids, while Sphere tells panda to make a collision sphere around them # Keep means to keep the polygons in the group as visable geometry (good # for the ball, not for the triggers), and descend means to make sure that # the settings are applied to any subgroups. # # Once we have the collision tags in the models, we can get to them using # NodePath's find command # Find the collision node named wall_collide self.walls = self.maze.find("**/wall_collide") # Collision objects are sorted using BitMasks. BitMasks are ordinary numbers # with extra methods for working with them as binary bits. Every collision # solid has both a from mask and an into mask. Before Panda tests two # objects, it checks to make sure that the from and into collision masks # have at least one bit in common. That way things that shouldn't interact # won't. Normal model nodes have collision masks as well. By default they # are set to bit 20. If you want to collide against actual visable polygons, # set a from collide mask to include bit 20 # # For this example, we will make everything we want the ball to collide with # include bit 0 self.walls.node().setIntoCollideMask(BitMask32.bit(0)) # CollisionNodes are usually invisible but can be shown. Uncomment the next # line to see the collision walls # self.walls.show() # We will now find the triggers for the holes and set their masks to 0 as # well. We also set their names to make them easier to identify during # collisions self.loseTriggers = [] for i in range(6): trigger = self.maze.find("**/hole_collide" + str(i)) trigger.node().setIntoCollideMask(BitMask32.bit(0)) trigger.node().setName("loseTrigger") self.loseTriggers.append(trigger) # Uncomment this line to see the triggers # trigger.show() # Ground_collide is a single polygon on the same plane as the ground in the # maze. We will use a ray to collide with it so that we will know exactly # what height to put the ball at every frame. Since this is not something # that we want the ball itself to collide with, it has a different # bitmask. self.mazeGround = self.maze.find("**/ground_collide") self.mazeGround.node().setIntoCollideMask(BitMask32.bit(1)) # Load the ball and attach it to the scene # It is on a root dummy node so that we can rotate the ball itself without # rotating the ray that will be attached to it self.ballRoot = render.attachNewNode("ballRoot") self.ball = loader.loadModel("models/ball") self.ball.reparentTo(self.ballRoot) # Find the collison sphere for the ball which was created in the egg file # Notice that it has a from collision mask of bit 0, and an into collison # mask of no bits. This means that the ball can only cause collisions, not # be collided into self.ballSphere = self.ball.find("**/ball") self.ballSphere.node().setFromCollideMask(BitMask32.bit(0)) self.ballSphere.node().setIntoCollideMask(BitMask32.allOff()) # No we create a ray to start above the ball and cast down. This is to # Determine the height the ball should be at and the angle the floor is # tilting. We could have used the sphere around the ball itself, but it # would not be as reliable self.ballGroundRay = CollisionRay() # Create the ray self.ballGroundRay.setOrigin(0,0,10) # Set its origin self.ballGroundRay.setDirection(0,0,-1) # And its direction # Collision solids go in CollisionNode self.ballGroundCol = CollisionNode('groundRay') # Create and name the node self.ballGroundCol.addSolid(self.ballGroundRay) # Add the ray self.ballGroundCol.setFromCollideMask(BitMask32.bit(1)) # Set its bitmasks self.ballGroundCol.setIntoCollideMask(BitMask32.allOff()) # Attach the node to the ballRoot so that the ray is relative to the ball # (it will always be 10 feet over the ball and point down) self.ballGroundColNp = self.ballRoot.attachNewNode(self.ballGroundCol) # Uncomment this line to see the ray # self.ballGroundColNp.show() # Finally, we create a CollisionTraverser. CollisionTraversers are what # do the job of calculating collisions self.cTrav = CollisionTraverser() # Collision traverservs tell collision handlers about collisions, and then # the handler decides what to do with the information. We are using a # CollisionHandlerQueue, which simply creates a list of all of the # collisions in a given pass. There are more sophisticated handlers like # one that sends events and another that tries to keep collided objects # apart, but the results are often better with a simple queue self.cHandler = CollisionHandlerQueue() # Now we add the collision nodes that can create a collision to the # traverser. The traverser will compare these to all others nodes in the # scene. There is a limit of 32 CollisionNodes per traverser # We add the collider, and the handler to use as a pair self.cTrav.addCollider(self.ballSphere, self.cHandler) self.cTrav.addCollider(self.ballGroundColNp, self.cHandler) # Collision traversers have a built in tool to help visualize collisions. # Uncomment the next line to see it. # self.cTrav.showCollisions(render) # This section deals with lighting for the ball. Only the ball was lit # because the maze has static lighting pregenerated by the modeler ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.55, .55, .55, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0, 0, -1)) directionalLight.setColor(Vec4(0.375, 0.375, 0.375, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) self.ballRoot.setLight(render.attachNewNode(ambientLight)) self.ballRoot.setLight(render.attachNewNode(directionalLight)) # This section deals with adding a specular highlight to the ball to make # it look shiny m = Material() m.setSpecular(Vec4(1,1,1,1)) m.setShininess(96) self.ball.setMaterial(m, 1) # Finally, we call start for more initialization self.start() def start(self): # The maze model also has a locator in it for where to start the ball # To access it we use the find command startPos = self.maze.find("**/start").getPos() self.ballRoot.setPos(startPos) # Set the ball in the starting position self.ballV = Vec3(0,0,0) # Initial velocity is 0 self.accelV = Vec3(0,0,0) # Initial acceleration is 0 # For a traverser to actually do collisions, you need to call # traverser.traverse() on a part of the scene. Fortunatly, base has a # task that does this for the entire scene once a frame. This sets up our # traverser as the one to be called automatically base.cTrav = self.cTrav # Create the movement task, but first make sure it is not already running taskMgr.remove("rollTask") self.mainLoop = taskMgr.add(self.rollTask, "rollTask") self.mainLoop.last = 0 # This function handles the collision between the ray and the ground # Information about the interaction is passed in colEntry def groundCollideHandler(self, colEntry): # Set the ball to the appropriate Z value for it to be exactly on the ground newZ = colEntry.getSurfacePoint(render).getZ() self.ballRoot.setZ(newZ+.4) # Find the acceleration direction. First the surface normal is crossed with # the up vector to get a vector perpendicular to the slope norm = colEntry.getSurfaceNormal(render) accelSide = norm.cross(UP) # Then that vector is crossed with the surface normal to get a vector that # points down the slope. By getting the acceleration in 3D like this rather # than in 2D, we reduce the amount of error per-frame, reducing jitter self.accelV = norm.cross(accelSide) # This function handles the collision between the ball and a wall def wallCollideHandler(self, colEntry): # First we calculate some numbers we need to do a reflection norm = colEntry.getSurfaceNormal(render) * -1 # The normal of the wall curSpeed = self.ballV.length() # The current speed inVec = self.ballV / curSpeed # The direction of travel velAngle = norm.dot(inVec) # Angle of incidance hitDir = colEntry.getSurfacePoint(render) - self.ballRoot.getPos() hitDir.normalize() hitAngle = norm.dot(hitDir) # The angle between the ball and the normal # Ignore the collision if the ball is either moving away from the wall # already (so that we don't accidentally send it back into the wall) # and ignore it if the collision isn't dead-on (to avoid getting caught on # corners) if velAngle > 0 and hitAngle > .995: # Standard reflection equation reflectVec = (norm * norm.dot(inVec * -1) * 2) + inVec # This makes the velocity half of what it was if the hit was dead-on # and nearly exactly what it was if this is a glancing blow self.ballV = reflectVec * (curSpeed * (((1-velAngle)*.5)+.5)) # Since we have a collision, the ball is already a little bit buried in # the wall. This calculates a vector needed to move it so that it is # exactly touching the wall disp = (colEntry.getSurfacePoint(render) - colEntry.getInteriorPoint(render)) newPos = self.ballRoot.getPos() + disp self.ballRoot.setPos(newPos) # This is the task that deals with making everything interactive def rollTask(self, task): # Standard technique for finding the amount of time since the last frame dt = task.time - task.last task.last = task.time # If dt is large, then there has been a # hiccup that could cause the ball # to leave the field if this functions runs, so ignore the frame if dt > .2: return Task.cont # The collision handler collects the collisions. We dispatch which function # to handle the collision based on the name of what was collided into for i in range(self.cHandler.getNumEntries()): entry = self.cHandler.getEntry(i) name = entry.getIntoNode().getName() if name == "wall_collide": self.wallCollideHandler(entry) elif name == "ground_collide": self.groundCollideHandler(entry) elif name == "loseTrigger": self.loseGame(entry) # Read the mouse position and tilt the maze accordingly if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() # get the mouse position self.maze.setP(mpos.getY() * -10) self.maze.setR(mpos.getX() * 10) # Finally, we move the ball # Update the velocity based on acceleration self.ballV += self.accelV * dt * ACCEL # Clamp the velocity to the maximum speed if self.ballV.lengthSquared() > MAX_SPEED_SQ: self.ballV.normalize() self.ballV *= MAX_SPEED # Update the position based on the velocity self.ballRoot.setPos(self.ballRoot.getPos() + (self.ballV * dt)) # This block of code rotates the ball. It uses something called a quaternion # to rotate the ball around an arbitrary axis. That axis perpendicular to # the balls rotation, and the amount has to do with the size of the ball # This is multiplied on the previous rotation to incrimentally turn it. prevRot = LRotationf(self.ball.getQuat()) axis = UP.cross(self.ballV) newRot = LRotationf(axis, 45.5 * dt * self.ballV.length()) self.ball.setQuat(prevRot * newRot) return Task.cont # Continue the task indefinitely # If the ball hits a hole trigger, then it should fall in the hole. # This is faked rather than dealing with the actual physics of it. def loseGame(self, entry): # The triggers are set up so that the center of the ball should move to the # collision point to be in the hole toPos = entry.getInteriorPoint(render) taskMgr.remove('rollTask') # Stop the maze task # Move the ball into the hole over a short sequence of time. Then wait a # second and call start to reset the game Sequence( Parallel( LerpFunc(self.ballRoot.setX, fromData = self.ballRoot.getX(), toData = toPos.getX(), duration = .1), LerpFunc(self.ballRoot.setY, fromData = self.ballRoot.getY(), toData = toPos.getY(), duration = .1), LerpFunc(self.ballRoot.setZ, fromData = self.ballRoot.getZ(), toData = self.ballRoot.getZ() - .9, duration = .2)), Wait(1), Func(self.start)).start()
class RoamingRalphDemo(ShowBase): def __init__(self): # Set up the window, camera, etc. ShowBase.__init__(self) # Set the background color to black self.win.setClearColor((0, 0, 0, 1)) # This is used to store which keys are currently pressed. self.keyMap = { "left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0 } # Post the instructions self.title = addTitle( "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.06, "[ESC]: Quit") self.inst2 = addInstructions(0.12, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.18, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.24, "[Up Arrow]: Run Ralph Forward") self.inst6 = addInstructions(0.30, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.36, "[S]: Rotate Camera Right") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", { "run": "models/ralph-run", "walk": "models/ralph-walk" }) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos + (0, 0, 0.5)) # Create a floater object, which floats 2 units above ralph. We # use this as a target for the camera to look at. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(self.ralph) self.floater.setZ(2.0) # Accept the control keys for movement and rotation self.accept("escape", sys.exit) self.accept("arrow_left", self.setKey, ["left", True]) self.accept("arrow_right", self.setKey, ["right", True]) self.accept("arrow_up", self.setKey, ["forward", True]) self.accept("a", self.setKey, ["cam-left", True]) self.accept("s", self.setKey, ["cam-right", True]) self.accept("arrow_left-up", self.setKey, ["left", False]) self.accept("arrow_right-up", self.setKey, ["right", False]) self.accept("arrow_up-up", self.setKey, ["forward", False]) self.accept("a-up", self.setKey, ["cam-left", False]) self.accept("s-up", self.setKey, ["cam-right", False]) taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera self.disableMouse() self.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 9) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(CollideMask.bit(0)) self.ralphGroundCol.setIntoCollideMask(CollideMask.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0, 0, 9) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(CollideMask.bit(0)) self.camGroundCol.setIntoCollideMask(CollideMask.allOff()) self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection((-5, -5, -5)) directionalLight.setColor((1, 1, 1, 1)) directionalLight.setSpecularColor((1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # Get the time that elapsed since last frame. We multiply this with # the desired speed in order to find out with which distance to move # in order to achieve that desired speed. dt = globalClock.getDt() # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. if self.keyMap["cam-left"]: self.camera.setX(self.camera, -20 * dt) if self.keyMap["cam-right"]: self.camera.setX(self.camera, +20 * dt) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if self.keyMap["left"]: self.ralph.setH(self.ralph.getH() + 300 * dt) if self.keyMap["right"]: self.ralph.setH(self.ralph.getH() - 300 * dt) if self.keyMap["forward"]: self.ralph.setY(self.ralph, -25 * dt) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if self.keyMap["forward"] or self.keyMap["left"] or self.keyMap[ "right"]: if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - self.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if camdist > 10.0: self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if camdist < 5.0: self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Normally, we would have to call traverse() to check for collisions. # However, the class ShowBase that we inherit from has a task to do # this for us, if we assign a CollisionTraverser to self.cTrav. #self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = list(self.ralphGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName( ) == "terrain": self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = list(self.camGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName( ) == "terrain": self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if self.camera.getZ() < self.ralph.getZ() + 2.0: self.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.camera.lookAt(self.floater) return task.cont
class MyApp(ShowBase): def insertTile(self, node, submap_center, xel: Xel.Xel, tile_z, terrain): dx, dy = submap_center (q, r) = xel.exa.x, xel.exa.e v_center = VBase2(s3 * q, v3s * 2 * (q / 2 + r)) tile_color = "rock" #TODO #if abs(q) == Map.radius or abs(r) == Map.radius or abs(xel.exa.a) == Map.radius: # tile_color = "yellow" #else: #temporary if terrain == "water": tile_z = 0 tile_color = terrain return self.model.loadExaTile(node, v_center[0] + dx, v_center[1] + dy, tile_z, tile_color) def drawTriangle(self, node, submap_center, submap_xel, triangle_index, nodes_ZTH, open_simplex): global god center_map = submap_xel for d in range(1, Map.radius + 1): # distance from center moving along triangle side t center_map = center_map.link[dirs[triangle_index]] tmp_map = center_map for n in range( 0, d ): # each cell from triangle_index triangle edge (included) to next triangle edge (excluded) if d == Map.radius and n == 0: cell_z = nodes_ZTH[0][triangle_index] cell_t = nodes_ZTH[1][triangle_index] cell_h = nodes_ZTH[2][triangle_index] else: interna = ((nodes_ZTH[0][6], nodes_ZTH[0][triangle_index], nodes_ZTH[0][(triangle_index + 1) % 6]), (nodes_ZTH[1][6], nodes_ZTH[1][triangle_index], nodes_ZTH[1][(triangle_index + 1) % 6]), (nodes_ZTH[2][6], nodes_ZTH[2][triangle_index], nodes_ZTH[2][(triangle_index + 1) % 6])) res = ExaRandom.interpolate( self, interna, Map.radius, (tmp_map.exa.e, tmp_map.exa.x, tmp_map.exa.a)) (cell_z, cell_t, cell_h) = res cell_z += open_simplex.noise2d(tmp_map.exa.x, tmp_map.exa.e) / 5 esterna = god.creation( submap_center, (tmp_map.exa.e, tmp_map.exa.x, tmp_map.exa.a), cell_t, cell_h) #animale, vegetale, terreno #load models dx, dy = submap_center (q, r) = tmp_map.exa.x, tmp_map.exa.e v_center = VBase2(s3 * q, v3s * 2 * (q / 2 + r)) if esterna[0] != None: self.model.loadAnimal(node, v_center[0] + dx, v_center[1] + dy, cell_z, esterna[0].nome) if esterna[1] != None: self.model.loadPlant(node, v_center[0] - side + dx, v_center[1] + dy, cell_z, esterna[1].nome) if esterna[2] != None: terrain_name = esterna[2].nome else: terrain_name = "rock" self.insertTile(node, submap_center, tmp_map, cell_z, terrain_name) tmp_map = tmp_map.link[dirs[(triangle_index + 2) % 6]] def drawSubmap(self, submap): l_map = Map.l_map # TODO: chose if letting this way or pass l_map as parameter open_s = OpenSimplex(submap.noise_seed) #Center global god esterna = god.creation(submap.centerXY, (0, 0, 0), submap.array_T[6], submap.array_H[6]) #animale, vegetale, terreno if esterna[2] != None: terrain_name = esterna[2].nome else: terrain_name = "rock" self.insertTile(submap.node, submap.centerXY, l_map, submap.array_Z[6], terrain_name) ### Graphic map construction, triangle-by-triangle way center_map = l_map for t in range(6): # scan each triangle interna = (submap.array_Z, submap.array_T, submap.array_H) self.drawTriangle(submap.node, submap.centerXY, center_map, t, interna, open_s) ### return submap def drawMap(self, submap): global current_submap global stored_submaps_list global rendered_submaps new_seven_centers = [] for d, v in coords.items(): temp_c = ((v[0] + submap.centerXY[0]), (v[1] + submap.centerXY[1])) #print("-----------------------",v, submap.centerXY, temp_c) #BUGGONE new_seven_centers.append(temp_c) new_seven_centers.append(submap.centerXY) if len(rendered_submaps) == 0: # Starting case submap.node = SubmapNode("0") submap.node.reparentTo(self.render) center = self.drawSubmap(submap) rendered_submaps.append(center) tmp_rendered_submaps = [None, None, None, None, None, None, center] else: tmp_rendered_submaps = [None, None, None, None, None, None, None] useful_values = [] for i in range(7): draw = True #check if a sub_map in new_seven_centers has to be drawn. #print all rendenew_seven_centersred maps """print("Rendered:") for s in rendered_submaps: print(s, end='') print("")""" c = new_seven_centers[i] for s in rendered_submaps: #diff = (abs(c[0] - s.centerXY[0]), abs(c[1] - s.centerXY[1])) print("_--------------", c, s) print( "DIFF= ", math.isclose(c[0], s.centerXY[0], abs_tol=0.1) and math.isclose(c[1], s.centerXY[1], abs_tol=0.1)) if math.isclose(c[0], s.centerXY[0], abs_tol=0.1) and math.isclose( c[1], s.centerXY[1], abs_tol=0.1): draw = False #if a map in new_seven_centers is already in rendered_submaps set draw to false tmp_rendered_submaps[i] = s # prova useful_values.append(s) break if draw == True: #if draw is still True, then draw the map in new_seven_centers if c in stored_submaps_list.keys(): s_map = stored_submaps_list[c] else: s_map = ExaRandom().create_submap(c) stored_submaps_list[c] = s_map s_map.node = SubmapNode("1") s_map.node.reparentTo(self.render) tmp_rendered_submaps[i] = self.drawSubmap(s_map) #rendered_submaps.append(self.drawSubmap(self.render, s_map)) print(c, "drawn\n") else: print(c, "NOT drawn\n") # identify no-longer loaded submaps and clear their nodes for s in rendered_submaps: if s not in tmp_rendered_submaps: self.clear_node(s.node) s.node.removeNode() # needs to be tested (TODO) s.node = None # if previous line doesn't remove it automatically rendered_submaps = tmp_rendered_submaps current_submap = submap print("Rendered:") for s in rendered_submaps: print(s, end='') print("") def clear_node(self, nodepath): if not nodepath.isEmpty(): for model in nodepath.getChildren(): model.removeNode() def clear_all_nodes(self): self.clear_node(rendered_submaps[random.randint( 0, 5)].node) # temporary madness #for n in all_nodes: # self.clear_node(n) # n.remove_node() def print_all_nodes(self): string = "" for n in all_nodes: string += str(n) + "; " print(string) def __init__(self): ShowBase.__init__(self) # Load Lights self.light = LoadLight.Light self.light.setupLight(self) # Load Environment self.model = LoadModel.Model() self.model.initialize(self) Map.init() map_center = (0, 0) subprova = Submap.Submap(map_center) global stored_submaps_list global current_submap stored_submaps_list[map_center] = subprova current_submap = subprova print("stored in init:", stored_submaps_list) self.drawMap(subprova) """ self.model.loadAnimal(5,6,0, "bear") self.model.loadAnimal(12,-6,0, "cow") self.model.loadAnimal(7,-9,0, "panther") self.model.loadAnimal(-17,5,0, "rabbit") self.model.loadAnimal(-7,5,0, "wolf") self.model.loadPlant(8,-2,0, "fir") self.model.loadPlant(-3,-2,0, "grass") self.model.loadPlant(-4,2,0, "oak") self.model.loadPlant(-1,17,0, "berry_bush") """ # Text on screen self.text_char_pos = None self.text_submap = None self.text_lock = None # Create the main character self.char = self.model.loadCharacter(0, 0, 0) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above char's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.charGroundRay = CollisionRay() self.charGroundRay.setOrigin(0, 0, 9) self.charGroundRay.setDirection(0, 0, -1) self.charGroundCol = CollisionNode('charRay') self.charGroundCol.addSolid(self.charGroundRay) self.charGroundCol.setFromCollideMask(CollideMask.bit(0)) self.charGroundCol.setIntoCollideMask(CollideMask.allOff()) self.charGroundColNp = self.char.attachNewNode(self.charGroundCol) self.charGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.charGroundColNp, self.charGroundHandler) # Uncomment this line to see the collision rays #self.charGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # This is used to store which keys are currently pressed. self.keyMap = { "restart": 0, "left": 0, "right": 0, "forward": 0, "backward": 0, "cam-q": 0, "cam-w": 0, "cam-e": 0, "cam-d": 0, "cam-s": 0, "cam-a": 0 } # Post the instructions self.title = addTitle("Isometric HexaMap test") self.inst1 = addInstructions(0.06, "[ESC]: Quit") self.inst2 = addInstructions(0.12, "[Arrow Keys]: Move char") self.inst3 = addInstructions( 0.18, "[Q,W,E,D,S,A]: Change camera's angle of view") #self.inst8 = addInstructions(0.48, "[R]: Restart") # Accept the control keys for movement and rotation self.accept("escape", sys.exit) self.accept("n", self.print_all_nodes) self.accept("k", self.clear_all_nodes) self.accept("arrow_left", self.setKey, ["left", True]) self.accept("arrow_right", self.setKey, ["right", True]) self.accept("arrow_up", self.setKey, ["forward", True]) self.accept("arrow_down", self.setKey, ["backward", True]) self.accept("q", self.setKey, ["cam-q", True]) self.accept("w", self.setKey, ["cam-w", True]) self.accept("e", self.setKey, ["cam-e", True]) self.accept("d", self.setKey, ["cam-d", True]) self.accept("s", self.setKey, ["cam-s", True]) self.accept("a", self.setKey, ["cam-a", True]) self.accept("arrow_left-up", self.setKey, ["left", False]) self.accept("arrow_right-up", self.setKey, ["right", False]) self.accept("arrow_up-up", self.setKey, ["forward", False]) self.accept("arrow_down-up", self.setKey, ["backward", False]) self.accept("q-up", self.setKey, ["cam-q", False]) self.accept("w-up", self.setKey, ["cam-w", False]) self.accept("e-up", self.setKey, ["cam-e", False]) self.accept("d-up", self.setKey, ["cam-d", False]) self.accept("s-up", self.setKey, ["cam-s", False]) self.accept("a-up", self.setKey, ["cam-a", False]) # self.accept("restart", self.char.setPos(0,0,0)) self.taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera with isometric perspective self.disableMouse() lens = OrthographicLens() lens.setFilmSize(20, 11.25) lens.setNear(-20) self.cam.node().setLens(lens) self.camera.setPos(self.char.getPos() + (math.sin(cam_angle[cam_view]) * cam_dist, -math.cos(cam_angle[cam_view]) * cam_dist, cam_dz)) self.camera.lookAt(self.char) # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value def move(self, task): # Get the time that elapsed since last frame. We multiply this with # the desired speed in order to find out with which distance to move # in order to achieve that desired speed. dt = globalClock.getDt() # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. global cam_view temp_cam = cam_view if self.keyMap["cam-q"]: cam_view = 'q' if self.keyMap["cam-w"]: cam_view = 'w' if self.keyMap["cam-e"]: cam_view = 'e' if self.keyMap["cam-d"]: cam_view = 'd' if self.keyMap["cam-s"]: cam_view = 's' if self.keyMap["cam-a"]: cam_view = 'a' global cam_rotating final_angle = int(round((cam_angle[cam_view] * RAD_DEG))) % 360 current_angle = int(round(self.camera.getH())) % 360 # Camera rotation task is triggered when a different angle of view is selected. # The direction of rotation is chosen by comparing the two angles # and changing the sign of the camera rotation angle: cam_delta_angle if final_angle != current_angle: if not self.taskMgr.hasTaskNamed("SpinCameraTask"): global cam_delta_angle diff = final_angle - current_angle cam_delta_angle = math.copysign(cam_delta_angle, diff) if diff > 180: cam_delta_angle = math.copysign(cam_delta_angle, -1) elif diff < -180: cam_delta_angle = math.copysign(cam_delta_angle, 1) self.taskMgr.doMethodLater(cam_task_time, self.spinCameraTask, "SpinCameraTask") cam_rotating = True if not cam_rotating: # save char's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.char.getPos() # If a move-key is pressed, turn and move char in the relative direction. # The pressure of multiple keys at the same time is handled by the v_rot vector # Movements in 2D plane depend on camera's position & orientation v_rot = VBase3(0, 0, 0) if self.keyMap["forward"]: v_rot += (0, 1, 0) if self.keyMap["backward"]: v_rot += (0, -1, 0) if self.keyMap["left"]: v_rot += (-v3, 0, 0) if self.keyMap["right"]: v_rot += (v3, 0, 0) if v_rot.normalize(): self.char.lookAt(self.char.getPos() + v_rot) self.char.setH(self.char.getH() + self.camera.getH()) self.char.setY(self.char, step * dt) # Normally, we would have to call traverse() to check for collisions. # However, the class ShowBase that we inherit from has a task to do # this for us, if we assign a CollisionTraverser to self.cTrav. self.cTrav.traverse(render) # Adjust char's Z coordinate. If char's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = list(self.charGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if (len(entries) > 0 and entries[0].getIntoNode().getName() == "ExaTile" and entries[0].getSurfacePoint(render).getZ() - self.char.getZ() <= CHAR_MAX_ZGAP): self.char.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.char.setPos(startpos) # Put on screen the lock's value #if self.text_lock != None: # self.text_lock.destroy() #self.text_lock = addInfo(0.15, "Lock: "+str(Map.new_dir_lock)) #QUIIIIIII+ global pix_pos_tmp pix_pos = self.char.getPos() exa_pos = None #if (math.isclose(abs(pix_pos[0])%(apo+0.05), apo, rel_tol=0.05) or math.isclose(abs(pix_pos[1])%(apo+0.05), apo,rel_tol=0.05)): exa_pos = -1 / 3 * pix_pos[0] + math.sqrt( 3) / 3 * pix_pos[1], 2 / 3 * pix_pos[0] pix_pos = VBase3(round(exa_pos[0]), round(exa_pos[1]), 0) pix_pos += VBase3(0, 0, round(-pix_pos[0] - pix_pos[1])) pix_pos_diff = VBase3(abs(pix_pos[0] - exa_pos[0]), abs(pix_pos[1] - exa_pos[1]), abs(pix_pos[2] - (-exa_pos[0] - exa_pos[1]))) if pix_pos_diff[0] > pix_pos_diff[1] and pix_pos_diff[ 0] > pix_pos_diff[2]: pix_pos[0] = -pix_pos[1] - pix_pos[2] elif pix_pos_diff[1] > pix_pos_diff[2]: pix_pos[1] = -pix_pos[0] - pix_pos[2] else: pix_pos[2] = -pix_pos[0] - pix_pos[1] if pix_pos_tmp != pix_pos: direc = pix_pos - pix_pos_tmp directions = { VBase3(1, -1, 0): 'q', VBase3(1, 0, -1): 'w', VBase3(0, 1, -1): 'e', VBase3(-1, 1, 0): 'd', VBase3(-1, 0, 1): 's', VBase3(0, -1, 1): 'a' } Map.menu(directions.get(direc)) print(Map.position) #print(self.char.getPos()) if self.text_char_pos != None: self.text_char_pos.destroy() self.text_char_pos = addInfo( 0, "Char position: (" + str(round(self.char.getX(), 2)) + " , " + str(round(self.char.getY(), 2)) + ")") #Map.new_dir_lock=False # New submap check if Map.new_dir != None: global current_submap global new_submap #Map.new_dir_lock=True d = Map.new_dir Map.new_dir = None new_center = (current_submap.centerXY[0] + coords[d][0], current_submap.centerXY[1] + coords[d][1]) for c, s in stored_submaps_list.items(): if math.isclose(c[0], new_center[0], abs_tol=0.1) and math.isclose( c[1], new_center[1], abs_tol=0.1): new_submap = s break self.drawMap( new_submap ) # TODO: maybe we can give direction as parameter global rendered_submaps print("Rendered.length = " + str(len(rendered_submaps))) pix_pos_tmp = pix_pos #Map.position= l_map.findXel() #print(Exa.Exa(pix_pos[0], pix_pos[1], -pix_pos[2])) # Camera position handling: it depends on char's position self.camera.setX(self.char.getX() + math.sin(current_angle * DEG_RAD) * cam_dist) self.camera.setY(self.char.getY() - math.cos(current_angle * DEG_RAD) * cam_dist) self.camera.setZ(self.char.getZ() + cam_dz) self.camera.lookAt(self.char) else: # cam is rotating if final_angle == current_angle: print("CAM IN PLACE!") self.taskMgr.remove("SpinCameraTask") cam_rotating = False #print("curr: ", self.camera.getH()) #print("dest: ", cam_angle[cam_view]*RAD_DEG) return task.cont # Task to animate the camera when user changes the angle of view. # Make the camera rotate counterclockwise around the character in x,y plane def spinCameraTask(self, task): angle_deg = int(round(self.camera.getH())) + cam_delta_angle angle_rad = angle_deg * DEG_RAD delta_v = VBase3(self.char.getX() + cam_dist * math.sin(angle_rad), self.char.getY() - cam_dist * math.cos(angle_rad), self.camera.getZ()) self.camera.setPos(delta_v) self.camera.lookAt(self.char) return task.done def restartGame(self): pass
class World(DirectObject): def __init__(self): #create Queue to hold the incoming chat #request the heartbeat so that the caht interface is being refreshed in order to get the message from other player self.keyMap = { "left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0, "charge": 0 } base.win.setClearColor(Vec4(0, 0, 0, 1)) self.cManager = ConnectionManager() self.cManager.startConnection() #------------------------------ #Chat Chat(self.cManager) #send dummy login info of the particular client #send first chat info #--------------------------------------- self.userName = username dummy_login = { 'user_id': self.userName, 'factionId': faction, 'password': '******' } self.cManager.sendRequest(Constants.RAND_STRING, dummy_login) chat = { 'userName': self.userName, #username 'message': '-------Login------' } self.cManager.sendRequest(Constants.CMSG_CHAT, chat) #-------------------------------------- #self.minimap = OnscreenImage(image="images/minimap.png", scale=(0.2,1,0.2), pos=(-1.1,0,0.8)) #frame = DirectFrame(text="Resource Bar", scale=0.001) resource_bar = DirectWaitBar(text="", value=35, range=100, pos=(0, 0, 0.9), barColor=(255, 255, 0, 1), frameSize=(-0.3, 0.3, 0, 0.03)) cp_bar = DirectWaitBar(text="", value=70, range=100, pos=(1.0, 0, 0.9), barColor=(0, 0, 255, 1), frameSize=(-0.3, 0.3, 0, 0.03), frameColor=(255, 0, 0, 1)) # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) self.environ.setPos(0, 0, 0) # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", { "run": "models/ralph-run", "walk": "models/ralph-walk" }) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos) nameplate = TextNode('textNode username_' + str(self.userName)) nameplate.setText(self.userName) npNodePath = self.ralph.attachNewNode(nameplate) npNodePath.setScale(0.8) npNodePath.setBillboardPointEye() #npNodePath.setPos(1.0,0,6.0) npNodePath.setZ(6.5) bar = DirectWaitBar(value=100, scale=1.0) bar.setColor(255, 0, 0) #bar.setBarRelief() bar.setZ(6.0) bar.setBillboardPointEye() bar.reparentTo(self.ralph) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Accept the control keys for movement and rotation 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.accept("c", self.setKey, ["charge", 1]) self.accept("c-up", self.setKey, ["charge", 0]) taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = CollisionTraverser() self.ralphGroundRay = CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 1000) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) 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(0)) self.camGroundCol.setIntoCollideMask(BitMask32.allOff()) self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(-5, -5, -5)) directionalLight.setColor(Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. base.camera.lookAt(self.ralph) 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()) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if (self.keyMap["left"] != 0): self.ralph.setH(self.ralph.getH() + 300 * globalClock.getDt()) if (self.keyMap["right"] != 0): self.ralph.setH(self.ralph.getH() - 300 * globalClock.getDt()) if (self.keyMap["forward"] != 0): self.ralph.setY(self.ralph, -25 * globalClock.getDt()) if (self.keyMap["charge"] != 0): self.ralph.setY(self.ralph, -250 * globalClock.getDt()) #ribbon = Ribbon(self.ralph, Vec4(1,1,1,1), 3, 10, 0.3) #ribbon.getRoot().setZ(2.0) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if (self.keyMap["forward"] != 0) or (self.keyMap["charge"] != 0) or ( self.keyMap["left"] != 0) or (self.keyMap["right"] != 0): if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False # If the camera is too far from ralph, move it closer. # If the camera is too close to ralph, move it farther. camvec = self.ralph.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Adjust ralph's Z coordinate. If ralph's ray hit terrain, # update his Z. If it hit anything else, or didn't hit anything, put # him back where he was last frame. entries = [] for i in range(self.ralphGroundHandler.getNumEntries()): entry = self.ralphGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): self.ralph.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.ralph.setPos(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = [] for i in range(self.camGroundHandler.getNumEntries()): entry = self.camGroundHandler.getEntry(i) entries.append(entry) entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if (len(entries) > 0) and (entries[0].getIntoNode().getName() == "terrain"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if (base.camera.getZ() < self.ralph.getZ() + 2.0): base.camera.setZ(self.ralph.getZ() + 2.0) # The camera should look in ralph's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above ralph's head. self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) return task.cont
class moveMario(ShowBase): def __init__(self): # Set up the window, camera, etc. ShowBase.__init__(self) self.ser = serial.Serial('/dev/tty.usbmodem1421', 9600) # Set the background color to black self.win.setClearColor((0, 0, 0, 1)) # This is used to store which keys are currently pressed. self.keyMap = { "left": 0, "right": 0, "forward": 0, "reverse": 0, "cam-left": 0, "cam-right": 0 } #Initialize Track self.track = self.loader.loadModel("luigi_circuit") self.track.setScale(1.5) self.track.reparentTo(render) #Intitial where Mario needs to be #marioStartPos = self.track.find("**/start_point").getPos() marioStartPos = Vec3(50, -29, 0.35) #Actual start possition #Using ralph because the model is made with correct collision masking and animation self.marioActor = Actor("models/ralph", { "run": "models/ralph-run", "walk": "models/ralph-walk" }) self.marioActor.setScale(0.1, 0.1, 0.1) self.marioActor.setH(self.marioActor, 270) self.marioActor.reparentTo(self.render) self.marioActor.setPos(marioStartPos + (0, 0, 0.5)) #Floater above so Camera has something to look at self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(self.marioActor) self.floater.setZ(2.0) taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera self.disableMouse() self.camera.setPos(self.marioActor.getX() + 100, self.marioActor.getY(), 1) #Collision Rays self.cTrav = CollisionTraverser() self.marioGroundRay = CollisionRay() self.marioGroundRay.setOrigin(0, 0, 9) self.marioGroundRay.setDirection(0, 0, -1) self.marioGroundCol = CollisionNode('marioRay') self.marioGroundCol.addSolid(self.marioGroundRay) self.marioGroundCol.setFromCollideMask(CollideMask.bit(0)) self.marioGroundCol.setIntoCollideMask(CollideMask.allOff()) self.marioGroundColNp = self.marioActor.attachNewNode( self.marioGroundCol) self.marioGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.marioGroundColNp, self.marioGroundHandler) self.camGroundRay = CollisionRay() self.camGroundRay.setOrigin(0, 0, 9) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(CollideMask.bit(0)) self.camGroundCol.setIntoCollideMask(CollideMask.allOff()) self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value def move(self, task): elapsed = globalClock.getDt() # If a move-key is pressed, move Mario in the specified direction. startpos = self.marioActor.getPos() line = self.ser.readline() listOfCoord = line.split(":") if (len(listOfCoord) == 7): x = listOfCoord[1] g = listOfCoord[3] r = listOfCoord[5] if (10 <= float(x) <= 180): #MAKE IT TURN RIGHT self.setKey("right", True) self.setKey("left", False) elif (180 < float(x) <= 350): #MAKE IT TURN LEFT self.setKey("right", False) self.setKey("left", True) else: self.setKey("right", False) self.setKey("left", False) #Make it move forward if (int(g) == 1): self.setKey("forward", True) else: self.setKey("forward", False) #Make it move in Reverse if (int(r) == 1): self.setKey("reverse", True) else: self.setKey("reverse", False) if self.keyMap["left"]: self.marioActor.setH(self.marioActor.getH() + 50 * elapsed) self.camera.setX(self.camera, +5 * elapsed) if self.keyMap["right"]: self.marioActor.setH(self.marioActor.getH() - 50 * elapsed) self.camera.setX(self.camera, -5 * elapsed) if self.keyMap["forward"]: self.marioActor.setY(self.marioActor, -100 * elapsed) if self.keyMap["reverse"]: self.marioActor.setY(self.marioActor, 100 * elapsed) #When moving - run the animation - Taken from roaming ralph example if self.keyMap["forward"] or self.keyMap["left"] or self.keyMap[ "right"]: if self.isMoving is False: self.marioActor.loop("run") self.isMoving = True else: if self.isMoving: self.marioActor.stop() self.marioActor.pose("walk", 5) self.isMoving = False #Camera uses - modified from roaming ralph camvec = self.marioActor.getPos() - self.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if camdist > 5.0: self.camera.setPos(self.camera.getPos() + camvec * (camdist - 5)) camdist = 5.0 if camdist < 2.5: self.camera.setPos(self.camera.getPos() - camvec * (2.5 - camdist)) camdist = 2.5 #Collission terrain checking - taken from roaming ralph entries = list(self.marioGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName( ) == "terrain": self.marioActor.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.marioActor.setPos(startpos) # Keep the camera at level - taken from roaming ralph entries = list(self.camGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName( ) == "terrain": self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if self.camera.getZ() < self.marioActor.getZ() + 1.0: self.camera.setZ(self.marioActor.getZ() + 1.0) self.camera.lookAt(self.floater) return task.cont