Exemplo n.º 1
0
def printTransform(self, other=None, sd=2, fRecursive=0):
    from panda3d.pandac import Vec3
    fmtStr = '%%0.%df' % sd
    name = self.getName()
    if other == None:
        transform = self.getTransform()
    else:
        transform = self.getTransform(other)
    if transform.hasPos():
        pos = transform.getPos()
        if not pos.almostEqual(Vec3(0)):
            outputString = '%s.setPos(%s, %s, %s)' % (name, fmtStr, fmtStr,
                                                      fmtStr)
            print outputString % (pos[0], pos[1], pos[2])
    if transform.hasHpr():
        hpr = transform.getHpr()
        if not hpr.almostEqual(Vec3(0)):
            outputString = '%s.setHpr(%s, %s, %s)' % (name, fmtStr, fmtStr,
                                                      fmtStr)
            print outputString % (hpr[0], hpr[1], hpr[2])
    if transform.hasScale():
        if transform.hasUniformScale():
            scale = transform.getUniformScale()
            if scale != 1.0:
                outputString = '%s.setScale(%s)' % (name, fmtStr)
                print outputString % scale
        else:
            scale = transform.getScale()
            if not scale.almostEqual(Vec3(1)):
                outputString = '%s.setScale(%s, %s, %s)' % (name, fmtStr,
                                                            fmtStr, fmtStr)
                print outputString % (scale[0], scale[1], scale[2])
    if fRecursive:
        for child in self.getChildren():
            child.printTransform(other, sd, fRecursive)
Exemplo n.º 2
0
  def regenTree(self):
    forest=	render.findAllMatches("Tree Holder")
    forest.detach()


    bodydata=GeomVertexData("body vertices", self.format, Geom.UHStatic)

    treeNodePath=NodePath("Tree Holder")
    makeFractalTree(bodydata, treeNodePath,Vec3(4,4,7), Vec3(0,0,0),self.numIterations, self.numCopies)

    treeNodePath.setTexture(self.barkTexture,1)
    treeNodePath.reparentTo(render)
Exemplo n.º 3
0
  def addTree(self):

    bodydata=GeomVertexData("body vertices", self.format, Geom.UHStatic)

    randomPlace=Vec3(200*random.random()-100, 200*random.random()-100, 0)
    #randomPlace.normalize()


    treeNodePath=NodePath("Tree Holder")
    makeFractalTree(bodydata, treeNodePath,Vec3(4,4,7), randomPlace, self.numIterations, self.numCopies)

    treeNodePath.setTexture(self.barkTexture,1)
    treeNodePath.reparentTo(render)
Exemplo n.º 4
0
    def asteroidHit(self, index):
        #If the asteroid is small it is simply removed
        if self.asteroids[index].getScale().getX() <= AST_MIN_SCALE:
            self.asteroids[index].remove()
            #This uses a Python feature called slices. Basically it's saying
            #Make the list the current list up to index plus the rest of the list
            #after index
            #This has the effect of removing the object at index
            self.asteroids = self.asteroids[:index] + self.asteroids[index +
                                                                     1:]
        else:
            #If it is big enough, split it instead
            #First we update the current asteroid
            newScale = self.asteroids[index].getScale().getX() * AST_SIZE_SCALE
            self.asteroids[index].setScale(newScale)  #Rescale it

            #The new direction is chosen as perpendicular to the old direction
            #This is determined using the cross product, which returns a vector
            #perpendicular to the two input vectors. By crossing velocity with a
            #vector that goes into the screen, we get a vector that is perpendicular
            #to the original velocity in the plane of the screen
            vel = self.getVelocity(self.asteroids[index])
            speed = vel.length() * AST_VEL_SCALE
            vel.normalize()
            vel = Vec3(0, 1, 0).cross(vel)
            vel *= speed
            self.setVelocity(self.asteroids[index], vel)

            #Now we create a new asteroid identical to the current one
            newAst = loadObject(scale=newScale)
            self.setVelocity(newAst, vel * -1)
            newAst.setPos(self.asteroids[index].getPos())
            newAst.setTexture(self.asteroids[index].getTexture(), 1)
            self.asteroids.append(newAst)
Exemplo n.º 5
0
    def updateShip(self, dt):
        heading = self.ship.getR()  #Heading is the roll value for this model
        #Change heading if left or right is being pressed
        if self.keys["turnRight"]:
            heading += dt * TURN_RATE
            self.ship.setR(heading % 360)
        elif self.keys["turnLeft"]:
            heading -= dt * TURN_RATE
            self.ship.setR(heading % 360)

        #Thrust causes acceleration in the direction the ship is currently facing
        if self.keys["accel"]:
            heading_rad = DEG_TO_RAD * heading
            #This builds a new velocity vector and adds it to the current one
            #Relative to the camera, the screen in Panda is the XZ plane.
            #Therefore all of our Y values in our velocities are 0 to signify no
            #change in that direction
            newVel = (Vec3(sin(heading_rad), 0, cos(heading_rad)) *
                      ACCELERATION * dt)
            newVel += self.getVelocity(self.ship)
            #Clamps the new velocity to the maximum speed. lengthSquared() is used
            #again since it is faster than length()
            if newVel.lengthSquared() > MAX_VEL_SQ:
                newVel.normalize()
                newVel *= MAX_VEL
            self.setVelocity(self.ship, newVel)

        #Finally, update the position as with any other object
        self.updatePos(self.ship, dt)
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
def makeCircle(vdata, numVertices=40,offset=Vec3(0,0,0), direction=1):
  circleGeom=Geom(vdata)

  vertWriter=GeomVertexWriter(vdata, "vertex")
  normalWriter=GeomVertexWriter(vdata, "normal")
  colorWriter=GeomVertexWriter(vdata, "color")
  uvWriter=GeomVertexWriter(vdata, "texcoord")
  drawWriter=GeomVertexWriter(vdata, "drawFlag")

  #make sure we start at the end of the GeomVertexData so we dont overwrite anything
  #that might be there already
  startRow=vdata.getNumRows()

  vertWriter.setRow(startRow)
  colorWriter.setRow(startRow)
  uvWriter.setRow(startRow)
  normalWriter.setRow(startRow)
  drawWriter.setRow(startRow)

  angle=2*math.pi/numVertices
  currAngle=angle

  for i in range(numVertices):
    position=Vec3(math.cos(currAngle)+offset.getX(), math.sin(currAngle)+offset.getY(),offset.getZ())
    vertWriter.addData3f(position)
    uvWriter.addData2f(position.getX()/2.0+0.5,position.getY()/2.0+0.5)
    colorWriter.addData4f(1.0, 1.0, 1.0, 1.0)
    position.setZ(position.getZ()*direction)
    position.normalize()
    normalWriter.addData3f(position)

    #at default Opengl only draws "front faces" (all shapes whose vertices are arranged CCW). We
    #need direction so we can specify which side we want to be the front face
    currAngle+=angle*direction

  circle=GeomTrifans(Geom.UHStatic)
  circle.addConsecutiveVertices(startRow, numVertices)
  circle.closePrimitive()

  circleGeom.addPrimitive(circle)

  return circleGeom
Exemplo n.º 8
0
 def getGridSizeFromSphere(self, sphereRadius, spherePos, cellWidth, gridRadius):
     # NOTE: This ensures that the grid is at least a "gridRadius" number
     # of cells larger than the trigger sphere that loads the grid.  This
     # gives us some room to start setting interest to the grid before we
     # expect to see any objects on it.
     xMax = abs(spherePos[0])+sphereRadius
     yMax = abs(spherePos[1])+sphereRadius
     sphereRadius = Vec3(xMax,yMax,0).length()
     
     # sphereRadius = max(sphereRadius, gridRadius*cellWidth)
     return max(2 * (sphereRadius // cellWidth), 1)
Exemplo n.º 9
0
 def setupLights(self):    #This function sets up some default lighting
   lAttrib = LightAttrib.makeAllOff()
   ambientLight = AmbientLight( "ambientLight" )
   ambientLight.setColor( Vec4(.8, .8, .8, 1) )
   lAttrib = lAttrib.addLight( ambientLight )
   directionalLight = DirectionalLight( "directionalLight" )
   directionalLight.setDirection( Vec3( 0, 45, -45 ) )
   directionalLight.setColor( Vec4( 0.2, 0.2, 0.2, 1 ) )
   lAttrib = lAttrib.addLight( directionalLight )
   render.attachNewNode( directionalLight ) 
   render.attachNewNode( ambientLight ) 
   render.node().setAttrib( lAttrib )
Exemplo n.º 10
0
 def setupLights(self):
     lAttrib = LightAttrib.makeAllOff()
     ambientLight = AmbientLight("ambientLight")
     ambientLight.setColor(Vec4(.8, .8, .75, 1))
     lAttrib = lAttrib.addLight(ambientLight)
     directionalLight = DirectionalLight("directionalLight")
     directionalLight.setDirection(Vec3(0, 0, -2.5))
     directionalLight.setColor(Vec4(0.9, 0.8, 0.9, 1))
     lAttrib = lAttrib.addLight(directionalLight)
     render.attachNewNode(directionalLight)
     render.attachNewNode(ambientLight)
     render.node().setAttrib(lAttrib)
Exemplo n.º 11
0
 def setupLights(self):  #Sets up some default lighting
     lAttrib = LightAttrib.makeAllOff()
     ambientLight = AmbientLight("ambientLight")
     ambientLight.setColor(Vec4(.4, .4, .35, 1))
     lAttrib = lAttrib.addLight(ambientLight)
     directionalLight = DirectionalLight("directionalLight")
     directionalLight.setDirection(Vec3(0, 8, -2.5))
     directionalLight.setColor(Vec4(0.9, 0.8, 0.9, 1))
     lAttrib = lAttrib.addLight(directionalLight)
     render.attachNewNode(directionalLight)
     render.attachNewNode(ambientLight)
     render.node().setAttrib(lAttrib)
Exemplo n.º 12
0
def makeCylinder(vdata,numVertices=40):
  topCircleGeom=makeCircle(vdata, numVertices,Vec3(0,0, 1))
  bottomCircleGeom=makeCircle(vdata, numVertices,Vec3(0,0,0),-1)


  body=GeomTristrips(Geom.UHStatic)

  j=40
  i=0
  while i < numVertices+1:
    body.addVertex(i)
    body.addVertex(j)
    i+=1
    if j==40:
      j=2*numVertices-1
    else:
      j-=1
    body.addVertex(i)
    body.addVertex(j)
    j-=1
    i+=1

  body.addVertex(numVertices-1)
  body.addVertex(0)
  body.addVertex(numVertices)
  body.closePrimitive()
  #print body



  cylinderGeom=Geom(vdata)

  cylinderGeom.addPrimitive(body)
  cylinderGeom.copyPrimitivesFrom(topCircleGeom)
  cylinderGeom.copyPrimitivesFrom(bottomCircleGeom)


  cylinderGeom.decomposeInPlace()
  cylinderGeom.unifyInPlace()
  return cylinderGeom
Exemplo n.º 13
0
 def setupLights(self):
     lAttrib = LightAttrib.makeAllOff()
     ambientLight = AmbientLight("ambientLight")
     ambientLight.setColor(Vec4(.4, .4, .35, 1))
     lAttrib = lAttrib.addLight(ambientLight)
     directionalLight = DirectionalLight("directionalLight")
     directionalLight.setDirection(Vec3(0, 8, -2.5))
     directionalLight.setColor(Vec4(0.9, 0.8, 0.9, 1))
     lAttrib = lAttrib.addLight(directionalLight)
     #set lighting on teapot so steam doesn't get affected
     self.t.attachNewNode(directionalLight)
     self.t.attachNewNode(ambientLight)
     self.t.node().setAttrib(lAttrib)
Exemplo n.º 14
0
    def __init__(self):
        #This code puts the standard title and instruction text on screen
        self.title = OnscreenText(text="Panda3D: Tutorial - Tasks",
                                  style=1,
                                  fg=(1, 1, 0, 1),
                                  pos=(0.8, -0.95),
                                  scale=.07,
                                  font=font)
        self.escapeText = genLabelText("ESC: Quit", 0)
        self.leftkeyText = genLabelText("[Left Arrow]: Turn Left (CCW)", 1)
        self.rightkeyText = genLabelText("[Right Arrow]: Turn Right (CW)", 2)
        self.upkeyText = genLabelText("[Up Arrow]: Accelerate", 3)
        self.spacekeyText = genLabelText("[Space Bar]: Fire", 4)

        base.disableMouse()  #Disable default mouse-based camera control

        self.bg = loadObject(
            "stars", scale=146, depth=200,
            transparency=False)  #Load the background starfield

        self.ship = loadObject("ship")  #Load the ship
        self.setVelocity(self.ship, Vec3(0, 0, 0))  #Initial velocity

        #A dictionary of what keys are currently being pressed
        #The key events update this list, and our task will query it as input
        self.keys = {"turnLeft": 0, "turnRight": 0, "accel": 0, "fire": 0}

        self.accept("escape", sys.exit)  #Escape quits
        #Other keys events set the appropriate value in our key dictionary
        self.accept("arrow_left", self.setKey, ["turnLeft", 1])
        self.accept("arrow_left-up", self.setKey, ["turnLeft", 0])
        self.accept("arrow_right", self.setKey, ["turnRight", 1])
        self.accept("arrow_right-up", self.setKey, ["turnRight", 0])
        self.accept("arrow_up", self.setKey, ["accel", 1])
        self.accept("arrow_up-up", self.setKey, ["accel", 0])
        self.accept("space", self.setKey, ["fire", 1])

        #Now we create the task. taskMgr is the task manager that actually calls
        #The function each frame. The add method creates a new task. The first
        #argument is the function to be called, and the second argument is the name
        #for the task. It returns a task object, that is passed to the function
        #each frame
        self.gameTask = taskMgr.add(self.gameLoop, "gameLoop")
        #The task object is a good place to put variables that should stay
        #persistant for the task function from frame to frame
        self.gameTask.last = 0  #Task time of the last frame
        self.gameTask.nextBullet = 0  #Task time when the next bullet may be fired

        self.bullets = []  #This empty list will contain fired bullets
        self.spawnAsteroids(
        )  #Complete initialization by spawning the asteroids
Exemplo n.º 15
0
    def fire(self, time):
        direction = DEG_TO_RAD * self.ship.getR()
        pos = self.ship.getPos()
        bullet = loadObject("bullet", scale=.2)  #Create the object
        bullet.setPos(pos)
        #Velocity is in relation to the ship
        vel = (self.getVelocity(self.ship) +
               (Vec3(sin(direction), 0, cos(direction)) * BULLET_SPEED))
        self.setVelocity(bullet, vel)
        #Set the bullet expiration time to be a certain amount past the current time
        self.setExpires(bullet, time + BULLET_LIFE)

        #Finally, add the new bullet to the list
        self.bullets.append(bullet)
Exemplo n.º 16
0
def drawLeaf(nodePath,vdata,pos=Vec3(0,0,0),vecList=[Vec3(0,0,1), Vec3(1,0,0),Vec3(0,-1,0)], scale=0.125):

  #use the vectors that describe the direction the branch grows to make the right
    #rotation matrix
  newCs=Mat4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
  newCs.setRow(0, vecList[2]) #right
  newCs.setRow(1, vecList[1]) #up
  newCs.setRow(2, vecList[0]) #forward
  newCs.setRow(3, Vec3(0,0,0))
  newCs.setCol(3,Vec4(0,0,0,1))

  axisAdj=Mat4.scaleMat(scale)*newCs*Mat4.translateMat(pos)

  #orginlly made the leaf out of geometry but that didnt look good
  #I also think there should be a better way to handle the leaf texture other than
  #hardcoding the filename
  leafModel=loader.loadModel("models/samples/fractal_plants/shrubbery")
  leafTexture=loader.loadTexture("models/samples/fractal_plants/material-10-cl.png")


  leafModel.reparentTo(nodePath)
  leafModel.setTexture(leafTexture,1)
  leafModel.setTransform(TransformState.makeMat(axisAdj))
Exemplo n.º 17
0
def makeFractalTree(bodydata, nodePath,length, pos=Vec3(0,0,0), numIterations=11, numCopies=4,vecList=[Vec3(0,0,1),Vec3(1,0,0), Vec3(0,-1,0)]):
  if numIterations>0:

    drawBody(nodePath, bodydata, pos, vecList, length.getX())


    #move foward along the right axis
    newPos=pos+vecList[0]*length.length()


    #only branch every third level (sorta)
    if numIterations%3==0:
      #decrease dimensions when we branch
      length=Vec3(length.getX()/2, length.getY()/2, length.getZ()/1.1)
      for i in range(numCopies):
        makeFractalTree(bodydata, nodePath,length,newPos, numIterations-1, numCopies,randomAxis(vecList))
    else:
      #just make another branch connected to this one with a small variation in direction
      makeFractalTree(bodydata, nodePath,length,newPos, numIterations-1,numCopies,smallRandomAxis(vecList))

  else:
    drawBody(nodePath,bodydata, pos, vecList, length.getX(),False)
    drawLeaf(nodePath,bodydata, pos,vecList)
Exemplo n.º 18
0
    def setupLights(self):
        #Create some lights and add them to the scene. By setting the lights on
        #render they affect the entire scene
        #Check out the lighting tutorial for more information on lights
        lAttrib = LightAttrib.makeAllOff()
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.4, .4, .35, 1))
        lAttrib = lAttrib.addLight(ambientLight)
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0, 8, -2.5))
        directionalLight.setColor(Vec4(0.9, 0.8, 0.9, 1))
        lAttrib = lAttrib.addLight(directionalLight)
        render.attachNewNode(directionalLight)
        render.attachNewNode(ambientLight)
        render.node().setAttrib(lAttrib)

        #Explicitly set the environment to not be lit
        lAttrib = LightAttrib.makeAllOff()
        self.env.node().setAttrib(lAttrib)
Exemplo n.º 19
0
 def addFirefly(self):
     pos1 = Point3(random.uniform(-50, 50), random.uniform(-100, 150),
                   random.uniform(-10, 80))
     dir = Vec3(random.uniform(-1, 1), random.uniform(-1, 1),
                random.uniform(-1, 1))
     dir.normalize()
     pos2 = pos1 + (dir * 20)
     fly = self.lightroot.attachNewNode(PandaNode("fly"))
     glow = fly.attachNewNode(PandaNode("glow"))
     dot = fly.attachNewNode(PandaNode("dot"))
     color_r = random.uniform(0.7, 1.0)
     color_g = 1.0
     color_b = 0.8
     fly.setShaderInput("lightcolor", color_r, color_g, color_b, 1.0)
     int1 = fly.posInterval(random.uniform(7, 12), pos1, pos2)
     int2 = fly.posInterval(random.uniform(7, 12), pos2, pos1)
     si1 = fly.scaleInterval(random.uniform(0.8, 1.5),
                             Point3(0.2, 0.2, 0.2), Point3(0.2, 0.2, 0.2))
     si2 = fly.scaleInterval(random.uniform(1.5, 0.8),
                             Point3(1.0, 1.0, 1.0), Point3(0.2, 0.2, 0.2))
     si3 = fly.scaleInterval(random.uniform(1.0, 2.0),
                             Point3(0.2, 0.2, 0.2), Point3(1.0, 1.0, 1.0))
     siseq = Sequence(si1, si2, si3)
     siseq.loop()
     siseq.setT(random.uniform(0, 1000))
     seq = Sequence(int1, int2)
     seq.loop()
     self.spheremodel.instanceTo(glow)
     self.spheremodel.instanceTo(dot)
     glow.setScale(self.fireflysize * 1.1)
     glow.hide(BitMask32(self.modelMask | self.plainMask))
     dot.setScale(0.6)
     dot.hide(BitMask32(self.modelMask | self.lightMask))
     dot.setColor(color_r, color_g, color_b, 1.0)
     self.fireflies.append(fly)
     self.sequences.append(seq)
     self.glowspheres.append(glow)
     self.scaleseqs.append(siseq)
Exemplo n.º 20
0
  def __init__(self):
    formatArray=GeomVertexArrayFormat()
    formatArray.addColumn(InternalName.make("drawFlag"), 1, Geom.NTUint8, Geom.COther)

    format=GeomVertexFormat(GeomVertexFormat.getV3n3cpt2())
    format.addArray(formatArray)
    self.format=GeomVertexFormat.registerFormat(format)

    bodydata=GeomVertexData("body vertices", format, Geom.UHStatic)

    self.barkTexture=loader.loadTexture( \
      "models/samples/fractal_plants/bark.jpg")
    treeNodePath=NodePath("Tree Holder")
    makeFractalTree(bodydata,treeNodePath,Vec3(4,4,7))

    treeNodePath.setTexture(self.barkTexture,1)
    treeNodePath.reparentTo(render)

    self.accept("q", self.regenTree)
    self.accept("w", self.addTree)
    self.accept("arrow_up", self.upIterations)
    self.accept("arrow_down", self.downIterations)
    self.accept("arrow_right", self.upCopies)
    self.accept("arrow_left", self.downCopies)

    self.numIterations=11
    self.numCopies=4


    self.upDownEvent = OnscreenText(
      text="Up/Down: Increase/Decrease the number of iterations ("+str(self.numIterations)+")",
          style=1, fg=(1,1,1,1), pos=(-1.3, 0.85), font = font,
      align=TextNode.ALeft, scale = .05, mayChange=True)

    self.leftRightEvent = OnscreenText(
      text="Left/Right: Increase/Decrease branching("+str(self.numCopies)+")",
          style=1, fg=(1,1,1,1), pos=(-1.3, 0.80), font = font,
      align=TextNode.ALeft, scale = .05, mayChange=True)
Exemplo n.º 21
0
 def spawnAsteroids(self):
     self.alive = True  #Control variable for if the ship is alive
     self.asteroids = []  #List that will contain our asteroids
     for i in range(10):
         #This loads an asteroid. The texture chosen is random from "asteroid1" to
         #"asteroid3"
         self.asteroids.append(
             loadObject("asteroid" + str(randint(1, 3)),
                        scale=AST_INIT_SCALE))
         #This is kind of a hack, but it keeps the asteroids from spawning near
         #the player. It creates the list (-20, -19 ... -5, 5, 6, 7, ... 20)
         #and chooses a value from it. Since the player starts at 0 and this list
         #doesn't contain anything from -4 to 4, it won't be close to the player
         self.asteroids[i].setX(
             choice(range(-SCREEN_X, -5) + range(5, SCREEN_X)))
         #Same thing for Y, but from -15 to 15
         self.asteroids[i].setZ(
             choice(range(-SCREEN_Y, -5) + range(5, SCREEN_Y)))
         heading = random() * 2 * pi  #Heading is a random angle in radians
         #Converts the heading to a vector and multiplies it by speed to get a
         #velocity vector
         v = Vec3(sin(heading), 0, cos(heading)) * AST_INIT_VEL
         self.setVelocity(self.asteroids[i], v)
Exemplo n.º 22
0
    def __init__(self):

        #Our standard title and instructions text
        self.title = OnscreenText(text="Panda3D: Tutorial - Musicbox(sounds)",
                                  font=font,
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  pos=(0.7, -0.95),
                                  scale=.07)
        self.escapeEventText = OnscreenText(text="ESC: Quit",
                                            font=font,
                                            style=1,
                                            fg=(1, 1, 1, 1),
                                            pos=(-1.3, 0.95),
                                            align=TextNode.ALeft,
                                            scale=.05)

        #Set up the key input
        self.accept('escape', sys.exit)

        #Fix the camera position
        base.disableMouse()

        #Loading sounds is done in a similar way to loading other things
        #Loading the main music box song
        self.musicBoxSound = base.loadMusic(
            'models/samples/music_box/musicbox.mp3')
        self.musicBoxSound.setVolume(.5)  #Volume is a percentage from 0 to 1
        self.musicBoxSound.setLoopCount(
            0)  #0 means loop forever, 1 (default) means
        #play once. 2 or higher means play that
        #many times

        #Sound objects do not have a pause function, just play and stop. So we will
        #Use this variable to keep track of where the sound is at when it was stoped
        #to impliment pausing
        self.musicTime = 0

        #Loading the open/close effect
        #loadSFX and loadMusic are identical. They are often used for organization
        #(loadMusic is used for background music, loadSfx is used for other effects)
        self.lidSfx = base.loadSfx('models/samples/music_box/openclose.mp3')
        #The open/close file has both effects in it. Fortunatly we can use intervals
        #to easily define parts of a sound file to play
        self.lidOpenSfx = SoundInterval(self.lidSfx, duration=2, startTime=0)
        self.lidCloseSfx = SoundInterval(self.lidSfx, startTime=5)

        #For this tutorial, it seemed appropriate to have on screen controls. The
        #following code creates them
        #This is a label for a slider
        self.sliderText = OnscreenText("Volume",
                                       font=font,
                                       style=1,
                                       fg=(1, 1, 1, 1),
                                       pos=(0, 0.8),
                                       scale=.07)
        #The slider itself. It calls self.setMusicBoxVolume when changed
        self.slider = DirectSlider(pos=Vec3(0, 0, .7),
                                   value=.50,
                                   command=self.setMusicBoxVolume)
        #A button that calls self.toggleMusicBox when pressed
        self.button = DirectButton(pos=Vec3(.7, 0, .7),
                                   text="Open Box",
                                   scale=.1,
                                   pad=(.5, .5),
                                   text_font=font,
                                   rolloverSound=None,
                                   clickSound=None,
                                   command=self.toggleMusicBox)

        #A variable to represent the state of the simulation. It starts closed
        self.boxOpen = False

        #Here we load and set up the music box. It was modeled in a complex way, so
        #setting it up will be complicated
        self.musicBox = loader.loadModel('models/samples/music_box/musicbox')
        self.musicBox.setPos(0, 60, -10)
        self.musicBox.reparentTo(render)
        #Just like the scene graph contains hierarchies of nodes, so can
        #models. You can get the NodePath for the node using the find
        #function, and then you can animate the model by moving its parts
        #To see the hierarchy of a model, use, the ls function
        #self.musicBox.ls() prints out the entire hierarchy of the model

        #Finding pieces of the model
        self.Lid = self.musicBox.find('**/lid')
        self.Panda = self.musicBox.find('**/turningthing')

        #This model was made with the hinge in the wrong place
        #this is here so we have something to turn
        self.HingeNode = self.musicBox.find('**/box').attachNewNode(
            'nHingeNode')
        self.HingeNode.setPos(.8659, 6.5, 5.4)
        #WRT - ie with respect to. Reparents the object without changing
        #its position, size, or orientation
        self.Lid.wrtReparentTo(self.HingeNode)
        self.HingeNode.setHpr(0, 90, 0)

        #This sets up an interval to play the close sound and actually close the box
        #at the same time.
        self.lidClose = Parallel(
            self.lidCloseSfx,
            LerpFunc(self.HingeNode.setP,
                     duration=2,
                     fromData=0,
                     toData=90,
                     blendType='easeInOut'))

        #Same thing for opening the box
        self.lidOpen = Parallel(
            self.lidOpenSfx,
            LerpFunc(self.HingeNode.setP,
                     duration=2,
                     fromData=90,
                     toData=0,
                     blendType='easeInOut'))

        #The interval for turning the panda
        self.PandaTurn = self.Panda.hprInterval(7, Vec3(360, 0, 0))
        #Do a quick loop and pause to set it as a looping interval so it can be
        #started with resume and loop properly
        self.PandaTurn.loop()
        self.PandaTurn.pause()
Exemplo n.º 23
0
    def __init__(self):
        base.disableMouse()
        base.cam.node().getLens().setNear(10.0)
        base.cam.node().getLens().setFar(200.0)
        camera.setPos(0, -50, 0)

        # Check video card capabilities.

        if (base.win.getGsg().getSupportsBasicShaders() == 0):
            addTitle(
                "Toon Shader: Video driver reports that shaders are not supported."
            )
            return

        # Enable a 'light ramp' - this discretizes the lighting,
        # which is half of what makes a model look like a cartoon.
        # Light ramps only work if shader generation is enabled,
        # so we call 'setShaderAuto'.

        tempnode = NodePath(PandaNode("temp node"))
        tempnode.setAttrib(LightRampAttrib.makeSingleThreshold(0.5, 0.4))
        tempnode.setShaderAuto()
        base.cam.node().setInitialState(tempnode.getState())

        # Use class 'CommonFilters' to enable a cartoon inking filter.
        # This can fail if the video card is not powerful enough, if so,
        # display an error and exit.

        self.separation = 1  # Pixels
        self.filters = CommonFilters(base.win, base.cam)
        filterok = self.filters.setCartoonInk(separation=self.separation)
        if (filterok == False):
            addTitle(
                "Toon Shader: Video card not powerful enough to do image postprocessing"
            )
            return

        # Post the instructions.

        self.title = addTitle(
            "Panda3D: Tutorial - Toon Shading with Normals-Based Inking")
        self.inst1 = addInstructions(0.95, "ESC: Quit")
        self.inst2 = addInstructions(
            0.90, "Up/Down: Increase/Decrease Line Thickness")
        self.inst3 = addInstructions(0.85,
                                     "V: View the render-to-texture results")

        # Load a dragon model and animate it.

        self.character = Actor()
        self.character.loadModel('models/samples/cartoon/nik_dragon')
        self.character.reparentTo(render)
        self.character.loadAnims({'win': 'models/samples/cartoon/nik_dragon'})
        self.character.loop('win')
        self.character.hprInterval(15, Point3(360, 0, 0)).loop()

        # Create a non-attenuating point light and an ambient light.

        plightnode = PointLight("point light")
        plightnode.setAttenuation(Vec3(1, 0, 0))
        plight = render.attachNewNode(plightnode)
        plight.setPos(30, -50, 0)
        alightnode = AmbientLight("ambient light")
        alightnode.setColor(Vec4(0.8, 0.8, 0.8, 1))
        alight = render.attachNewNode(alightnode)
        render.setLight(alight)
        render.setLight(plight)

        # Panda contains a built-in viewer that lets you view the
        # results of all render-to-texture operations.  This lets you
        # see what class CommonFilters is doing behind the scenes.

        self.accept("v", base.bufferViewer.toggleEnable)
        self.accept("V", base.bufferViewer.toggleEnable)
        base.bufferViewer.setPosition("llcorner")
        self.accept("s", self.filters.manager.resizeBuffers)

        # These allow you to change cartooning parameters in realtime

        self.accept("escape", sys.exit, [0])
        self.accept("arrow_up", self.increaseSeparation)
        self.accept("arrow_down", self.decreaseSeparation)
Exemplo n.º 24
0
    def startCarousel(self):
        #Here's where we actually create the intervals to move the carousel
        #The first type of interval we use is one created directly from a NodePath
        #This interval tells the NodePath to vary its orientation (hpr) from its
        #current value (0,0,0) to (360,0,0) over 20 seconds. Intervals created from
        #NodePaths also exist for position, scale, color, and shear

        self.carouselSpin = self.carousel.hprInterval(20, Vec3(360, 0, 0))
        #Once an interval is created, we need to tell it to actually move.
        #start() will cause an interval to play once. loop() will tell an interval
        #to repeat once it finished. To keep the carousel turning, we use loop()
        self.carouselSpin.loop()

        #The next type of interval we use is called a LerpFunc interval. It is
        #called that becuase it linearly interpolates (aka Lerp) values passed to
        #a function over a given amount of time.

        #In this specific case, horses on a carousel don't move contantly up,
        #suddenly stop, and then contantly move down again. Instead, they start
        #slowly, get fast in the middle, and slow down at the top. This motion is
        #close to a sine wave. This LerpFunc calls the function oscilatePanda
        #(which we will create below), which changes the hieght of the panda based
        #on the sin of the value passed in. In this way we achieve non-linear
        #motion by linearly changing the input to a function
        for i in range(4):
            self.moves[i] = LerpFunc(
                self.oscilatePanda,  #function to call
                duration=3,  #3 second duration
                fromData=0,  #starting value (in radians)
                toData=2 * pi,  #ending value (2pi radians = 360 degrees)
                #Additional information to pass to
                #self.oscialtePanda
                extraArgs=[self.models[i], pi * (i % 2)])
            #again, we want these to play continuously so we start them with loop()
            self.moves[i].loop()

        #Finally, we combine Sequence, Parallel, Func, and Wait intervals,
        #to schedule texture swapping on the lights to simulate the lights turning
        #on and off.
        #Sequence intervals play other intervals in a sequence. In other words,
        #it waits for the current interval to finish before playing the next
        #one.
        #Parallel intervals play a group of intervals at the same time
        #Wait intervals simply do nothing for a given amount of time
        #Func intervals simply make a single function call. This is helpful because
        #it allows us to schedule functions to be called in a larger sequence. They
        #take virtually no time so they don't cause a Sequence to wait.

        self.lightBlink = Sequence(
            #For the first step in our sequence we will set the on texture on one
            #light and set the off texture on the other light at the same time
            Parallel(Func(self.lights1.setTexture, self.lightOnTex, 1),
                     Func(self.lights2.setTexture, self.lightOffTex, 1)),
            Wait(1),  #Then we will wait 1 second
            #Then we will switch the textures at the same time
            Parallel(Func(self.lights1.setTexture, self.lightOffTex, 1),
                     Func(self.lights2.setTexture, self.lightOnTex, 1)),
            Wait(1)  #Then we will wait another second
        )

        self.lightBlink.loop()  #Loop this sequence continuously
Exemplo n.º 25
0
def makeSquare(x1, y1, z1, x2, y2, z2):
    format = GeomVertexFormat.getV3n3cpt2()
    vdata = GeomVertexData('square', format, Geom.UHDynamic)

    vertex = GeomVertexWriter(vdata, 'vertex')
    normal = GeomVertexWriter(vdata, 'normal')
    color = GeomVertexWriter(vdata, 'color')
    texcoord = GeomVertexWriter(vdata, 'texcoord')

    #make sure we draw the sqaure in the right plane
    if x1 != x2:
        vertex.addData3f(x1, y1, z1)
        vertex.addData3f(x2, y1, z1)
        vertex.addData3f(x2, y2, z2)
        vertex.addData3f(x1, y2, z2)

        normal.addData3f(myNormalize(Vec3(2 * x1 - 1, 2 * y1 - 1, 2 * z1 - 1)))
        normal.addData3f(myNormalize(Vec3(2 * x2 - 1, 2 * y1 - 1, 2 * z1 - 1)))
        normal.addData3f(myNormalize(Vec3(2 * x2 - 1, 2 * y2 - 1, 2 * z2 - 1)))
        normal.addData3f(myNormalize(Vec3(2 * x1 - 1, 2 * y2 - 1, 2 * z2 - 1)))

    else:
        vertex.addData3f(x1, y1, z1)
        vertex.addData3f(x2, y2, z1)
        vertex.addData3f(x2, y2, z2)
        vertex.addData3f(x1, y1, z2)

        normal.addData3f(myNormalize(Vec3(2 * x1 - 1, 2 * y1 - 1, 2 * z1 - 1)))
        normal.addData3f(myNormalize(Vec3(2 * x2 - 1, 2 * y2 - 1, 2 * z1 - 1)))
        normal.addData3f(myNormalize(Vec3(2 * x2 - 1, 2 * y2 - 1, 2 * z2 - 1)))
        normal.addData3f(myNormalize(Vec3(2 * x1 - 1, 2 * y1 - 1, 2 * z2 - 1)))

    #adding different colors to the vertex for visibility
    color.addData4f(1.0, 0.0, 0.0, 1.0)
    color.addData4f(0.0, 1.0, 0.0, 1.0)
    color.addData4f(0.0, 0.0, 1.0, 1.0)
    color.addData4f(1.0, 0.0, 1.0, 1.0)

    texcoord.addData2f(0.0, 1.0)
    texcoord.addData2f(0.0, 0.0)
    texcoord.addData2f(1.0, 0.0)
    texcoord.addData2f(1.0, 1.0)

    #quads arent directly supported by the Geom interface
    #you might be interested in the CardMaker class if you are
    #interested in rectangle though
    tri1 = GeomTriangles(Geom.UHDynamic)
    tri2 = GeomTriangles(Geom.UHDynamic)

    tri1.addVertex(0)
    tri1.addVertex(1)
    tri1.addVertex(3)

    tri2.addConsecutiveVertices(1, 3)

    tri1.closePrimitive()
    tri2.closePrimitive()

    square = Geom(vdata)
    square.addPrimitive(tri1)
    square.addPrimitive(tri2)

    return square
Exemplo n.º 26
0
from panda3d.pandac import LightAttrib, TextNode
from panda3d.pandac import Vec3, Vec4, BitMask32
from panda3d.direct.gui.OnscreenText import OnscreenText
from panda3d.direct.showbase.DirectObject import DirectObject
from panda3d.direct.interval.MetaInterval import Sequence, Parallel
from panda3d.direct.interval.LerpInterval import LerpFunc
from panda3d.direct.interval.FunctionInterval import Func, Wait
from panda3d.direct.task.Task import Task
import sys

#Some constants for the program
ACCEL = 70  #Acceleration in ft/sec/sec
MAX_SPEED = 5  #Max speed in ft/sec
MAX_SPEED_SQ = MAX_SPEED**2  #Squared to make it easier to use lengthSquared
#Instead of length
UP = Vec3(0, 0, 1)  #We need this vector a lot, so its better to just have one
#instead of creating a new one every time we need it
font = loader.loadFont("cmss12")


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,
            font=font)
        self.instructions = OnscreenText(text="Mouse pointer tilts the board",
Exemplo n.º 27
0
    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,
            font=font)
        self.instructions = OnscreenText(text="Mouse pointer tilts the board",
                                         pos=(-1.3, .95),
                                         fg=(1, 1, 1, 1),
                                         font=font,
                                         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/samples/ball_in_maze/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/samples/ball_in_maze/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
        lAttrib = LightAttrib.makeAllOff()
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.55, .55, .55, 1))
        lAttrib = lAttrib.addLight(ambientLight)
        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))
        lAttrib = lAttrib.addLight(directionalLight)
        self.ballRoot.node().setAttrib(lAttrib)

        #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()
Exemplo n.º 28
0
  def __init__( self ):
  #The main initialization of our class
    #This creates the on screen title that is in every tutorial
    self.title = OnscreenText(text="Panda3D: Tutorial - Lighting",
                              style=1, fg=(1,1,0,1), font = font,
                              pos=(0.87,-0.95), scale = .07)

    #Creates labels used for onscreen instructions
    self.ambientText = self.makeStatusLabel(0)
    self.directionalText = self.makeStatusLabel(1)
    self.spotlightText = self.makeStatusLabel(2)
    self.pointLightText = self.makeStatusLabel(3)
    self.spinningText = self.makeStatusLabel(4)
    self.ambientBrightnessText = self.makeStatusLabel(5)
    self.directionalBrightnessText = self.makeStatusLabel(6)
    self.spotlightBrightnessText = self.makeStatusLabel(7)
    self.spotlightExponentText = self.makeStatusLabel(8)
    self.lightingPerPixelText = self.makeStatusLabel(9)

    self.disco = loader.loadModel("models/samples/disco_lights/disco_hall")
    self.disco.reparentTo(render)
    self.disco.setPosHpr(0, 50, -4, 90, 0, 0)

    # First we create an ambient light. All objects are affected by ambient
    # light equally
    #Create and name the ambient light
    self.ambientLight = render.attachNewNode( AmbientLight( "ambientLight" ) )
    #Set the color of the ambient light
    self.ambientLight.node().setColor( Vec4( .1, .1, .1, 1 ) )
    #add the newly created light to the lightAttrib

    # Now we create a directional light. Directional lights add shading from a
    # given angle. This is good for far away sources like the sun
    self.directionalLight = render.attachNewNode( DirectionalLight(
"directionalLight" ) )
    self.directionalLight.node().setColor( Vec4( .35, .35, .35, 1 ) )
    # The direction of a directional light is set as a 3D vector
    self.directionalLight.node().setDirection( Vec3( 1, 1, -2 ) )

    # Now we create a spotlight. Spotlights light objects in a given cone
    # They are good for simulating things like flashlights
    self.spotlight = camera.attachNewNode( Spotlight( "spotlight" ) )
    self.spotlight.node().setColor( Vec4( .45, .45, .45, 1 ) )
    #The cone of a spotlight is controlled by it's lens. This creates the lens
    self.spotlight.node().setLens( PerspectiveLens() )
    #This sets the Field of View (fov) of the lens, in degrees for width and
    #height. The lower the numbers, the tighter the spotlight.
    self.spotlight.node().getLens().setFov( 16, 16 )
    # Attenuation controls how the light fades with distance. The numbers are
    # The three values represent the three constants (constant, linear, and
    # quadratic) in the internal lighting equation. The higher the numbers the
    # shorter the light goes.
    self.spotlight.node().setAttenuation( Vec3( 1, 0.0, 0.0 ) ) 
    # This exponent value sets how soft the edge of the spotlight is. 0 means a
    # hard edge. 128 means a very soft edge.
    self.spotlight.node().setExponent( 60.0 )

    # Now we create three colored Point lights. Point lights are lights that
    # radiate from a single point, like a light bulb. Like spotlights, they
    # are given position by attaching them to NodePaths in the world
    self.redHelper = loader.loadModel('models/samples/disco_lights/sphere')
    self.redHelper.setColor( Vec4( 1, 0, 0, 1 ) )
    self.redHelper.setPos( -6.5, -3.75, 0 )
    self.redHelper.setScale(.25)
    self.redPointLight = self.redHelper.attachNewNode( PointLight(
"redPointLight" ) )
    self.redPointLight.node().setColor( Vec4( .35, 0, 0, 1 ) )
    self.redPointLight.node().setAttenuation( Vec3( .1, 0.04, 0.0 ) ) 

    #The green point light and helper
    self.greenHelper = loader.loadModel('models/samples/disco_lights/sphere')
    self.greenHelper.setColor( Vec4( 0, 1, 0, 1 ) )
    self.greenHelper.setPos( 0, 7.5, 0 )
    self.greenHelper.setScale(.25)
    self.greenPointLight = self.greenHelper.attachNewNode( PointLight(
"greenPointLight" ) )
    self.greenPointLight.node().setAttenuation( Vec3( .1, .04, .0 ) ) 
    self.greenPointLight.node().setColor( Vec4( 0, .35, 0, 1 ) )

    #The blue point light and helper
    self.blueHelper = loader.loadModel('models/samples/disco_lights/sphere')
    self.blueHelper.setColor( Vec4( 0, 0, 1, 1 ) )
    self.blueHelper.setPos( 6.5, -3.75, 0 )
    self.blueHelper.setScale(.25)
    self.bluePointLight = self.blueHelper.attachNewNode( PointLight( "bluePointLight" ) )
    self.bluePointLight.node().setAttenuation( Vec3( .1, 0.04, 0.0 ) ) 
    self.bluePointLight.node().setColor( Vec4( 0, 0, .35, 1 ) )
    self.bluePointLight.node().setSpecularColor( Vec4( 1 ) )

    #Create a dummy node so the lights can be spun with one command
    self.pointLightHelper = render.attachNewNode( "pointLightHelper" )
    self.pointLightHelper.setPos(0, 50, 11)
    self.redHelper.reparentTo( self.pointLightHelper )
    self.greenHelper.reparentTo( self.pointLightHelper )
    self.blueHelper.reparentTo( self.pointLightHelper )

    #Finally we store the lights on the root of the scene graph.
    #This will cause them to affect everything in the scene.

    render.setLight( self.ambientLight )
    render.setLight( self.directionalLight )
    render.setLight( self.spotlight )
    render.setLight( self.redPointLight )
    render.setLight( self.greenPointLight )
    render.setLight( self.bluePointLight )

    # Create and start interval to spin the lights, and a variable to
    # manage them.
    self.pointLightsSpin = self.pointLightHelper.hprInterval(6, Vec3(360, 0, 0))
    self.pointLightsSpin.loop()
    self.arePointLightsSpinning = True

    # Per-pixel lighting is initially off
    self.perPixelEnabled = False

    # listen to keys for controlling the lights
    self.accept( "escape", sys.exit)
    self.accept( "a", self.toggleLights, [[self.ambientLight]] )
    self.accept( "d", self.toggleLights, [[self.directionalLight]] )
    self.accept( "s", self.toggleLights, [[self.spotlight]] )
    self.accept( "p", self.toggleLights, [[self.redPointLight,
                                           self.greenPointLight,
                                           self.bluePointLight]] )
    self.accept( "r", self.toggleSpinningPointLights )
    self.accept( "l", self.togglePerPixelLighting )
    self.accept( "z", self.addBrightness, [self.ambientLight, -.05] )
    self.accept( "x", self.addBrightness, [self.ambientLight, .05] )
    self.accept( "c", self.addBrightness, [self.directionalLight, -.05] )
    self.accept( "v", self.addBrightness, [self.directionalLight, .05] )
    self.accept( "b", self.addBrightness, [self.spotlight, -.05] )
    self.accept( "n", self.addBrightness, [self.spotlight, .05] )
    self.accept( "q", self.adjustSpotlightExponent, [self.spotlight, -1] )
    self.accept( "w", self.adjustSpotlightExponent, [self.spotlight, 1] )

    #Finally call the function that builds the instruction texts
    self.updateStatusLabel()
Exemplo n.º 29
0
 def getVelocity(self, obj):
     list = cPickle.loads(obj.getTag("velocity"))
     return Vec3(list[0], list[1], list[2])
Exemplo n.º 30
0
    def gameLoop(self, task):
        #task contains a variable time, which is the time in seconds the task has
        #been running. By default, it does not have a delta time (or dt), which is
        #the amount of time elapsed from the last frame. A common way to do this is
        #to store the current time in task.last. This can be used to find dt
        dt = task.time - task.last
        task.last = task.time

        #If the ship is not alive, do nothing. Tasks return Task.cont to signify
        #that the task should continue running. If Task.done were returned instead,
        #the task would be removed and would no longer be called every frame
        if not self.alive: return Task.cont

        #update ship position
        self.updateShip(dt)

        #check to see if the ship can fire
        if self.keys["fire"] and task.time > task.nextBullet:
            self.fire(task.time)  #If so, call the fire function
            #And disable firing for a bit
            task.nextBullet = task.time + BULLET_REPEAT
        self.keys[
            "fire"] = 0  #Remove the fire flag until the next spacebar press

        #update asteroids
        for obj in self.asteroids:
            self.updatePos(obj, dt)

        #update bullets
        newBulletArray = []
        for obj in self.bullets:
            self.updatePos(obj, dt)  #Update the bullet
            #Bullets have an experation time (see definition of fire)
            #If a bullet has not expired, add it to the new bullet list so that it
            #will continue to exist
            if self.getExpires(obj) > task.time: newBulletArray.append(obj)
            else: obj.remove()  #Otherwise remove it from the scene
        #Set the bullet array to be the newly updated array
        self.bullets = newBulletArray

        #Check bullet collision with asteroids
        #In short, it checks every bullet against every asteroid. This is quite
        #slow. An big optimization would be to sort the objects left to right and
        #check only if they overlap. Framerate can go way down if there are too
        #many bullets on screen, but for the most part it's okay.
        for bullet in self.bullets:
            #This range statement makes it step though the astroid list backwards
            #This is because if an asteroid is removed, the elements after it
            #will change position in the list. If you go backwards, the
            #length stays constant
            for i in range(len(self.asteroids) - 1, -1, -1):
                #Panda's collision detection is more complicated than we need here.
                #This is the basic sphere collision check. If the distance between
                #the object centers is less than sum of the radii of the two objects,
                #then we have a collision. We use lengthSquared since it is a quicker
                #vector operation than length
                if ((bullet.getPos() -
                     self.asteroids[i].getPos()).lengthSquared() <
                    (((bullet.getScale().getX() +
                       self.asteroids[i].getScale().getX()) * .5)**2)):
                    self.setExpires(bullet,
                                    0)  #Schedule the bullet for removal
                    self.asteroidHit(i)  #Handle the hit

        #Now we do the same collision pass for the ship
        for ast in self.asteroids:
            #Same sphere collision check for the ship vs. the asteroid
            if ((self.ship.getPos() - ast.getPos()).lengthSquared() <
                (((self.ship.getScale().getX() + ast.getScale().getX()) * .5)**
                 2)):
                #If there is a hit, clear the screen and schedule a restart
                self.alive = False  #Ship is no longer alive
                #Remove every object in asteroids and bullets from the scene
                for i in self.asteroids + self.bullets:
                    i.remove()
                self.bullets = []  #Clear the bullet list
                self.ship.hide()  #Hide the ship
                self.setVelocity(self.ship, Vec3(0, 0, 0))  #Reset the velocity
                Sequence(
                    Wait(2),  #Wait 2 seconds
                    Func(self.ship.setR, 0),  #Reset heading
                    Func(self.ship.setX, 0),  #Reset position X
                    Func(self.ship.setZ, 0),  #Reset position Y (Z for Panda)
                    Func(self.ship.show),  #Show the ship
                    Func(self.spawnAsteroids)).start(
                    )  #And respawn the asteriods
                return Task.cont

        #If the player has successfully destroyed all asteroids, respawn them
        if len(self.asteroids) == 0: self.spawnAsteroids()

        return Task.cont  #Since every return is Task.cont, the task will