/ Published in: Python
Expand |
Embed | Plain Text
import direct.directbase.DirectStart from pandac.PandaModules import * from pandac.PandaModules import CollisionTraverser,CollisionNode from pandac.PandaModules import CollisionHandlerQueue,CollisionRay from pandac.PandaModules import Filename,GeomNode from pandac.PandaModules import PandaNode,NodePath,Camera,TextNode from pandac.PandaModules import Vec3,Vec4,BitMask32 from direct.gui.OnscreenText import OnscreenText from direct.actor.Actor import Actor from direct.task.Task import Task from direct.showbase.DirectObject import DirectObject import random, sys, os, math SPEED = 0.5 # Figure out what directory this program is in. MYDIR=os.path.abspath(sys.path[0]) MYDIR=Filename.fromOsSpecific(MYDIR).getFullpath() # Function to put instructions on the screen. def addInstructions(pos, msg): return OnscreenText(text=msg, style=1, fg=(1,1,1,1), pos=(-1.3, pos), align=TextNode.ALeft, scale = .05,mayChange=True) # Function to put title on the screen. def addTitle(text): return OnscreenText(text=text, style=1, fg=(1,1,1,1), pos=(1.3,-0.95), align=TextNode.ARight, scale = .07) class World(DirectObject): def __init__(self): self.onCollisionText = OnscreenText( text="", style=1, fg=(1,1,1,1), pos=(-1.3, 0.15), align=TextNode.ALeft, scale = .05) self.keyMap = {"left":0, "right":0, "forward":0, "shift":0, "control":0,"alt":0} base.win.setClearColor(Vec4(0,0,0,1)) self.picker = CollisionTraverser() self.queue = CollisionHandlerQueue() # 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.inst5 = addInstructions(0.75, "[Down Arrow]: Home") self.inst10 = addInstructions(0.60, "!!!") self.inst11 = addInstructions(0.50, "...") self.inst30 = addInstructions(0.10, " ") self.loadPicker() 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.setTag('pickable', 'R') # 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("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", self.Home) self.accept("mouse1", self.collisionCheck,[1]) self.accept("mouse3", self.collisionCheck,[2]) self.accept("mouse2", self.collisionCheck,[3]) taskMgr.add(self.move,"moveTask") #~ taskMgr.add(self.cam,"camTask") # Set up the camera base.disableMouse() base.camera.setPos(self.ralph.getX(),self.ralph.getY()+10,8) # Game state variables self.prevtime = 0 self.isMoving = False # 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) # 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) #=======================LIGHTS/SHADOWS=====================# #load s light========================= plight = PointLight('plight') plight.setColor(VBase4(1, 1, 1, 1)) plnp = render.attachNewNode(plight) plnp.setPos(-107, 25, 10) render.setLight(plnp) #~ ============================= #Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value #teleport ralph def teleport(self, pos): self.ralph.setPos(pos) #the same def move2(self, pos): self.ralph.setPos(pos) def loadPicker(self): #attach a CollisionRay node to the camera self.pickerNode = CollisionNode('mouseRay') self.pickerNP = camera.attachNewNode(self.pickerNode) self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask()) self.pickerRay = CollisionRay() self.pickerNode.addSolid(self.pickerRay) self.pickerNP.show() #add collision node (fromObject) to the traverser self.picker.addCollider(self.pickerNP, self.queue) self.picker.showCollisions(render) if base.mouseWatcherNode.hasMouse(): #get the mouse position mpos = base.mouseWatcherNode.getMouse() #aim the collision ray self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.inst30.destroy() self.inst30 = addInstructions(-0.50, str(mpos.getX())+" "+str(mpos.getY())) #fire the ray and record, in the queue, any collisions self.picker.traverse(render) if self.queue.getNumEntries() > 0: if self.queue.getNumEntries() == 1: self.mytext = "A collision with: _ " \ + str(self.queue.getEntry(0).getIntoNodePath()) +" at point of: _ " \ + str(self.queue.getEntry(0).getInteriorPoint(self.queue.getEntry(0).getIntoNodePath())) else: #organize the collisions from first hit to second... self.queue.sortEntries() #output the name of the node paths the ray collided with self.mytext = "A collision occured first with " \ + str(self.queue.getEntry(0).getIntoNodePath()) \ + " and then with " + str(self.queue.getEntry(1).getIntoNodePath()) self.onCollisionText.setText(self.mytext) def collisionCheck(self,but): if base.mouseWatcherNode.hasMouse(): #get the mouse position mpos = base.mouseWatcherNode.getMouse() #aim the collision ray self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY()) self.inst30.destroy() self.inst30 = addInstructions(-0.50, str(mpos.getX())+" "+str(mpos.getY())) #fire the ray and record, in the queue, any collisions self.picker.traverse(render) if self.queue.getNumEntries() > 0: if self.queue.getNumEntries() == 1: self.mytext = "A collision with: _ " \ + str(self.queue.getEntry(0).getIntoNodePath()) +" at point of: _ " \ + str(self.queue.getEntry(0).getInteriorPoint(self.queue.getEntry(0).getIntoNodePath())) else: #organize the collisions from first hit to second... self.queue.sortEntries() #output the name of the node paths the ray collided with self.mytext = "A collision occured first with " \ + str(self.queue.getEntry(0).getIntoNodePath()) \ + " and then with " + str(self.queue.getEntry(1).getIntoNodePath()) if but ==1: #self.teleport(self.queue.getEntry(0).getInteriorPoint(self.queue.getEntry(0).getIntoNodePath())) self.moveTo = self.queue.getEntry(0).getInteriorPoint(self.queue.getEntry(0).getIntoNodePath()) self.ralph.loop("run") if but ==2: self.move2(self.queue.getEntry(0).getInteriorPoint(self.queue.getEntry(0).getIntoNodePath())) self.onCollisionText.setText(self.mytext) # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection #~ def cam(self, task): #~ if base.mouseWatcherNode.hasMouse(): #~ #get the mouse position #~ xwpos = base.mouseWatcherNode.getMouse() #~ #~ if xwpos.getX() > 0.9: #~ base.camera.setPos(camera.getX()-0.15 ,camera.getY(),10) #~ if xwpos.getX() < -0.9: #~ base.camera.setPos(camera.getX()+0.15 ,camera.getY(),10) #~ if xwpos.getY() > 0.9: #~ base.camera.setPos(camera.getX() ,camera.getY()-0.15,10) #~ if xwpos.getY() < -0.9: #~ base.camera.setPos(camera.getX() ,camera.getY()+0.15,10) #~(base.win.movePointer(0, base.win.getXSize()/2, base.win.getYSize()/2)) #~ return Task.cont def move(self, task): #time saving elapsed = task.time - self.prevtime # 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() + elapsed*300) if (self.keyMap["right"]!=0): self.ralph.setH(self.ralph.getH() - elapsed*300) if (self.keyMap["forward"]!=0): backward = self.ralph.getNetTransform().getMat().getRow3(1) backward.setZ(0) backward.normalize() self.ralph.setPos(self.ralph.getPos() - backward*(elapsed*5)) #mose moving =) thanks InternZero if hasattr(self, "moveTo"): self.ralph.lookAt(self.moveTo) self.ralph.setH(self.ralph, 180) backward = self.ralph.getNetTransform().getMat().getRow3(1) backward.setZ(0) backward.normalize() self.ralph.setPos(self.ralph.getPos() - backward*(elapsed*5)) #stop when reash the destination point if self.ralph.getPos(render).almostEqual(self.moveTo, 0.05): #~ print "Comparison:", self.ralph.getPos(render), self.moveTo self.ralph.setPos(self.moveTo) self.isMoving = False self.ralph.pose("walk",5) backward = self.ralph.getNetTransform().getMat().getRow3(1) backward.setZ(0) backward.normalize() del self.moveTo # 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 # 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) #camera look at self.floater.setPos(self.ralph.getPos()) self.floater.setZ(self.ralph.getZ() + 2.0) base.camera.lookAt(self.floater) self.inst10.destroy() self.inst10 = addInstructions(0.55, str(self.ralph.getPos)+"(ralph position):") self.inst11.destroy() self.inst11 = addInstructions(0.50, str(self.ralph.getPos())) # Store the task time and continue. self.prevtime = task.time return Task.cont def Home(self): ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph.setPos(ralphStartPos) #suka rabotay!!! w = World() run()
You need to login to post a comment.
