Beispiel #1
0
def clipOnTie(enemy, hitPoint):
    tie = Actor('phase_3.5/models/props/clip-on-tie-mod.bam',
                {'clip-on-tie': 'phase_3.5/models/props/clip-on-tie-chan.bam'})
    tie.getChild(0).setHpr(23.86, -16.03, 9.18)

    enemyType = enemy.style.body

    if enemyType == 'a':
        throwDelay = 2.17
    elif enemyType == 'b':
        throwDelay = 2.17
    elif enemyType == 'c':
        throwDelay = 1.45

    enemyTrack = enemy.actorInterval('throw-paper')
    posPoints = [Point3(0.66, 0.51, 0.28), VBase3(-69.652, -17.199, 67.96)]

    propTrack = Sequence(
        getPropAppearTrack(tie,
                           enemy.getRightHand(),
                           posPoints,
                           0.5,
                           PNT3_ONE,
                           scaleUpTime=0.5,
                           poseExtraArgs=['clip-on-tie', 0]),
        tie.actorInterval('clip-on-tie', duration=throwDelay, startTime=1.1),
        Func(tie.setHpr, 0, -90, 0),
        getPropThrowTrack(tie, [hitPoint],
                          hitDuration=0.4,
                          callback=enemy.arena.damageHQ))

    sound = loader.loadSfx('phase_5/audio/sfx/SA_powertie_throw.ogg')
    soundTrack = Sequence(Wait(throwDelay + 1), SoundInterval(sound,
                                                              node=enemy))
    return Parallel(enemyTrack, propTrack, soundTrack)
Beispiel #2
0
 def makeWalkingPanda(self, root, pos=(64,128, 0), axis_pos=(128, 128, 0),  scale=0.02, time=90.0):
     axis = root.attachNewNode('axis')
     axis.setPos(axis_pos)
     actor = Actor('panda-model', {'walk': 'panda-walk4'})
     actor.setPos(pos)
     actor.wrtReparentTo(axis)        
     actor.setScale(scale)
     walk = actor.actorInterval('walk', playRate=1.3)
     walk.loop()
     axis.hprInterval(time, LPoint3(360, 0, 0), startHpr=LPoint3(0, 0, 0)).loop()
     return actor
Beispiel #3
0
class LookingGrippingDemo(ShowBase):
    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)

        # This code puts the standard title and instruction text on screen
        self.title = OnscreenText(
            text="Panda3D: Tutorial - Joint Manipulation",
            fg=(1, 1, 1, 1),
            parent=base.a2dBottomRight,
            align=TextNode.ARight,
            pos=(-0.1, 0.1),
            shadow=(0, 0, 0, .5),
            scale=.08)

        self.onekeyText = genLabelText("ESC: Quit", 1)
        self.onekeyText = genLabelText("[1]: Teapot", 2)
        self.twokeyText = genLabelText("[2]: Candy cane", 3)
        self.threekeyText = genLabelText("[3]: Banana", 4)
        self.fourkeyText = genLabelText("[4]: Sword", 5)

        # Set up key input
        self.accept('escape', sys.exit)
        self.accept('1', self.switchObject, [0])
        self.accept('2', self.switchObject, [1])
        self.accept('3', self.switchObject, [2])
        self.accept('4', self.switchObject, [3])

        base.disableMouse()  # Disable mouse-based camera-control
        camera.setPos(0, -15, 2)  # Position the camera

        self.eve = Actor(
            "models/eve",  # Load our animated charachter
            {'walk': "models/eve_walk"})
        self.eve.reparentTo(render)  # Put it in the scene

        # Now we use controlJoint to get a NodePath that's in control of her neck
        # This must be done before any animations are played
        self.eveNeck = self.eve.controlJoint(None, 'modelRoot', 'Neck')

        # We now play an animation. An animation must be played, or at least posed
        # for the nodepath we just got from controlJoint to actually effect the
        # model
        self.eve.actorInterval("walk", playRate=2).loop()

        # Now we add a task that will take care of turning the head
        taskMgr.add(self.turnHead, "turnHead")

        # Now we will expose the joint the hand joint. ExposeJoint allows us to
        # get the position of a joint while it is animating. This is different than
        # controlJonit which stops that joint from animating but lets us move it.
        # This is particularly usefull for putting an object (like a weapon) in an
        # actor's hand
        self.rightHand = self.eve.exposeJoint(None, 'modelRoot', 'RightHand')

        # This is a table with models, positions, rotations, and scales of objects to
        # be attached to our exposed joint. These are stock models and so they needed
        # to be repositioned to look right.
        positions = [("teapot", (0, -.66, -.95), (90, 0, 90), .4),
                     ("models/candycane", (.15, -.99, -.22), (90, 0, 90), 1),
                     ("models/banana", (.08, -.1, .09), (0, -90, 0), 1.75),
                     ("models/sword", (.11, .19, .06), (0, 0, 90), 1)]

        self.models = []  # A list that will store our models objects
        for row in positions:
            np = loader.loadModel(row[0])  # Load the model
            np.setPos(row[1][0], row[1][1], row[1][2])  # Position it
            np.setHpr(row[2][0], row[2][1], row[2][2])  # Rotate it
            np.setScale(row[3])  # Scale it
            # Reparent the model to the exposed joint. That way when the joint moves,
            # the model we just loaded will move with it.
            np.reparentTo(self.rightHand)
            self.models.append(np)  # Add it to our models list

        self.switchObject(0)  # Make object 0 the first shown
        self.setupLights()  # Put in some default lighting

    # This is what we use to change which object it being held. It just hides all of
    # the objects and then unhides the one that was selected
    def switchObject(self, i):
        for np in self.models:
            np.hide()
        self.models[i].show()

    # This task gets the position of mouse each frame, and rotates the neck based
    # on it.
    def turnHead(self, task):
        # Check to make sure the mouse is readable
        if base.mouseWatcherNode.hasMouse():
            # get the mouse position as a LVector2. The values for each axis are from -1 to
            # 1. The top-left is (-1,-1), the bottom right is (1,1)
            mpos = base.mouseWatcherNode.getMouse()
            # Here we multiply the values to get the amount of degrees to turn
            # Restrain is used to make sure the values returned by getMouse are in the
            # valid range. If this particular model were to turn more than this,
            # significant tearing would be visable
            self.eveNeck.setP(clamp(mpos.getX()) * 50)
            self.eveNeck.setH(clamp(mpos.getY()) * 20)

        return Task.cont  # Task continues infinitely

    def setupLights(self):  # Sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.4, .4, .35, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 8, -2.5))
        directionalLight.setColor((0.9, 0.8, 0.9, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
Beispiel #4
0
class World(DirectObject): #subclassing here is necessary to accept events
    def __init__(self):
        #turn off default mouse control, otherwise can't reposition camera
        base.disableMouse()
        camera.setPosHpr(0, -15, 7, 0, -15, 0)
        self.loadModels()
        self.setupLights()
        self.setupCollisions()
        render.setShaderAuto() #turns on per-pixel lighting, normal mapping, etc (you probably want to use this)
        self.keyMap = {"left":0, "right":0, "forward":0}
        taskMgr.add(self.move, "moveTask")
        self.prevtime = 0
        self.ismoving = False
        self.accept("escape", sys.exit)
        self.accept("arrow_up", self.setKey, ["forward", 1])
        self.accept("arrow_right", self.setKey, ["right", 1])
        self.accept("arrow_left", self.setKey, ["left", 1])
        self.accept("arrow_up-up", self.setKey, ["forward", 0])
        self.accept("arrow_right-up", self.setKey, ["right", 0])
        self.accept("arrow_left-up", self.setKey, ["left", 0])
        #"mouse1" is left mouse button is clicked
        #append "-up" for equivalent of for equivalent of KEYUP event
        self.accept("ate-smiley", self.eat)
    
    def setKey(self, key, value):
        self.keyMap[key] = value
        
    def loadModels(self):
        """loads initial models into the world."""
        self.panda = Actor("models/panda-model", {"walk":"panda-walk4", "eat":"panda-eat"})
        self.panda.reparentTo(render)
        self.panda.setScale(0.005)
        self.panda.setH(180)
        self.env = loader.loadModel("models/environment")
        self.env.reparentTo(render)
        self.env.setScale(.25)
        self.env.setPos(-8, 42, 0)
        
        #load targets
        self.targets = []
        for i in range(10):
            target = loader.loadModel("smiley")
            target.setScale(.5)
            target.setPos(random.uniform(-20, 20), random.uniform(-15, 15), 2)
            target.reparentTo(render)
            self.targets.append(target)
    
    def setupLights(self):
        #ambient light
        self.ambientLight = AmbientLight("ambientLight") #parameter is a name
        #four values, RGBA, Alpha is largely irrelevant, value [0,1]
        self.ambientLight.setColor((.25, .25, .25, 1))
        self.ambientLightNP = render.attachNewNode(self.ambientLight)
        #the nodepath that calls setLight is what gets illuminated by the light
        render.setLight(self.ambientLightNP)
        #call clearLight() to turn it off
        
        self.keyLight = DirectionalLight("keyLight")
        self.keyLight.setColor((.6, .6, .6, 1))
        self.keyLightNP = render.attachNewNode(self.keyLight)
        self.keyLightNP.setHpr(0, -26, 0)
        render.setLight(self.keyLightNP)
        
        self.fillLight = DirectionalLight("fillLight")
        self.fillLight.setColor((.3, .3, .3, 1))
        self.fillLightNP = render.attachNewNode(self.fillLight)
        self.fillLightNP.setHpr(30, 0, 0)
        render.setLight(self.fillLightNP)
    
    def walk(self):
        """compound interval for walking"""
        #self.pandaWalk = self.panda.posInterval(1, (0, -5, 0))
        #some interval methods:
        #start(), loop(), pause(), resume(), finish()
        #start() can take arguments: start(starttime, endtime, playrate)
        dist = 5
        angle = deg2Rad(self.panda.getH())
        dx = dist * math.sin(angle)
        dy = dist * -math.cos(angle)
        pandaWalk = Parallel(self.panda.posInterval(1, (self.panda.getX()+dx, self.panda.getY()+dy, 0)), \
            self.panda.actorInterval("walk", loop=1, duration=1))
        pandaWalk.start()
    
    def turn(self, direction):
        pandaTurn = self.panda.hprInterval(.2, (self.panda.getH() - (10*direction), 0, 0))
        pandaTurn.start()
    
    def move(self, task):
        elapsed = task.time - self.prevtime
        camera.lookAt(self.panda)
        if self.keyMap["left"]:
            self.panda.setH(self.panda.getH() + elapsed*100)
        if self.keyMap["right"]:
            self.panda.setH(self.panda.getH() - elapsed*100)
        if self.keyMap["forward"]:
            dist = 15 * elapsed
            angle = deg2Rad(self.panda.getH())
            dx = dist * math.sin(angle)
            dy = dist * -math.cos(angle)
            self.panda.setPos(self.panda.getX()+dx, self.panda.getY()+dy, 0)
        if self.keyMap["left"] or self.keyMap["right"] or self.keyMap["forward"]:
            if self.ismoving == False:
                self.ismoving = True
                self.panda.loop("walk")
        else:
            if self.ismoving:
                self.ismoving = False
                self.panda.stop()
                self.panda.pose("walk",4)
                
        self.prevtime = task.time
        return Task.cont
    
    def setupCollisions(self):
        #instantiates a collision traverser and sets it to the default
        base.cTrav = CollisionTraverser()
        self.cHandler = CollisionHandlerEvent()
        #set pattern for event sent on collision
        #"%in" is substituted with the name of the into object
        self.cHandler.setInPattern("ate-%in")
        
        cSphere = CollisionSphere((0,0,0), 500)#because the panda is scaled way down, radius has to be huge
        cNode = CollisionNode("panda")
        cNode.addSolid(cSphere)
        cNode.setIntoCollideMask(BitMask32.allOff())#panda is *only* a from object
        cNodePath = self.panda.attachNewNode(cNode)
        #cNodePath.show()
        #registers a from object with the traverser with a corresponding handler
        base.cTrav.addCollider(cNodePath, self.cHandler)
        
        for target in self.targets:
            cSphere = CollisionSphere((0,0,0), 2)
            cNode = CollisionNode("smiley")
            cNode.addSolid(cSphere)
            cNodePath = target.attachNewNode(cNode)
            #cNodePath.show()
    
    def eat(self, cEntry):
        """handles panda eating a smiley"""
        #remove target from list of targets
        self.targets.remove(cEntry.getIntoNodePath().getParent())
        #remove from scene graph
        cEntry.getIntoNodePath().getParent().remove()
        self.panda.play("eat")
class RainbowSplash:
    def __init__(self, pattern=Pattern.SQUARESTAR, colors=Colors.RGB_BANDS, pattern_freq=2, cycle_freq=10):
        self.pattern = pattern
        self.colors = colors
        self.pattern_freq = pattern_freq
        self.cycle_freq = cycle_freq

    def setup(self):
        # Store current values
        self.entry_background_color = VBase4(base.win.get_clear_color())
        self.entry_cam_pos = VBase3(base.cam.get_pos())
        self.entry_cam_hpr = VBase3(base.cam.get_hpr())
        self.entry_cam_scale = VBase3(base.cam.get_scale())
        self.entry_cam_fov = VBase2(base.cam.node().get_lens().get_fov())

        # Set values for splash
        base.win.set_clear_color((0,0,0,1))
        cam_dist = 2
        base.cam.set_pos(0, -2.2 * cam_dist, 0)
        base.cam.set_hpr(0, 0, 0)
        base.cam.set_scale(1)
        base.cam.node().get_lens().set_fov(45/cam_dist)

        # Set up the splash itself
        self.logo_animation = Actor(asset_path / "panda3d_logo.bam")
        self.logo_animation.reparent_to(render)
        self.logo_animation.set_two_sided(True)

        shader = Shader.load(
            Shader.SL_GLSL,
            vertex=asset_path / "panda3d_logo.vert",
            fragment=asset_path / "panda3d_logo.frag",
        )
        self.logo_animation.set_shader(shader)
        self.logo_animation.set_shader_input("fade", 0.0)
        self.logo_animation.set_shader_input("pattern", self.pattern.value)
        self.logo_animation.set_shader_input("colors", self.colors.value)
        self.logo_animation.set_shader_input("pattern_freq", self.pattern_freq)
        self.logo_animation.set_shader_input("cycle_freq", self.cycle_freq)
        self.logo_sound = base.loader.loadSfx(asset_path / "panda3d_logo.wav")

        # Build interval
        def shader_time(t):
            self.logo_animation.set_shader_input("time", t)
        def fade_background_to_white(t):
            base.win.set_clear_color((t,t,t,1))
            self.logo_animation.set_shader_input("time", t/3.878)
            self.logo_animation.set_shader_input("fade", t)
        def fade_to_black(t):
            base.win.set_clear_color((1-t,1-t,1-t,1))
            #self.logo_animation.set_shader_input("time", t/3.878)
            #self.logo_animation.set_shader_input("fade", t)

        # Timing:
        # 0.000     Start
        # 3.878     Logo is assembled, fade to black-on-whitey
        # 4.878     Black on white achieved
        # <+1.500>  Begin fade to black
        # <+1.741>  Black on black achieved
        # 8.119 Sound ends
        effects = Parallel(
            self.logo_animation.actorInterval(
                "splash",
                loop=False,
            ),
            SoundInterval(
                self.logo_sound,
                loop=False,
            ),
            Sequence(
                LerpFunc(
                    shader_time,
                    fromData=0,
                    toData=1,
                    duration=3.878,
                ),
                LerpFunc(
                    fade_background_to_white,
                    fromData=0,
                    toData=1,
                    duration=1.0,
                ),
                Wait(1.5),
                LerpFunc(
                    fade_to_black,
                    fromData=0,
                    toData=1,
                    duration=1.741,
                ),
            ),
        )
        return effects

    def teardown(self):
        # Store current values
        base.win.set_clear_color(self.entry_background_color)
        base.cam.set_pos(self.entry_cam_pos)
        base.cam.set_hpr(self.entry_cam_hpr)
        base.cam.set_scale(self.entry_cam_scale)
        base.cam.node().get_lens().set_fov(self.entry_cam_fov)

        self.logo_animation.cleanup()
class Digger(enemy.Enemy):

    def __init__(self, mainRef):
        enemy.Enemy.__init__(self, mainRef, enemy.koboldSkirmisher) # Change to correct kobold

        self.holeModel = None

    def initAttributes(self, attributes):
        super(Digger, self).initAttributes(attributes)

        rangeMultiplier = 1.5
        self.combatRange *= rangeMultiplier
        self.perceptionRange *= rangeMultiplier

    def loadEnemyModel(self, modelName):
        modelPrefix = 'models/digger-'
        self.enemyModel = Actor(modelPrefix + 'model', {
                'attack1':modelPrefix+'attack1',
                'attack2':modelPrefix+'attack2',
                'attack3':modelPrefix+'attack3',
                'attack4':modelPrefix+'attack4',
                'special-attack':modelPrefix+'special-attack',

                'pursue':modelPrefix+'pursue',
                'pursue-to-idle':modelPrefix+'pursue-stop',

                'idle-walk':modelPrefix+'idle-walk',
                'idle-walk-to-pursue':modelPrefix+'idle-walk-to-pursue',
                'idle-walk-to-dig':modelPrefix+'idle-walk-to-dig',
                'idle-walk-to-dig-to-sleep':modelPrefix+'idle-walk-to-dig-to-sleep',

                'hit1':modelPrefix+'hit1',
                'hit2':modelPrefix+'hit2',

                'death1':modelPrefix+'death1',
                'death2':modelPrefix+'death2',
                'death3':modelPrefix+'death3'
            })
        self.enemyModel.reparentTo(self.enemyNode)

        self.enemyNode.setPos(Point3.zero())

        self.enemyNode.setDepthOffset(-1)

    def enterIdle(self):
        #print 'enemy enterIdle'
        #idleTime = 60.0 * 3.0

        stopEnemy = self.enemyModel.actorInterval('pursue-to-idle', startFrame=0, endFrame=12)
        idleEnemy = self.enemyModel.actorInterval('idle-walk-to-dig', startFrame=0, endFrame=60)
        digHole = Parallel(Func(self.createHole), self.enemyModel.actorInterval('idle-walk-to-dig-to-sleep', startFrame=0, endFrame=120))
        #hideEnemy = Func(self.enemyNode.hide)
        #suicide = Func(self.suicide)

        self.stopSequence = Sequence(stopEnemy, idleEnemy,  digHole)
        self.stopSequence.start()

        self.isSleeping = True

        #taskMgr.doMethodLater(3, self.showEnemy, 'showEnemyTask')

    def showEnemy(self, task):
        if self.state == 'Idle':
            self.enemyNode.show()
        return task.done

    def enterPursue(self):
        #print('enemy enterPursue')
        loopWalkEnemy = Func(self.enemyModel.loop, 'pursue', fromFrame=0, toFrame=24)

        # Only awake enemy if it comes from idle
        if self.isSleeping:
            self.isSleeping = False

            awakeEnemy = self.enemyModel.actorInterval('idle-walk-to-pursue', startFrame=0, endFrame=24)
            self.awakeSequence = Sequence(awakeEnemy, loopWalkEnemy, Func(self.pursuePlayer))
        else:
            self.awakeSequence = Sequence(loopWalkEnemy, Func(self.pursuePlayer))

        self.awakeSequence.start()

    def enterDeath(self):
        #print('enemy enterDeath')
        self.enemyAIBehaviors.removeAi('all')
        randomDeathAnim = 'death' + str(utils.getDX(3))
        self.enemyModel.play(randomDeathAnim, fromFrame=0, toFrame=12)

    def playAttackAnimation(self):
        randomAttackAnim = 'attack' + str(utils.getD4())
        self.enemyModel.play(randomAttackAnim, fromFrame=0, toFrame=12)

    def playHitAnimation(self):
        randomHitAnim = 'hit' + str(utils.getDX(2))
        self.enemyModel.play(randomHitAnim, fromFrame=0, toFrame=12)

    def createHole(self):
        if self.holeModel == None:
            self.holeModel = Actor('models/hole-model',
                                    {'anim':'models/hole-anim'})
            self.holeModel.reparentTo(self._mainRef.mainNode)

            self.holeModel.setPos(self.enemyNode, 0, -.1, 0)

            self.holeModel.play('anim', fromFrame=0, toFrame=120)

            removeHoleDelay = 12
            taskMgr.doMethodLater(removeHoleDelay, self.removeHole, 'removeHoleTask')

    def removeHole(self, task):
        if self.holeModel != None:
            self.holeModel.cleanup()
            self.holeModel.delete()

            self.holeModel = None

        return task.done
Beispiel #7
0
class SimpleWeapon:
  """Provides a simple weapon system - not very sophisticaed, but good enough to test shooting things."""
  def __init__(self,manager,xml):
    self.gunView = render.attachNewNode('gun-view')
    self.ray = None

    self.reload(manager,xml)


  def destroy(self):
    self.gunView.removeNode()

    if self.ray!=None:
      self.ray.destroy()


  def reload(self,manager,xml):
    # Get the path to load weapons from...
    basePath = manager.get('paths').getConfig().find('weapons').get('path')

    # Variables to manage the firing state (Used G36 as reference for defaults.)...
    bullet = xml.find('bullet')
    if bullet!=None:
      self.bulletRate = float(bullet.get('rate',1.0/12.5))
      self.bulletSpeed = float(bullet.get('speed',920.0))
      self.bulletWeight = float(bullet.get('mass',0.004))
    else:
      self.bulletRate = 1.0/12.5
      self.bulletSpeed = 920.0
      self.bulletWeight = 0.004

    # Determine the weapon meshes path...
    self.meshPath = posixpath.join(basePath, xml.find('egg').get('file'))

    # Get the camera interface, so we can zoom in when the player aims...
    self.camera = manager.get(xml.find('camera').get('plugin'))

    # Create our gun node - both the gun and the ray used for shooting track this - allows for gun jitter, kick back etc...
    parent = xml.find('parent')
    self.gunView.reparentTo(manager.get(parent.get('plugin')).getNode(parent.get('node')))

    # Create a ray cast to detect what the player is looking at... and what will be shot...
    self.space = manager.get('ode').getSpace()

    if self.ray!=None:
      self.ray.destroy()

    self.ray = OdeRayGeom(100.0)
    self.ray.setCategoryBits(BitMask32(0xfffffffe))
    self.ray.setCollideBits(BitMask32(0xfffffffe))

    # Get all the stuff we need to do the muzzle flash particle effect...
    flash = xml.find('muzzle_flash')
    self.flashManager = manager.get(flash.get('plugin'))
    self.flashEffect = flash.get('effect')
    self.flashBone = flash.get('bone') # Will be swapped out for the actual node latter.
    self.flashPos = csp.getPos(flash.get('pos'))

    # Get all the stuff we need to do the bullet hit sparks effect...
    sparks = xml.find('sparks')
    self.sparksManager = manager.get(sparks.get('plugin'))
    self.sparksEffect = sparks.get('effect')

    # Create a quaternion that rotates +ve z to +ve y - used to point it in the weapon direction rather than up...
    self.zToY = Quat()
    self.zToY.setFromAxisAngle(-90.0,Vec3(1.0,0.0,0.0))
    
    # State for the animation...
    self.state = False # False==casual, True==aim.
    self.nextState = False
    
    # Firing state...
    self.firing = False # True if the trigger is being held.
    self.triggerTime = 0.0 # How long the trigger has been held for, so we know when to eject ammo.

    # For bullet holes
    bh = xml.find('bullet_holes')
    if bh != None:
      self.bulletHoles = manager.get(bh.get('plugin'))
    else:
      self.bulletHoles = None

  def postInit(self):
    for i in self.postReload():
      yield i

  def postReload(self):
    # Load the actor...
    self.mesh = Actor(self.meshPath)
    yield

    # Shader generator makes it shiny, plus we need it in the right places in the render graph...
    self.mesh.setShaderAuto()
    self.mesh.reparentTo(self.gunView)
    self.mesh.hide()
    yield

    # Set its animation going... except we pause it until needed...
    self.nextAni()
    self.interval.pause()

    # Gun flash requires an exposed bone...
    self.flashBone = self.mesh.exposeJoint(None,"modelRoot",self.flashBone)
    yield


  def gunControl(self,task):
    # Update the gun direction ray to follow the players view...
    self.ray.setPosition(self.gunView.getPos(render))
    self.ray.setQuaternion(self.zToY.multiply(self.gunView.getQuat(render)))

    # If the gun is firing update the trigger time, if a bullet is ejected do the maths...
    if self.firing:
      dt = globalClock.getDt()
      self.triggerTime += dt
      while self.triggerTime>self.bulletRate:
        self.triggerTime -= self.bulletRate
        hit,pos,norm = ray_cast.nearestHit(self.space,self.ray)

        # Create a muzzle flash effect...
        self.flashManager.doEffect(self.flashEffect, self.flashBone, True, self.flashPos)

        if hit:
          # Create an impact sparks effect...
          # Calculate the reflection direction...
          rd = self.ray.getDirection()
          sparkDir = (norm * (2.0*norm.dot(rd))) - rd

          # Convert the reflection direction into a quaternion that will rotate +ve z to the required direction...
          try:
            ang = -math.acos(sparkDir[2])
          except:
            print 'Angle problem', sparkDir
            ang = 0.0
          axis = Vec3(0.0,0.0,1.0).cross(sparkDir)
          axis.normalize()
          sparkQuat = Quat()
          sparkQuat.setFromAxisAngleRad(ang,axis)

          # Set it going...
          self.sparksManager.doEffect(self.sparksEffect, render, False, pos, sparkQuat)

          # Make a bullet hole
          if hit.hasBody() and isinstance(hit.getBody().getData(), NodePath):
            self.bulletHoles.makeNew(pos, norm, hit.getBody().getData())
          else:
            self.bulletHoles.makeNew(pos, norm, None)

        # Impart some energy on the object...
        if hit and hit.hasBody():
          body = hit.getBody()

          # Calculate the force required to supply the energy the bullet contains to the body...
          force = self.bulletWeight*self.bulletSpeed/0.05

          # Get the direction of travel of the bullet, multiply by force...
          d = self.ray.getDirection()
          d *= force

          # If the object is asleep awaken it...
          if not body.isEnabled():
            body.enable()

          # Add the force to the object...
          body.addForceAtPos(d,pos)

    return task.cont


  def start(self):
    # Make the gun visible...
    self.mesh.show()
    
    # Set the gun animation going...
    self.interval.finish()

    # Weapon task - this primarily makes it shoot...
    self.task = taskMgr.add(self.gunControl,'GunControl')


  def stop(self):
    self.interval.pause()
    self.mesh.hide()
    taskMgr.remove(self.task)


  def nextAni(self):
    self.state = self.nextState
    if self.state:
      ani = random.choice(('aim_wiggle_a','aim_wiggle_b','aim_wiggle_c'))
    else:
      ani = random.choice(('casual_wiggle_a','casual_wiggle_b','casual_wiggle_c'))
    self.mesh.pose(ani,0)
    self.interval = Sequence(self.mesh.actorInterval(ani),Func(self.nextAni))
    self.interval.start()


  def setAiming(self,s):
    if self.nextState!=s:
      self.interval.pause()
      self.nextState = s
      self.camera.setZoomed(s)
      
      def wib():
        self.interval.finish()
      
      if s: ani = 'casual_aim'
      else: ani = 'aim_casual'
      transition = Sequence(self.mesh.actorInterval(ani),Func(wib))
      transition.start()


  def setFiring(self,s):
    self.firing = s
    if self.firing:
      self.triggerTime = 0.0
Beispiel #8
0
class Enemy(FSM, Unit):

    # Declare private variables
    _enemyActive = False
    _removeCorpseDelay = 2  # seconds before corpse is cleaned

    def __init__(self, mainRef, attributes):
        print("Enemy instantiated")
        Unit.__init__(self)
        FSM.__init__(self, 'playerFSM')

        self._mainRef = mainRef
        self._playerRef = mainRef.player
        self._AIworldRef = mainRef.AIworld
        self._enemyListRef = mainRef.enemyList
        self._ddaHandlerRef = mainRef.DDAHandler
        self._stateHandlerRef = mainRef.stateHandler
        self._scenarioHandlerRef = mainRef.scenarioHandler

        #self.topEnemyNode = mainRef.mainNode.attachNewNode('topEnemyNode')
        self.initEnemyNode(mainRef.mainNode)

        utils.enemyDictionary[self.enemyNode.getName()] = self

        self.loadEnemyModel(attributes.modelName)
        self.initAttributes(attributes)
        self.initEnemyAi()

        self.initEnemyDDA()

        self.initEnemyCollisionHandlers()
        self.initEnemyCollisionSolids()

        #self.request('Idle')
        self.request('Disabled')

        # Start enemy updater task
        self.enemyUpdaterTask = taskMgr.add(self.enemyUpdater,
                                            'enemyUpdaterTask')

    def initEnemyNode(self, parentNode):
        enemyName = 'enemy' + str(len(self._enemyListRef))
        self.enemyNode = parentNode.attachNewNode(enemyName)
        self._enemyListRef.append(self)

    def loadEnemyModel(self, modelName):
        modelPrefix = 'models/' + modelName
        self.enemyModel = Actor(
            modelPrefix + '-model', {
                'walk': modelPrefix + '-walk',
                'attack': modelPrefix + '-attack',
                'idle': modelPrefix + '-idle',
                'awake': modelPrefix + '-awake',
                'stop': modelPrefix + '-stop',
                'hit': modelPrefix + '-hit',
                'death1': modelPrefix + '-death1',
                'death2': modelPrefix + '-death2'
            })
        self.enemyModel.reparentTo(self.enemyNode)

        self.enemyNode.setPos(Point3.zero())

        self.enemyNode.setDepthOffset(-1)

    def initAttributes(self, attributes):
        perceptionRangeMultiplier = 1.2
        combatRangeMultiplier = .3
        speedMultiplier = .1

        self.strength = attributes.strength
        self.constitution = attributes.constitution
        self.dexterity = attributes.dexterity

        self.mass = attributes.mass
        self.movementSpeed = speedMultiplier * attributes.movementSpeed
        self.perceptionRange = perceptionRangeMultiplier * attributes.perceptionRange
        self.combatRange = combatRangeMultiplier * attributes.combatRange
        self.attackBonus = attributes.attackBonus
        self.damageBonus = attributes.damageBonus
        self.damageRange = attributes.damageRange
        self.initiativeBonus = attributes.initiativeBonus
        self.fixedHealthPoints = attributes.fixedHealthPoints
        self.armorClass = attributes.armorClass

        if attributes.startLevel > 1:
            for i in range(attributes.startLevel - 1):
                self.increaseLevel()

        self.expAward = attributes.expAward

        self.initHealth()

    def initEnemyDDA(self):
        if self._scenarioHandlerRef.getHasDDA():
            maxLevelDifference = self._ddaHandlerRef.maxLevelDifference

            # Level enemy up to player's level minus maxLevelDifference
            levelDifference = self._playerRef.level - self.level
            if levelDifference >= maxLevelDifference:
                for i in range(levelDifference - maxLevelDifference):
                    self.increaseLevel()

    def getAttackBonus(self):
        modifier = self.getStrengthModifier() if self.getStrengthModifier(
        ) > self.getDexterityModifier() else self.getDexterityModifier()
        ab = self.attackBonus + (self.level / 2) + modifier  # + utils.getD20()

        if self._scenarioHandlerRef.getHasDDA():
            attackBonusModifier = self._ddaHandlerRef.attackBonusModifier
            if attackBonusModifier < 0:
                ab -= attackBonusModifier
                if ab < 1:
                    ab = 1

        return ab + utils.getD20()

    def initEnemyAi(self):
        self.enemyAI = AICharacter(
            'enemy',
            self.enemyNode,
            self.mass,  # Mass
            0.1,  # Movt force
            self.movementSpeed)  # Max force
        self._AIworldRef.addAiChar(self.enemyAI)

        self.enemyAIBehaviors = self.enemyAI.getAiBehaviors()
        #self.enemyAIBehaviors.obstacleAvoidance(1.0)

    def initEnemyCollisionHandlers(self):
        self.groundHandler = CollisionHandlerQueue()
        self.collPusher = CollisionHandlerPusher()

    def initEnemyCollisionSolids(self):
        # Enemy ground ray
        groundRay = CollisionRay(0, 0, 2, 0, 0, -1)
        groundColl = CollisionNode('enemyGroundRay')
        groundColl.addSolid(groundRay)

        groundColl.setIntoCollideMask(BitMask32.allOff())
        groundColl.setFromCollideMask(BitMask32.bit(1))

        self.groundRayNode = self.enemyNode.attachNewNode(groundColl)
        #self.groundRayNode.show()

        base.cTrav.addCollider(self.groundRayNode, self.groundHandler)

        # Enemy collision sphere
        collSphereNode = CollisionNode('enemyCollSphere')
        collSphere = CollisionSphere(0, 0, 0.1, 0.2)
        collSphereNode.addSolid(collSphere)

        collSphereNode.setIntoCollideMask(BitMask32.allOff())
        collSphereNode.setFromCollideMask(BitMask32.bit(2))

        self.sphereNode = self.enemyNode.attachNewNode(collSphereNode)
        #sphereNode.show()

        base.cTrav.addCollider(self.sphereNode, self.collPusher)
        self.collPusher.addCollider(self.sphereNode, self.enemyNode)

        # Enemy picker collision sphere
        pickerSphereCollNode = CollisionNode(self.enemyNode.getName())
        pickerCollSphere = CollisionSphere(0, 0, 0, 0.5)
        pickerSphereCollNode.addSolid(pickerCollSphere)

        pickerSphereCollNode.setFromCollideMask(BitMask32.allOff())
        pickerSphereCollNode.setIntoCollideMask(BitMask32.bit(1))

        self.pickerNode = self.enemyNode.attachNewNode(pickerSphereCollNode)
        #sphereNodePath.show()

        # Enemy attack collision sphere
        attackCollSphereNode = CollisionNode(self.enemyNode.getName() +
                                             'atkSph')
        attackCollSphere = CollisionSphere(0, 0, 0.1, 0.15)
        attackCollSphereNode.addSolid(attackCollSphere)

        attackCollSphereNode.setIntoCollideMask(BitMask32.bit(3))
        attackCollSphereNode.setFromCollideMask(BitMask32.allOff())

        attackSphereNode = self.enemyNode.attachNewNode(attackCollSphereNode)
        #attackSphereNode.show()

    def slowMovementByPercentage(self, percentage=30, slowDuration=20):
        #print self.enemyNode.getName(), ' slowed by ', percentage, ' %'
        oldSpeed = self.movementSpeed
        newSpeed = ((100.0 - percentage) / 100.0) * oldSpeed

        if newSpeed < 1.0:
            newSpeed = 1.0

        self.movementSpeed = newSpeed

        taskMgr.doMethodLater(slowDuration,
                              self.removeSlowMovement,
                              'removeSlowMovementTask',
                              extraArgs=[oldSpeed],
                              appendTask=True)

    def removeSlowMovement(self, oldSpeed, task):
        self.movementSpeed = oldSpeed
        return task.done

    def checkGroundCollisions(self):
        if self.groundHandler.getNumEntries() > 0:
            self.groundHandler.sortEntries()
            entries = []
            for i in range(self.groundHandler.getNumEntries()):
                entry = self.groundHandler.getEntry(i)
                #print('entry:', entry)
                entries.append(entry)

            entries.sort(lambda x, y: cmp(
                y.getSurfacePoint(render).getZ(),
                x.getSurfacePoint(render).getZ()))

            for i in range(len(entries)):
                if entries[i].getIntoNode().getName()[:6] == 'ground':
                    #print('entryFound:', entries[0])
                    newZ = entries[i].getSurfacePoint(base.render).getZ()
                    self.enemyNode.setZ(newZ)
                    #print('enemyZ:', newZ)
                    break

    def enemyUpdater(self, task):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY or not self._enemyActive:
            self.enemyModel.stop()
            # Do not do anything when paused
            return task.cont

        self.checkGroundCollisions()

        if self.getIsDead():
            self.onDeath()
            return task.done

        if self._playerRef.getIsDead():
            return task.cont

        playerPos = self._playerRef.playerNode.getPos()
        enemyPos = self.enemyNode.getPos()

        # If player is within enemy perception range
        if utils.getIsInRange(playerPos, enemyPos, self.perceptionRange):

            # If enemy is not doing anything
            if self.state == 'Idle':
                # Start pursuing
                if self.state != 'Pursue':
                    self.request('Pursue')

            # If enemy is already pursueing
            elif self.state == 'Pursue':
                # If player is within combat range
                if utils.getIsInRange(playerPos, enemyPos, self.combatRange):
                    #print 'enemy go to combat'
                    # Go to combat
                    if self.state != 'Combat':
                        self.request('Combat')

            # If enemy is already in combat
            elif self.state == 'Combat':
                # If player has moved out of combat range
                if not utils.getIsInRange(playerPos, enemyPos,
                                          self.combatRange):
                    # Start pursuing
                    if self.state != 'Pursue':
                        self.request('Pursue')

            # If enemy is disabled
            elif self.state == 'Disabled':
                if self.enemyAI.getMaxForce() != self.movementSpeed:
                    self.enemyAI.setMaxForce(self.movementSpeed)

        # If player is not within perception range
        else:
            if self.state != 'Idle':
                self.request('Idle')

        return task.cont

    def pursuePlayer(self):
        taskMgr.add(self.pursue, 'pursueTask')

    def pursue(self, task):
        if self.state == 'Pursue' and not self.getIsDead():
            pitchRoll = self.enemyNode.getP(), self.enemyNode.getR()
            self.enemyNode.headsUp(self._playerRef.playerNode)
            self.enemyNode.setHpr(self.enemyNode.getH() - 180, *pitchRoll)

            speed = -self.movementSpeed * globalClock.getDt()
            self.enemyNode.setFluidPos(self.enemyNode, 0, speed, 0)

            return task.cont
        else:
            task.done

    def enterIdle(self):
        #print 'enemy enterIdle'
        stopEnemy = self.enemyModel.actorInterval('stop', loop=0)
        idleEnemy = self.enemyModel.actorInterval('idle',
                                                  startFrame=0,
                                                  endFrame=1,
                                                  loop=0)

        self.stopSequence = Sequence(stopEnemy, idleEnemy)
        self.stopSequence.start()

        self.isSleeping = True

    def exitIdle(self):
        #print('enemy exitIdle')
        self.stopSequence.finish()

    def enterPursue(self):
        #print('enemy enterPursue')
        loopWalkEnemy = Func(self.enemyModel.loop,
                             'walk',
                             fromFrame=0,
                             toFrame=12)

        # Only awake enemy if it comes from idle
        if self.isSleeping:
            self.isSleeping = False

            awakeEnemy = self.enemyModel.actorInterval('awake', loop=0)
            self.awakeSequence = Sequence(awakeEnemy, loopWalkEnemy,
                                          Func(self.pursuePlayer))
        else:
            self.awakeSequence = Sequence(loopWalkEnemy,
                                          Func(self.pursuePlayer))

        self.awakeSequence.start()

    def exitPursue(self):
        #print('enemy exitPursue')
        self.awakeSequence.finish()

    def enterCombat(self):
        #print('enemy enterCombat')
        self.enemyModel.stop()

        attackDelay = self.getInitiativeRoll()
        self.attackTask = taskMgr.doMethodLater(attackDelay, self.attackPlayer,
                                                'attackPlayerTask')

    def enterDisabled(self):
        #print 'enterDisable'
        pass

    def exitDisabled(self):
        #print 'exitDisable'
        pass

    def exitCombat(self):
        #print('enemy exitCombat')
        taskMgr.remove(self.attackTask)

    def enterDeath(self):
        #print('enemy enterDeath')
        self.enemyAIBehaviors.removeAi('all')
        randomDeathAnim = 'death' + str(utils.getD2())
        self.enemyModel.play(randomDeathAnim)

    def attack(self, other):
        if not self.getIsDead() and not other.getIsDead():
            if self.getAttackBonus() >= other.getArmorClass():
                dmg = self.getDamageBonus()
                #print(self.getName(), ' damaged ', other.getName(), ' for ', dmg, ' damage')
                other.receiveDamage(dmg)

                return 2  # Returns 2 when self damages other

            return 1  # Returns 1 when self attacks other, but misses

        return 0  # Returns 0 when either self or other is dead

    def attackPlayer(self, task):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY or not self._enemyActive:
            # Do not do anything when paused
            return task.again

        if self._playerRef.getIsDead():
            print('player is already dead')
            self.request('Idle')
            return task.done

        elif self.getIsDead():
            return task.done

        else:
            #print('Attack player!')
            # Make sure enemy is facing player when attacking
            pitchRoll = self.enemyNode.getP(), self.enemyNode.getR()
            self.enemyNode.headsUp(self._playerRef.playerNode)
            self.enemyNode.setHpr(self.enemyNode.getH() - 180, *pitchRoll)

            attacked = self.attack(self._playerRef)
            if attacked != 0:
                self.playAttackAnimation()
                if attacked == 2:
                    self._playerRef.playerModel.play('hit')

            return task.again

    def playAttackAnimation(self):
        self.enemyModel.play('attack', fromFrame=0, toFrame=12)

    def playHitAnimation(self):
        self.enemyModel.play('hit')

    def moveEnemy(self, x, y):
        self.enemyNode.setPos(x, y, .01)

    def handleHealthGlobe(self):
        global dropChanceFactor
        global dropChance
        global maxDropChance

        # if we drop, create health goblet
        chance = dropChanceFactor + dropChance
        if self._scenarioHandlerRef.getHasDDA():
            chance *= self._ddaHandlerRef.healthGobletModifier

        if utils.getD100() <= chance:
            HealthGoblet(self._mainRef, self)
            print 'dropping health goblet'
        # Otherwise, increase dropChance
        else:
            if dropChance + dropChanceFactor <= maxDropChance:
                dropChance += dropChanceFactor

    def suicide(self):
        print('suicide: ', self)
        # Remove AI behavior
        self.enemyAIBehaviors.removeAi('all')

        # Remove enemy picker sphere (handlerQueue)
        self.pickerNode.removeNode()

        taskMgr.add(self.removeCorpse, 'removeCorpseTask')

    def onDeath(self):
        if self.getIsDead():
            # Remove AI behavior
            self.enemyAIBehaviors.removeAi('all')

            # Award the player exp
            self._playerRef.receiveEXP(self.expAward)

            # Remove enemy picker sphere (handlerQueue)
            self.pickerNode.removeNode()

            # Change state
            self.request('Death')

            # Increase DDA death count
            if self._scenarioHandlerRef.getHasDDA():
                self._ddaHandlerRef.enemyDeathCount += 1

            # Handle health globe
            self.handleHealthGlobe()

            # Remove enemy corpse and clean up
            taskMgr.doMethodLater(self._removeCorpseDelay, self.removeCorpse,
                                  'removeCorpseTask')

    def removeCorpse(self, task):
        # Remove enemy collision sphere (pusher)
        self.sphereNode.removeNode()

        # Stop the collision pusher
        self.collPusher = None

        # Remove enemy from enemyList
        self._enemyListRef.remove(self)

        # Cleanup the enemy model
        self.enemyModel.cleanup()
        self.enemyModel.delete()

        # Cleanup FSM
        self.cleanup()

        # Remove the enemy node
        self.enemyNode.removeNode()
        #self.topEnemyNode.removeNode()

        # Remove enemy updater tasks
        taskMgr.remove(self.enemyUpdaterTask)

        # Remove the passive regeneration task (from Unit class)
        self.removePassiveRegeneration()

        # Remove references
        self._mainRef = None
        self._playerRef = None
        self._AIworldRef = None
        self._enemyListRef = None
        self._stateHandlerRef = None

        return task.done
Beispiel #9
0
class ArmorPlate:
    """An active shield locomotive upgrade.

    Represents an active defense upgrade - plate, which can
    cover one of the locomotive sides: left, right, top.

    Args:
        loc_model (panda3d.core.NodePath):
            The locomotive model - parent for the plate.
    """

    def __init__(self, loc_model):
        self._is_on_move = False
        self.cur_position = "top"

        self._snd = base.sound_mgr.loadSfx(  # noqa: F821
            "sounds/train/armor_plate_move.ogg"
        )
        base.sound_mgr.attachSoundToObject(self._snd, loc_model)  # noqa: F821

        self._model = Actor(address("armor_plate"))
        self._model.reparentTo(loc_model)

        self._right_to_left = Sequence(
            Parallel(
                self._model.actorInterval("right", playRate=-2.5),
                SoundInterval(self._snd),
            ),
            Parallel(
                self._model.actorInterval("left", playRate=2.5),
                SoundInterval(self._snd),
            ),
        )
        self._left_to_right = Sequence(
            Parallel(
                self._model.actorInterval("left", playRate=-2.5),
                SoundInterval(self._snd),
            ),
            Parallel(
                self._model.actorInterval("right", playRate=2.5),
                SoundInterval(self._snd),
            ),
        )
        base.accept("4", self._turn_left)  # noqa: F821
        base.accept("5", self._turn_top)  # noqa: F821
        base.accept("6", self._turn_right)  # noqa: F821

    def _cover_side(self, side):
        """Actually change the plate position.

        Args:
            side (str):
                Side of the locomotive, which is now covered by the plate.
        """
        self.cur_position = side

    def _stop_move(self, task):
        """Release the plate moving block."""
        self._is_on_move = False
        return task.done

    def _turn_left(self):
        """Cover the left side of the locomotive with the plate."""
        if self.cur_position == "left" or self._is_on_move:
            return

        if self.cur_position == "top":
            self._model.actorInterval("left", playRate=2.5).start()
            delay = 0.9
            cover_delay = 0.45
            self._snd.play()
        else:
            self._right_to_left.start()
            delay = 1.8
            cover_delay = 1.35

        self._is_on_move = True
        taskMgr.doMethodLater(delay, self._stop_move, "stop_move_plate")  # noqa: F821
        taskMgr.doMethodLater(  # noqa: F821
            cover_delay, self._cover_side, "cover_side", extraArgs=["left"]
        )
        taskMgr.doMethodLater(  # noqa: F821
            cover_delay,
            base.train.cover_part,  # noqa: F821
            "cover_part",
            extraArgs=["part_left"],
        )
        taskMgr.doMethodLater(  # noqa: F821
            0.5,
            base.train.uncover_part,  # noqa: F821
            "uncover_part",
            extraArgs=[self.cur_position],
        )

    def _turn_right(self):
        """Cover the right side of the locomotive with the plate."""
        if self.cur_position == "right" or self._is_on_move:
            return

        if self.cur_position == "top":
            self._model.actorInterval("right", playRate=2.5).start()
            delay = 0.9
            cover_delay = 0.45
            self._snd.play()
        else:
            self._left_to_right.start()
            delay = 1.8
            cover_delay = 1.35

        self._is_on_move = True
        taskMgr.doMethodLater(delay, self._stop_move, "stop_move_plate")  # noqa: F821
        taskMgr.doMethodLater(  # noqa: F821
            cover_delay, self._cover_side, "cover_side", extraArgs=["right"]
        )
        taskMgr.doMethodLater(  # noqa: F821
            cover_delay,
            base.train.cover_part,  # noqa: F821
            "cover_part",
            extraArgs=["part_right"],
        )
        taskMgr.doMethodLater(  # noqa: F821
            0.5,
            base.train.uncover_part,  # noqa: F821
            "uncover_part",
            extraArgs=[self.cur_position],
        )

    def _turn_top(self):
        """Cover the top side of the Train with the plate."""
        if self.cur_position == "top" or self._is_on_move:
            return

        if self.cur_position == "left":
            self._snd.play()
            self._model.actorInterval("left", playRate=-2.5).start()
        elif self.cur_position == "right":
            self._snd.play()
            self._model.actorInterval("right", playRate=-2.5).start()

        self._is_on_move = True
        taskMgr.doMethodLater(0.9, self._stop_move, "stop_move_plate")  # noqa: F821
        taskMgr.doMethodLater(  # noqa: F821
            0.45, self._cover_side, "cover_side", extraArgs=["top"]
        )
        taskMgr.doMethodLater(  # noqa: F821
            0.5,
            base.train.uncover_part,  # noqa: F821
            "uncover_part",
            extraArgs=[self.cur_position],
        )
Beispiel #10
0
class ToontownCentral(DirectObject):
    def __init__(self):
        self.scene = render.getPythonTag('SceneManager').createScene("TTC")
        self.build()

    def build(self):
        self.skybox = loader.loadModel("phase_3.5/models/props/TT_sky.bam")
        self.skybox.set_depth_write(False)
        self.skybox.find("**/Sky").setBin("background", 0)
        self.skybox.find('**/cloud1').setBin("background", 3)
        self.skybox.find('**/cloud2').setBin("background", 5)
        self.skybox.reparentTo(render)
        self.environ = loader.loadModel('ttc.bam')

    def __animateEnv(self):
        TTC = self.environ
        toonHall = TTC.find('**/sz13:toon_landmark_TT_toonhall_DNARoot')
        render.setPythonTag(
            "ToonHall",
            ToonHall(toonHall, toonHall.find('**/door_double_round_ur')))
        phase_4 = 'phase_4/models/props/'
        self.fish = TTC.find(
            '**/animated_prop_PetShopFishAnimatedProp_DNARoot')
        self.fish.removeNode()
        self.fish = Actor(phase_4 + 'exteriorfish-zero.bam',
                          {'anim': phase_4 + 'exteriorfish-swim.bam'})
        self.fish.reparentTo(
            TTC.find('**/sz22:toon_landmark_TT_pet_shop_DNARoot'))
        self.fish.loop('anim')
        self.periscope = Actor(
            TTC.find('**/animated_prop_HQPeriscopeAnimatedProp_DNARoot'),
            copy=0)
        self.periscope.reparentTo(render)
        self.periscope.loadAnims(
            {'anim': 'phase_3.5/models/props/HQ_periscope-chan.bam'})
        self.periscope.pose('anim', 0)
        self.periscopeTrack = Sequence(
            Wait(2.0),
            self.periscope.actorInterval('anim', startFrame=0, endFrame=40),
            Wait(0.7),
            self.periscope.actorInterval('anim', startFrame=40, endFrame=90),
            Wait(0.7),
            self.periscope.actorInterval('anim', startFrame=91, endFrame=121),
            Wait(0.7),
            self.periscope.actorInterval('anim', startFrame=121, endFrame=91),
            Wait(0.7),
            self.periscope.actorInterval('anim', startFrame=90, endFrame=40),
            Wait(0.7),
            self.periscope.actorInterval('anim', startFrame=40, endFrame=90),
            Wait(0.7),
            self.periscope.actorInterval('anim', startFrame=91, endFrame=121),
            Wait(0.5),
            self.periscope.actorInterval('anim', startFrame=121, endFrame=148),
            Wait(3.0))
        self.periscopeTrack.loop()
        self.telescope = Actor(
            TTC.find('**/animated_prop_HQTelescopeAnimatedProp_DNARoot'),
            copy=0)
        self.telescope.reparentTo(render)
        self.telescope.loadAnims(
            {'anim': 'phase_3.5/models/props/HQ_telescope-chan.bam'})
        self.telescope.pose('anim', 0)
        self.telescopeTrack = Sequence(
            Wait(5.0),
            self.telescope.actorInterval('anim', startFrame=0, endFrame=32),
            Wait(0.5),
            self.telescope.actorInterval('anim', startFrame=32, endFrame=78),
            Wait(0.5),
            self.telescope.actorInterval('anim', startFrame=79, endFrame=112),
            Wait(0.5),
            self.telescope.actorInterval('anim', startFrame=112, endFrame=79),
            Wait(0.5),
            self.telescope.actorInterval('anim', startFrame=78, endFrame=32),
            Wait(0.5),
            self.telescope.actorInterval('anim', startFrame=32, endFrame=78),
            Wait(0.5),
            self.telescope.actorInterval('anim', startFrame=79, endFrame=112),
            Wait(0.5),
            self.telescope.actorInterval('anim', startFrame=112, endFrame=148),
            Wait(4.0))
        self.telescopeTrack.loop()
        #base.taskMgr.add(self.__moveClouds, "Move Clouds")
        self.__fixTrashcans()
        self.environ.flattenStrong()
        self.scene.addModel(self.environ)
        render.find('**/TTC').setPythonTag('Class', self)

    def __fixTrashcans(self):
        TTC = self.environ
        trashcans = TTC.findAllMatches('**/prop_trashcan_metal_DNARoot')
        for trashcan in trashcans:
            pos = trashcan.getPos()
            hpr = trashcan.getHpr()
            trashcan.removeNode()
            new_trashcan = loader.loadModel(
                'phase_5/models/props/trashcan_TT.bam')
            new_trashcan.setPos(pos)
            new_trashcan.setHpr(hpr)
            new_trashcan.reparentTo(TTC)

    def __moveClouds(self, task):
        model = self.skybox
        model.find("**/cloud1").setHpr(task.time * 0.3, 0, 0)
        model.find("**/cloud2").setHpr(task.time * -0.3, 0, 0)
        return Task.cont

    def doFade(self):
        TTC = render.find('**/TTC')
        skyFade = self.skybox.colorScaleInterval(4,
                                                 Vec4(0.1, 0.1, 0.1, 1),
                                                 startColorScale=Vec4(
                                                     1, 1, 1, 1),
                                                 blendType='easeInOut')
        TTCFade = TTC.colorScaleInterval(3.8,
                                         Vec4(0.2509803921568627,
                                              0.2509803921568627,
                                              0.2509803921568627, 1),
                                         startColorScale=Vec4(1, 1, 1, 1),
                                         blendType='easeInOut')
        skyFade.start()
        TTCFade.start()

    def loadScene(self):
        self.scene.loadScene()
        self.__animateEnv()

    def unloadScene(self):
        base.taskMgr.remove("Move Clouds")
        self.scene.delete()
Beispiel #11
0
class Player(FSM, Unit):

    # Declare private variables
    _cameraYModifier = -6 # Relative to player Y position
    _cameraZModifier = 4.5 # Relative to player Z position

    _currentTarget = None

#------------------- CONSTRUCTOR ----------------------#
    def __init__(self, mainRef):
        print("Player instantiated")
        Unit.__init__(self)
        FSM.__init__(self, 'playerFSM')

        self._hudRef = None
        self._mainRef = mainRef
        self._enemyListRef = mainRef.enemyList
        self._ddaHandlerRef = mainRef.DDAHandler
        self._mapHandlerRef = mainRef.mapHandler
        self._stateHandlerRef = mainRef.stateHandler
        self._scenarioHandlerRef = mainRef.scenarioHandler

        self.playerNode = mainRef.mainNode.attachNewNode('playerNode')

        self.initPlayerAttributes()
        self.initPlayerModel()
        self.initPlayerCamera()
        self.initPlayerAbilities()

        self.initPlayerCollisionHandlers()
        self.initPlayerCollisionSolids()

        self.initPlayerDDA()

        # Start mouse picking and movement
        self.mouseHandler = utils.MouseHandler(self)

        # Start player update task
        playerUpdateTask = taskMgr.add(self.playerUpdate, 'playerUpdateTask')

        # Initialize player FSM state
        self.request('Idle')

        DO = DirectObject()
        DO.accept('shift-mouse1', self.onShiftDown)
        DO.accept('shift-up', self.onShiftUp)

        self._shiftButtonDown = False

    def onShiftDown(self):
        self._shiftButtonDown = True

        attackDelay = self.getInitiativeRoll()
        taskMgr.doMethodLater(attackDelay, self.shiftAttack, 'shiftAttackTask')

    def onShiftUp(self):
        self._shiftButtonDown = False

        taskMgr.remove('shiftAttackTask')

#----------------------------- INITIALIZATION ---------------------------------#
    def initPlayerAttributes(self):
        # Initialize player attributes
        self.strength = 16
        self.constitution = 14
        self.dexterity = 10

        self.combatRange = 0.75 # Melee
        self.movementSpeed = 1 # ?
        self.attackBonus = 6 # ?
        self.damageBonus = 0 # ?
        self.damageRange = 8 # = Longsword
        self.initiativeBonus = 1 # ?
        self.armorClass = 10 + 8 # Base armor class + fullplate armor
        self.mass = 90

        self.startLevel = 3

        for i in range(1, self.startLevel):
            self.increaseLevel()

        self.initHealth()

        # Used by area transition system
        self.areaTransitioning = False

    def initPlayerModel(self):
        # Initialize the player model (Actor)
        modelPrefix = 'models/player-'
        self.playerModel = Actor(modelPrefix + 'model', {
            'run':modelPrefix+'run',
            'attack':modelPrefix+'attack',
            'stop':modelPrefix+'stop',
            'hit':modelPrefix+'hit',
            'defense':modelPrefix+'defense',
            'death':modelPrefix+'death',
            'idle':modelPrefix+'idle',
            'bull-rush':modelPrefix+'bull-rush',
            'thicket-blades':modelPrefix+'thicket-blades',
            'level-up':modelPrefix+'level-up'
            })

        self.playerModel.reparentTo(self.playerNode)

        # Make sure that visible geometry does not collide
        self.playerModel.setCollideMask(BitMask32.allOff())
        # Model is backwards, fix by changing the heading
        self.playerModel.setH(180)

    def initPlayerCamera(self): 
        # Initialize the camera
        base.disableMouse()

        base.camera.setPos(self.playerNode, (0, self._cameraYModifier, self._cameraZModifier))
        base.camera.lookAt(self.playerNode)

        self.stopCamera = False

    def initStartPosition(self, playerStartPos, playerExitPos):
        self.exitPos = playerExitPos
        self.startPos = playerStartPos

        self.initPlayerMovement()

    def initPlayerMovement(self):
        # Make sure the player starts at the starting position
        self.playerNode.setPos(self.startPos)
        self.destination = Point3(self.startPos)
        self.velocity = Vec3.zero()

        self.playerNode.headsUp(self.exitPos)

    def initPlayerAbilities(self):
        DO = DirectObject()
        DO.accept('1', self.fireAbility, [1])
        DO.accept('2', self.fireAbility, [2])
        DO.accept('3', self.fireAbility, [3])
        DO.accept('4', self.fireAbility, [4])

        self.abilityDict = {'offensive':1, 'defensive':1, 'evasive':1, 'area':1}

    def initPlayerDDA(self):
        if self._scenarioHandlerRef.getHasDDA():
            self.damageHistory = []
            self.healthHistory = []
            self.deathHistory = []

            self.damageReceived = 0
            self.deathCount = 0

            self._ddaHandlerRef.initPlayerDDA(self)

            ddaMonitorTask = taskMgr.doMethodLater(1, self.ddaMonitor, 'ddaMonitorTask')
            ddaMonitorTask.count = 0

#-------------------- COLLISION INITIALIZATION ---------------------------#
    def initPlayerCollisionHandlers(self):
        self.groundHandler = CollisionHandlerQueue()
        self.collPusher = CollisionHandlerPusher()
        self.attackCollisionHandler = CollisionHandlerQueue()
        self.cameraGroundHandler = CollisionHandlerQueue()

    def initPlayerCollisionSolids(self):
        # Player ground ray #
        groundRay = CollisionRay(0, 0, 1, 0, 0, -1)
        groundColl = CollisionNode('playerGroundRay')

        groundColl.addSolid(groundRay)
        groundColl.setIntoCollideMask(BitMask32.allOff())
        groundColl.setFromCollideMask(BitMask32.bit(1))
        self.groundRayNode = self.playerNode.attachNewNode(groundColl)
        #self.groundRayNode.show()

        base.cTrav.addCollider(self.groundRayNode, self.groundHandler)

        # Player collision sphere #
        collSphereNode = CollisionNode('playerCollSphere')

        collSphere = CollisionSphere(0, 0, 0.1, 0.2)
        collSphereNode.addSolid(collSphere)

        #collSphereNode.setCollideMask(BitMask32.bit(2))
        collSphereNode.setIntoCollideMask(BitMask32.allOff())
        collSphereNode.setFromCollideMask(BitMask32.bit(2))
        
        sphereNode = self.playerNode.attachNewNode(collSphereNode)
        #sphereNode.show()

        base.cTrav.addCollider(sphereNode, self.collPusher)
        self.collPusher.addCollider(sphereNode, self.playerNode)

        # Player attack collision sphere # 
        attackCollSphereNode = CollisionNode('playerAttackCollSphere')

        attackCollSphere = CollisionSphere(0, 0.3, 0.1, 0.2)
        attackCollSphereNode.addSolid(attackCollSphere)

        attackCollSphereNode.setIntoCollideMask(BitMask32.allOff())
        attackCollSphereNode.setFromCollideMask(BitMask32.bit(3))

        attackSphereNode = self.playerNode.attachNewNode(attackCollSphereNode)
        #attackSphereNode.show()

        base.cTrav.addCollider(attackSphereNode, self.attackCollisionHandler)

#---------------------------- EXPERIENCE ----------------------------------------#
    def getEXPToNextLevel(self):
        return self._prevEXP + (self.level * 1000)

    def receiveEXP(self, value):
        expGain = value * self._ddaHandlerRef.EXPFactor
        self.experience += expGain
        self._hudRef.printFeedback('Experience gained: ' + str(int(expGain)), False)

        if self.experience >= self.getEXPToNextLevel():
            self.increaseLevel()
            self._hudRef.printFeedback('Level gained!', False)
            self.playerModel.play('level-up', fromFrame=0, toFrame=25)

    def getEXPToNextLevelInPercentage(self):
        currentEXP = self.experience - self._prevEXP
        expToNextLevel = self.level * 1000.0

        result = int(currentEXP / expToNextLevel * 100.0)

        return result

#-------------------------- PLAYER MOVEMENT -------------------------------------#
    def setPlayerDestination(self, destination):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY:
            # Do not do anything when paused
            return 

        if self.getIsDead():
            return

        pitchRoll = self.playerNode.getP(), self.playerNode.getR()
        self.playerNode.headsUp(destination)
        self.playerNode.setHpr(self.playerNode.getH(), *pitchRoll)

        distance = abs(self.playerNode.getX() - destination.getX()) + abs(self.playerNode.getY() - destination.getY())
        if distance > .5:
            self.destination = destination
            self.velocity = self.destination - self.playerNode.getPos()

            self.velocity.normalize()
            self.velocity *= self.movementSpeed

#-------------------- PLAYER TARGET ------------------------------------#
    def setCurrentTarget(self, target):
        self._currentTarget = target

    def getCurrentTarget(self):
        return self._currentTarget

    def removeCurrentTarget(self):
        self.setCurrentTarget(None)

#-------------------- PLAYER ABILITIES ----------------------------------#
    def startCooldown(self, ability, cooldown, task):
        task.count += 1

        if task.count >= cooldown:
            self.abilityDict[ability] = 1
            if ability == 'offensive':
                self._hudRef.activateIcon(1)
            elif ability == 'defensive':
                self._hudRef.activateIcon(2)
            elif ability == 'evasive':
                self._hudRef.activateIcon(3)
            elif ability == 'area':
                self._hudRef.activateIcon(4)
            return task.done
        else:
            return task.again

    def fireAbility(self, ability):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY:
            # Do not do anything when paused
            return 

        self.playerModel.stop()

        # Offensive ability - Bull Rush 10 sec cd
        if ability == 1:
            off = 'offensive'
            if self.abilityDict[off] == 1:
                if self.bullRush():
                    self.abilityDict[off] = 0
                    cd = taskMgr.doMethodLater(1, self.startCooldown, 'startCooldownTask', extraArgs=[off, 10], appendTask=True)
                    cd.count = 0

                    self._hudRef.deactivateIcon(1)
                    self.playerModel.play('bull-rush', fromFrame=0, toFrame=25)
            else:
                #print 'Bull Rush in cd'
                self._hudRef.printFeedback('Bull Rush is in cooldown')

        # Defensive - Unstoppable 10 sec cd
        elif ability == 2:
            defe = 'defensive'
            if self.abilityDict[defe] == 1:
                if self.unstoppable():
                    self.abilityDict[defe] = 0
                    cd = taskMgr.doMethodLater(1, self.startCooldown, 'startCooldownTask', extraArgs=[defe, 10], appendTask=True)
                    cd.count = 0

                    self._hudRef.deactivateIcon(2)
                    self.playerModel.play('defense', fromFrame=0, toFrame=12)
            else:
                #print 'Unstoppable in cd'
                self._hudRef.printFeedback('Unstoppable is in cooldown')

        # Evasive - Thicket of Blades 20 sec cd
        elif ability == 3:
            eva = 'evasive'
            if self.abilityDict[eva] == 1:
                if self.thicketOfBlades():
                    self.abilityDict[eva] = 0
                    cd = taskMgr.doMethodLater(1, self.startCooldown, 'startCooldownTask', extraArgs=[eva, 20], appendTask=True)
                    cd.count = 0

                    self._hudRef.deactivateIcon(3)
                    self.playerModel.play('thicket-blades', fromFrame=0, toFrame=27)
            else:
                #print 'Thicket of Blades in cd'
                self._hudRef.printFeedback('Thicket of Blades is in cooldown')

        # Area of Effect - Shift the Battlefield 30 sec cd
        elif ability == 4:
            aoe = 'area'
            if self.abilityDict[aoe] == 1:
                if self.shiftTheBattlefield():
                    self.abilityDict[aoe] = 0
                    cd = taskMgr.doMethodLater(1, self.startCooldown, 'startCooldownTask', extraArgs=[aoe, 30], appendTask=True)
                    cd.count = 0

                    self._hudRef.deactivateIcon(4)
            else:
                #print 'Shift the Battlefield in cd'
                self._hudRef.printFeedback('Shift the Battlefield is in cooldown')

    def bullRush(self):
        bSuccess = False

        enemy = self.getCurrentTarget()
        if enemy is not None and not enemy.getIsDead():
            if self.state == 'Combat':
                node = enemy.enemyNode
                print 'Bull rush:', node
                bSuccess = True

                if self.getStrengthModifier() + utils.getD20() > enemy.armorClass:
                    self._hudRef.printFeedback('Bull Rush hit', True)
                    self.enemyFleeFromPlayer(enemy)

                    self.playerModel.play('attack')
                    enemy.playHitAnimation()
                else:
                    #print 'bullRush missed'
                    self._hudRef.printFeedback('Bull Rush missed')

        return bSuccess

    def unstoppable(self):
        tempHp = utils.getD6() + utils.getD6() + self.getConstitutionModifier()
        self.receiveTemporaryHealth(tempHp)
        print 'unstoppable:', tempHp

        taskMgr.doMethodLater(1.5, self.stopDefenseAnimation, 'stopDefenseAnimationTask')

        self._hudRef.printFeedback('Unstoppable activated', False)

        duration = 30.0 # Half a minute (30 seconds) duration of temp hp
        taskMgr.doMethodLater(duration, self.removeTempHp, 'removeTempHpTask')

        return True

    def stopDefenseAnimation(self, task):
        #print('stop defense animation')
        self.playerModel.loop('idle')

        return task.done

    def removeTempHp(self, task):
        print 'removeTempHp'
        self.removeTemporaryHealth()
        return task.done

    def thicketOfBlades(self):
        bSuccess = False

        numEntries = self.attackCollisionHandler.getNumEntries()
        if numEntries > 0:
            self.attackCollisionHandler.sortEntries()

            for i in range(numEntries):
                entry = self.attackCollisionHandler.getEntry(i).getIntoNode()
                entryName = entry.getName()[:-6]
                #print('entryFound:', entryName)

                enemy = utils.enemyDictionary[entryName]
                if enemy is not None and not enemy.getIsDead():
                    if utils.getIsInRange(self.playerNode.getPos(), enemy.enemyNode.getPos(), self.combatRange):
                        bSuccess  = True
                        if self.getStrengthModifier() + utils.getD20() > enemy.armorClass:
                            self._hudRef.printFeedback('Thicket of Blades hit', True)
                            enemy.slowMovementByPercentage(50, 10) # slow by 50 % in 10 seconds, automatically removes it again
                            enemy.enemyModel.play('hit')
                        else:
                            #print 'thicketOfBlades missed'
                            self._hudRef.printFeedback('Thicket of Blades missed')

        return bSuccess

    def shiftTheBattlefield(self):
        bSuccess = False

        playerPos = self.playerNode.getPos()
        for enemy in self._enemyListRef:
            enemyPos = enemy.enemyNode.getPos()
            if utils.getIsInRange(playerPos, enemyPos, self.combatRange):
                bSuccess = True
                if self.getStrengthModifier() + utils.getD20() > enemy.armorClass:
                    self._hudRef.printFeedback('Shift the Battlefield hit', True)
                    self.enemyFleeFromPlayer(enemy)
    
                    # Might want to replace the getD8 to depend on the player's weapon
                    dmg = 2 * utils.getD8() + self.getStrengthModifier()
                    enemy.receiveDamage(dmg)

                    enemy.enemyModel.play('hit')
                else:
                    #print 'shiftTheBattlefield missed'
                    self._hudRef.printFeedback('Shift the Battlefield missed')
                    dmg = (2 * utils.getD8() + self.getStrengthModifier()) / 2
                    enemy.receiveDamage(dmg)

                    enemy.enemyModel.play('hit')

        return bSuccess

    def enemyFleeFromPlayer(self, enemy):
        if enemy.state != 'Disabled':
            #print 'enemyFleeFromPlayer:', enemy
            enemy.enemyAIBehaviors.removeAi('all')
            enemy.enemyAIBehaviors.flee(self.playerNode)

            enemy.enemyModel.loop('walk', fromFrame=0, toFrame=12)
            enemy.request('Disabled')

            taskMgr.doMethodLater(1.5, self.removeEnemyFlee, 'removeEnemyFleeTask', extraArgs=[enemy], appendTask=True)

    def removeEnemyFlee(self, enemy, task):
        if enemy.state == 'Disabled':
            #print 'removeEnemyFlee'
            enemy.enemyModel.stop()
            enemy.enemyAIBehaviors.removeAi('flee')
            enemy.request('Idle')
        return task.done

#------------------ UPDATE FUNCTIONS ---------------------------------#
    def checkGroundCollisions(self):
        numEntries = self.groundHandler.getNumEntries()
        if numEntries > 0:
            self.groundHandler.sortEntries()
            entries = []
            for i in range(numEntries):
                entry = self.groundHandler.getEntry(i)
                entries.append(entry)

            entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                         x.getSurfacePoint(render).getZ()))

            for i in range(numEntries):
                entry = entries[i]
                if entry.getIntoNode().getName()[:6] == 'ground':
                    newZ = entry.getSurfacePoint(base.render).getZ()
                    self.playerNode.setZ(newZ)
                    break;

    def updateCameraPosition(self):
        pos = self.playerNode.getPos()
        base.camera.setPos(pos.getX(), pos.getY() + self._cameraYModifier, pos.getZ() + self._cameraZModifier)

    def updatePlayerPosition(self, deltaTime):
        if not self._shiftButtonDown:
            #print('updatePlayerPosition')
            newX = self.playerNode.getX() + self.velocity.getX() * deltaTime
            newY = self.playerNode.getY() + self.velocity.getY() * deltaTime
            newZ = self.playerNode.getZ()

            self.playerNode.setFluidPos(newX, newY, newZ)

            self.velocity = self.destination - self.playerNode.getPos()
            #print('distance to dest: ', self.velocity.lengthSquared())

            if self.velocity.lengthSquared() < .2:
                self.velocity = Vec3.zero()

                if self.state == 'Run':
                    self.request('Idle')
            else:
                self.velocity.normalize()
                self.velocity *= self.movementSpeed

                if self.state != 'Run':
                    self.request('Run')
        else:
            self.destination = self.playerNode.getPos()

    def playerUpdate(self, task):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY:
            # Do not do anything when paused
            return task.cont

        if self._hudRef == None:
            self._hudRef = self._mainRef.hud

        self.checkGroundCollisions()
        self.updateCameraPosition()

        if self.getIsDead():
            if self.state != 'Death':
                self.request('Death')

            return task.cont

        self.updatePlayerPosition(globalClock.getDt())

        return task.cont

    def ddaMonitor(self, task):
        task.count += 1
        self.healthHistory.append(self.currentHealthPoints)
        self.damageHistory.append(self.damageReceived)
        self.damageReceived = 0

        #print self.healthHistory
        #print self.damageHistory

        if (task.count + 1) % 60 == 0:
            self.deathHistory.append(self.deathCount)
            self.deathCount = 0

            print self.deathHistory

        return task.again

    def receiveDamage(self, damageAmount):
        super(Player, self).receiveDamage(damageAmount)
        if self._scenarioHandlerRef.getHasDDA():
            self.damageReceived += damageAmount

#------------------------------- COMBAT ------------------------------#
    def shiftAttack(self, task):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY:
            return task.done

        #print 'shiftAttack. shift:', self._shiftButtonDown

        if self._shiftButtonDown and base.mouseWatcherNode.hasMouse(): 
            #print 'attack!'
            self.playerModel.play('attack')

            self.plane = Plane(Vec3(0, 0, 1), Point3(0, 0, 0))
            mousePos = base.mouseWatcherNode.getMouse()

            pos3d = Point3()
            nearPoint = Point3()
            farPoint = Point3()

            base.camLens.extrude(mousePos, nearPoint, farPoint)
            if self.plane.intersectsLine(pos3d, 
                        base.render.getRelativePoint(camera, nearPoint),
                        base.render.getRelativePoint(camera, farPoint)):
                #print('Mouse ray intersects ground at ', pos3d)
                destination = pos3d

            pitchRoll = self.playerNode.getP(), self.playerNode.getR()
            self.playerNode.headsUp(destination)
            self.playerNode.setHpr(self.playerNode.getH(), *pitchRoll)

            numEntries = self.attackCollisionHandler.getNumEntries()
            if numEntries > 0:
                self.attackCollisionHandler.sortEntries()
                bAttacked = 0

                for i in range(numEntries):
                    entry = self.attackCollisionHandler.getEntry(i).getIntoNode()
                    entryName = entry.getName()[:-6]
                    #print('entryFound:', entryName)

                    enemy = utils.enemyDictionary[entryName]
                    if enemy is not None and not enemy.getIsDead():
                        if utils.getIsInRange(self.playerNode.getPos(), enemy.enemyNode.getPos(), self.combatRange):
                            bAttacked = self.attack(enemy) # Returns 1 if player attacked but did not hit, returns 2 on hit

                if bAttacked != 0:
                    #print('attackEnemies')

                    for i in range(numEntries):
                        enemyTargetName = self.attackCollisionHandler.getEntry(i).getIntoNode().getName()[:-6]
                        enemyTarget = utils.enemyDictionary[enemyTargetName]

                        if enemyTarget is not None and not enemyTarget.getIsDead():
                            self.setCurrentTarget(enemyTarget)
                            break;
            
            return task.again
        else:
            self.playerModel.stop()

            return task.done

    def attackEnemies(self, task):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY:
            return task.done

        if self._shiftButtonDown:
            return task.again

        numEntries = self.attackCollisionHandler.getNumEntries()
        if numEntries > 0:
            self.attackCollisionHandler.sortEntries()
            bAttacked = 0

            for i in range(numEntries):
                entry = self.attackCollisionHandler.getEntry(i).getIntoNode()
                entryName = entry.getName()[:-6]
                #print('entryFound:', entryName)

                enemy = utils.enemyDictionary[entryName]
                if enemy is not None and not enemy.getIsDead():
                    if utils.getIsInRange(self.playerNode.getPos(), enemy.enemyNode.getPos(), self.combatRange):
                        bAttacked = self.attack(enemy) # Returns 1 if player attacked but did not hit, returns 2 on hit

                        if bAttacked == 2:
                            enemy.enemyModel.play('hit')

            # Only play animations if player actually attacked
            if bAttacked != 0:
                #print('attackEnemies')
                self.playerModel.play('attack')

                for i in range(numEntries):
                    enemyTargetName = self.attackCollisionHandler.getEntry(i).getIntoNode().getName()[:-6]
                    enemyTarget = utils.enemyDictionary[enemyTargetName]

                    if enemyTarget is not None and not enemyTarget.getIsDead():
                        self.setCurrentTarget(enemyTarget)
                        break;

            return task.again

        else:
            #print('go to idle')
            self.removeCurrentTarget()

            if self.state == 'Combat':
                self.request('Idle')

            return task.done


#----------------------- PLAYER STATES --------------------------------------#
    def enterRun(self):
        self.playerModel.loop('run', fromFrame=0, toFrame=12)

    def exitRun(self):
        self.playerModel.stop()

    def enterCombat(self):
        #print('enterCombat')
        self.playerModel.stop()
        self.destination = self.playerNode.getPos()

        attackDelay = self.getInitiativeRoll()
        self.combatTask = taskMgr.doMethodLater(attackDelay, self.attackEnemies, 'combatTask')

        self._hudRef.printFeedback('In combat', True)

    def exitCombat(self):
        #print('exitCombat')
        taskMgr.remove(self.combatTask)
        self._hudRef.printFeedback('Combat ended', False)

    def enterIdle(self):
        stopPlayer = self.playerModel.actorInterval('stop', loop=0)
        idlePlayer = Func(self.playerModel.loop, 'idle', fromFrame=0, toFrame=50)

        self.stopMovingSequence = Sequence(stopPlayer, idlePlayer)
        self.stopMovingSequence.start()

    def exitIdle(self):
        self.stopMovingSequence.finish()

    def enterDeath(self):
        self.playerModel.play('death')

        self.deathCount += 1

        taskMgr.doMethodLater(3, self.respawn, 'respawnTask')

    def exitDeath(self):
        print('exitDeath')

#--------------------- PLAYER DEATH ---------------------------#
    def respawn(self, task):
        self._hudRef.printFeedback('Respawning')

        # Move player back to start pos
        self.destination = self.startPos
        self.playerNode.setPos(self.startPos)

        # Heal the player again
        self.fullHeal()

        # Make sure that isDead variable is set to false
        self.setIsNotDead()

        # Reset state back to idle
        self.request('Idle')

        return task.done
Beispiel #12
0
class Golem(FSM, DirectObject):
    def __init__(self):
        FSM.__init__(self, "FSM-Golem")
        random.seed()
        self.golem = loader.loadModel("Golem")
        self.golem = Actor("Golem", {
            "Idle":"Golem-Idle",
            "Walk":"Golem-Walk",
            "Attack":"Golem-Attack",
            "Destroyed":"Golem-Destroyed"})
        self.golem.setBlend(frameBlend = True)
        golemViewSphere = CollisionSphere(0, 0, 0.5, 6)
        golemViewSphere.setTangible(False)
        golemViewColNP = self.golem.attachNewNode(CollisionNode('golemViewField'))
        golemViewColNP.node().addSolid(golemViewSphere)
        golemHitSphere = CollisionSphere(0, 0, 0.5, 1)
        golemHitColNP = self.golem.attachNewNode(CollisionNode('golemHitField'))
        golemHitColNP.node().addSolid(golemHitSphere)

        # a collision segment to check attacks
        self.attackCheckSegment = CollisionSegment(0, 0, 1, 0, -1.3, 1)
        self.golemAttackRay = self.golem.attachNewNode(CollisionNode("golemAttackCollision"))
        self.golemAttackRay.node().addSolid(self.attackCheckSegment)
        self.golemAttackRay.node().setIntoCollideMask(0)
        self.attackqueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.golemAttackRay, self.attackqueue)

        attackAnim = self.golem.actorInterval("Attack", playRate = 2)
        self.AttackSeq = Parallel(
            attackAnim,
            Sequence(
                Wait(0.5),
                Func(self.ceckAttack)
            ))

        self.lookatFloater = NodePath(PandaNode("golemTracker"))
        self.lookatFloater.setPos(self.golem, 0, 0, 3.4)
        self.lookatFloater.hide()
        self.lookatFloater.reparentTo(render)
        self.trackerObject = loader.loadModel("misc/Pointlight")
        self.trackerObject.setColor(0, 1, 0)
        self.trackerObject.setScale(0.25)
        self.trackerObject.reparentTo(self.lookatFloater)

    def start(self, startPos):
        self.golem.setPos(startPos.getPos())
        self.golem.setHpr(startPos.getHpr())
        self.golem.reparentTo(render)
        self.trackedEnemy = None
        self.health = 5
        self.accept("playerCollision-in-golemViewField",
                    lambda extraArgs: base.messenger.send("golemSeesPlayer", [self.golem]))

    def stop(self):
        self.trackedEnemy = None
        taskMgr.remove("GolemAI_task")
        self.golem.hide()
        self.ignoreAll()

    def cleanup(self):
        self.stop()
        self.lookatFloater.removeNode()
        self.golem.cleanup()
        self.golem.removeNode()

    def activate(self, trackedEnemy):
        self.trackedEnemy = trackedEnemy
        taskMgr.add(self.aiTask, "GolemAI_task")
        self.lookatFloater.show()

    def aiTask(self, task):
        dt = globalClock.getDt()
        if self.AttackSeq.isPlaying(): return task.cont

        self.lookatFloater.setPos(self.golem, 0, 0, 3.4)
        self.lookatFloater.lookAt(self.trackedEnemy)
        self.lookatFloater.setH(self.lookatFloater.getH() + 180)
        self.lookatFloater.setP(0)
        self.lookatFloater.setR(0)

        self.golem.lookAt(self.trackedEnemy)
        self.golem.setH(self.golem.getH() + 180)

        distanceVec = self.golem.getPos() - self.trackedEnemy.getPos()
        enemyDist = distanceVec.length()

        if enemyDist < 2.0:
            # close enough for combat
            action = random.choice(["Attack", "Idle"])
            if action == "Attack":
                self.request("Attack")
            else:
                if self.state != "Idle":
                    self.request("Idle")
        else:
            self.golem.setY(self.golem, -0.5 * dt)
            if self.state != "Walk":
                self.request("Walk")

        return task.cont

    def hit(self):
        hitInterval = Sequence(
            Func(self.golem.setColorScale, 1, 0, 0, 0.75),
            Wait(0.15),
            Func(self.golem.clearColorScale),
            Wait(0.15),
            Func(self.golem.setColorScale, 1, 0, 0, 0.75),
            Wait(0.15),
            Func(self.golem.clearColorScale),
            Wait(0.15),
            Func(self.golem.setColorScale, 1, 0, 0, 0.75),
            Wait(0.15),
            Func(self.golem.clearColorScale),
            Wait(0.15),
            Func(self.golem.setColorScale, 1, 0, 0, 0.75),
            Wait(0.15),
            Func(self.golem.clearColorScale),
            Wait(0.15))
        self.health -= 1
        if self.health == 4:
            self.trackerObject.setColor(0, 1, 0)
            hitInterval.start()
        elif self.health == 3:
            self.trackerObject.setColor(0.25, 0.75, 0)
            hitInterval.start()
        elif self.health == 2:
            self.trackerObject.setColor(0.5, .5, 0)
            hitInterval.start()
        elif self.health == 1:
            self.trackerObject.setColor(0.75, 0.25, 0)
            hitInterval.start()
        elif self.health == 0:
            self.trackerObject.setColor(0, 0, 0)
            self.request("Destroyed")

    def ceckAttack(self):
        for i in range(self.attackqueue.getNumEntries()):
            entry = self.attackqueue.getEntry(i)
            into = entry.getIntoNode()
            if "playerCollision" in into.getName():
                if random.random() > .5:
                    base.messenger.send("HitPlayer")

    def enterIdle(self):
        self.golem.loop("Idle")

    def enterWalk(self):
        self.golem.setPlayRate(2, "Walk")
        self.golem.loop("Walk")

    def enterAttack(self):
        self.AttackSeq.start()

    def enterDestroyed(self):
        self.ignoreAll()
        taskMgr.remove("GolemAI_task")
        self.AttackSeq.finish()
        self.golem.play("Destroyed")
        self.lookatFloater.hide()
        base.messenger.send("GolemDestroyed")
Beispiel #13
0
class Character(Shooter, Unit):
    """A game character.

    Represents a unit controlled by a player.

    Args:
        id_ (int): This character unique id.
        name (str): This character name.
        class_ (str): This character class.
        sex (str): This character gender.
        team (crew.Crew): The Crew object.
        desc (dict):
            Optional. This character description (used
            for loading character from a saved game).
    """

    def __init__(self, id_, name, class_, sex, team, desc=None):
        Unit.__init__(
            self, "character_" + str(id_), class_, CLASSES[sex + "_" + class_]
        )
        Shooter.__init__(self)

        self._team = team
        self._current_pos = None
        self._current_anim = None
        self._idle_seq = None
        self._cohesion_ball = None
        self._is_stunned = False
        self._is_stimulated = False
        self._health_bar = None

        self.inhale = 15
        self.damage_range = [5, 8]
        self.clear_damage = [5, 8]
        self.effects = {}
        self._yeah_snds = []

        self.name = name
        self.sex = sex
        if sex == "male":
            self.heshe = base.labels.PRONOUNS[0]  # noqa: F821
            self.hisher = base.labels.PRONOUNS[1]  # noqa: F821
            self.himher = base.labels.PRONOUNS[2]  # noqa: F821
        else:
            self.heshe = base.labels.PRONOUNS[3]  # noqa: F821
            self.hisher = base.labels.PRONOUNS[4]  # noqa: F821
            self.himher = base.labels.PRONOUNS[5]  # noqa: F821

        if desc:
            self._energy = desc["energy"]
            self.is_diseased = desc["is_diseased"]
            self.get_well_score = desc["get_well_score"]
            self.traits = desc["traits"]
            self.disabled_traits = desc["disabled_traits"]

            if self.is_diseased:
                taskMgr.doMethodLater(  # noqa: F821
                    60, self.get_well, self.id + "_get_well"
                )
        else:
            self._energy = 100
            self.is_diseased = False
            self.get_well_score = 0

            self.disabled_traits = []
            self.traits = []
            traits = copy.copy(base.labels.TRAITS)  # noqa: F821
            for _ in range(random.randint(0, 2)):
                self.traits.append(random.choice(take_random(traits)))

    @property
    def clear_delay(self):
        """
        Delay between this character death
        and clearing the character object.

        Returns:
            float: Seconds to wait before clearing.
        """
        return 3.5

    @property
    def damage(self):
        """This character one-time calculated damage.

        Returns:
            float: Damage one-time made by this character.
        """
        return random.uniform(*self.damage_range) * self.damage_factor

    @property
    def damage_factor(self):
        """This character damage factor.

        The damage factor depends on cohesion with another
        character on the same part of the Train.

        Returns:
            float: Damage one-time made by this character.
        """
        factor = self._team.calc_cohesion_factor(self.current_part.chars, self)
        if (
            # Loner
            base.labels.TRAITS[4][1] in self.traits  # noqa: F821
            and len(self.current_part.chars) == 1
        ):
            return factor * 1.3

        return factor

    @property
    def description(self):
        """This character state in saveable form.

        Used for saving the character.

        Returns:
            dict: This character description.
        """
        return {
            "id": int(self.id.split("_")[1]),
            "name": self.name,
            "sex": self.sex,
            "class": self.class_,
            "health": self.health,
            "energy": self.energy,
            "place": self.current_part.name,
            "traits": self.traits,
            "disabled_traits": self.disabled_traits,
            "is_diseased": self.is_diseased,
            "get_well_score": self.get_well_score,
        }

    @property
    def energy(self):
        """This character energy.

        Returns:
            int: This character energy points.
        """
        return self._energy

    @energy.setter
    def energy(self, value):
        """This character energy setter.

        Args:
            value (int): New energy value.
        """
        self._energy = min(max(value, 0), 80 if self.is_diseased else 100)

    @property
    def shooting_speed(self):
        """Delay between shots of this unit.

        Returns:
            float: Delay between shots in seconds.
        """
        if base.labels.TRAITS[0][0] in self.traits:  # noqa: F821
            # Fast hands
            return 1.1 + random.uniform(0.1, 0.8)

        if base.labels.TRAITS[0][1] in self.traits:  # noqa: F821
            # Snail
            return 2 + random.uniform(0.1, 1.1)

        return 1.7 + random.uniform(0.1, 0.9)

    @property
    def statuses(self):
        """Return strings describing the current character status.

        Returns:
            list: Status description lines.
        """
        statuses = []
        if base.world.sun.is_dark:  # noqa: F821
            if base.labels.TRAITS[1][0] in self.traits:  # noqa: F821
                statuses.append(base.labels.STATUSES[0])  # noqa: F821
            elif base.train.lights_on:  # noqa: F821
                if "Floodlights" not in base.train.upgrades:  # noqa: F821
                    statuses.append(base.labels.STATUSES[1])  # noqa: F821
            else:
                statuses.append(base.labels.STATUSES[2])  # noqa: F821

        if self.energy <= 95:
            statuses.append(
                base.labels.STATUSES[3].format((100 - self.energy) // 5)  # noqa: F821
            )

        if not base.world.is_in_city and self.current_part is not None:  # noqa: F821
            factor = round(self.damage_factor, 2)
            if factor != 1:
                statuses.append(base.labels.STATUSES[4].format(factor))  # noqa: F821

        if self.health < 50 and base.labels.TRAITS[2][1] in self.traits:  # noqa: F821
            statuses.append(base.labels.STATUSES[5])  # noqa: F821

        if self.is_diseased:
            statuses.append(base.labels.STATUSES[6])  # noqa: F821

        if (
            base.labels.TRAITS[6][1] in self.traits  # noqa: F821
            and base.train.ctrl.current_speed > 0.75  # noqa: F821
        ):
            statuses.append(base.labels.STATUSES[7])  # noqa: F821

        return statuses[:4]

    @property
    def tooltip(self):
        """Tooltip to show on this character mouse pointing.

        Returns:
            str: This character name.
        """
        return self.name

    def attack(self, enemy_unit):
        """Make the given enemy unit this character's target.

        Args:
            enemy_unit (units.enemy.EnemyUnit): Enemy unit to attack.
        """
        if enemy_unit in self.current_part.enemies:
            self._target = enemy_unit

    def prepare(self):
        """Load the character model and positionate it.

        Tweak collision solid and sounds.
        """
        animations = {
            name: address(self.class_ + "-" + name)
            for name in (
                "die",
                "gun_up",
                "incline1",
                "release_gun",
                "stand_and_aim",
                "stand",
                "surrender",
                "tread1",
                "turn_head1",
                "stunned",
                "cough",
                "celebrate",
            )
        }
        self.model = Actor(address(self.sex + "_" + self.class_), animations)
        self.model.enableBlend()
        self.model.setControlEffect("stand", 1)

        self.model.setPlayRate(0.8, "stand_and_aim")
        self.model.setPlayRate(0.6, "stand")
        self.model.loop("stand")
        self._current_anim = "stand"

        self._health_bar = HealthBar(self)

        base.team.init_relations(self)  # noqa: F821

        taskMgr.doMethodLater(  # noqa: F821
            random.randint(40, 60), self._idle_animation, self.id + "_idle_anim"
        )
        self._col_node = self._init_col_node(
            NO_MASK, MOUSE_MASK, CollisionCapsule(0, 0, 0, 0, 0, 0.035, 0.035)
        )
        self.shot_snd = self._set_shoot_snd(self.class_data["shot_snd"])
        self._cough_snd = base.sound_mgr.loadSfx(  # noqa: F821
            "sounds/{sex}_cough.ogg".format(sex=self.sex)
        )
        base.sound_mgr.attachSoundToObject(self._cough_snd, self.model)  # noqa: F821
        self._die_snd = base.sound_mgr.loadSfx(  # noqa: F821
            "sounds/combat/{sex}_death.ogg".format(sex=self.sex)
        )
        base.sound_mgr.attachSoundToObject(self._die_snd, self.model)  # noqa: F821

        for i in range(1, 4):
            yeah_snd1 = base.sound_mgr.loadSfx(  # noqa: F821
                "sounds/{sex}_yes{num}.ogg".format(sex=self.sex, num=str(i))
            )
            base.sound_mgr.attachSoundToObject(yeah_snd1, self.model)  # noqa: F821

            self._yeah_snds.append(yeah_snd1)

        if self.class_ == "soldier":
            z = 0.064 if self.sex == "male" else 0.062
        elif self.class_ == "raider":
            z = 0.047
        elif self.class_ == "anarchist":
            z = 0.06 if self.sex == "male" else 0.057

        self._shoot_anim = self._set_shoot_anim(
            (0.004, 0.045, z), 97, self.class_data["shots_num"]
        )
        taskMgr.doMethodLater(  # noqa: F821
            self.class_data["energy_spend"],
            self._reduce_energy,
            self.id + "_reduce_energy",
        )
        self._prepare_cohesion_particles()
        self._prepare_auras()

    def _prepare_cohesion_particles(self):
        """Prepare cohesion skills particle effects."""
        effect = ParticleEffect()
        effect.loadConfig("effects/recall_the_past.ptf")

        self.effects["recall_the_past"] = {"length": 0.7, "effect": effect}

        effect = ParticleEffect()
        effect.loadConfig("effects/not_leaving_ours.ptf")

        self.effects["not_leaving_ours"] = {"length": 2, "effect": effect}

        effect = ParticleEffect()
        effect.loadConfig("effects/common_rage.ptf")

        self.effects["common_rage"] = {"length": 90, "effect": effect}

    def _prepare_auras(self):
        """Prepare cohesion skills aura effects."""
        aura = loader.loadModel(address("cover_fire_aura"))  # noqa: F821
        aura.hide()
        aura.reparentTo(self.model)
        aura.setY(0.007)

        self.effects["cover_fire"] = {
            "model": aura,
            "seq": Sequence(
                LerpScaleInterval(aura, 1.5, (2, 2, 2), (1, 1, 1)),
                LerpScaleInterval(aura, 1.5, (1, 1, 1), (2, 2, 2)),
            ),
        }

        aura = loader.loadModel(address("common_rage_aura"))  # noqa: F821
        aura.hide()
        aura.reparentTo(self.model)
        aura.setY(0.007)

        self.effects["common_rage_aura"] = {
            "model": aura,
            "seq": Sequence(
                LerpScaleInterval(aura, 1.5, (2, 2, 2), (1, 1, 1)),
                LerpScaleInterval(aura, 1.5, (1, 1, 1), (2, 2, 2)),
            ),
        }

        aura = loader.loadModel(address("hold_together_aura"))  # noqa: F821
        aura.hide()
        aura.reparentTo(self.model)
        aura.setY(0.007)

        self.effects["hold_together"] = {
            "model": aura,
            "seq": Sequence(
                LerpScaleInterval(aura, 1.5, (2, 2, 2), (1, 1, 1)),
                LerpScaleInterval(aura, 1.5, (1, 1, 1), (2, 2, 2)),
            ),
        }

    def play_cohesion_effect(self, name):
        """Play the given cohesion skill effect.

        Args:
            name (str): Name of the skill.
        """
        self.effects[name]["effect"].start(self.model, self.model)
        self.effects[name]["effect"].softStart()

        taskMgr.doMethodLater(  # noqa: F821
            self.effects[name]["length"],
            self.effects[name]["effect"].softStop,
            "stop_cohesion_effect",
            extraArgs=[],
        )

    def play_cohesion_aura(self, name):
        """Play the given aura effect.

        Args:
            name (str): The effect name.
        """
        self.effects[name]["model"].show()
        self.effects[name]["seq"].loop()

    def play_yes(self):
        """Play a voice sound, when the character is chosen."""
        random.choice(self._yeah_snds).play()

    def stop_aura_effect(self, name):
        """Stop the given aura effect.

        Args:
            name (str): The effect name.
        """
        self.effects[name]["model"].hide()
        self.effects[name]["seq"].finish()

    def celebrate(self, task):
        """Play victory celebration animation."""
        if self.current_part.name == "part_rest":
            return task.done

        LerpAnimInterval(self.model, 0.1, self._current_anim, "celebrate").start()
        self._current_anim = "celebrate"
        self.model.play("celebrate")
        return task.done

    def move_to(self, part, to_pos=None):
        """Move this Character to the given Train part.

        If the movement is done with a positions exchange
        between two characters, the method doesn't
        take or release characters cells, just replaces
        one character with another one.

        Args:
            part (train.part.TrainPart):
                Train part to move this Character to.
            to_pos (dict):
                Position to move this Character to.

        Returns:
            bool: True, if the character was moved.
        """
        if to_pos:
            part.chars.append(self)
            pos = to_pos
        else:
            pos = part.give_cell(self)

        if not pos:  # no free cells on the chosen part
            return

        if self.current_part is not None:
            if to_pos:
                self.current_part.chars.remove(self)
            else:
                self.current_part.release_cell(self._current_pos, self)

            if self.current_part.name == "part_rest":
                self.stop_rest()

        if part.name == "part_rest":
            self.rest()

        self.model.wrtReparentTo(part.parent)
        self.model.setPos(pos)
        self.model.setH(part.angle)

        self.current_part = part
        self._current_pos = pos

        if part.name == "part_rest" and base.char_gui.rest_list_shown:  # noqa: F821
            base.char_gui.update_resting_chars(part)  # noqa: F821

        return True

    def do_effects(self, effects):
        """Do outing effects to this character.

        Effects are: adding traits, changing health and energy.

        Args:
            effects (dict): Effects and their values.
        """
        if effects is None:
            return

        effects = copy.deepcopy(effects)
        self.get_damage(-effects.pop("health", 0))

        if "add_trait" in effects and len(self.traits + self.disabled_traits) < 3:
            ind1, ind2 = effects["add_trait"]
            trait = base.labels.TRAITS[ind1][ind2]  # noqa: F821

            if trait and trait not in self.traits + self.disabled_traits:
                self.traits.append(trait)
                base.char_gui.move_status_label(-1)  # noqa: F821
                effects.pop("add_trait")

        for key, value in effects.items():
            if hasattr(self, key):
                setattr(self, key, getattr(self, key) + value)

    def prepare_to_fight(self):
        """Prepare this character for a fight.

        Switch animations and run a task to choose a target.
        """
        self._stop_tasks("_idle_anim")
        if self._idle_seq is not None:
            self._idle_seq.finish()

        self.model.loop("stand_and_aim")
        LerpAnimInterval(self.model, 0.8, self._current_anim, "stand_and_aim").start()
        LerpAnimInterval(self.model, 0.8, "stand", "stand_and_aim").start()
        self._current_anim = "stand_and_aim"

        taskMgr.doMethodLater(  # noqa: F821
            0.5, self._choose_target, self.id + "_choose_target"
        )
        self._health_bar.show_health()

    def rest(self):
        """Make this character rest.

        Stops all the active tasks and starts energy regaining/healing.
        """
        self._stop_tasks(
            "_reduce_energy", "_shoot", "_aim", "_choose_target", "_idle_anim"
        )
        self.model.hide()
        self._col_node.stash()

        taskMgr.doMethodLater(  # noqa: F821
            0.05, self._calm_down, self.id + "_calm_down", extraArgs=[True],
        )
        taskMgr.doMethodLater(  # noqa: F821
            self.class_data["energy_gain"], self._gain_energy, self.id + "_gain_energy"
        )
        if self.health < self.class_data["health"]:
            taskMgr.doMethodLater(  # noqa: F821
                self.class_data["healing"], self._heal, self.id + "_heal"
            )

    def surrender(self):
        """Stop fighting, surrender."""
        self._stop_tasks("_shoot", "_aim", "_choose_target")
        self._col_node.removeNode()
        self._shoot_anim.finish()

        LerpAnimInterval(self.model, 0.5, "stand_and_aim", "surrender").start()
        self.model.play("surrender")

    def stop_rest(self):
        """Stop this character rest."""
        self.model.show()
        self._col_node.unstash()
        base.char_gui.destroy_char_button(self.id)  # noqa: F821

        self._stop_tasks("_gain_energy", "_heal")
        taskMgr.doMethodLater(  # noqa: F821
            self.class_data["energy_spend"],
            self._reduce_energy,
            self.id + "_reduce_energy",
        )
        if base.world.enemy.active_units:  # noqa: F821
            self.prepare_to_fight()

    def _reduce_energy(self, task):
        """
        Reduce the character energy according to
        day part and status: fighting or not.
        """
        if base.world.sun.is_dark:  # noqa: F821
            if not base.train.lights_on:  # noqa: F821
                task.delayTime = 15
            elif "Floodlights" in base.train.upgrades:  # noqa: F821
                task.delayTime = self.class_data["energy_spend"]
            else:
                task.delayTime = 20

            if base.labels.TRAITS[1][1] in self.traits:  # noqa: F821
                # Fear of dark
                task.delayTime /= 2

        elif self._target:
            # Nervousness
            task.delayTime = (
                15 if base.labels.TRAITS[5][1] in self.traits else 20  # noqa: F821
            )
        else:
            task.delayTime = self.class_data["energy_spend"]

        if (
            base.labels.TRAITS[2][1] in self.traits  # noqa: F821
            and self.health < self.class_data["health"] / 2
        ):
            # Hemophobia
            task.delayTime *= 0.75

        self.energy -= 1
        if base.labels.TRAITS[7][0] in self.traits:  # noqa: F821
            # Mechanic
            base.train.get_damage(-3)  # noqa: F821

        return task.again

    def _gain_energy(self, task):
        """Regain this character energy.

        Used as a timed task while the character is resting.
        """
        if (
            base.labels.TRAITS[6][1] in self.traits  # noqa: F821
            and base.train.ctrl.current_speed > 0.75  # noqa: F821
        ):
            # Motion sickness
            return task.again

        self.energy += 3

        for char in self.current_part.chars:
            if char.sex == "female" and self.id != char.id:
                task.delayTime = self.class_data["energy_gain"] - 5
                return task.again

        return task.again

    def _heal(self, task):
        """Regain this character health.

        Used as a timed task while the character is resting.
        """
        if (
            base.labels.TRAITS[6][1] in self.traits  # noqa: F821
            and base.train.ctrl.current_speed > 0.75  # noqa: F821
        ):
            # Motion sickness
            return task.again

        if base.labels.TRAITS[7][1] in self.traits and chance(40):  # noqa: F821
            # Pharmacophobia
            return task.again

        if self.health < self.class_data["health"]:
            self.health += 1
            return task.again

        return task.done

    def _choose_target(self, task):
        """Choose an enemy to shoot.

        Only an enemy from the Train part shooting
        range can be chosen as a target.
        """
        if self.current_part and self.current_part.enemies:
            self._target = random.choice(self.current_part.enemies)
            taskMgr.doMethodLater(0.1, self._aim, self.id + "_aim")  # noqa: F821
            taskMgr.doMethodLater(1, self._shoot, self.id + "_shoot")  # noqa: F821
            return task.done

        # enemies retreated - return to passive state
        if not base.world.enemy.active_units:  # noqa: F821
            taskMgr.doMethodLater(  # noqa: F821
                7, self._calm_down, self.id + "_calm_down", extraArgs=[False],
            )
            return task.done

        return task.again

    def _aim(self, task):
        """Rotate the character to aim on enemy."""
        if (
            self._target
            and self._target.is_dead
            and base.labels.TRAITS[5][0] in self.traits  # noqa: F821
        ):
            # Bloodthirsty
            self.health += 7

        if self.current_part and self._target in self.current_part.enemies:
            self.model.headsUp(self._target.model)
            return task.again

        self._stop_tasks("_shoot")
        self._target = None

        if base.world.enemy.active_units:  # noqa: F821
            taskMgr.doMethodLater(  # noqa: F821
                0.5, self._choose_target, self.id + "_choose_target"
            )
            return task.done

        taskMgr.doMethodLater(  # noqa: F821
            7, self._calm_down, self.id + "_calm_down", extraArgs=[False]
        )
        return task.done

    def _calm_down(self, force):
        """Return to passive state on a combat over.

        Args:
            force (bool):
                If True, change to passive animation fast.
                Change animation in usual speed otherwise.
        """
        self._stop_tasks("_shoot", "_calm_down")
        if self.current_part:
            self.model.hprInterval(
                0.1 if force else 2, (self.current_part.angle, 0, 0)
            ).start()

        if force:
            for anim in self.model.get_anim_names():
                self.model.setControlEffect(anim, 0)

            self.model.stop()
            self.model.setControlEffect("stand", 1)
            self.model.loop("stand")
        else:
            LerpAnimInterval(self.model, 2, self._current_anim, "stand").start()

        self._current_anim = "stand"
        taskMgr.doMethodLater(  # noqa: F821
            random.randint(40, 60), self._idle_animation, self.id + "_idle_anim"
        )
        self._health_bar.hide_health()

    def _idle_animation(self, task):
        """Play one of the idle animations.

        Args:
            task (panda3d.core.PythonTask): Task object.
        """
        if self.is_diseased and chance(80):
            self._current_anim = "cough"
            self._cough_snd.play()
        else:
            self._current_anim = random.choice(
                ("incline1", "gun_up", "release_gun", "tread1", "turn_head1")
            )
        LerpAnimInterval(self.model, 0.2, "stand", self._current_anim).start()

        self._idle_seq = Sequence(
            self.model.actorInterval(self._current_anim, playRate=0.75),
            Func(self._stand),
        )
        self._idle_seq.start()

        task.delayTime = random.randint(40, 60)
        return task.again

    def _stand(self):
        """Return to the idle stand animation."""
        LerpAnimInterval(self.model, 0.2, self._current_anim, "stand").start()
        self._current_anim = "stand"

    def _die(self):
        """Character death sequence.

        Stop all the character's tasks, play death animation
        and plan the character object clearing.
        """
        if self._team.hold_together:
            self.health = 1
            return False

        if not Shooter._die(self):
            return False

        Unit._die(self)

        if base.common_ctrl.chosen_char == self:  # noqa: F821
            base.common_ctrl.deselect(clear_resting=False)  # noqa: F821

        self._health_bar.hide_health()
        self._stop_tasks(
            "_reduce_energy", "_get_well", "_infect", "_stop_stimul", "_gain_energy"
        )

        base.char_gui.destroy_char_button(self.id)  # noqa: F821
        self._team.delete_relations(self.id)

        LerpAnimInterval(self.model, 0.3, "stand_and_aim", "die").start()
        LerpAnimInterval(self.model, 0.3, self._current_anim, "die").start()
        self.model.hprInterval(1, (self.current_part.angle, 0, 0)).start()
        self.model.play("die")
        self._die_snd.play()

        taskMgr.doMethodLater(3, self._hide, self.id + "_hide")  # noqa: F821

    def _hide(self, task):
        """Hide the main model."""
        self.model.hide()
        return task.done

    def leave(self):
        """Make this character leave, plan clearing.

        Used only when sending a character away in a city.
        """
        self._stop_tasks("_calm_down", "_gain_energy", "_heal", "_infect", "_get_well")
        taskMgr.doMethodLater(0.05, self.clear, self.id + "_clear")  # noqa: F821

    def clear(self, task):
        """Clear this character.

        Release models and sounds memory, release the part
        cell and delete the character from the team list.
        """
        self.model.cleanup()
        self._health_bar.removeNode()
        self.model.removeNode()
        base.sound_mgr.detach_sound(self.shot_snd)  # noqa: F821
        base.sound_mgr.detach_sound(self._cough_snd)  # noqa: F821
        base.sound_mgr.detach_sound(self._die_snd)  # noqa: F821
        for snd in self._yeah_snds:
            base.sound_mgr.detach_sound(snd)  # noqa: F821

        self._team.chars.pop(self.id)
        base.res_gui.update_chars()  # noqa: F821
        self.current_part.release_cell(self._current_pos, self)
        self.current_part = None

        return task.done

    def exchange_pos(self, char):
        """Exchange positions of this Character and the given one.

        Args:
            char (units.character.Character):
                Character to exchange the positions with.
        """
        o_part, o_pos = self.current_part, self._current_pos
        self.move_to(char.current_part, char._current_pos)
        char.move_to(o_part, o_pos)

    def hide_relations_ball(self):
        """Hide the relations ball of this character."""
        if self._cohesion_ball is not None:
            self._cohesion_ball.removeNode()
            self._cohesion_ball = None

    def show_relation(self, cohesion):
        """Show a relations ball above this character.

        The color of the ball shows the strength of cohesion
        between the chosen character and this one.

        Args:
            cohesion (float):
                Value of the cohesion between the
                chosen character and this one.
        """
        if self._cohesion_ball is None:
            self._cohesion_ball = loader.loadModel(  # noqa: F821
                address("relation_ball")
            )
            self._cohesion_ball.clearLight()
            base.world.sun.ignore_shadows(self._cohesion_ball)  # noqa: F821

            self._cohesion_ball.reparentTo(self.model)
            self._cohesion_ball.setZ(0.14)

        self._cohesion_ball.setColorScale(*RELATION_COLORS[cohesion // 20])

    def _missed_shot(self):
        """Calculate if character missed the current shot.

        Returns:
            bool: True if character missed, False otherwise.
        """
        miss_chance = 0
        if self.class_ == "soldier":
            if (
                abs(self._target.node.getX()) < 0.56
                and abs(self._target.node.getY()) < 0.95
            ):
                miss_chance += 20
        elif self.class_ == "raider":
            if (
                abs(self._target.node.getX()) > 0.56
                and abs(self._target.node.getY()) > 0.95
            ):
                miss_chance += 20

        if base.world.sun.is_dark:  # noqa: F821
            if base.labels.TRAITS[1][0] in self.traits:  # noqa: F821
                # Cat eyes
                miss_chance -= 5
            elif base.train.lights_on:  # noqa: F821
                if "Floodlights" not in base.train.upgrades:  # noqa: F821
                    miss_chance += 10
            else:
                miss_chance += 20

        miss_chance += (100 - self.energy) // 5
        if self._team.cover_fire:
            miss_chance = min(100, max(0, miss_chance - 25))

        return chance(miss_chance)

    def get_stunned(self):
        """Make this character stunned for some time.

        Stunned unit can't shoot.
        """
        if self._is_stunned or self._is_stimulated:
            return

        self._is_stunned = True
        self._stop_tasks("_aim", "_shoot")

        self._current_anim = "stunned"
        self.model.play("stunned")
        LerpAnimInterval(self.model, 0.05, "stand_and_aim", "stunned").start()

        taskMgr.doMethodLater(  # noqa: F821
            6, self._stop_stunning, self.id + "_stop_stunning"
        )

    def get_sick(self, is_infect=False):
        """Calculations to get this character sick.

        The worse condition the character has the higher is the chance
        for him to get sick. Sick character has lower energy maximum,
        and all his positive traits are disabled until getting well.

        Args:
            is_infect (bool):
                True if the disease came from a
                character on the same Train part.
        """
        if self.is_diseased:
            return

        cond_percent = (self.energy + self.health) / (100 + self.class_data["health"])
        percent = (1 - cond_percent) * 30

        sick_chance = max(
            0,  # not less than zero
            (
                percent
                + (20 if is_infect else 0)
                # Immunity
                - (40 if base.labels.TRAITS[3][0] in self.traits else 0)  # noqa: F821
                # Weak immunity
                + (20 if base.labels.TRAITS[3][1] in self.traits else 0)  # noqa: F821
            ),
        )

        if chance(sick_chance):
            self.is_diseased = True
            self.get_well_score = 0

            for traits_pair in base.labels.TRAITS:  # noqa: F821
                if traits_pair[0] in self.traits:

                    self.traits.remove(traits_pair[0])
                    self.disabled_traits.append(traits_pair[0])

            taskMgr.doMethodLater(  # noqa: F821
                60, self.get_well, self.id + "_get_well"
            )
            taskMgr.doMethodLater(240, self.infect, self.id + "_infect")  # noqa: F821
            self.energy = min(self.energy, 80)

    def get_stimulated(self):
        """Use a stimulator on this character.

        Disables all the negative traits for some time.
        """
        for traits_pair in base.labels.TRAITS:  # noqa: F821
            if traits_pair[1] in self.traits:
                self.traits.remove(traits_pair[1])
                self.disabled_traits.append(traits_pair[1])

        self._is_stimulated = True
        taskMgr.doMethodLater(  # noqa: F821
            300, self._stop_stimul, self.id + "_stop_stimul"
        )

    def _stop_stimul(self, task):
        """Stop stimulation of this character.

        Returns back all the disabled negative traits.
        """
        for trait_pair in base.labels.TRAITS:  # noqa: F821
            if trait_pair[1] in self.disabled_traits:
                self.traits.append(trait_pair[1])
                self.disabled_traits.remove(trait_pair[1])

        self._is_stimulated = False
        return task.done

    def get_well(self, task):
        """Get this character well.

        When the character got well, his energy maximum is restored to
        the default value, and his positive traits are back operational.
        """
        self.get_well_score += 1
        if self.get_well_score < 20:
            return task.again

        self.is_diseased = False
        for trait_pair in base.labels.TRAITS:  # noqa: F821
            if trait_pair[0] in self.disabled_traits:
                self.traits.append(trait_pair[0])
                self.disabled_traits.remove(trait_pair[0])

        self._stop_tasks("_infect")
        return task.done

    def infect(self, task):
        """Infect other characters on the same Train part."""
        for char in self.current_part.chars:
            if char.id != self.id:
                char.get_sick(is_infect=True)

        return task.again

    def _shoot(self, task):
        """Play shooting animation and sound, make damage."""
        if self.current_part and not self.current_part.is_covered:
            return Shooter._shoot(self, task)

        return task.again

    def _stop_stunning(self, task):
        """Stop this character stun and continue fighting."""
        self._is_stunned = False

        LerpAnimInterval(self.model, 0.8, self._current_anim, "stand_and_aim").start()
        self._current_anim = "stand_and_aim"
        self.model.loop("stand_and_aim")

        taskMgr.doMethodLater(0.1, self._aim, self.id + "_aim")  # noqa: F821
        taskMgr.doMethodLater(1, self._shoot, self.id + "_shoot")  # noqa: F821

        return task.done

    def get_damage(self, damage):
        """Getting damage.

        Args:
            damage (int): Damage points to get.
        """
        if base.labels.TRAITS[2][0] in self.traits:  # noqa: F821
            # Masochism
            self.energy += 1

        Unit.get_damage(self, damage)

    def get_stench_damage(self):
        """Get damage from the Stench."""
        if base.labels.TRAITS[6][0] in self.traits and self.inhale > 0:  # noqa: F821
            # Deep breath
            self.inhale -= 1
            return

        if (
            self.current_part
            and self.current_part.name == "part_rest"
            and "Window Frames" in base.train.upgrades  # noqa: F821
        ):
            return

        self.get_damage(1)
Beispiel #14
0
class ToontownCentral(DirectObject):
    
    def __init__(self):
        self.scene = render.getPythonTag('SceneManager').createScene("TTC")
        self.build()
        
    def build(self):
        self.skybox = loader.loadModel("phase_3.5/models/props/TT_sky.bam")
        self.skybox.set_depth_write(False)
        self.skybox.find("**/Sky").setBin("background", 0)
        self.skybox.find('**/cloud1').setBin("background", 3)
        self.skybox.find('**/cloud2').setBin("background", 5)
        self.skybox.reparentTo(render)
        self.environ = loader.loadModel('ttc.bam')
    
    def __animateEnv(self):
        TTC = self.environ
        toonHall = TTC.find('**/sz13:toon_landmark_TT_toonhall_DNARoot')
        render.setPythonTag("ToonHall", ToonHall(toonHall, toonHall.find('**/door_double_round_ur')))
        phase_4 = 'phase_4/models/props/'
        self.fish = TTC.find('**/animated_prop_PetShopFishAnimatedProp_DNARoot')
        self.fish.removeNode()
        self.fish = Actor(phase_4 + 'exteriorfish-zero.bam', {'anim' : phase_4 + 'exteriorfish-swim.bam'})
        self.fish.reparentTo(TTC.find('**/sz22:toon_landmark_TT_pet_shop_DNARoot'))
        self.fish.loop('anim')
        self.periscope = Actor(TTC.find('**/animated_prop_HQPeriscopeAnimatedProp_DNARoot'), copy = 0)
        self.periscope.reparentTo(render)
        self.periscope.loadAnims({'anim': 'phase_3.5/models/props/HQ_periscope-chan.bam'})
        self.periscope.pose('anim', 0)
        self.periscopeTrack = Sequence(Wait(2.0), self.periscope.actorInterval('anim', startFrame=0, endFrame=40), Wait(0.7), self.periscope.actorInterval('anim', startFrame=40, endFrame=90), Wait(0.7), self.periscope.actorInterval('anim', startFrame=91, endFrame=121), Wait(0.7), self.periscope.actorInterval('anim', startFrame=121, endFrame=91), Wait(0.7), self.periscope.actorInterval('anim', startFrame=90, endFrame=40), Wait(0.7), self.periscope.actorInterval('anim', startFrame=40, endFrame=90), Wait(0.7), self.periscope.actorInterval('anim', startFrame=91, endFrame=121), Wait(0.5), self.periscope.actorInterval('anim', startFrame=121, endFrame=148), Wait(3.0))
        self.periscopeTrack.loop()
        self.telescope = Actor(TTC.find('**/animated_prop_HQTelescopeAnimatedProp_DNARoot'), copy = 0)
        self.telescope.reparentTo(render)
        self.telescope.loadAnims({'anim': 'phase_3.5/models/props/HQ_telescope-chan.bam'})
        self.telescope.pose('anim', 0)
        self.telescopeTrack = Sequence(Wait(5.0), self.telescope.actorInterval('anim', startFrame=0, endFrame=32), Wait(0.5), self.telescope.actorInterval('anim', startFrame=32, endFrame=78), Wait(0.5), self.telescope.actorInterval('anim', startFrame=79, endFrame=112), Wait(0.5), self.telescope.actorInterval('anim', startFrame=112, endFrame=79), Wait(0.5), self.telescope.actorInterval('anim', startFrame=78, endFrame=32), Wait(0.5), self.telescope.actorInterval('anim', startFrame=32, endFrame=78), Wait(0.5), self.telescope.actorInterval('anim', startFrame=79, endFrame=112), Wait(0.5), self.telescope.actorInterval('anim', startFrame=112, endFrame=148), Wait(4.0))
        self.telescopeTrack.loop()
        #base.taskMgr.add(self.__moveClouds, "Move Clouds")
        self.__fixTrashcans()
        self.environ.flattenStrong()
        self.scene.addModel(self.environ)
        render.find('**/TTC').setPythonTag('Class', self)
        
    def __fixTrashcans(self):
        TTC = self.environ
        trashcans = TTC.findAllMatches('**/prop_trashcan_metal_DNARoot')
        for trashcan in trashcans:
            pos = trashcan.getPos()
            hpr = trashcan.getHpr()
            trashcan.removeNode()
            new_trashcan = loader.loadModel('phase_5/models/props/trashcan_TT.bam')
            new_trashcan.setPos(pos)
            new_trashcan.setHpr(hpr)
            new_trashcan.reparentTo(TTC)
        
        
    def __moveClouds(self, task):
        model = self.skybox
        model.find("**/cloud1").setHpr(task.time * 0.3, 0, 0)
        model.find("**/cloud2").setHpr(task.time * -0.3, 0, 0) 
        return Task.cont
        
    def doFade(self):
        TTC = render.find('**/TTC')
        skyFade = self.skybox.colorScaleInterval(4, Vec4(0.1, 0.1, 0.1, 1), startColorScale=Vec4(1, 1, 1, 1), blendType='easeInOut')
        TTCFade = TTC.colorScaleInterval(3.8, Vec4(0.2509803921568627, 0.2509803921568627, 0.2509803921568627, 1), startColorScale=Vec4(1, 1, 1, 1), blendType='easeInOut')
        skyFade.start()
        TTCFade.start()
        
    def loadScene(self):
        self.scene.loadScene()
        self.__animateEnv()
        
    def unloadScene(self):
        base.taskMgr.remove("Move Clouds")
        self.scene.delete()
Beispiel #15
0
class Lvl02(DirectObject):

	#constructor
	def start(self):	

		base.disableMouse() #turn off mouse camera control

		camera.setPosHpr(Vec3(0,-55,30), Vec3(0,-20,0))
		self.ballNum = 34
		self.loadModels()
		self.setupLighting()
		self.setupCollisions()
		self.setupIntervals()
			
		#self.clock = ClockObject
		
		self.gameLen = 60
		
		self.music = loader.loadMusic("models/gamedev/DFC.mp3")
		self.music.play()
		
		self.hud = DirectFrame(image = 'models/gamedev/lvl2hud.jpg')
		self.hud['pos'] = (-100,0,-100)
		self.hud['frameSize'] = (0,0,0,0)
		self.hud['image_pos'] = (0,-10,24.5)
		self.hud['image_scale'] = (22.25,1,2)
		self.hud['image_hpr'] = (0,-45,0)
		self.hud.reparentTo(render)
	
		globalClock.reset()
		self.drop()
		self.timer = DirectFrame(text = "%d" % (self.gameLen-globalClock.getRealTime(),), pos = Vec3(0,-11.5,23.5),text_fg = (1,1,1,1),text_scale=4.0)
		self.timer['frameSize'] = (0,0,0,0)
		self.timer.reparentTo(render)
		taskMgr.add(self.clockTask,"clockTask")
		
		self.player1Score = 0
		self.player2Score = 0
		
		self.speed1 = 8.0
		self.speed2 = 8.0
		self.turnSpeed1 = 80.0
		self.turnSpeed2 = 80.0
		
		self.ignoreColl= 0
		
		self.player1IsColliding = 0
		self.player2IsColliding = 0
		
		taskMgr.doMethodLater(self.gameLen, self.endGame,'gameFinished')
		
		taskMgr.doMethodLater(self.gameLen/2.0,self.changeMusic,'musicSwitch')
		
		#setup key controls
		self.accept("escape",sys.exit)

		# Player 1 movement

		self.acceptOnce("w",self.walk)
		self.acceptOnce("a",self.turn,[-1])
		self.acceptOnce("d",self.turn,[1])
		
		self.accept("w-up",self.stopWalk)
		self.accept("a-up",self.stopTurn)
		self.accept("d-up",self.stopTurn)
		
		# Player 2 movement

		self.acceptOnce("o",self.walk2,)
		self.acceptOnce("k",self.turn2,[-1])
		self.acceptOnce(";",self.turn2,[1])

		self.accept("o-up",self.stopWalk2)
		self.accept("k-up",self.stopTurn2)
		self.accept(";-up",self.stopTurn2)

	def loadModels(self):
		
		self.environment = loader.loadModel("models/gamedev/grassy")
		self.environment.reparentTo(render)
		self.environment.setScale(3.4)
		self.environment.setPos(0,12,-0.45)
		self.environment.setH(78)

		self.background = OnscreenImage(image = 'models/gamedev/lvl2background.jpg', pos = (0,40,0),scale=42.5, hpr = (0,-1,0))
		self.background.reparentTo(render)

		bounds = self.environment.getChild(0).getBounds()
		radius = bounds.getRadius()*1.5
		center = bounds.getCenter()+Vec3(0,12,0)
	
		#print center
	
		self.ball = []
		for i in range(self.ballNum+1):
			balls.define(self.ball,i,render,center,radius)

		# ** Load male character that will represent first player** #
		
		self.playerModel = Actor("models/gamedev/redguy-model",{"walk":"models/gamedev/redguy-run"})
		self.playerModel.reparentTo(render)
		self.playerModel.setScale(.1)
		self.playerModel.setH(90)

		# ** Position player at center of the field with it lying directly above the field. ** #
		self.playerModel.setPos(-10,0,0.76)

		# ** Load female character that will represent second player** #
		
		self.playerModel2 = Actor("models/gamedev/bluegirl-model",{"walk2":"models/gamedev/bluegirl-run"})
		self.playerModel2.reparentTo(render)
		self.playerModel2.setScale(.1)
		self.playerModel2.setH(0)

		# ** Position player at center of the field with it lying directly above the field. ** #

		self.playerModel2.setPos(10,0,1.0)

	def setupLighting(self):
		ambientLight = AmbientLight('ambientLight')
		ambientLight.setColor(Vec4(0.55,0.55,0.55,1.0))
		ambientLightNP = render.attachNewNode(ambientLight)
		render.setLight(ambientLightNP)
		dirLight = DirectionalLight('dirLight')
		dirLight.setColor(Vec4(0.6,0.6,0.6,1))
		dirLightNP = render.attachNewNode(dirLight)
		dirLightNP.setHpr(Vec3(0.0,-26.0,0.0))
		render.setLight(dirLightNP)

	def setupIntervals(self):
		self.charWalk1 = self.playerModel.actorInterval("walk")
		self.charWalk1.loop()
		self.charWalk1.pause()

		self.charWalk2 = self.playerModel2.actorInterval("walk2")
		self.charWalk2.loop( )
		self.charWalk2.pause( )

	def drop(self):
		dist = 49

		for i in range(self.ballNum+1):
			ballDrop = self.ball[i].posInterval(5.0,Vec3(self.ball[i].getX(),self.ball[i].getY(),self.ball[i].getZ()-dist))
			ballDrop.start()

	def dropSingle(self):
		dist = 49

		ballDrop = self.ball[self.ballNum].posInterval(5.0,Vec3(self.ball[self.ballNum].getX(),self.ball[self.ballNum].getY(),self.ball[self.ballNum].getZ()-dist))
		ballDrop.start()
				
	# #################
	# Begin definitions for tasks:  #
	# #################
	

	def walk(self):
		taskMgr.add(self.walkTask,'walkTask')
		self.charWalk1.loop()
	# end walk

	def stopWalk(self):
		taskMgr.remove('walkTask')
		self.charWalk1.pause()
		self.acceptOnce("w",self.walk)	
	# end stopWalk

	def walkTask(self,task):
		dt = globalClock.getDt()
		dist = self.speed1*dt
		angle = (self.playerModel.getH())*math.pi/180.0
		dx = dist*math.sin(angle)
		dy = dist*-math.cos(angle)
		self.playerModel.setPos(Vec3(self.playerModel.getX()+dx,self.playerModel.getY()+dy,self.playerModel.getZ()))
		return Task.cont
	# end walkTask

	def turn(self,dir):
		taskMgr.add(self.turnTask,'turnTask',extraArgs=[dir])
		#self.charTurn1.loop()
		self.ignore("a")
		self.ignore("d")
	# end turn

	def stopTurn(self):
		taskMgr.remove('turnTask')
		self.acceptOnce("a",self.turn,[-1])
		self.acceptOnce("d",self.turn,[1])
	# end stopTurn

	def turnTask(self,dir):
		dt = globalClock.getDt()
		angle = dir*self.turnSpeed1*dt
		self.playerModel.setH(self.playerModel.getH()-angle)
		return Task.cont
	# end turnTask

    # Player 2's Movement #

	def walk2(self):
		taskMgr.add(self.walkTask2,'walkTask2')
		self.charWalk2.loop()
	# end walk

	def stopWalk2(self):
		taskMgr.remove('walkTask2')
		self.charWalk2.pause()
		self.acceptOnce("o",self.walk2)
		# end stopWalk

	def walkTask2(self,task):
		dt = globalClock.getDt()
		dist = self.speed2*dt
		angle = (self.playerModel2.getH()-90)*math.pi/180.0
		dx = dist*math.sin(angle)
		dy = dist*-math.cos(angle)

		self.playerModel2.setPos(Vec3(self.playerModel2.getX()+dx,self.playerModel2.getY()+dy,self.playerModel2.getZ()))
		return Task.cont
		# end walkTask

	def turn2(self,dir):
		taskMgr.add(self.turnTask2,'turnTask2',extraArgs=[dir])
		self.ignore("k")
		self.ignore(";")
		# end turn

	def stopTurn2(self):
		taskMgr.remove('turnTask2')
		self.acceptOnce("k",self.turn2,[-1])
		self.acceptOnce(";",self.turn2,[1])
		# end stopTurn

	def turnTask2(self,dir):
		dt = globalClock.getDt()
		angle = dir*self.turnSpeed2*dt
		self.playerModel2.setH(self.playerModel2.getH()-angle)
		return Task.cont
		# end turnTask	

	def setupCollisions(self):
		self.cHandler = CollisionHandlerEvent()
		self.cHandler.setInPattern("ate-%in")
		self.cHandler.addInPattern('%fn-into-%in')        
		self.cHandler.setAgainPattern('%fn-again-%in')          
		self.cHandler.setOutPattern('%fn-outof-%in')        
		self.cTrav = CollisionTraverser()
		base.cTrav = self.cTrav

		#Player 1 collision solid
		
		bounds = self.playerModel.getChild(0).getBounds()
		center = bounds.getCenter()-Vec3(0,0,12)
		radius = bounds.getRadius()-18
		boundsB = self.playerModel.getChild(0).getBounds()
		centerB = bounds.getCenter()-Vec3(0,0,-4)
		radiusB = bounds.getRadius()-20
		cSphere = CollisionSphere(center,radius)
		cSphereB = CollisionSphere(centerB,radiusB)
		cNode = CollisionNode("player1")
		cNode.addSolid(cSphere)
		cNode.addSolid(cSphereB)
		cNodePath = self.playerModel.attachNewNode(cNode)
		#cNodePath.show()
	
		#Player 2 collision solid
		bounds2 = self.playerModel2.getChild(0).getBounds()
		center2 = bounds2.getCenter()-Vec3(0,0,-4)
		radius2 = bounds2.getRadius()-20
		cSphere2 = CollisionSphere(center2,radius2)
		bounds2B = self.playerModel2.getChild(0).getBounds()
		center2B = bounds2B.getCenter()-Vec3(0,0,12)
		radius2B = bounds2B.getRadius()-18
		cSphere2B = CollisionSphere(center2B,radius2B)
		cNode2 = CollisionNode("player2")
		cNode2.addSolid(cSphere2)
		cNode2.addSolid(cSphere2B)
		cNodePath2 = self.playerModel2.attachNewNode(cNode2)
		#cNodePath2.show()

		self.cTrav.addCollider(cNodePath,self.cHandler)
		self.cTrav.addCollider(cNodePath2,self.cHandler)
		self.cTrav.addCollider(cNodePath,self.cHandler)
		self.cTrav.addCollider(cNodePath2,self.cHandler)       

		bounds = self.environment.getChild(0).getBounds()
		center = bounds.getCenter()
		radius = bounds.getRadius()*.71
		#print radius
		cSphere = CollisionInvSphere(center,radius)
		cNode = CollisionNode("Arena")
		cNode.addSolid(cSphere)
		cNodePath = self.environment.attachNewNode(cNode)
		#cNodePath.show()


		for i in range(self.ballNum+1):
			boundsB = self.ball[i].getChild(0).getBounds()
			centerB = boundsB.getCenter()
			radiusB = boundsB.getRadius()*.8
			cSphereB = CollisionSphere(centerB,radiusB)
			cNodeB = CollisionNode("ball")
			cNodeB.addSolid(cSphereB)
			cNodePathB = self.ball[i].attachNewNode(cNodeB)
			#cNodePath3.show()
		
		self.accept("ate-ball", self.eat)
		self.accept( 'player1-into-Arena', self.colliding1)
		self.accept( 'player1-again-Arena', self.colliding1)
		self.accept( 'player1-outof-Arena', self.notColliding1)
	
		self.accept( 'player2-into-Arena', self.colliding2)
		self.accept( 'player2-again-Arena', self.colliding2)
		self.accept( 'player2-outof-Arena', self.notColliding2)
		
		self.accept( 'player1-into-player2', self.colliding1)
		self.accept( 'player1-again-player2', self.colliding1)
		self.accept( 'player1-outof-player2', self.notColliding1)
		
		self.accept( 'player2-into-player1', self.colliding2)
		self.accept( 'player2-again-player1', self.colliding2)
		self.accept( 'player2-outof-player1', self.notColliding2)

	def eat(self,cEntry):
		if str(cEntry.getIntoNodePath().getParent()) == "render/blueball": #Blue ball picked up, update score
			self.player2Score+=1

		elif str(cEntry.getIntoNodePath().getParent()) == "render/redball": #Red ball picked up, update score
			self.player1Score+=1

		elif str(cEntry.getIntoNodePath().getParent()) == "render/crystalball":  #Freezes the field (Ice)
			self.environment.setColor(0,.9,1)
			taskMgr.doMethodLater(10, self.switch, 'changeStage') 
			self.speed1 = 14
			self.speed2 = 14
			self.turnSpeed1 = 110
			self.turnSpeed2 = 110
			taskMgr.doMethodLater(10, self.returnSpeeds, 'returnSpeedsToNormal') 

		elif str(cEntry.getIntoNodePath().getParent()) == "render/red_blue": #Switch Sphere Colors
			for i in self.ball:
				if i.getName() == "blueball":
					i.removeNode() 
					children = i.getGeomNode().getChildren() 
					children.detach() 
					i.loadModel("models/gamedev/redball") 
					i.setName("redball")
					i.reparentTo(render) 
	
				elif i.getName() == "redball":
					i.removeNode() 
					children = i.getGeomNode().getChildren() 
					children.detach() 
					i.loadModel("models/gamedev/blueball")
					i.setName("blueball")					
					i.reparentTo(render) 
	
		elif str(cEntry.getIntoNodePath().getParent()) == "render/fireball": #Stop your opponent for a few seconds
			if (str(cEntry.getFromNodePath().getParent()) == "render/redgirl") or (str(cEntry.getFromNodePath().getParent()) == "render/redguy"):
				self.speed2 = 0
				self.turnSpeed2 = 0
				self.ignore("o")
				taskMgr.doMethodLater(3, self.returnSpeeds2, 'returnSpeedsToNormal') 
			else:
				self.speed1 = 0
				self.turnSpeed1 = 0
				self.ignore("w")
				taskMgr.doMethodLater(3, self.returnSpeeds2, 'returnSpeedsToNormal') 
	
		elif str(cEntry.getIntoNodePath().getParent()) == "render/black_white":
			self.ignoreColl = 1
			x = Vec3(self.playerModel.getPos())
			y = Vec3(self.playerModel2.getPos())
			self.playerModel.setPos(y)
			self.playerModel2.setPos(x)
			self.ignoreColl = 0

		elif str(cEntry.getIntoNodePath().getParent()) == "render/golden":
			if (str(cEntry.getFromNodePath().getParent()) == "render/redgirl") or (str(cEntry.getFromNodePath().getParent()) == "render/redguy"):
				self.speed1 = 14
				self.turnSpeed1 = 110
				taskMgr.doMethodLater(8, self.returnSpeeds3, 'returnSpeedsToNormal') 
			else:
				self.speed2 = 14
				self.turnSpeed2 = 110
				taskMgr.doMethodLater(8, self.returnSpeeds3, 'returnSpeedsToNormal') 
	
		elif str(cEntry.getIntoNodePath().getParent()) == "render/greenball":
			if (str(cEntry.getFromNodePath().getParent()) == "render/redgirl") or (str(cEntry.getFromNodePath().getParent()) == "render/redguy"):
				self.player1Score += 5
			else:
				self.player2Score += 5

		elif str(cEntry.getIntoNodePath().getParent()) == "render/blackball":
			camera.setPosHpr(Vec3(0,-55,110), Vec3(0,-20,0))
			taskMgr.doMethodLater(5,self.restoreCamera,'restoreCamera')
	
		elif str(cEntry.getIntoNodePath().getParent()) == "render/translucent":
			for i in self.ball:
				i.hide()
				taskMgr.doMethodLater(6,self.showBalls,'returnBallsToNormal')
	
		cEntry.getIntoNodePath().getParent().removeNode()
		
		#Drop a New Ball
		
		bounds = self.environment.getChild(0).getBounds()
		radius = bounds.getRadius()*1.8
		center = bounds.getCenter()+Point3(0,10,0)
		self.ballNum+=1
		balls.define(self.ball,self.ballNum,render,center,radius)
		
		boundsB = self.ball[self.ballNum].getChild(0).getBounds()
		centerB = boundsB.getCenter()
		radiusB = boundsB.getRadius()*.8
		cSphereB = CollisionSphere(centerB,radiusB)
		cNodeB = CollisionNode("ball")
		cNodeB.addSolid(cSphereB)
		cNodePathB = self.ball[self.ballNum].attachNewNode(cNodeB)
		
		self.dropSingle()

	def showBalls(self,task):
		for i in self.ball:
			i.show()

	def restoreCamera(self,task):
		camera.setPosHpr(Vec3(0,-55,30), Vec3(0,-20,0))

	def switch(self,task):
		self.environment.removeNode()
		self.environment = loader.loadModel("models/gamedev/grassy")
		self.environment.reparentTo(render)
		self.environment.setScale(3.4)
		self.environment.setPos(0,12,-0.45)
		self.environment.setH(78)

	def colliding1( self, collEntry ): # accept a collision entry argument    
		if self.ignoreColl == 0:
			self.player1IsColliding = 1 # we are colliding        
			self.stopWalk( ) # pause all walking animation and movement        
			disp = ( collEntry.getSurfacePoint( render ) - collEntry.getInteriorPoint( render ) )
			newPos = self.playerModel.getPos( ) + disp # get new position
			self.playerModel.setPos( newPos ) # and set it to tiny's position
	# end colliding        

	def notColliding1( self, collEntry ): 
		self.player1IsColliding = 0    

	def colliding2( self, collEntry ): # accept a collision entry argument 
		if self.ignoreColl == 0:
			self.player2IsColliding = 1 # we are colliding        
			self.stopWalk2( ) # pause all walking animation and movement               
			disp = ( collEntry.getSurfacePoint( render ) - collEntry.getInteriorPoint( render ) )
			newPos = self.playerModel2.getPos( ) + disp # get new position
			self.playerModel2.setPos( newPos ) # and set it to tiny's position
	# end colliding        

	def notColliding2( self, collEntry ): 
		self.player2IsColliding = 0    

	def returnSpeeds(self,task):
		self.speed1 = 8.0
		self.speed2 = 8.0
		self.turnSpeed1 = 80.0
		self.turnSpeed2 = 80.0

	def returnSpeeds2(self,task):
		self.acceptOnce("w",self.walk)
		self.acceptOnce("o",self.walk2)
		self.speed1 = 8.0
		self.speed2 = 8.0
		self.turnSpeed1 = 80.0
		self.turnSpeed2 = 80.0

	def returnSpeeds3(self,task):
		self.speed1 = 8.0
		self.speed2 = 8.0
		self.turnSpeed1 = 80.0
		self.turnSpeed2 = 80.0

	def changeMusic(self,task):
		self.music.stop()
		self.music2  = loader.loadMusic("models/gamedev/ADRENALINE.mp3")
		self.music2.play()

	def clockTask(self,task):
		self.timer.removeNode()
		self.timer = DirectFrame(text = "%d" % (self.gameLen-globalClock.getRealTime(),), pos = Vec3(0,-11.5,23.5),text_fg = (1,1,1,1),text_scale= 4.0)
		self.timer['frameSize'] = (0,0,0,0)
		self.timer.reparentTo(render)
		return Task.cont

	def endGame(self,task):
		taskMgr.removeTasksMatching('returnSpeedsToNormal')
		taskMgr.removeTasksMatching('restoreCamera')
		taskMgr.removeTasksMatching('clockTask')
		taskMgr.removeTasksMatching('walkTask')
		taskMgr.removeTasksMatching('walkTask2')
		taskMgr.removeTasksMatching('turnTask')
		taskMgr.removeTasksMatching('turnTask2')

		self.music2.stop()
		self.music3  = loader.loadMusic("models/gamedev/CSTAR.mp3")
		self.music3.play()

		self.speed1 = 0
		self.speed2 = 0
		self.turnSpeed1 = 0.0
		self.turnSpeed2 = 0.0
		
	def getScores(self):
		return (self.player1Score, self.player2Score)
		
	def getGameLen(self):
		return self.gameLen
		
	def stopMusic(self):
		self.music3.stop()
		
	def destroy(self):
		self.hud.destroy()
		self.timer.destroy()
		self.environment.removeNode()
		self.playerModel.removeNode()
		self.playerModel2.removeNode()
		self.background.destroy()
		
		for i in range(self.ballNum+1):
			self.ball[i].removeNode()

#lvl02 = Lvl02()
#run()
Beispiel #16
0
class Lvl01(DirectObject):
	#constructor
	def start(self):
		base.disableMouse() #turn off mouse camera control
		#camera.setPosHpr(Vec3(93,-90,0), Vec3(0,0,0))
		# Turn off the default camera and replace it with two new cameras, with 
		# side-by-side DisplayRegions. 
		
		base.camNode.setActive(0)
		base.makeCamera(base.win, displayRegion = (0, 0.48, 0, 1)) 
		base.makeCamera(base.win, displayRegion = (0.52, 1, 0, 1))
		base.makeCamera(base.win, displayRegion = (0.48,0.52,0,1))
	
		base.camList[3].setPos(Vec3(144,0,-1000))
		
		self.gameLen = 100
		
		self.numActuator = 10
		
		self.music = loader.loadMusic("models/gamedev/AD.mp3")
		self.music.play()
		
		globalClock.reset()
		self.timer = OnscreenText("%d" % (self.gameLen-globalClock.getRealTime(),), pos = (98,145), scale = 18.0)
		self.timer.setColor(1,1,1)
		taskMgr.add(self.clockTask,"clockTask")
	
		self.actCount = 0
		self.speed1 = 3
		self.speed2 = 3
		self.climbSpeed1 = 1
		self.climbSpeed2 = 1
		self.climbing1 = 0
		self.climbing2 = 0
	
                self.array = []
                
                self.loadModels()
                self.setupLighting()
                self.setupStage()
                self.setupCollisions()
                self.setupIntervals()
                
                self.player1Score = 0
                self.player2Score = 0
                  
                self.dir1 = 1
                self.dir2 = 1
                self.nodeCount1 = 0
		self.nodeCount2 = 0

		taskMgr.add(self.cameraFollowTask,"cameraFollowTask")
		taskMgr.add(self.boulderTask,"boulderTask")
		
		taskMgr.doMethodLater(self.gameLen,self.endGame,'endGame')

		#setup key controls
		self.accept("escape",sys.exit)
		#self.accept("w",self.rise)
		#self.accept("o",self.rise2)
	
		#Player 1 movement keys
	
		#self.accept("s",self.fall)
		
		self.acceptOnce("a",self.left)
		self.acceptOnce("d",self.right)
	
		self.accept("a-up",self.stopLeft)
		self.accept("d-up",self.stopRight)
	
		self.acceptOnce("w", self.jump)
		self.acceptOnce("o", self.jumpT2)
	
		#Player 2 movement keys
		#self.accept("l",self.fall2)
		
		self.acceptOnce("k",self.left2)
		self.acceptOnce(";",self.right2)
	
		self.accept("k-up",self.stopLeft2)
		self.accept(";-up",self.stopRight2)
	
		self.jumpOK = 1

	def loadModels(self):
		
		print "start loadModels"
		
		self.playerModel = Actor("models/gamedev/redguy-model",{"walk":"models/gamedev/redguyrun",
			"jump":"models/gamedev/redguy-jump","climb":"models/gamedev/redguy-climb"})
		self.playerModel.reparentTo(render)
		self.playerModel.setScale(.7)
		self.playerModel.setPosHpr(Vec3(46,0,0),Vec3(0,0,0))
		self.playerModel.setH(90)
	
	
		self.playerModel2 = Actor("models/gamedev/bluegirl-model",{"walk2":"models/gamedev/bluegirlrun",
			"jump2":"models/gamedev/bluegirl-jump","climb2":"models/gamedev/bluegirl-climb"})
		self.playerModel2.reparentTo(render)
		self.playerModel2.setScale(.7)
		self.playerModel2.setPosHpr(Vec3(333,0,0),Vec3(0,0,0))
		self.playerModel2.setH(270)

		self.divider = loader.loadModel("models/gamedev/divider")
		self.divider.setPos(144,0,-1000)
		self.divider.setScale(5.0)
		self.divider.reparentTo(render)
		
		self.boulder1 = loader.loadModel("models/gamedev/boulder")
		self.boulder1.reparentTo(render)
		self.boulder1.setScale(7)
		self.boulder1.setPos(46,0,-50)
		self.boulder2 = loader.loadModel("models/gamedev/boulder")
		self.boulder2.reparentTo(render)
		self.boulder2.setScale(7)
		self.boulder2.setPos(333,0,-50)
		
		#loader.loadModel("models/gamedev/actuatorOn")
		
		bounds = self.boulder1.getChild(0).getBounds()
		center = bounds.getCenter()
		radius = bounds.getRadius()*.7
		cSphere = CollisionSphere(center,radius)
		cNode = CollisionNode("boulder")
		cNode.addSolid(cSphere)
		cNodePath = self.boulder1.attachNewNode(cNode)
		#cNodePath.show()
		cNodePath = self.boulder2.attachNewNode(cNode)
		#cNodePath.show()
		
		print "end loadModels"

	def setupStage(self):
		
		print "start setupStage"
		
		self.background = OnscreenImage(image = 'models/gamedev/lvl1background.jpg', pos = (175,5,0),scale=500)
		self.background.reparentTo(render)
	
		x1= 4.9
		x2 = -4.9
		len = 9.8
		h = 0
		a = 0
		p = 0
		j=0
		m=0
		x1b=0
		x2b=0

		while self.actCount < self.numActuator:
			if j > 0:
				lOld = l
				rOld = r
				x1Old = x1
				x2Old = x2
				x1 = (x1Old+x2Old)/2 + 4.9
				x2 = (x1Old+x2Old)/2 - 4.9
				x1o=x1
				x2o=x2
				
				for count in range(1):
					l = random.randint(0,(10-lOld)+((10+rOld)-(10-lOld))/2)
					r = random.randint(0,20-((10-lOld)+((10+rOld)-(10-lOld))/2))
					if r+2 <= 20-((10-lOld)+((10+rOld)-(10-lOld))/2):
						r += 2
					if l+2 < (10-lOld)+((10+rOld)-(10-lOld))/2:
						l += 2
					if 	l+r < 4:
						count = 0
				p = random.randint(0,1)
			else:
				l = 10
				r = 10
				c = 10
			#while a == 0:
			a = random.randint(-l,r)
			if j > 0:
				if j % 2 == 0:
					self.ladder = loader.loadModel("models/gamedev/ladder")
					self.ladder.reparentTo(render)
					self.ladder.setScale(1.5)
					self.ladder.setPos(x1+m,0,h-20)
					self.ladder2 = loader.loadModel("models/gamedev/ladder")
					self.ladder2.reparentTo(render)
					self.ladder2.setScale(1.5)
					self.ladder2.setPos(x1+286+m,0,h-20)
                                        self.array.append(self.ladder)
                                        self.array.append(self.ladder2)
					
				else:
					self.ladder = loader.loadModel("models/gamedev/ladder")
					self.ladder.reparentTo(render)
					self.ladder.setScale(1.5)
					self.ladder.setPos(x2,0,h-20)
					self.ladder2 = loader.loadModel("models/gamedev/ladder")
					self.ladder2.reparentTo(render)
					self.ladder2.setScale(1.5)
					self.ladder2.setPos(x2+286,0,h-20)
                                        self.array.append(self.ladder)
                                        self.array.append(self.ladder2)
				k=-10
				while k <= 13:
					cSphere = CollisionSphere(Point3(1.5,0,k),.5)
					cNode = CollisionNode("ladder")
					cNode.addSolid(cSphere)
					cNodePath = self.ladder.attachNewNode(cNode)
					cNodePath = self.ladder2.attachNewNode(cNode)
					#cNodePath.show()
					k+=1
                                        self.array.append(self.ladder)
				
				#cSphere = CollisionSphere(Point3(1.5,0,h-40),.5)
				#cNodeB = CollisionNode("canWalk")
				#cNodeB.addSolid(cSphere)
				#cNodePath = self.ladder.attachNewNode(cNodeB)
				#cNodePath = self.ladder2.attachNewNode(cNodeB)
			for i in range(r):
				'''Right half of stage'''
				self.environment = loader.loadModel("models/gamedev/platform")
				self.environment.reparentTo(render)
				self.environment.setScale(5)
				self.environment.setPos(x1,0,h)
				self.environment2 = loader.loadModel("models/gamedev/platform")
				self.environment2.reparentTo(render)
				self.environment2.setScale(5)
				self.environment2.setPos(x1+286,0,h)
                                self.array.append(self.environment)
                                self.array.append(self.environment2)
				
				#if i == 0 and j > 0:
				#	cSphere = CollisionSphere(Point3((m/9.8)*1.9,0,0),.5)
				#	cNode = CollisionNode("platform")
				#	cNode.addSolid(cSphere)
				#	cNodePath = self.environment.attachNewNode(cNode)
				#	cNodePath = self.environment2.attachNewNode(cNode)
				#	cNodePath.show()
				
				if r == i+1:
					cSphere = CollisionSphere(Point3(2,0,0),2)
					if i == 9:
						cNode = CollisionNode("rwall")
					else:
						cNode = CollisionNode("redge")
					cNode.addSolid(cSphere)
					cNodePath = self.environment.attachNewNode(cNode)
					cNodePath = self.environment2.attachNewNode(cNode)
					#cNodePath.show()
				if a == i:
					self.actCount+=1
					self.actuator = Actor("models/gamedev/actuator")
					self.actuator.reparentTo(render)
					self.actuator.setPos(self.environment.getPos())
					if p == 1:
						self.actuator.setZ(self.actuator.getZ())
						self.actuator.setP(self.actuator.getP()+180)
					self.actuator.setScale(2)
					self.actuator.setH(self.actuator.getH()+180)
                                        self.array.append(self.actuator)
					bounds = self.actuator.getChild(0).getBounds()
					center = bounds.getCenter()
					radius = bounds.getRadius()-.5
					cSphere = CollisionSphere(center,radius)
					cNode = CollisionNode("actuator")
					cNode.addSolid(cSphere)
					cNodePath = self.actuator.attachNewNode(cNode)
					#cNodePath.show()
					
					self.actuator2 = Actor("models/gamedev/actuator")
					self.actuator2.reparentTo(render)
					self.actuator2.setPos(self.environment2.getPos())
					if p == 1:
						self.actuator2.setZ(self.actuator2.getZ())
						self.actuator2.setP(self.actuator2.getP()+180)
					self.actuator2.setScale(2)
					self.actuator2.setH(self.actuator2.getH()+180)
                                        self.array.append(self.actuator2)
					bounds = self.actuator2.getChild(0).getBounds()
					center = bounds.getCenter()
					radius = bounds.getRadius()-.5
					cSphere = CollisionSphere(center,radius)
					cNode = CollisionNode("actuator")
					cNode.addSolid(cSphere)
					cNodePath = self.actuator2.attachNewNode(cNode)
					#cNodePath.show()
				x1 = x1 + len

			for i in range(l):
				'''Left Half of stage'''
				self.environment = loader.loadModel("models/gamedev/platform")
				self.environment.reparentTo(render)
				self.environment.setScale(5)
				self.environment.setPos(x2,0,h)
                                self.array.append(self.environment)
				self.environment2 = loader.loadModel("models/gamedev/platform")
				self.environment2.reparentTo(render)
				self.environment2.setScale(5)
				self.environment2.setPos(x2+286,0,h)
                                self.array.append(self.environment2)

				if l == i+1:
					cSphere = CollisionSphere(Point3(-2,0,0),2)
					if i == 9:
						cNode = CollisionNode("lwall")
					else:
						cNode = CollisionNode("ledge")
					cNode.addSolid(cSphere)
					cNodePath = self.environment.attachNewNode(cNode)
					cNodePath = self.environment2.attachNewNode(cNode)
					#cNodePath.show()
				if a == -i:
					self.actCount+=1
					self.actuator = Actor("models/gamedev/actuator")
					self.actuator.reparentTo(render)
					self.actuator.setPos(self.environment.getPos())
					self.actuator.setScale(2)
                                        self.array.append(self.actuator)
					bounds = self.actuator.getChild(0).getBounds()
					center = bounds.getCenter()
					radius = bounds.getRadius()-.5
					cSphere = CollisionSphere(center,radius)
					cNode = CollisionNode("actuator")
					cNode.addSolid(cSphere)
					cNodePath = self.actuator.attachNewNode(cNode)
					#cNodePath.show()
					
					self.actuator = Actor("models/gamedev/actuator")
					self.actuator.reparentTo(render)
					self.actuator.setPos(self.environment2.getPos())
					self.actuator.setScale(2)
                                        self.array.append(self.actuator)
					bounds = self.actuator.getChild(0).getBounds()
					center = bounds.getCenter()
					radius = bounds.getRadius()-.5
					cSphere = CollisionSphere(center,radius)
					cNode = CollisionNode("actuator")
					cNode.addSolid(cSphere)
					cNodePath = self.actuator.attachNewNode(cNode)
					#cNodePath.show()
				x2 = x2 - len
			j+=1    
			h = h+40
			#x1 = 4.9
			#x2 = -4.9
			a = 0
		self.h = h+50
		x2b=x2o
		x1b=x1o
		
		print "end setupStage"

	def setupLighting(self):
		
		print "start setupLighting"
		
		ambientLight = AmbientLight('ambientLight')
		ambientLight.setColor(Vec4(0.55,0.55,0.55,1.0))
		ambientLightNP = render.attachNewNode(ambientLight)
		render.setLight(ambientLightNP)
		dirLight = DirectionalLight('dirLight')
		dirLight.setColor(Vec4(0.6,0.6,0.6,1))
		dirLightNP = render.attachNewNode(dirLight)
		dirLightNP.setHpr(Vec3(0.0,-26.0,0.0))
		render.setLight(dirLightNP)
		
		print "end setupLighting"
	
	def setupIntervals(self):
		
		print "start setupIntervals"
		
		self.charWalk1 = self.playerModel.actorInterval("walk")
		self.charWalk1.loop( )
		self.charWalk1.pause( )
		
		self.charWalk2 = self.playerModel2.actorInterval("walk2")
		self.charWalk2.loop( )
		self.charWalk2.pause( )
		
		self.jump1 = self.playerModel.actorInterval("jump")
		self.jump1.loop()
		self.jump1.pause()
		
		self.jump2 = self.playerModel2.actorInterval("jump2")
		self.jump2.loop()
		self.jump2.pause()
		
		self.climb1 = self.playerModel.actorInterval("climb")
		self.climb1.loop()
		self.climb1.pause()
		
		self.climb2 = self.playerModel2.actorInterval("climb2")
		self.climb2.loop()
		self.climb2.pause()
		
		print "end setupIntervals"
	
	# PLAYER ONE #

	def left(self):
		taskMgr.add(self.leftTask,'leftTask')
		self.charWalk1.loop()
		#end left
		
	def leftTask(self,task):
		if self.climbing1 == 0:
			self.playerModel.setH(270)
			self.playerModel.setPos(Vec3(self.playerModel.getX()-self.speed1, self.playerModel.getY(), self.playerModel.getZ()))
		return Task.cont

	def right(self):
		taskMgr.add(self.rightTask,'rightTask')
		self.charWalk1.loop()
		#end right
		
	def rightTask(self,task):
		if self.climbing1 == 0:
			self.playerModel.setH(90)
			self.playerModel.setPos(Vec3(self.playerModel.getX()+self.speed1, self.playerModel.getY(), self.playerModel.getZ()))
		return Task.cont	

	def climbable(self,cEntry):
		self.nodeCount1+=1
		print self.nodeCount1
		self.ignore("w")
		self.ignore("w-up")
		self.ignore("s")
		self.ignore("s-up")
		self.acceptOnce("w",self.climb,[1])
		self.accept("w-up",self.noClimb)
		self.acceptOnce("s",self.climb,[-1])
		self.accept("s-up",self.noClimb)

	def climb(self,dir):
		self.dir1 = dir
		self.climbing1 = 1
		self.climbSpeed1 = 1
		self.ignore("a")
		self.ignore("a-up")
		self.ignore("d")
		self.ignore("d-up")
		taskMgr.add(self.climbTask,'climbTask')
		self.climb1.loop()
		
	def noClimb(self):
		taskMgr.remove('climbTask')
		self.climb1.pause()
		if self.nodeCount1 == 0:
			self.climbing = 0
		self.climbSpeed1 = 0
		self.acceptOnce("w",self.climb,[1])
		self.acceptOnce("s",self.climb,[-1])
		
	def jumpable(self,cEntry):
		self.nodeCount1+=-1
		print self.nodeCount1
		if self.nodeCount1 == 0:
			taskMgr.remove('climbTask')
			self.ignore("w")
			self.ignore("w-up")
			self.ignore("s")
			self.ignore("s-up")
			self.acceptOnce("w",self.jump)
			self.acceptOnce("a",self.left)
			self.acceptOnce("d",self.right)
			self.accept("a-up",self.stopLeft)
			self.accept("d-up",self.stopRight)
			self.climbing1 = 0
			self.climbSpeed1 = 0
			self.climb1.pause()
			
	def walkable(self,cEntry):
		self.ignore("w")
		self.ignore("w-up")
		self.ignore("s")
		self.ignore("s-up")
		self.acceptOnce("w",self.climb,[1])
		self.accept("w-up",self.noClimb)
		self.acceptOnce("s",self.climb,[-1])
		self.accept("s-up",self.noClimb)
		self.acceptOnce("a",self.left)
		self.acceptOnce("d",self.right)
		self.accept("a-up",self.stopLeft)
		self.accept("d-up",self.stopRight)
		self.climbing1 = 0
		self.climbSpeed1 = 0
		self.climb1.pause()
			
	def climbTask(self,task):
		if self.playerModel.getZ() >=0:
			self.playerModel.setH(0)
			self.playerModel.setPos(Vec3(self.playerModel.getX(), self.playerModel.getY(), self.playerModel.getZ()+self.climbSpeed1*self.dir1))
		return Task.cont	
	
	def jump(self):
		if self.nodeCount1 == 0:
			self.ignore("w")
			self.ignore("w-up")
			z = self.playerModel.getZ()
			j = ProjectileInterval(self.playerModel, startPos = self.playerModel.getPos(), startVel = Point3(0,0,27), endZ = z)
			j.start()
			taskMgr.doMethodLater(3,self.jumpTask,"jumpTask")
		else:
			self.acceptOnce("w",self.climb,[1])
			
	def jumpTask(self, task):
		if self.climbing1 == 0:
			self.jump1.pause()
			self.acceptOnce("w",self.jump)
		#return task.cont

	def allowRight(self):
		self.acceptOnce("d",self.right)

	def noRight(self):
		taskMgr.remove('rightTask')
		self.charWalk1.pause()
		self.acceptOnce("d",self.right)

	def stopRight(self):
		self.noRight()
		#self.allowRight()
		
	def rightWall(self,cEntry):
		self.ignore("d")
		self.noRight()
		
	def rightEdge(self,cEntry):
		self.ignore("d")
		self.noRight()
				
	def rightOK(self,cEntry):
		self.allowRight()	
		
	def allowLeft(self):
		self.acceptOnce("a",self.left)

	def noLeft(self):
		taskMgr.remove('leftTask')
		self.charWalk1.pause()
		self.acceptOnce("a",self.left)

	def stopLeft(self):
		self.noLeft()
		#self.allowLeft()
		
	def leftWall(self,cEntry):
		self.ignore("a")
		self.noLeft()
		
	def leftEdge(self,cEntry):
		self.ignore("a")
		self.noLeft()
		
	def leftOK(self,cEntry):
		self.allowLeft()

	# PLAYERTWO #

	def left2(self):
		taskMgr.add(self.leftTask2,'leftTask2')
		self.charWalk2.loop()
		#end left
		
	def leftTask2(self,task):
		if self.climbing2 == 0:
			self.playerModel2.setH(0)
			self.playerModel2.setPos(Vec3(self.playerModel2.getX()-self.speed2, self.playerModel2.getY(), self.playerModel2.getZ()))
		return Task.cont

	def right2(self):
		taskMgr.add(self.rightTask2,'rightTask2')
		self.charWalk2.loop()
		#end right
		
	def rightTask2(self,task):
		if self.climbing2 == 0:
			self.playerModel2.setH(180)
			self.playerModel2.setPos(Vec3(self.playerModel2.getX()+self.speed2, self.playerModel2.getY(), self.playerModel2.getZ()))
		return Task.cont	

	def climbable2(self,cEntry):
		self.nodeCount2+=1
		#print self.nodeCount1
		self.ignore("o")
		self.ignore("o-up")
		self.ignore("l")
		self.ignore("l-up")
		self.acceptOnce("o",self.climbT2,[1])
		self.accept("o-up",self.noClimb2)
		self.acceptOnce("l",self.climbT2,[-1])
		self.accept("l-up",self.noClimb2)

	def climbT2(self,dir):
		self.dir2 = dir
		self.climbing2 = 1
		self.climbSpeed2 = 1
		self.ignore("k")
		self.ignore("k-up")
		self.ignore(";")
		self.ignore(";-up")
		taskMgr.add(self.climbTask2,'climbTask2')
		self.climb2.loop()
		
	def noClimb2(self):
		taskMgr.remove('climbTask2')
		self.climb2.pause()
		if self.nodeCount2 == 0:
			self.climbing2 = 0
		self.climbSpeed2 = 0
		self.acceptOnce("o",self.climbT2,[1])
		self.acceptOnce("l",self.climbT2,[-1])
		
	def jumpable2(self,cEntry):
		self.nodeCount2+=-1
		#print self.nodeCount2
		if self.nodeCount2 == 0:
			taskMgr.remove('climbTask2')
			self.ignore("o")
			self.ignore("o-up")
			self.ignore("l")
			self.ignore("l-up")
			self.acceptOnce("o",self.jumpT2)
			self.acceptOnce("k",self.left2)
			self.acceptOnce(";",self.right2)
			self.accept("k-up",self.stopLeft2)
			self.accept(";-up",self.stopRight2)
			self.climbing2 = 0
			self.climbSpeed2 = 0
			self.climb2.pause()
			
	def walkable2(self,cEntry):
		self.ignore("o")
		self.ignore("o-up")
		self.ignore("l")
		self.ignore("l-up")
		self.acceptOnce("o",self.climbT2,[1])
		self.accept("o-up",self.noClimb2)
		self.acceptOnce("l",self.climbT2,[-1])
		self.accept("l-up",self.noClimb2)
		self.acceptOnce("k",self.left2)
		self.acceptOnce(";",self.right2)
		self.accept("k-up",self.stopLeft)
		self.accept(";-up",self.stopRight)
		self.climbing2 = 0
		self.climbSpeed2 = 0
		self.climb2.pause()
			
	def climbTask2(self,task):
		if self.playerModel2.getZ() >=0:
			self.playerModel2.setH(90)
			self.playerModel2.setPos(Vec3(self.playerModel2.getX(), self.playerModel2.getY(), self.playerModel2.getZ()+self.climbSpeed2*self.dir2))
		return Task.cont	
	
	def jumpT2(self):
		if self.nodeCount2 == 0:
			self.ignore("o")
			self.ignore("o-up")
			z = self.playerModel2.getZ()
			j = ProjectileInterval(self.playerModel2, startPos = self.playerModel2.getPos(), startVel = Point3(0,0,27), endZ = z)
			j.start()
			taskMgr.doMethodLater(3,self.jumpTask2,"jumpTask2")
		else:
			self.acceptOnce("w",self.climb,[1])
			
	def jumpTask2(self, task):
		if self.climbing2 == 0:
			self.jump2.pause()
			self.acceptOnce("o",self.jumpT2)
		#return task.cont

	def allowRight2(self):
		self.acceptOnce(";",self.right2)

	def noRight2(self):
		taskMgr.remove('rightTask2')
		self.charWalk2.pause()
		self.acceptOnce(";",self.right2)

	def stopRight2(self):
		self.noRight2()
		#self.allowRight()
		
	def rightWall2(self,cEntry):
		self.ignore(";")
		self.noRight2()
		
	def rightEdge2(self,cEntry):
		self.ignore(";")
		self.noRight2()
				
	def rightOK2(self,cEntry):
		self.allowRight2()	
		
	def allowLeft2(self):
		self.acceptOnce("k",self.left2)

	def noLeft2(self):
		taskMgr.remove('leftTask2')
		self.charWalk2.pause()
		self.acceptOnce("k",self.left2)

	def stopLeft2(self):
		self.noLeft2()
		#self.allowLeft()
		
	def leftWall2(self,cEntry):
		self.ignore("k")
		self.noLeft2()
		
	def leftEdge2(self,cEntry):
		self.ignore("k")
		self.noLeft2()
		
	def leftOK2(self,cEntry):
		self.allowLeft2()

	def cameraFollowTask(self,task):
		base.camList[1].setPos(Vec3(self.playerModel.getX(),-200,self.playerModel.getZ()+30))
		base.camList[2].setPos(Vec3(self.playerModel2.getX(),-200,self.playerModel2.getZ()+30))
		return task.cont
	
	def activate(self,cEntry):
		i = cEntry.getIntoNodePath().getParent()
		where = i.getPos()
		which = i.getHpr()
		i.detachNode() 
		i = Actor("models/gamedev/actuatorOn")
		i.setName("actuatorOn")
		i.setPosHpr(where,which)
		i.setScale(2)
                i.reparentTo(render)
                self.array.append(i)
                
                if i.getX() < 144:
                        self.player1Score += 3
                else:
                        self.player2Score += 3

	def stun(self,cEntry):
		ow = Sequence(Func(self.startStun), Wait(3), Func(self.stopStun))
		ow.start()
	
	def startStun(self):
		self.speed1 = 0
		self.climbspeed1 = 0
		self.ignore("w")
		self.ignore("w-up")
		self.ignore("a")
		self.ignore("d")
		self.ignore("a-up")
		self.ignore("d-up")
		taskMgr.remove('leftTask')
		taskMgr.remove('rightTask')
		taskMgr.remove('climbTask')
		taskMgr.remove('jumpTask')
		self.playerModel.stop()
		#self.ignore("player1-ladder")
	
	def stopStun(self):
		self.speed1 = 3
		self.climbspeed1 = 1
		self.acceptOnce("a",self.left)
		self.acceptOnce("d",self.right)
		self.accept("a-up",self.stopLeft)
		self.accept("d-up",self.stopRight)
		self.acceptOnce("w",self.jump)
		#self.accept("player1-ladder", self.climbable)
	
	def stun2(self,cEntry):
		ow = Sequence(Func(self.startStun2), Wait(3), Func(self.stopStun2))
		ow.start()
	
	def startStun2(self):
		self.speed2 = 0
		self.climbspeed2 = 0
		self.ignore("k")
		self.ignore(";")
		self.ignore("k-up")
		self.ignore(";-up")
		self.ignore("o")
		self.ignore("o-up")
		taskMgr.remove('leftTask2')
		taskMgr.remove('rightTask2')
		taskMgr.remove('climbTask2')
		taskMgr.remove('jumpTask2')
		self.playerModel2.stop()
		#self.ignore("player2-ladder")
	
	def stopStun2(self):
		self.speed2 = 3
		self.climbspeed2 = 1
		self.acceptOnce("k",self.left2)
		self.acceptOnce(";",self.right2)
		self.accept("k-up",self.stopLeft2)
		self.accept(";-up",self.stopRight2)
		self.acceptOnce("o",self.jumpT2)
		#self.accept("player2-ladder", self.climbable2)

	def setupCollisions(self):
		
		print "start setupCollisions"
		
		self.cHandler = CollisionHandlerEvent()
		self.cHandler = CollisionHandlerEvent()
		self.cHandler.setInPattern("%fn-%in")
		self.cHandler.setAgainPattern("%fn-is-on-%in")        
		self.cHandler.setOutPattern("%fn-left-%in")
		self.cTrav = CollisionTraverser()
		base.cTrav = self.cTrav

		#Player 1 collision solid
		bounds = self.playerModel.getChild(0).getBounds()
		center = bounds.getCenter()-Vec3(0,0,12.5)
		radius = bounds.getRadius()-21
		cSphere = CollisionSphere(center,radius)
		cNode = CollisionNode("player1")
		cNode.addSolid(cSphere)
		
		centerB = bounds.getCenter()-Vec3(0,0,-11)
		radiusB = bounds.getRadius()-21
		cSphereB = CollisionSphere(centerB,radiusB)
		cNode.addSolid(cSphereB)
		cNodePath = self.playerModel.attachNewNode(cNode)
		#cNodePath.show()
		
		#centerBB = bounds.getCenter()-Vec3(0,0,25)
		#radiusBB = bounds.getRadius()-28
		#cSphereBB = CollisionSphere(centerB,radiusB)
		#cNodeT = CollisionNode("player1B")
		#cNodeT.addSolid(cSphereBB)
		#cNodePath = self.playerModel.attachNewNode(cNodeT)
		#cNodePath.show()

		#Player 2 collision solid
		bounds2 = self.playerModel2.getChild(0).getBounds()
		center2 = bounds2.getCenter()-Vec3(0,0,12.5)
		radius2 = bounds2.getRadius()-21
		cSphere2 = CollisionSphere(center2,radius2)
		cNode2 = CollisionNode("player2")
		cNode2.addSolid(cSphere2)
		
		bounds2B = self.playerModel2.getChild(0).getBounds()
		center2B = bounds2B.getCenter()-Vec3(0,0,-11)
		radius2B = bounds2B.getRadius()-21
		cSphere2B = CollisionSphere(center2B,radius2B)
		cNode2.addSolid(cSphere2B)
		cNodePath2 = self.playerModel2.attachNewNode(cNode2)
		#cNodePath2.show()

		self.cTrav.addCollider(cNodePath,self.cHandler)
		self.cTrav.addCollider(cNodePath2,self.cHandler)
		self.cTrav.addCollider(cNodePath,self.cHandler)
		self.cTrav.addCollider(cNodePath2,self.cHandler)

		self.accept("player1-ladder", self.climbable)
		self.accept("player1-left-ladder", self.jumpable)
		#self.accept("player1b-canWalk", self.walkable)
		self.accept("player2-ladder", self.climbable2)
		self.accept("player2-left-ladder", self.jumpable2)
		#self.accept("player1-platform", self.climbable)
		#self.accept("player1-left-platform",self.
		#self.accept("player1-left-ladder-down", self.noDrop)
		#self.accept("player2-ladder-down", self.drop2)
		#self.accept("player2-left-ladder-down", self.noDrop2)
		self.accept("player1-actuator", self.activate)
		self.accept("player2-actuator", self.activate)
		self.accept("player1-boulder", self.stun)
		self.accept("player2-boulder", self.stun2)
		self.accept("boulder-player1", self.stun)
		self.accept("boulder-player2", self.stun2)
		self.accept("player1-is-on-ledge", self.leftEdge)
		self.accept("player2-is-on-ledge", self.leftEdge2)
		self.accept("player1-is-on-redge", self.rightEdge)
		self.accept("player2-is-on-redge", self.rightEdge2)
		self.accept("player1-is-on-lwall", self.leftWall)
		self.accept("player2-is-on-lwall", self.leftWall2)
		self.accept("player1-is-on-rwall", self.rightWall)
		self.accept("player2-is-on-rwall", self.rightWall2)
		
		self.accept("player1-left-ledge", self.leftOK)
		self.accept("player2-left-ledge", self.leftOK2)
		self.accept("player1-left-redge", self.rightOK)
		self.accept("player2-left-redge", self.rightOK2)
		self.accept("player1-left-lwall", self.leftOK)
		self.accept("player2-left-lwall", self.leftOK2)
		self.accept("player1-left-rwall", self.rightOK)
		self.accept("player2-left-rwall", self.rightOK2)
		
		print "end setupCollisions"
	
	def boulderTask(self,task):
		drop1 = ProjectileInterval(self.boulder1, startPos = Point3(46+random.randint(-9,9)*9.8,0,self.h), startVel = Point3(0,0,0), endZ = -50)
	
		drop2 = ProjectileInterval(self.boulder2, startPos = Point3(253+random.randint(-9,9)*9.8,0,self.h),startVel = Point3(0,0,0), endZ = -50)
	
		dropBoth = Parallel(drop1,drop2)
		if self.boulder1.getZ() <= -50.0:
			drop1.start()
		if self.boulder2.getZ() <= -50.0:
			drop2.start()
	
		return task.cont
	
	def clockTask(self,task):
		self.timer.detachNode()
		self.timer = OnscreenText("%d" % (self.gameLen-globalClock.getRealTime(),), pos = (98,145), scale = 18.0)
		self.timer.setColor(1,1,1)
		self.timer.reparentTo(render)
		
		return Task.cont

	def endGame(self,task):
		taskMgr.removeTasksMatching('cameraFollowTask')
		taskMgr.removeTasksMatching('boulderTask')
		taskMgr.removeTasksMatching('clockTask')
			
		#base.camList[3].removeNode()
		#base.camList[2].removeNode()
		#base.camList[1].removeNode()
		
		base.makeCamera(base.win, displayRegion = (0, 1, 0, 1))
		
		self.music.stop()
	
                #self.destroy()

		self.music3  = loader.loadMusic("models/gamedev/CSTAR.mp3")
		self.music3.play()
	
	def getScores(self):
		return (self.player1Score, self.player2Score)
		
	def getGameLen(self):
		return self.gameLen
	
	def stopMusic(self):
		self.music3.stop()
	
	def destroy(self):	
		self.playerModel.detachNode()
		self.playerModel2.detachNode()
		self.divider.detachNode()
		self.background.destroy()
		self.timer.destroy()
                while len(self.array) > 0:
                        print len(self.array)
                        self.array[0].remove()
                        del self.array[0]
		
#world = World()
#run()
Beispiel #17
0
class CharGen(DirectObject):
    def __init__(self, common):
        self.common = common
        self.common['chargen'] = self
        self.load()

    def load(self):
        self.newGame = True
        self.font = loader.loadFont('Bitter-Bold.otf')
        self.common['font'] = self.font

        self.common['pc_stat1'] = 50
        self.common['pc_stat2'] = 50
        self.common['pc_stat3'] = 50
        #render.setShaderAuto()
        #base.disableMouse()
        #render.setAntialias(AntialiasAttrib.MMultisample)
        #base.setBackgroundColor(0, 0, 0)
        wp = base.win.getProperties()
        winX = wp.getXSize()
        winY = wp.getYSize()

        self.campmap = loader.loadModel("models/camp3")
        self.campmap.reparentTo(render)

        #music
        self.common['music'] = MusicPlayer(self.common)
        self.common['music'].loop(0)
        #self.common['music']=base.loadMusic("music/LuridDeliusion.ogg")
        #self.common['music'].setLoop(True)
        #self.common['music'].play()

        self.common["random-objects-freq"] = 0.65

        self.node = render.attachNewNode("node")

        self.cameraNode = self.node.attachNewNode("cameraNode")
        self.cameraNode.setZ(-1)
        base.camera.setY(-8)
        base.camera.setZ(5)
        base.camera.lookAt((0, 3, 0))
        base.camera.wrtReparentTo(self.cameraNode)
        self.pointer = self.cameraNode.attachNewNode("pointerNode")

        #light
        self.pLight = PointLight('plight')
        self.pLight.setColor(VBase4(1, .95, .9, 1))
        self.pLight.setAttenuation(Point3(.5, 0, 0.1))
        self.pLightNode = self.node.attachNewNode(self.pLight)
        self.pLightNode.setZ(1.0)
        render.setLight(self.pLightNode)

        self.sLight = Spotlight('sLight')
        self.sLight.setColor(VBase4(.4, .25, .25, 1))
        if self.common['extra_ambient']:
            self.sLight.setColor(VBase4(.7, .5, .5, 1))
        spot_lens = PerspectiveLens()
        spot_lens.setFov(40)
        self.sLight.setLens(spot_lens)
        self.Ambient = self.cameraNode.attachNewNode(self.sLight)
        self.Ambient.setPos(base.camera.getPos(render))
        self.Ambient.lookAt((0, 3, 0))
        render.setLight(self.Ambient)

        self.fire_node = self.node.attachNewNode("fireNode")
        self.fire = vfx(self.fire_node,
                        texture='vfx/big_fire3.png',
                        scale=.29,
                        Z=.5,
                        depthTest=True,
                        depthWrite=True)
        self.fire.show()
        self.fire.loop(0.02)

        self.character1 = Actor(
            "models/pc/male", {
                "attack": "models/pc/male_attack2",
                "idle": "models/pc/male_ready2",
                "block": "models/pc/male_block"
            })
        self.character1.reparentTo(self.node)
        self.character1.setBlend(frameBlend=True)
        self.character1.setPos(1, 2, 0)
        self.character1.setScale(.025)
        self.character1.setH(-25.0)
        self.character1.setBin("opaque", 10)
        self.character1.loop("idle")
        self.swingSound = base.loader.loadSfx("sfx/swing2.ogg")

        coll_sphere = self.node.attachNewNode(CollisionNode('monsterSphere'))
        coll_sphere.node().addSolid(CollisionSphere(1, 2, 1, 1))
        coll_sphere.setTag("class", "1")
        coll_sphere.node().setIntoCollideMask(BitMask32.bit(1))

        self.character2 = Actor("models/pc/female", {
            "attack": "models/pc/female_attack1",
            "idle": "models/pc/female_idle"
        })
        #self.character2.setPlayRate(.4, "attack")
        self.character2.reparentTo(self.node)
        self.character2.setBlend(frameBlend=True)
        self.character2.setPos(-1, 2, 0)
        self.character2.setScale(.026)
        self.character2.setH(25.0)
        #self.character2.setBin("opaque", 10)
        self.character2.loop("idle")

        self.char2_magic = loader.loadModel('vfx/vfx3')
        self.char2_magic.setPos(self.character2.getPos())
        self.char2_magic.setH(self.character2.getH())
        self.char2_magic.setP(-10.0)
        self.char2_magic.setZ(0.71)
        self.char2_magic.setScale(1, 2, 1)
        self.char2_magic.wrtReparentTo(self.character2)
        self.char2_magic.setY(-10)
        self.char2_magic.setDepthWrite(False)
        self.char2_magic.setDepthTest(False)
        self.char2_magic.setLightOff()
        self.char2_magic.hide()
        self.vfxU = -0.125
        self.vfxV = 0
        self.magicSound = base.loader.loadSfx("sfx/thunder3.ogg")

        coll_sphere = self.node.attachNewNode(CollisionNode('monsterSphere'))
        coll_sphere.node().addSolid(CollisionSphere(-1, 2, 1, 1))
        coll_sphere.setTag("class", "2")
        coll_sphere.node().setIntoCollideMask(BitMask32.bit(1))

        self.character3 = Actor(
            "models/pc/female2", {
                "attack": "models/pc/female2_arm",
                "reset": "models/pc/female2_fire",
                "idle": "models/pc/female2_idle"
            })
        #self.character2.setPlayRate(.4, "attack")
        self.character3.reparentTo(self.node)
        self.character3.setBlend(frameBlend=True)
        self.character3.setPos(-1.8, 0.9, 0)
        self.character3.setScale(.026)
        self.character3.setH(40.0)
        #self.character2.setBin("opaque", 10)
        self.character3.loop("idle")

        coll_sphere = self.node.attachNewNode(CollisionNode('monsterSphere'))
        coll_sphere.node().addSolid(CollisionSphere(-1.8, 0.9, 0, 1))
        coll_sphere.setTag("class", "3")
        coll_sphere.node().setIntoCollideMask(BitMask32.bit(1))

        self.arrow_bone = self.character3.exposeJoint(None, 'modelRoot',
                                                      'arrow_bone')
        self.arrow = loader.loadModel('models/arrow')
        self.arrow.reparentTo(self.arrow_bone)
        self.arrow.setP(-45)
        self.movingArrow = None
        self.arrowTime = 0.0
        self.drawSound = base.loader.loadSfx("sfx/draw_bow2.ogg")
        self.fireSound = base.loader.loadSfx("sfx/fire_arrow3.ogg")

        self.character4 = Actor("models/pc/male2", {
            "attack": "models/pc/male2_aura",
            "idle": "models/pc/male2_idle"
        })
        #self.character2.setPlayRate(.4, "attack")
        self.character4.reparentTo(self.node)
        self.character4.setBlend(frameBlend=True)
        self.character4.setPos(1.8, 0.9, 0)
        self.character4.setScale(.024)
        self.character4.setH(-60.0)
        #self.character2.setBin("opaque", 10)
        self.character4.loop("idle")
        self.FFSound = base.loader.loadSfx("sfx/teleport.ogg")
        #self.FFSound = base.loader.loadSfx("sfx/walk_new3.ogg")

        coll_sphere = self.node.attachNewNode(CollisionNode('monsterSphere'))
        coll_sphere.node().addSolid(CollisionSphere(1.8, 0.9, 0, 1))
        coll_sphere.setTag("class", "4")
        coll_sphere.node().setIntoCollideMask(BitMask32.bit(1))

        #gui
        self.mp_logo = DirectFrame(frameSize=(-512, 0, 0, 128),
                                   frameColor=(1, 1, 1, 1),
                                   frameTexture='images/mp_logo.png',
                                   state=DGG.NORMAL,
                                   parent=pixel2d)
        self.mp_logo.setPos(256 + winX / 2, 0, -winY)
        self.mp_logo.setBin('fixed', 1)
        self.mp_logo.hide()
        self.mp_logo.setTransparency(TransparencyAttrib.MDual)
        self.mp_logo.bind(DGG.B1PRESS, self.open_www,
                          ['http://www.matthewpablo.com/'])
        #self.mp_logo.bind(DGG.WITHIN, self.GUIOnEnter, ["MP"])
        #self.mp_logo.bind(DGG.WITHOUT, self.GUIOnExit)

        self.title = DirectFrame(frameSize=(-512, 0, 0, 128),
                                 frameColor=(1, 1, 1, 1),
                                 frameTexture='images/select.png',
                                 parent=pixel2d)
        self.title.setPos(256 + winX / 2, 0, -128)
        self.title.setBin('fixed', 1)
        self.title.setTransparency(TransparencyAttrib.MDual)
        #self.title.hide()
        self.close = DirectFrame(frameSize=(-32, 0, 0, 32),
                                 frameColor=(1, 1, 1, 1),
                                 frameTexture='icon/close.png',
                                 state=DGG.NORMAL,
                                 parent=pixel2d)
        self.close.setPos(winX, 0, -32)
        self.close.setBin('fixed', 1)
        self.close.bind(DGG.B1PRESS, self.exit)

        self.new_game_button = DirectButton(
            frameSize=(-0.2, 0.2, 0, 0.08),
            frameColor=(1, 1, 1, 1),
            frameTexture='images/level_select.png',
            text_font=self.font,
            text='START NEW GAME',
            text_pos=(-0.16, 0.026, 0),
            text_scale=0.035,
            text_fg=(0, 0, 0, 1),
            text_align=TextNode.ALeft,
            textMayChange=1,
            state=DGG.FLAT,
            relief=DGG.FLAT,
            pos=(0, 0, 0.5),
            command=self.onStart,
            parent=aspect2d)
        self.new_game_button.setBin('fixed', 1)
        self.new_game_button.hide()
        self.continue_button = DirectButton(
            frameSize=(-0.2, 0.2, 0, 0.08),
            frameColor=(1, 1, 1, 1),
            frameTexture='images/level_select.png',
            text_font=self.font,
            text='CONTINUE GAME',
            text_pos=(-0.16, 0.026, 0),
            text_scale=0.035,
            text_fg=(0, 0, 0, 1),
            text_align=TextNode.ALeft,
            textMayChange=1,
            state=DGG.FLAT,
            relief=DGG.FLAT,
            pos=(0, 0, 0.4),
            command=self.loadAndStart,
            parent=aspect2d)
        self.continue_button.setBin('fixed', 1)
        self.continue_button.hide()

        self.cursor = DirectFrame(frameSize=(-32, 0, 0, 32),
                                  frameColor=(1, 1, 1, 1),
                                  frameTexture='icon/cursor1.png',
                                  parent=pixel2d)
        self.cursor.setPos(32, 0, -32)
        self.cursor.flattenLight()
        self.cursor.setBin('fixed', 10)
        self.cursor.setTransparency(TransparencyAttrib.MDual)

        self.frameDesc = DirectFrame(frameSize=(0, 1, 0, 0.3),
                                     frameColor=(1, 1, 1, 1),
                                     frameTexture='images/frame1.png',
                                     state=DGG.NORMAL,
                                     pos=(-0.5, 0, 0.6),
                                     parent=aspect2d)
        self.labelDesc = DirectLabel(
            text="",
            text_fg=(1, 1, 1, 1),
            frameColor=(0, 0, 0, 0),
            #text_font=self.font,
            text_scale=0.06,
            text_align=TextNode.ALeft,
            pos=(0.1, 0, 0.2),
            parent=self.frameDesc)
        self.frameDesc.setBin('fixed', 1)
        self.frameDesc.hide()
        self.frameDesc.bind(DGG.WITHIN, self.GUIOnEnter, ["3B"])
        self.frameDesc.bind(DGG.WITHOUT, self.GUIOnExit)

        #tooltip

        #self.font.setPixelsPerUnit(16)
        #self.font.setMinfilter(Texture.FTNearest )
        #self.font.setMagfilter(Texture.FTNearest )
        #self.font.setAnisotropicDegree(4)
        #self.font.setNativeAntialias(False)
        #self.font.setPageSize(1024,1024)

        self.Tooltip = DirectLabel(
            frameColor=(0, 0, 0, 0),
            text_font=self.font,
            text=
            'Lorem ipsum dolor sit amet,\n consectetur adipisicing elit,\n sed do eiusmod tempor incididunt \nut labore et dolore magna aliqua.',
            #pos = (0, 0,-35),
            text_scale=16,
            text_fg=(1, 1, 1, 1),
            text_align=TextNode.ALeft,
            textMayChange=1,
            parent=pixel2d)
        self.Tooltip.flattenLight()
        self.Tooltip.setBin('fixed', 300)
        self.Tooltip.hide()
        #collisions
        #self.traverser=CollisionTraverser("playerTrav")
        #self.traverser.setRespectPrevTransform(True)
        #self.queue = CollisionHandlerQueue()
        self.MousePickerNode = CollisionNode('mouseRay')
        self.pickerNP = base.camera.attachNewNode(self.MousePickerNode)
        self.MousePickerNode.setFromCollideMask(BitMask32.bit(1))
        self.MousePickerNode.setIntoCollideMask(BitMask32.allOff())
        self.pickerRay = CollisionSegment()  #Make our ray
        self.MousePickerNode.addSolid(
            self.pickerRay)  #Add it to the collision node
        self.common['traverser'].addCollider(self.pickerNP,
                                             self.common['queue'])

        self.accept("mouse1", self.onClick)

        taskMgr.doMethodLater(0.2, self.flicker, 'flicker')
        #taskMgr.add(self.camera_spin, "camera_spin")
        taskMgr.add(self.__getMousePos, "chargenMousePos")

        self.current_class = None
        self.currentLevel = 0
        self.camLoop = Sequence(
            LerpHprInterval(self.cameraNode,
                            10.0,
                            VBase3(-20, 0, 0),
                            bakeInStart=0),
            LerpHprInterval(self.cameraNode,
                            10.0,
                            VBase3(20, 0, 0),
                            bakeInStart=0))
        self.camLoop.loop()
        self.accept('window-event', self.windowEventHandler)

    def selectLevel(self, next, event=None):
        self.currentLevel += next
        if self.currentLevel < 0:
            self.currentLevel = 0
        if self.currentLevel > self.common['max_level']:
            self.currentLevel = self.common['max_level']
        self.start_main['text'] = "Start in Level " + str(self.currentLevel +
                                                          1)

    def moveArrow(self, task):
        if self.movingArrow:
            self.arrowTime += task.time
            if self.arrowTime > 3.0:
                self.movingArrow.removeNode()
                self.arrowTime = 0.0
                return task.done
            dt = globalClock.getDt()
            self.movingArrow.setX(self.movingArrow, 400 * dt)
            return task.again
        else:
            return task.done

    def fireArrow(self):
        self.movingArrow = loader.loadModel('models/arrow')
        self.movingArrow.reparentTo(self.arrow_bone)
        self.movingArrow.setP(-45)
        self.movingArrow.wrtReparentTo(render)
        self.arrow.hide()
        self.fireSound.play()
        taskMgr.add(self.moveArrow, "moveArrowTask")
        Sequence(Wait(0.5), Func(self.arrow.show)).start()

    def loadAndStart(self):
        self.newGame = False
        self.common['levelLoader'].loadGame(PCLoad=False)
        self.onStart()

    def onStart(self, event=None):
        #unload stuff
        self.camLoop.pause()
        self.camLoop = None
        base.camera.reparentTo(render)
        self.campmap.removeNode()
        self.node.removeNode()
        self.fire.remove_loop()
        if taskMgr.hasTaskNamed('flicker'):
            taskMgr.remove('flicker')
        if taskMgr.hasTaskNamed('chargenMousePos'):
            taskMgr.remove('chargenMousePos')
        self.common['traverser'].removeCollider(self.pickerNP)
        self.pickerNP.removeNode()
        self.Ambient.removeNode()

        self.frameDesc.destroy()
        self.labelDesc.destroy()
        self.Tooltip.destroy()
        self.cursor.destroy()
        self.new_game_button.destroy()
        self.continue_button.destroy()
        self.close.destroy()
        self.title.destroy()
        self.mp_logo.destroy()

        render.setLightOff()
        self.ignoreAll()

        #self.common['music'].stop()

        #self.common['spawner']=Spawner(self.common)
        #self.common['levelLoader']=LevelLoader(self.common)
        if not self.newGame and 'max_level' in self.common:
            self.currentLevel = self.common['max_level']
        else:
            self.currentLevel = 0
        self.common['levelLoader'].load(self.currentLevel, PCLoad=False)
        #render.ls()
        if self.newGame or not 'current_class' in self.common:
            self.common['current_class'] = self.current_class
        else:
            self.current_class = self.common['current_class']

        if self.current_class == "1":
            self.common['PC'] = Knight(self.common)
            #self.common['PC'].node.setPos(-12, 0, 0)
        elif self.current_class == "2":
            self.common['PC'] = Witch(self.common)
            #self.common['PC'].node.setPos(-12, 0, 0)
        elif self.current_class == "3":
            self.common['PC'] = Archer(self.common)
            #self.common['PC'].node.setPos(-12, 0, 0)
        elif self.current_class == "4":
            self.common['PC'] = Wizard(self.common)
            #self.common['PC'].node.setPos(-12, 0, 0)
        pos = (data.levels[self.currentLevel]["enter"][0],
               data.levels[self.currentLevel]["enter"][1],
               data.levels[self.currentLevel]["enter"][2])
        self.common['PC'].node.setPos(pos)
        self.common['music'].loop(1, fadeIn=True)
        if not self.newGame:
            self.common['levelLoader'].loadGame(PCLoad=True)

    def open_www(self, url, event=None):
        webbrowser.open_new(url)

    def windowEventHandler(self, window=None):
        #print "resize"
        if window is not None:  # window is none if panda3d is not started
            wp = base.win.getProperties()
            X = wp.getXSize() / 2
            Y = wp.getYSize()

            #            self.frameDesc.setPos(-96+X, 0, -32)
            self.title.setPos(256 + X, 0, -128)
            self.close.setPos(X * 2, 0, -32)
            self.mp_logo.setPos(256 + X, 0, -Y)

    def GUIOnEnter(self, object, event=None):
        if object[0] == "4":
            if object[1] == "A":
                self.Tooltip['text'] = "Click to start!"
            elif object[1] == "B":
                self.Tooltip['text'] = "Next level"
            elif object[1] == "C":
                self.Tooltip['text'] = "Previous level"
            self.Tooltip['text_pos'] = (10, -40, 0)
            self.Tooltip['text_align'] = TextNode.ACenter
            self.Tooltip.show()
            return
        if not self.current_class:
            return
        #print int(self.current_class)

    def GUIOnExit(self, event=None):
        self.Tooltip.hide()
        #print "out"

    def start_lightning(self, time=0.03):
        taskMgr.doMethodLater(time, self.lightning, 'vfx')
        self.magicSound.play()

    def lightning(self, task):
        self.char2_magic.show()
        self.vfxU = self.vfxU + 0.5
        if self.vfxU >= 1.0:
            self.vfxU = 0
            self.vfxV = self.vfxV - 0.125
        if self.vfxV <= -1:
            self.char2_magic.hide()
            self.vfxU = 0
            self.vfxV = 0
            return task.done
        self.char2_magic.setTexOffset(TextureStage.getDefault(), self.vfxU,
                                      self.vfxV)
        return task.again

    def loopAnim(self, actor, anim):
        actor.loop(anim)

    def set_slider(self, id):
        #self.current_class=id
        #print id,
        if id == "1":
            self.common['pc_stat1'] = int(self.slider1['value'])
            #print self.common['pc_stat1']
        elif id == "2":
            self.common['pc_stat2'] = int(self.slider2['value'])
            #print self.common['pc_stat2']
        elif id == "3":
            self.common['pc_stat3'] = int(self.slider3['value'])
            #print self.common['pc_stat3']

    def onClick(self):
        self.common['traverser'].traverse(render)
        my_class = None
        for entry in self.common['queue'].getEntries():
            if entry.getIntoNodePath().hasTag("class"):
                my_class = entry.getIntoNodePath().getTag("class")

        if Path("save.dat").exists():
            self.continue_button.show()

        if my_class == "1":

            self.current_class = my_class
            self.title.hide()
            self.labelDesc.setText(
                "Knight:\nHe has greater resistance.\nHe can attack with the sword\nand defend with a shield."
            )
            self.frameDesc.show()
            self.new_game_button.show()
            Sequence(self.character1.actorInterval("attack"),
                     self.character1.actorInterval("block"),
                     Func(self.loopAnim, self.character1, "idle")).start()
            self.swingSound.play()
            #self.character1.play("attack")
            self.character2.loop("idle")
        elif my_class == "2":
            self.current_class = my_class
            self.title.hide()
            self.labelDesc.setText(
                "Witch:\nShe can throw energy balls and\na long distance beam."
            )
            self.frameDesc.show()
            self.new_game_button.show()
            Sequence(self.character2.actorInterval("attack", playRate=0.8),
                     Func(self.loopAnim, self.character2, "idle")).start()
            Sequence(Wait(0.3), Func(self.start_lightning, 0.05)).start()
            #self.character2.play("attack")
            self.character1.loop("idle")
            #RayVfx(self.character2, texture='vfx/lightning.png').start()
        elif my_class == "3":
            self.current_class = my_class
            self.title.hide()
            self.labelDesc.setText(
                "Archer:\nShe can throw arrows\nand run faster.")
            self.frameDesc.show()
            self.new_game_button.show()
            self.drawSound.play()
            self.character3.play("attack")
            Sequence(Wait(1.5), Func(self.fireArrow),
                     Func(self.character3.play, "reset"), Wait(1.0),
                     Func(self.loopAnim, self.character3, "idle")).start()
        elif my_class == "4":
            self.current_class = my_class
            self.title.hide()
            self.labelDesc.setText(
                "Wizard:\nHe can throw magma balls\nand teleport himself.")
            self.frameDesc.show()
            self.new_game_button.show()
            self.character4.loop("attack")
            aura = vfx(self.character4,
                       texture='vfx/tele2.png',
                       scale=.5,
                       Z=.85,
                       depthTest=False,
                       depthWrite=False)
            aura.show()
            aura.start()
            self.FFSound.play()
            Sequence(Wait(2.2), Func(self.loopAnim, self.character4,
                                     "idle")).start()

    def exit(self, event=None):
        self.common['root'].save_and_exit()
        #sys.exit()

    def __getMousePos(self, task):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
            pos2d = Point3(mpos.getX(), 0, mpos.getY())
            self.cursor.setPos(pixel2d.getRelativePoint(render2d, pos2d))
            self.Tooltip.setPos(self.cursor.getPos())
        return task.again

    def flicker(self, task):
        self.pLight.setAttenuation(Point3(1, 0, random.uniform(.1, 0.15)))
        self.pLightNode.setZ(random.uniform(.9, 1.1))
        #self.pLight.setColor(VBase4(random.uniform(.9, 1.0), random.uniform(.9, 1.0), .9, 1))
        return task.again

    def camera_spin(self, task):
        H = self.cameraNode.getH()
        #Z=self.cameraNode.getZ()
        #print H
        if H <= -20.0 or H >= 20.0:
            if self.reverse_spin:
                self.reverse_spin = False
            else:
                self.reverse_spin = True
        if self.reverse_spin:
            self.cameraNode.setH(self.cameraNode, 4 * globalClock.getDt())
            #self.cameraNode.setZ(Z+0.1*globalClock.getDt())
        else:
            self.cameraNode.setH(self.cameraNode, -4 * globalClock.getDt())
            #self.cameraNode.setZ(Z-0.1*globalClock.getDt())
        return task.again
Beispiel #18
0
class LookingGrippingDemo(ShowBase):

    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)

        # This code puts the standard title and instruction text on screen
        self.title = OnscreenText(text="Panda3D: Tutorial - Joint Manipulation",
                                  fg=(1, 1, 1, 1), parent=base.a2dBottomRight,
                                  align=TextNode.ARight, pos=(-0.1, 0.1),
                                  shadow=(0, 0, 0, .5), scale=.08)

        self.onekeyText = genLabelText("ESC: Quit", 1)
        self.onekeyText = genLabelText("[1]: Teapot", 2)
        self.twokeyText = genLabelText("[2]: Candy cane", 3)
        self.threekeyText = genLabelText("[3]: Banana", 4)
        self.fourkeyText = genLabelText("[4]: Sword", 5)

        # Set up key input
        self.accept('escape', sys.exit)
        self.accept('1', self.switchObject, [0])
        self.accept('2', self.switchObject, [1])
        self.accept('3', self.switchObject, [2])
        self.accept('4', self.switchObject, [3])

        base.disableMouse()  # Disable mouse-based camera-control
        camera.setPos(0, -15, 2)  # Position the camera

        self.eve = Actor("models/eve",  # Load our animated charachter
                         {'walk': "models/eve_walk"})
        self.eve.reparentTo(render)  # Put it in the scene

        # Now we use controlJoint to get a NodePath that's in control of her neck
        # This must be done before any animations are played
        self.eveNeck = self.eve.controlJoint(None, 'modelRoot', 'Neck')

        # We now play an animation. An animation must be played, or at least posed
        # for the nodepath we just got from controlJoint to actually effect the
        # model
        self.eve.actorInterval("walk", playRate=2).loop()

        # Now we add a task that will take care of turning the head
        taskMgr.add(self.turnHead, "turnHead")

        # Now we will expose the joint the hand joint. ExposeJoint allows us to
        # get the position of a joint while it is animating. This is different than
        # controlJonit which stops that joint from animating but lets us move it.
        # This is particularly usefull for putting an object (like a weapon) in an
        # actor's hand
        self.rightHand = self.eve.exposeJoint(None, 'modelRoot', 'RightHand')

        # This is a table with models, positions, rotations, and scales of objects to
        # be attached to our exposed joint. These are stock models and so they needed
        # to be repositioned to look right.
        positions = [("teapot", (0, -.66, -.95), (90, 0, 90), .4),
                     ("models/candycane", (.15, -.99, -.22), (90, 0, 90), 1),
                     ("models/banana", (.08, -.1, .09), (0, -90, 0), 1.75),
                     ("models/sword", (.11, .19, .06), (0, 0, 90), 1)]

        self.models = []  # A list that will store our models objects
        for row in positions:
            np = loader.loadModel(row[0])  # Load the model
            np.setPos(row[1][0], row[1][1], row[1][2])  # Position it
            np.setHpr(row[2][0], row[2][1], row[2][2])  # Rotate it
            np.setScale(row[3])  # Scale it
            # Reparent the model to the exposed joint. That way when the joint moves,
            # the model we just loaded will move with it.
            np.reparentTo(self.rightHand)
            self.models.append(np)  # Add it to our models list

        self.switchObject(0)  # Make object 0 the first shown
        self.setupLights()  # Put in some default lighting

    # This is what we use to change which object it being held. It just hides all of
    # the objects and then unhides the one that was selected
    def switchObject(self, i):
        for np in self.models:
            np.hide()
        self.models[i].show()

    # This task gets the position of mouse each frame, and rotates the neck based
    # on it.
    def turnHead(self, task):
        # Check to make sure the mouse is readable
        if base.mouseWatcherNode.hasMouse():
            # get the mouse position as a LVector2. The values for each axis are from -1 to
            # 1. The top-left is (-1,-1), the bottom right is (1,1)
            mpos = base.mouseWatcherNode.getMouse()
            # Here we multiply the values to get the amount of degrees to turn
            # Restrain is used to make sure the values returned by getMouse are in the
            # valid range. If this particular model were to turn more than this,
            # significant tearing would be visable
            self.eveNeck.setP(clamp(mpos.getX()) * 50)
            self.eveNeck.setH(clamp(mpos.getY()) * 20)

        return Task.cont  # Task continues infinitely

    def setupLights(self):  # Sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.4, .4, .35, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 8, -2.5))
        directionalLight.setColor((0.9, 0.8, 0.9, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
Beispiel #19
0
class application( ShowBase ):
    # begin of '__init__' member function
    # this sets it all up for the scene
    def __init__( self ):
        # fog and background colors
        self.mRed = 0.2
        self.mGreen = 0.2
        self.mBlue = 0.2
        # the fog density 0 = none & 1 = full
        self.mDen = .01
        # setup the fog for the scene
        self.fogSetup( )
        # setup the background color for the scene
        self.backgroundSetup( )
        # setup the camera for the scene
        self.cameraSetup( )
        # setup the needed models for the scene
        self.loadModels( )
        # setup the needed light for the scene
        self.setupLights( )
        # setup the needed intervals for the scene
        self.setupIntervals( )
        # setup the needed states
        self.setupStates( )
        # setup the key events needed for the scene
        self.keyBoardSetup( )
        # begin collision code
        # here we create the collision traverser
        base.cTrav = CollisionTraverser()
        # here we create the event collision handler
        self.collHandEvent = CollisionHandlerEvent()
        # now we add an 'in' pattern
        # this consists of a string of an 'into' object
        self.collHandEvent.addInPattern('into-%in')
        # now we add an 'in' again pattern
        self.collHandEvent.addAgainPattern('again-%in')
        # now we add an 'out' pattern
        # this consists of a string of an outof with an into object
        self.collHandEvent.addOutPattern('outof-%in')
        # set this variable to zero for start
        # this aids in naming are collision nodes
        self.collCount = 0
        # add a collision sphere around tiny
        # tiny is a 'from' object
        self.tinyColl = self.initCollisionSphere( self.tiny )
        # add this collision sphere to the colllision traverser
        base.cTrav.addCollider( self.tinyColl[0], self.collHandEvent )
        # create 4 planes used for collision solids
        # each point in the z up position from their respective local
        # space not the world space
        self.planes = [
                    Plane( Vec3(  0, 0, 1 ),  Point3( 0, 0, 0 ) ),
                    Plane( Vec3(  0, 0, 1 ),  Point3( 0, 0, 0 ) ),
                    Plane( Vec3(  0, 0, 1 ),  Point3( 0, 0, 0 ) ),
                    Plane( Vec3(  0, 0, 1 ),  Point3( 0, 0, 0 ) )
        ]
        # create four infinite collision planes in front of the wall models
        # each uses the corresponding planes up above
        self.wallColl = [
                    self.initCollisionPlane( self.walls[0], self.planes[0] ),
                    self.initCollisionPlane( self.walls[1], self.planes[1] ),
                    self.initCollisionPlane( self.walls[2], self.planes[2] ),
                    self.initCollisionPlane( self.walls[3], self.planes[3] )
        ]
        # set up the events needed for the messenger
        # each passes the second element in the tuple in the list
        # also passes the needed functions for each into, again, and outof event
        self.accept( 'into-'  + self.wallColl[0][2], self.colliding)
        self.accept( 'again-' + self.wallColl[0][2], self.colliding)
        self.accept( 'outof-' + self.wallColl[0][2], self.notColliding)
        #
        self.accept( 'into-'  + self.wallColl[1][2], self.colliding)
        self.accept( 'again-' + self.wallColl[1][2], self.colliding)
        self.accept( 'outof-' + self.wallColl[1][2], self.notColliding)
        #
        self.accept( 'into-'  + self.wallColl[2][2], self.colliding)
        self.accept( 'again-' + self.wallColl[2][2], self.colliding)
        self.accept( 'outof-' + self.wallColl[2][2], self.notColliding)
        #
        self.accept( 'into-'  + self.wallColl[3][2], self.colliding)
        self.accept( 'again-' + self.wallColl[3][2], self.colliding)
        self.accept( 'outof-' + self.wallColl[3][2], self.notColliding)
        ShowBase.__init__(self)
        #self.props = WindowProperties()
        #self.props.setSize(1024,768)
        # end __init__
    # begin the colliding member function
    # this function is called when a 'from' object collides with an 'into' object
    def colliding( self, collEntry ): # accept a collision entry argument
        self.isColliding = 1 # we are colliding
        self.pauseWalk( ) # pause all walking animation and movement
        # here we calculate the displacement of how far the collision entry is in
        # in other words we are finding out how far the tiny collision sphere
        # is into the wall collision plane
        disp = ( collEntry.getSurfacePoint( render ) - collEntry.getInteriorPoint( render ) )
        # ok we now know how much tiny is into the wall
        # so we add this number to tiny's current position
        # making tiny sit right in front of the wall and not into it
        newPos = self.tiny.getPos( ) + disp # get new position
        self.tiny.setPos( newPos ) # and set it to tiny's position
        # end colliding
    # begin the notColliding member function
    # this function is called when tiny is no longer colliding with the wall
    def notColliding( self, collEntry ): # accept a collision entry argument
        self.isColliding = 0 # not colliding any more
        # end notColliding
    # begin the initCollisionSphere member function
    # this function creates a sphere used for collision
    # around the object passed to it as a argument
    def initCollisionSphere( self, obj, show = False ): # accept an object and  a defaulted to false
                                                        # show variable as an argument
        bounds = obj.getChild( 0 ).getBounds( ) # get the boundries of the passed object
        center = bounds.getCenter( ) # get the center of these boundries
        radius = bounds.getRadius( ) # get the radius of these boundries
        # here we construct a string based on the current collision count and the object name
        collSphereStr = 'CollisionHull' + str( self.collCount ) + "_" + obj.getName( )
        # increase the collision count to one more for the next call of this function
        self.collCount += 1
        # create a collision node with a the name or string created above
        cNode=CollisionNode( collSphereStr )
        # add a solid to this newly created node
        # we pass it a collision sphere with the center and radius of the boundries of the passed object
        cNode.addSolid( CollisionSphere( center, radius ) )
        # now we attach this collision node to the object node we were passed
        cNodepath = obj.attachNewNode(cNode) # here we save the collision node path for easy reference
        if show: # if show is true
            cNodepath.show() # render or show the collision node
        # now we return a tuple that contains the collision node and it's label
        return ( cNodepath, cNode, collSphereStr )
        # end initCollisionSphere
    # begin the initCollisionPlane member function
    # this code creates a collision plane in front of the object passed to it
    def initCollisionPlane( self, obj, plane, show=False ): # accept an object, plane, and a defaulted
                                                            # to false show variable as an argument
        # here we construct a string based on the current collision count and the object name
        collPlaneStr = 'CollisionPlane' + str( self.collCount ) + "_" + obj.getName( )
        # increase the collision count for the next call
        self.collCount += 1
        # here we create a collision node and assign the string or name to the node
        cNode = CollisionNode( collPlaneStr )
        # here we a add a solid or geometry to the node
        # we pass the collision plane function the plane we were passed
        cNode.addSolid( CollisionPlane( plane ) )
        # now we attach the newly created collision node the the object node we were passed
        cNodepath = obj.attachNewNode( cNode ) # here we save the collison node path for easy reference
        if show: # if show equals true
            cNodepath.show( ) # show the collision geometry or render it to screen
        # here we return a tuple which contains the collision node and it's label
        return ( cNodepath, cNode, collPlaneStr )
        # end initCollisionPlane
    # begin the fogSetup member function
    # this function creates the fog, sets its color, density and makes it affect
    # all in the scene
    def fogSetup( self ):
        self.mFog = Fog( "fog" ) # create
        self.mFog.setColor( self.mRed, self.mGreen, self.mBlue ) # set color
        self.mFog.setExpDensity( self.mDen )  #set density
        render.setFog( self.mFog ) # set to affect all in scene graph
        # end fogSetup
    # begin backgroundSetup member function
    # this sets the color to match that of the fog
    def backgroundSetup( self ):
        base.setBackgroundColor( self.mRed, self.mGreen, self.mBlue ) # set the color
        # end backgroundSetup
    # begin the cameraSetup member function
    def cameraSetup( self ):
        base.disableMouse( ) # disable the default camera controls that are created for us
        # set the position (x, y, and z), heading (cardinal direction), pitch (tilt foward backward), roll (rotation left or right)
        # here we set it a hundred units back from center on the y axis and 30 units up the z axis
        # then we pitch (tilt) the camera foward 15 units in degree
        camera.setPosHpr( Vec3( 0, -100, 30 ), Vec3( 0, -15, 0 ) )
        # ok now tell the task manager to add our camera following task
        taskMgr.add( self.cameraFollowTask, 'cameraFollowTask', sort=30 )
        # end cameraSetup
    # begin the loadModels member function
    # here we load all the models needed for our scene
    def loadModels( self ):
        # load the tiny actor
        # we use actor instead of model because we need to use animations
        self.tiny = Actor( "models/tiny", { "walk" : "models/tiny" } ) # dictionary that defines the walk animation
        self.tiny.reparentTo( render ) # parent 'tiny' to the renderer
        self.tiny.setH( -180 ) # here we change it's heading to face away from the camera
                               # a hundred and eighty degrees
                               # remember this later
        # now we scale tiny down a lot for it is a big mesh
        self.tiny.setScale( .1 ) # number achieved through trial and error
        # now we load the floor for tiny to walk on
        self.floor = loader.loadModel( "models/floor" ) # load static model (no animations)
        self.floor.reparentTo( render ) # parent to renderer
        self.floor.setScale( 5 ) # scale it up to match with tiny
        self.floor.setPos( 0, 0, -26 ) # set it's position down 26 units on the z axis
        # now we create the foor walls we need for tiny to walk into
        # this is a list similiar to an array in other languages
        self.walls = [
                      loader.loadModel( "models/wall" ),
                      loader.loadModel( "models/wall" ),
                      loader.loadModel( "models/wall" ),
                      loader.loadModel( "models/wall" )
        ]
        # ok now we parent to renderer, scale, and position
        self.walls[0].reparentTo( render ) # parent to renderer
        self.walls[0].setScale( 9 ) # scale up to match with others
        self.walls[0].setPos( 0, 900, 64 ) # 90 units y axis (into scene)
        self.walls[0].setP( 90 ) # pitch it up 90 degrees otherwise it would be laying down
        #
        self.walls[1].reparentTo( render ) # same
        self.walls[1].setScale( 9 ) # same
        self.walls[1].setPos( 900, 0, 64 ) # now we position 90 units along the positive x axis
                                          # and 64 units up the positive z axis
        self.walls[1].setH( -90 ) # then we turn it to face us from the left
        self.walls[1].setP( 90 ) # same
        #
        self.walls[2].reparentTo( render ) # same
        self.walls[2].setScale( 9 ) # same
        self.walls[2].setPos( 0, -900, 64 ) # the same but put it in the back of us down the
                                           # the negative y axis
        self.walls[2].setH( 0 ) # turn it around to face the back of us
        self.walls[2].setP( -90 ) # same
        #
        self.walls[3].reparentTo( render ) # same
        self.walls[3].setScale( 9 ) # same
        self.walls[3].setPos( -900, 0, 64 ) # down neg x axis 90 units same for z axis
        self.walls[3].setH( 90 ) # make it face us from the right
        self.walls[3].setP( 90 ) # same
        # ok four walls are up lets move on
        #end loadModels
    # begin the setupLights member function
    # this function creates a signle point light for our scene
    def setupLights( self ):
        # create a point light
        plight = PointLight('plight')
        # set its color
        plight.setColor(VBase4( 0.2, 0.2, 0.2, 1 ) )
        # attach it to the render as a new node
        # 'upcast' to a node otherwise Panda will crash
        # heard this will change in version 1.1.?
        plnp = render.attachNewNode( plight )
        # set the position of the node
        plnp.setPos( 0, 0, 0 )
        # set the light or 'turn' it on
        render.setLight( plnp )
        # the following code makes the 'shadows' less black or dark
        # same as above but we create a ambient light that affects all faces
        alight = AmbientLight( 'alight' ) # light
        alight.setColor( VBase4( 0.2, 0.2, 0.2, 1 ) ) # color
        alnp = render.attachNewNode( alight ) # attach
        render.setLight( alnp ) # turn on
        # end setupLights
    # begin the setupIntervals member function
    # this function setups up the needed intervals for the scene
    def setupIntervals( self ):
        # create a actor interval that calls the member function walk
        # to handle the grunt work
        self.tinyWalk = self.tiny.actorInterval( "walk" )
        # loop then pause to create a more fluid animation start and stop
        # later on (thanks russ)
        self.tinyWalk.loop( )
        self.tinyWalk.pause( )
        # end setupIntervals
    #begin the setupStates member function
    # this creates and sets the states for the scene
    def setupStates( self ):
        self.tinyWalking = 0 # is tiny walking, no
        self.turning = 0 # is tiny turning, no
        self.isColliding = 0 # is tiny colliding, no
        # end setupStates
    # begin the walk member function
    # this function is called in an actor interval each frame
    def walk( self ):
        if self.tinyWalking == 0: # if tiny is not walking
            taskMgr.add( self.walkTask,'walkTask' ) # add the walk task look below
            if self.turning == 0: # if tiny is not turning
                self.tinyWalk.resume( ) # pick up where we last left off in
                                        # in the walk animation
            self.tinyWalking = 1 # flag that tiny is walking now
    # begin the walkTask member function
    # this function is called each frame by the task manager
    def walkTask( self, task ): # accept a task as an argument
        # ok now for some math particulary trigonometry
        dist = 1.0 # the hypotenuse defined by r = sqrt( a^2 + b^2 )
        # here we get the current heading of tiny and convert that degree measurement
        # to radians because the math.sin/cos function needs it to be radians
        angle = self.tiny.getH( ) * math.pi / 180.0 # convert degrees to radians
        correction = math.pi / 2 # ninety degrees in radians
                                 # this is needed for the cofunction formulas
        # in trigonometry x is defined as x = r * cos( angle )
        #                 y is defined as y = r * sin( angle )
        # remember that tiny was turned 180 degrees? And would now be facing
        # 270 degrees (3pi/2 for radians) on the unit circle
        # so we need to use the cofuntion formulas defined as:
        # sin(pi/2 - angle) = cos(angle)
        # cos(pi/2 - angle) = sin(angle)
        # now knowing these we substitute
        # x = r * sin( angle )
        # y = r * cos( angle)
        # however I left it un-substituted for clearity
        dx = dist * math.cos( correction - angle )
        # one more thing, because we want tiny to walk into the scene we
        # make it negative to walk into the scene
        # remove the negative and she walks backwards
        # remember this if you want to make your avatar walk backwards
        dy = dist * -math.sin( correction - angle )
        # now that we know x and y we just add it to the current values since last frame
        self.tiny.setPos( Vec3( self.tiny.getX( ) + dx, self.tiny.getY( ) + dy, 0 ) )
        # on a side note, if you had trouble with the math I recommend
        # "Trigonometry the Easy Way" third edition by Douglas Downing
        # easy read and you should be up and running with trig in no time
        # and we continue on to the next frame
        return Task.cont
        # end walkTask
    # begin the pauseWalk member function
    # this function stops tiny from walking any further
    def pauseWalk( self ):
        if self.tinyWalking == 1: # if tiny is walking
            taskMgr.remove( 'walkTask' ) # remove the walk task now tiny stops moving
            if self.turning == 0: # if tiny is not turning
                self.tinyWalk.pause( ) # now walking animation stops
            self.tinyWalking = 0 # set flag to not walking
            # accept only once to listen for the up arrow pressed
            # if it is call the walk member function
            self.acceptOnce( "arrow_up", self.walk )
        # end pauseWalk
    # begin the turn member function
    # this function sets up the turn task and walk animation
    def turn( self, dir ): # accept a direction as an argument
        if self.turning == 0: # if tiny is not turning
            # add the turn task and pass the direction to the
            # turnTask member function
            taskMgr.add( self.turnTask, 'turnTask', extraArgs = [ dir ] )
            # tiny is now turning
            self.turning = 1
            if self.tinyWalking == 0: # if tiny is not walking
                                      # we check this because we
                                      # don't want to loop it because
                                      # it's already looping by the walk function
                self.tinyWalk.resume( )  # pick up where we left off in the animation
            self.ignore( "arrow_left" )  # ignore the left arrow being pressed
            self.ignore( "arrow_right" ) # ignore the right arrow being pressed
        # end turn
    # begin the turnTask member function
    # this function turns makes tiny walk in a circle if tiny isn't
    # already walking or colliding in a wall
    def turnTask( self, dir ): # accept direction (+/-) as an argument
        speed = 50.0 # degrees/s
        # here we get the time since the beginning of the application
        # not sure about this however
        dt = globalClock.getDt( )
        # here we create the angle of rotation based on the direction,
        # speed or rate, and time
        angle = dir * speed * dt
        # now we subtract this angle from tiny's current heading or angle
        self.tiny.setH( self.tiny.getH( ) - angle )
        if self.tinyWalking == 0: # if tiny is not already walking
                                  # below allows us to make tiny walk
                                  # in a circle instead of turning
                                  # in place
                                  # however we don't want to do this if
                                  # tiny is colliding with a wall
                                  # because then tiny could penetrate the
                                  # wall which we don't want
                                  # and we don't want to do this if tiny's
                                  # position is already being updated by
                                  # walkTask
            if self.isColliding == 0: # if tiny is not colliding
                # the following is the same math as before
                # please see 'walkTask' for details
                dist = .0
                angle = self.tiny.getH( ) * math.pi / 180.0
                correction = math.pi / 2
                dx = dist * math.cos( correction - angle )
                dy = dist * -math.sin( correction - angle )
                self.tiny.setPos( Vec3( self.tiny.getX( ) + dx, self.tiny.getY( ) + dy, 0 ) )
        # continue on to next frame
        return Task.cont
        # end turnTask
    # begin the turnPause member function
    # this function stops tiny from turning in place or in a circle
    def turnPause( self ):
        if self.turning == 1: # if tiny is turning
            taskMgr.remove( 'turnTask' ) # remove task
            self.turning = 0 # set flag, not turning
            if self.tinyWalking == 0: # if tiny is not already walking
                self.tinyWalk.pause( ) # pause the walk animation
            # accept only once the left and right arrow buttons corresponding
            # to each direction respecitively
            self.acceptOnce(  "arrow_left", self.turn, [ -1 ] )
            self.acceptOnce( "arrow_right", self.turn, [ 1 ] )
    # begin the cameraFollowTask member function
    # this function creates a third person view of the avatar at all times
    def cameraFollowTask( self, task ):
        print self.getSize()
        print self.winList
        #if base.mouseWatcherNode.hasMouse() and self.props.hasSize():
        #    x=(base.mouseWatcherNode.getMouseX() - (self.props.getXSize()/2)) * 0.05
        #    y=(base.mouseWatcherNode.getMouseY() - (self.props.getYSize()/2)) * 0.05
#        cx = getpointerx - halfwindowsize * 0.05
#        cy = getpointery - halfwindowsize * 0.05
        #    camera.setHpr(x, y, 0)
#        window.movepointer(0,0)
        return Task.cont
        speed = 100.0 # the speed at which the camera reaches its
                     # desired position
        offset = Vec3( 0, 0, 40 ) # the offset between the camera and tiny
        dt = globalClock.getDt( ) # time since beginning of application
        currPos = camera.getPos( ) # current position of camera
        # this calculates the desired position that camera should be at
        # there we get the current position of tiny and add that to the
        # x axis Quaternion rotation passing the desired offset
        # thus if tiny is able to face the camera, the camera will rotate to the
        # back of tiny
        # Quat is short for "Quaternion." This is a mathematical concept that
        # allows rotations on an arbitrary axis avoiding what is called "gimbal
        # lock."
        desiredPos = self.tiny.getPos( ) + self.tiny.getQuat( ).xform( offset )
        # now that we have the desired position vector we create a new direction vector
        # by subtracting the current position from the desired position
        # for example say our desired position is Vec3( 0, -100, 0) and we are at
        # Vec3(0, -20, 0) so we need to move in a foward direction down the
        # negative y axis eighty units
        direction = Vec3( desiredPos - currPos )
        if ( direction.length( ) > speed * dt ): # if the direction's length
                                                 # is greater than the speed
                                                 # times the time
            direction.normalize( ) # here we normalize the vector
                                   # which means we get a unit vector (magnitude of 1)
                                   # in the same direction as before normalization
            # here we update the camera's position (getting ever closer to the desired position)
            # by getting the current pos + the normlized (magnitude or length of 1 in the same direction)
            # * the speed or rate at which the camera catches up * the time
            camera.setPos( camera.getPos( ) + direction * speed * dt )
        else: # the directions length is less than speed * the time
              # we do this because the length is so close to the desired position
              # that if we just updated the camera's position like in the conditional
              # statement above then we would over shoot the desired position
              # come next frame of rendering which we do not want
            camera.setPos( desiredPos ) # set to desired position because we are so close to it
        camera.setHpr( 90., 0., 0. ) # always be 'looking' at the model tiny
        # continue this task on to next frame
        return Task.cont
        # end cameraFollowTask
    # begin the keyBoardSetup member function
    # this function sets up the keys we need to control tiny
    # and application it self
    def keyBoardSetup( self ):
        # set escape key to exit the application
        self.accept( "escape", sys.exit )
        # set the up arrow key to call the walk member function
        self.acceptOnce(    "arrow_up", self.walk )
        # set the left arrow key to call the turn member function with a left direction
        self.acceptOnce(  "arrow_left", self.turn, [ -1 ] )
        # set the right arrow key to call the turn member function with a right direction
        self.acceptOnce( "arrow_right", self.turn, [ 1 ] )
        # when the player lets up on the arrow keys call their respective pause functions
        self.accept(    "arrow_up-up", self.pauseWalk )
        self.accept(  "arrow_left-up", self.turnPause )
        self.accept( "arrow_right-up", self.turnPause )
Beispiel #20
0
class ControllerPepper(ShowBase):
	def __init__(self, scene, size=(960, 720), zNear=0.1, zFar=1000.0, fov=40.0, shadowing=False, showPosition=False,
				 cameraTransform=None, cameraMask=None, take_num=None):

		ShowBase.__init__(self)
		
		self.__dict__.update(scene=scene, size=size, fov=fov,
							 zNear=zNear, zFar=zFar, shadowing=shadowing, showPosition=showPosition,
							 cameraTransform=cameraTransform, cameraMask=cameraMask)

		# Find agent and reparent camera to it
		self.agent = self.scene.scene.find('**/agents/agent*/+BulletRigidBodyNode')
		self.camera.reparentTo(self.agent)
		if self.cameraTransform is not None:
			self.camera.setTransform(cameraTransform)

		if cameraMask is not None:
			self.cam.node().setCameraMask(self.cameraMask)
		lens = self.cam.node().getLens()
		lens.setFov(self.fov)
		lens.setNear(self.zNear)
		lens.setFar(self.zFar)

		# Change window size
		wp = WindowProperties()
		wp.setSize(size[0], size[1])
		wp.setTitle("Pepper")
		wp.setCursorHidden(True)
		self.win.requestProperties(wp)

		self.disableMouse()

		self.time = 0
		self.centX = wp.getXSize() / 2
		self.centY = wp.getYSize() / 2
		self.win.movePointer(0, int(self.centX), int(self.centY))

		# key controls
		self.forward = False
		self.backward = False
		self.fast = 1.2
		self.left = False
		self.right = False
		self.rotateXl = False
		self.rotateXr = False
		self.rotateYu = False
		self.rotateYd = False
		self.ss = False
		self.cv = False
		self.openpose = False
		self.visible_human = True

		# sensitivity settings
		self.sensTranslate = 3
		self.sensTranslateFast = self.sensTranslate * 5
		self.sensRotate = 0.005

		# Reparent the scene to render.
		self.scene.scene.reparentTo(self.render)

		self.render.setAntialias(AntialiasAttrib.MAuto)

		self.take_num = take_num

		# Task
		self.globalClock = ClockObject.getGlobalClock()
		self.taskMgr.add(self.update, 'pepper-update')

		self._addDefaultLighting()
		self._setupEvents()

		self.drawHuman()

	def _addDefaultLighting(self):
		alight = AmbientLight('alight')
		alight.setColor(VBase4(0.2, 0.2, 0.2, 1))
		alnp = self.render.attachNewNode(alight)
		self.render.setLight(alnp)

		# NOTE: Point light following the camera
		plight = PointLight('plight')
		plight.setColor(VBase4(0.4, 0.4, 0.4, 1))
		plnp = self.cam.attachNewNode(plight)
		self.render.setLight(plnp)

		if self.shadowing:
			# Use a 512x512 resolution shadow map
			plight.setShadowCaster(True, 512, 512)

			# Enable the shader generator for the receiving nodes
			self.render.setShaderAuto()
			self.render.setAntialias(AntialiasAttrib.MAuto)

	def _setupEvents(self):
		self.escapeEventText = OnscreenText(text="ESC: Quit",
											style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.95),
											align=TextNode.ALeft, scale=.05)

		if self.showPosition:
			self.positionText = OnscreenText(text="Position: ",
											 style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.85),
											 align=TextNode.ALeft, scale=.05)

			self.orientationText = OnscreenText(text="Orientation: ",
												style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.80),
												align=TextNode.ALeft, scale=.05)

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

		self.accept("w", setattr, [self, "forward", True])
		self.accept("w-up", setattr, [self, "forward", False])
		self.accept("s", setattr, [self, "backward", True])
		self.accept("s-up", setattr, [self, "backward", False])
		self.accept("a", setattr, [self, "left", True])
		self.accept("a-up", setattr, [self, "left", False])
		self.accept("d", setattr, [self, "right", True])
		self.accept("d-up", setattr, [self, "right", False])

		self.accept("q", setattr, [self, "rotateXl", True])
		self.accept("q-up", setattr, [self, "rotateXl", False])
		self.accept("e", setattr, [self, "rotateXr", True])
		self.accept("e-up", setattr, [self, "rotateXr", False])

		self.accept("r", setattr, [self, "rotateYu", True])
		self.accept("r-up", setattr, [self, "rotateYu", False])
		self.accept("f", setattr, [self, "rotateYd", True])
		self.accept("f-up", setattr, [self, "rotateYd", False])

		self.accept("c", setattr, [self, "ss", True])
		self.accept("c-up", setattr, [self, "ss", False])

		self.accept("o", setattr, [self, "openpose", True])
		self.accept("o-up", setattr, [self, "openpose", False])

		self.accept("m", setattr, [self, "cv", True])
		self.accept("m-up", setattr, [self, "cv", False])

		self.accept("h", setattr, [self, "visible_human", not self.visible_human])

	def update(self, task):

		# dt = self.globalClock.getDt()
		dt = task.time - self.time

		# handle key strokes
		if self.visible_human:
			self.pActor.show()
		else:
			self.pActor.hide()

		# rotational:
		if self.rotateXl == True:
			self.agent.setH(self.agent, self.agent.getH(self.agent) + self.centX * self.sensRotate)
		if self.rotateXr == True:
			self.agent.setH(self.agent, self.agent.getH(self.agent) - self.centX * self.sensRotate)
		if self.rotateYu == True:
			self.agent.setP(self.agent, self.agent.getP(self.agent) + 20 * self.sensRotate)
			self.agent.setR(self.agent, 0)
		if self.rotateYd == True:
			self.agent.setP(self.agent, self.agent.getP(self.agent) - 20 * self.sensRotate)
			self.agent.setR(self.agent, 0)

		# translational:
		linearVelocityX = 0.0
		linearVelocityY = 0.0
		if self.forward == True:
			linearVelocityY += self.sensTranslate * self.fast
		if self.backward == True:
			linearVelocityY -= self.sensTranslate * self.fast
		if self.left == True:
			linearVelocityX -= self.sensTranslate * self.fast
		if self.right == True:
			linearVelocityX += self.sensTranslate * self.fast
		linearVelocity = LVector3f(linearVelocityX, linearVelocityY, 0.0)

		# Apply the local transform to the velocity
		# XXX: use BulletCharacterControllerNode class, which already handles local transform?
		rotMat = self.agent.node().getTransform().getMat().getUpper3()
		linearVelocity = rotMat.xformVec(linearVelocity)
		linearVelocity.z = 0.0
		self.agent.node().setLinearVelocity(linearVelocity)

		# take screenshots:
		if self.ss == True:
			ShowBase.screenshot(self, namePrefix='SS', defaultFilename= True, source=None, imageComment="")

		# capture video:
		# if duration=2, fps=16, the total capture video: 32 png files.
		if self.cv == True:
			if self.take_num is not None:
				self.movie(namePrefix='take_{:02d}_frame'.format(self.take_num), duration=9, fps=30, format='png')
			else:
				print('take_num is not set.')
	
		# invoke OpenPose
		# if self.openpose == True:
		# 	p = subprocess.Popen(
		# 		('./build/examples/openpose/openpose.bin ' 
		# 			'--display 0 ' 
		# 			'--image_dir /home/teerawat/openpose/ ' 
		# 			'--render_pose 1 ' 
		# 			'--keypoint_scale 4 ' 
		# 			'--write_images /home/teerawat/Documents/Work/imagesOpenpose/ ' 
		# 			'--write_keypoint_json /home/teerawat/Documents/Work/keypointOpenposeJSON/'), 
		# 		shell=True, stdin=subprocess.PIPE)
		# 	p.wait()
		# 	for i in glob.glob(os.path.join('/home/teerawat/openpose/', "*.jpg")):
		# 		try:
		# 			os.chmod(i, 0o777)
		# 			os.remove(i)
		# 		except OSError:
		# 			pass
		# 	for i in glob.glob(os.path.join('/home/teerawat/openpose/', "*.png")):
		# 		try:
		# 			os.chmod(i, 0o777)
		# 			os.remove(i)
		# 		except OSError:
		# 			pass

		if self.showPosition:
			position = self.agent.getNetTransform().getPos()
			hpr = self.agent.getNetTransform().getHpr()
			self.positionText.setText(
				'Position: (x = %4.2f, y = %4.2f, z = %4.2f)' % (position.x, position.y, position.z))
			self.orientationText.setText('Orientation: (h = %4.2f, p = %4.2f, r = %4.2f)' % (hpr.x, hpr.y, hpr.z))

		self.time = task.time

		# Simulate physics
		if 'physics' in self.scene.worlds:
			self.scene.worlds['physics'].step(dt)

		# Rendering
		if 'render' in self.scene.worlds:
			self.scene.worlds['render'].step(dt)

		# Simulate acoustics
		if 'acoustics' in self.scene.worlds:
			self.scene.worlds['acoustics'].step(dt)

		return task.cont

	def step(self):
		self.taskMgr.step()

	def destroy(self):
		self.taskMgr.remove('peppers-update')
		ShowBase.destroy(self)
		# this should only be destroyed by the Python garbage collector
		# StaticShowBase.instance.destroy()

#------------------edit-------------------------

	def drawHuman(self):
		# self.pActor = Actor(
		# 	"/home/teerawat/Documents/Human Motions/Activities/Human.egg", 
		# 	{'Crouch': '/home/teerawat/Documents/Human Motions/Activities/Human-Crouch.egg'})
		# self.pActor.setScale(0.085, 0.085, 0.085)
		# self.pActor.setPos(41, -41, 0.025)
		# self.pActor.setPos(39.5, -42, 0.025)
		# self.pActor.setPos(40, -40, 0.025)
		# self.pActor.setHpr(90, 0, 0)
		# self.pActor.setPos(40.5, -41, 0.025)
		# self.pActor.reparentTo(self.scene.scene)
		# self.pActor.loop("look")#, fromFrame=500, toFrame=650)

#------Play Multi Animation at the same time.
		# self.pActor = Actor(
		#   "/home/teerawat/Documents/Human Motions/Activities/Human.egg", 
		#   {'Crouch': '/home/teerawat/Documents/Human Motions/Activities/Human-Crouch.egg', 
		#    'Walk': '/home/teerawat/Documents/Human Motions/Activities/Human-Walk.egg'})
		# self.pActor.setScale(0.085, 0.085, 0.085)
		# self.pActor.setPos(40, -40, 0.025)
		# self.pActor.reparentTo(self.scene.scene)
		# self.pActor.enableBlend()
		# self.pActor.setControlEffect('Crouch', 0.2)
		# self.pActor.setControlEffect('Walk', 0.8)
		# self.pActor.loop('Crouch')
		# self.pActor.loop('Walk')
#------End Play Multi Animation at the same time.
		self.pActor = Actor(
			"/Users/hikoyu/src/crest-home/human-models/Human.egg", 
			{'Move': '/Users/hikoyu/src/crest-home/human-models/Human-Crouch.egg'})
		self.pActor.setScale(0.085, 0.085, 0.085)
		self.pActor.setPos(43.22, -36.80, 0.025)
		self.pActor.setHpr(-126.4, 0., 0.)
		self.pActor.reparentTo(self.scene.scene)

		self.actionSequence = Sequence(
			self.pActor.actorInterval('Move'), 
			name = 'crouchSequence')
		self.actionSequence.loop()
Beispiel #21
0
class Enemy(FSM, Unit):

    # Declare private variables
    _enemyActive = False
    _removeCorpseDelay = 2 # seconds before corpse is cleaned

    def __init__(self, mainRef, attributes):
        print("Enemy instantiated")
        Unit.__init__(self)
        FSM.__init__(self, 'playerFSM')

        self._mainRef = mainRef
        self._playerRef = mainRef.player
        self._AIworldRef = mainRef.AIworld
        self._enemyListRef = mainRef.enemyList
        self._ddaHandlerRef = mainRef.DDAHandler
        self._stateHandlerRef = mainRef.stateHandler
        self._scenarioHandlerRef = mainRef.scenarioHandler

        #self.topEnemyNode = mainRef.mainNode.attachNewNode('topEnemyNode')
        self.initEnemyNode(mainRef.mainNode)

        utils.enemyDictionary[self.enemyNode.getName()] = self

        self.loadEnemyModel(attributes.modelName)
        self.initAttributes(attributes)
        self.initEnemyAi()

        self.initEnemyDDA()

        self.initEnemyCollisionHandlers()
        self.initEnemyCollisionSolids()

        #self.request('Idle')
        self.request('Disabled')

        # Start enemy updater task
        self.enemyUpdaterTask = taskMgr.add(self.enemyUpdater, 'enemyUpdaterTask')

    def initEnemyNode(self, parentNode):
        enemyName = 'enemy' + str(len(self._enemyListRef))
        self.enemyNode = parentNode.attachNewNode(enemyName)
        self._enemyListRef.append(self)

    def loadEnemyModel(self, modelName):
        modelPrefix = 'models/' + modelName
        self.enemyModel = Actor(modelPrefix + '-model', {
                'walk':modelPrefix+'-walk',
                'attack':modelPrefix+'-attack',
                'idle':modelPrefix+'-idle',
                'awake':modelPrefix+'-awake',
                'stop':modelPrefix+'-stop',
                'hit':modelPrefix+'-hit',
                'death1':modelPrefix+'-death1',
                'death2':modelPrefix+'-death2'
            })
        self.enemyModel.reparentTo(self.enemyNode)

        self.enemyNode.setPos(Point3.zero())

        self.enemyNode.setDepthOffset(-1)

    def initAttributes(self, attributes):
        perceptionRangeMultiplier = 1.2
        combatRangeMultiplier = .3
        speedMultiplier = .1

        self.strength = attributes.strength
        self.constitution = attributes.constitution
        self.dexterity = attributes.dexterity

        self.mass = attributes.mass
        self.movementSpeed = speedMultiplier * attributes.movementSpeed
        self.perceptionRange = perceptionRangeMultiplier * attributes.perceptionRange
        self.combatRange = combatRangeMultiplier * attributes.combatRange
        self.attackBonus = attributes.attackBonus
        self.damageBonus = attributes.damageBonus
        self.damageRange = attributes.damageRange
        self.initiativeBonus = attributes.initiativeBonus
        self.fixedHealthPoints = attributes.fixedHealthPoints
        self.armorClass = attributes.armorClass

        if attributes.startLevel > 1:
            for i in range(attributes.startLevel-1):
                self.increaseLevel()

        self.expAward = attributes.expAward

        self.initHealth()

    def initEnemyDDA(self):
        if self._scenarioHandlerRef.getHasDDA():
            maxLevelDifference = self._ddaHandlerRef.maxLevelDifference

            # Level enemy up to player's level minus maxLevelDifference
            levelDifference = self._playerRef.level - self.level
            if levelDifference >= maxLevelDifference:
                for i in range (levelDifference-maxLevelDifference):
                    self.increaseLevel()

    def getAttackBonus(self):
        modifier = self.getStrengthModifier() if self.getStrengthModifier() > self.getDexterityModifier() else self.getDexterityModifier()
        ab = self.attackBonus + (self.level / 2) + modifier# + utils.getD20()

        if self._scenarioHandlerRef.getHasDDA():
            attackBonusModifier = self._ddaHandlerRef.attackBonusModifier
            if attackBonusModifier < 0:
                ab -= attackBonusModifier
                if ab < 1:
                    ab = 1

        return ab + utils.getD20()

    def initEnemyAi(self):
        self.enemyAI = AICharacter('enemy',
                                self.enemyNode,
                                self.mass, # Mass
                                0.1, # Movt force
                                self.movementSpeed) # Max force
        self._AIworldRef.addAiChar(self.enemyAI)

        self.enemyAIBehaviors = self.enemyAI.getAiBehaviors()
        #self.enemyAIBehaviors.obstacleAvoidance(1.0)

    def initEnemyCollisionHandlers(self):
        self.groundHandler = CollisionHandlerQueue()
        self.collPusher = CollisionHandlerPusher()

    def initEnemyCollisionSolids(self):
        # Enemy ground ray
        groundRay = CollisionRay(0, 0, 2, 0, 0, -1)
        groundColl = CollisionNode('enemyGroundRay')
        groundColl.addSolid(groundRay)

        groundColl.setIntoCollideMask(BitMask32.allOff())
        groundColl.setFromCollideMask(BitMask32.bit(1))

        self.groundRayNode = self.enemyNode.attachNewNode(groundColl)
        #self.groundRayNode.show()

        base.cTrav.addCollider(self.groundRayNode, self.groundHandler)

        # Enemy collision sphere
        collSphereNode = CollisionNode('enemyCollSphere')
        collSphere = CollisionSphere(0, 0, 0.1, 0.2)
        collSphereNode.addSolid(collSphere)

        collSphereNode.setIntoCollideMask(BitMask32.allOff())
        collSphereNode.setFromCollideMask(BitMask32.bit(2))
        
        self.sphereNode = self.enemyNode.attachNewNode(collSphereNode)
        #sphereNode.show()

        base.cTrav.addCollider(self.sphereNode, self.collPusher)
        self.collPusher.addCollider(self.sphereNode, self.enemyNode)

        # Enemy picker collision sphere
        pickerSphereCollNode = CollisionNode(self.enemyNode.getName())
        pickerCollSphere = CollisionSphere(0, 0, 0, 0.5)
        pickerSphereCollNode.addSolid(pickerCollSphere)

        pickerSphereCollNode.setFromCollideMask(BitMask32.allOff())
        pickerSphereCollNode.setIntoCollideMask(BitMask32.bit(1))

        self.pickerNode = self.enemyNode.attachNewNode(pickerSphereCollNode)
        #sphereNodePath.show()

        # Enemy attack collision sphere
        attackCollSphereNode = CollisionNode(self.enemyNode.getName()+'atkSph')
        attackCollSphere = CollisionSphere(0, 0, 0.1, 0.15)
        attackCollSphereNode.addSolid(attackCollSphere)

        attackCollSphereNode.setIntoCollideMask(BitMask32.bit(3))
        attackCollSphereNode.setFromCollideMask(BitMask32.allOff())

        attackSphereNode = self.enemyNode.attachNewNode(attackCollSphereNode)
        #attackSphereNode.show()

    def slowMovementByPercentage(self, percentage=30, slowDuration=20):
        #print self.enemyNode.getName(), ' slowed by ', percentage, ' %'
        oldSpeed = self.movementSpeed
        newSpeed = ((100.0 - percentage) / 100.0) * oldSpeed

        if newSpeed < 1.0:
            newSpeed = 1.0

        self.movementSpeed = newSpeed

        taskMgr.doMethodLater(slowDuration, self.removeSlowMovement, 'removeSlowMovementTask', extraArgs=[oldSpeed], appendTask=True)

    def removeSlowMovement(self, oldSpeed, task):
        self.movementSpeed = oldSpeed
        return task.done

    def checkGroundCollisions(self):
        if self.groundHandler.getNumEntries() > 0:
            self.groundHandler.sortEntries()
            entries = []
            for i in range(self.groundHandler.getNumEntries()):
                entry = self.groundHandler.getEntry(i)
                #print('entry:', entry)
                entries.append(entry)

            entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                         x.getSurfacePoint(render).getZ()))

            for i in range(len(entries)):
                if entries[i].getIntoNode().getName()[:6] == 'ground':
                    #print('entryFound:', entries[0])
                    newZ = entries[i].getSurfacePoint(base.render).getZ()
                    self.enemyNode.setZ(newZ)
                    #print('enemyZ:', newZ)
                    break;

    def enemyUpdater(self, task):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY or not self._enemyActive:
            self.enemyModel.stop()
            # Do not do anything when paused
            return task.cont

        self.checkGroundCollisions()

        if self.getIsDead():
            self.onDeath()
            return task.done

        if self._playerRef.getIsDead():
            return task.cont

        playerPos = self._playerRef.playerNode.getPos()
        enemyPos = self.enemyNode.getPos()

        # If player is within enemy perception range
        if utils.getIsInRange(playerPos, enemyPos, self.perceptionRange):

            # If enemy is not doing anything
            if self.state == 'Idle':
                # Start pursuing
                if self.state != 'Pursue':
                    self.request('Pursue')

            # If enemy is already pursueing
            elif self.state == 'Pursue':
                # If player is within combat range
                if utils.getIsInRange(playerPos, enemyPos, self.combatRange):
                    #print 'enemy go to combat'
                    # Go to combat
                    if self.state != 'Combat':
                        self.request('Combat')

            # If enemy is already in combat
            elif self.state == 'Combat':
                # If player has moved out of combat range
                if not utils.getIsInRange(playerPos, enemyPos, self.combatRange):
                    # Start pursuing
                    if self.state != 'Pursue':
                        self.request('Pursue')

            # If enemy is disabled
            elif self.state == 'Disabled':
                if self.enemyAI.getMaxForce() != self.movementSpeed:
                    self.enemyAI.setMaxForce(self.movementSpeed)

        # If player is not within perception range
        else:
            if self.state != 'Idle':
                self.request('Idle')

        return task.cont

    def pursuePlayer(self):
        taskMgr.add(self.pursue, 'pursueTask')

    def pursue(self, task):
        if self.state == 'Pursue' and not self.getIsDead():
            pitchRoll = self.enemyNode.getP(), self.enemyNode.getR()
            self.enemyNode.headsUp(self._playerRef.playerNode)
            self.enemyNode.setHpr(self.enemyNode.getH()-180, *pitchRoll)

            speed = -self.movementSpeed * globalClock.getDt()
            self.enemyNode.setFluidPos(self.enemyNode, 0, speed, 0)

            return task.cont
        else:
            task.done

    def enterIdle(self):
        #print 'enemy enterIdle'
        stopEnemy = self.enemyModel.actorInterval('stop', loop=0)
        idleEnemy = self.enemyModel.actorInterval('idle', startFrame=0, endFrame=1, loop=0)

        self.stopSequence = Sequence(stopEnemy, idleEnemy)
        self.stopSequence.start()

        self.isSleeping = True

    def exitIdle(self):
        #print('enemy exitIdle')
        self.stopSequence.finish()

    def enterPursue(self):
        #print('enemy enterPursue')
        loopWalkEnemy = Func(self.enemyModel.loop, 'walk', fromFrame=0, toFrame=12)

        # Only awake enemy if it comes from idle
        if self.isSleeping: 
            self.isSleeping = False

            awakeEnemy = self.enemyModel.actorInterval('awake', loop=0)
            self.awakeSequence = Sequence(awakeEnemy, loopWalkEnemy, Func(self.pursuePlayer))
        else:
            self.awakeSequence = Sequence(loopWalkEnemy, Func(self.pursuePlayer))

        self.awakeSequence.start()

    def exitPursue(self):
        #print('enemy exitPursue')
        self.awakeSequence.finish()

    def enterCombat(self):
        #print('enemy enterCombat')
        self.enemyModel.stop()

        attackDelay = self.getInitiativeRoll()
        self.attackTask = taskMgr.doMethodLater(attackDelay, self.attackPlayer, 'attackPlayerTask')

    def enterDisabled(self):
        #print 'enterDisable'
        pass

    def exitDisabled(self):
        #print 'exitDisable'
        pass

    def exitCombat(self):
        #print('enemy exitCombat')
        taskMgr.remove(self.attackTask)

    def enterDeath(self):
        #print('enemy enterDeath')
        self.enemyAIBehaviors.removeAi('all')
        randomDeathAnim = 'death' + str(utils.getD2())
        self.enemyModel.play(randomDeathAnim)


    def attack(self, other):
        if not self.getIsDead() and not other.getIsDead():
            if self.getAttackBonus() >= other.getArmorClass():
                dmg = self.getDamageBonus()
                #print(self.getName(), ' damaged ', other.getName(), ' for ', dmg, ' damage')
                other.receiveDamage(dmg)

                return 2 # Returns 2 when self damages other

            return 1 # Returns 1 when self attacks other, but misses

        return 0 # Returns 0 when either self or other is dead

    def attackPlayer(self, task):
        if self._stateHandlerRef.state != self._stateHandlerRef.PLAY or not self._enemyActive:
            # Do not do anything when paused
            return task.again

        if self._playerRef.getIsDead():
            print('player is already dead')
            self.request('Idle')
            return task.done

        elif self.getIsDead():
            return task.done

        else:
            #print('Attack player!')
            # Make sure enemy is facing player when attacking
            pitchRoll = self.enemyNode.getP(), self.enemyNode.getR()
            self.enemyNode.headsUp(self._playerRef.playerNode)
            self.enemyNode.setHpr(self.enemyNode.getH()-180, *pitchRoll)

            attacked = self.attack(self._playerRef)
            if attacked != 0:
                self.playAttackAnimation()
                if attacked == 2:
                    self._playerRef.playerModel.play('hit')

            return task.again

    def playAttackAnimation(self):
        self.enemyModel.play('attack', fromFrame=0, toFrame=12)

    def playHitAnimation(self):
        self.enemyModel.play('hit')

    def moveEnemy(self, x, y):
        self.enemyNode.setPos(x, y, .01)

    def handleHealthGlobe(self):
        global dropChanceFactor
        global dropChance
        global maxDropChance

        # if we drop, create health goblet
        chance = dropChanceFactor + dropChance
        if self._scenarioHandlerRef.getHasDDA():
            chance *= self._ddaHandlerRef.healthGobletModifier

        if utils.getD100() <= chance:
            HealthGoblet(self._mainRef, self)
            print 'dropping health goblet'
        # Otherwise, increase dropChance
        else:
            if dropChance+dropChanceFactor <= maxDropChance:
                dropChance += dropChanceFactor

    def suicide(self):
        print('suicide: ', self)
        # Remove AI behavior
        self.enemyAIBehaviors.removeAi('all')

        # Remove enemy picker sphere (handlerQueue)
        self.pickerNode.removeNode()

        taskMgr.add(self.removeCorpse, 'removeCorpseTask')

    def onDeath(self):
        if self.getIsDead():
            # Remove AI behavior
            self.enemyAIBehaviors.removeAi('all')

            # Award the player exp
            self._playerRef.receiveEXP(self.expAward)

            # Remove enemy picker sphere (handlerQueue)
            self.pickerNode.removeNode()

            # Change state
            self.request('Death')

            # Increase DDA death count
            if self._scenarioHandlerRef.getHasDDA():
                self._ddaHandlerRef.enemyDeathCount += 1

            # Handle health globe
            self.handleHealthGlobe()

            # Remove enemy corpse and clean up
            taskMgr.doMethodLater(self._removeCorpseDelay, self.removeCorpse, 'removeCorpseTask')

    def removeCorpse(self, task):
        # Remove enemy collision sphere (pusher)
        self.sphereNode.removeNode()

        # Stop the collision pusher
        self.collPusher = None

        # Remove enemy from enemyList
        self._enemyListRef.remove(self)

        # Cleanup the enemy model
        self.enemyModel.cleanup()
        self.enemyModel.delete()

        # Cleanup FSM
        self.cleanup()

        # Remove the enemy node
        self.enemyNode.removeNode()
        #self.topEnemyNode.removeNode()

        # Remove enemy updater tasks
        taskMgr.remove(self.enemyUpdaterTask)

        # Remove the passive regeneration task (from Unit class)
        self.removePassiveRegeneration()

        # Remove references
        self._mainRef = None
        self._playerRef = None
        self._AIworldRef = None
        self._enemyListRef = None
        self._stateHandlerRef = None

        return task.done
Beispiel #22
0
class Npc():

    def __init__(self,controlPointId,id, anchorx, anchory, anchorz,render,team):
        self.id = id
        self.anchorx = anchorx
        self.anchory = anchory
        self.anchorz = anchorz
        self.controlPointId = controlPointId
        self.target = None
        self.isMoving = False
        self.health = 200
        self.isCurrentUser = False
        self.damage = 8
        self.attackTimer = 0
        self._is_dead = False
        self._team = team
        
        self.render = render
        '''Initializing NPC actors'''
        self.npc = Actor("models/priest",
                                {"walk": "models/priest-walk", "attack":"models/priest-attack", "hurt":"models/priest-hit", "die":"models/priest-die"})
        if self._team==0:
            self.npcTex = loader.loadTexture("models/tex/guard_red.png")
        else:
            self.npcTex = loader.loadTexture("models/tex/guard_blue.png")
        self.npc.setTexture(self.npcTex)
        self.npc.setScale(0.5, 0.5, 0.5)
        self.npc.clearColor()
        self.npc.clearColorScale()
        self.npc.setColor(255, 0, 0, 0)
        self.npc.setColorScale(255, 0, 0, 0)
        self.npc.reparentTo(self.render)
        self.npc.setPos(anchorx,anchory,anchorz)
        
        self.AIchar = AICharacter("npc"+str(self.id),self.npc, 100, 0.05, 5)
        self.AIbehaviors = self.AIchar.getAiBehaviors()
        
        self.hb = HealthBar(1.5, value=self.health)
        #self._floater = NodePath(PandaNode("char_info"))
        #self._floater.reparentTo(self.npc)
        self.hb.setPos(0, 0, 11.9)
        self.hb.reparentTo(self.npc)
        #self.hb.reparentTo(self.npc)
        
    def renderBlue(self,AIworld):
        if not self._is_dead:
            self.AIbehaviors.removeAi("pursue")
            self.npc.detachNode()
        
        print "Started delete procedure for npc ",
        print self.id    
        self.npc.delete()
        self.npc = Actor("models/priest",
                                {"walk": "models/priest-walk", "attack":"models/priest-attack", "hurt":"models/priest-hit", "die":"models/priest-die"})
        self.npcTex = loader.loadTexture("models/tex/guard_blue.png")
        self.npc.setTexture(self.npcTex)
        self.npc.setScale(0.5, 0.5, 0.5)
        self.npc.clearColor()
        self.npc.clearColorScale()
        self.npc.setColor(255, 0, 0, 0)
        self.npc.setColorScale(255, 0, 0, 0)
        self.npc.reparentTo(self.render)
        self.npc.setPos(self.anchorx,self.anchory,self.anchorz)
        
        AIworld.removeAiChar("npc"+str(self.id))
        self.AIchar = AICharacter("npc"+str(self.id),self.npc, 100, 0.05, 5)
        self.AIbehaviors = self.AIchar.getAiBehaviors()
        AIworld.addAiChar(self.AIchar)
        
        self.hb = HealthBar(1.5, value=self.health)
        self.hb.setPos(0, 0, 18.1)
        self.hb.reparentTo(self.npc)
        #self.hb.reparentTo(self.npc)
        
    def renderRed(self,AIworld):
        if not self._is_dead:
            self.AIbehaviors.removeAi("pursue")
            self.npc.detachNode()
            
        self.npc.delete()
        self.npc = Actor("models/priest",
                                {"walk": "models/priest-walk", "attack":"models/priest-attack", "hurt":"models/priest-hit", "die":"models/priest-die"})
        self.npcTex = loader.loadTexture("models/tex/guard_red.png")
        self.npc.setTexture(self.npcTex)
        self.npc.setScale(0.5, 0.5, 0.5)
        self.npc.clearColor()
        self.npc.clearColorScale()
        self.npc.setColor(255, 0, 0, 0)
        self.npc.setColorScale(255, 0, 0, 0)
        self.npc.reparentTo(self.render)
        self.npc.setPos(self.anchorx,self.anchory,self.anchorz)
        
        AIworld.removeAiChar("npc"+str(self.id))
        self.AIchar = AICharacter("npc"+str(self.id),self.npc, 100, 0.05, 5)
        self.AIbehaviors = self.AIchar.getAiBehaviors()
        AIworld.addAiChar(self.AIchar)
        AIworld.update()
        
        self.hb = HealthBar(1.5, value=self.health)
        self.hb.setPos(0, 0, 8.1)
        self.hb.reparentTo(self.npc)
        
    def switchTeam(self,AIworld):
        print self.id,
        print " from team ",
        print self._team,
        print " getting deleted."
        if self._team==0:
            self._team=1
            self.renderBlue(AIworld)
        else:
            self._team=0
            self.renderRed(AIworld)
            
        if self.isCurrentUser:
            main.freeDeadNpc(self.id)
            
        self.target = None
        self.isMoving = False
        self.health = 200
        self.isCurrentUser = False
        self.damage = 8
        self.attackTimer = 0
        self._is_dead = False
            
        
    def set_health(self, health):
        self.health = health
        
    def take_damage(self, health_change):
        health = self.health
        if health <= health_change and not self._is_dead:
            self.killNpc()
        else:
            health = health-health_change
            self.set_health(health)
            self.hb.setValue(self.health)
            self.npc.play("hurt")
            
    def killNpc(self):
        self.set_health(0)
        self.hb.setValue(0)
        self.AIbehaviors.removeAi("pursue")
        hurt_interval = self.npc.actorInterval("hurt")
        death_interval = self.npc.actorInterval("die")
        seq = Sequence(hurt_interval, death_interval)
        seq.start()
        self.npc.pose("die",45)
        self._is_dead = True
        self.npc.detachNode()
        if self.isCurrentUser:
            main.freeDeadNpc(self.id)
            #main.cManager.sendRequest(Constants.CMSG_NPCDEATH, [self.id])
            print Constants.CMSG_NPCDEATH,
            print " + ",
            print self.id
            
            
    def chaseTarget(self, target, status = False):
        if(not self.isMoving):
            self.target = target
            self.AIbehaviors.pursue(self.target)
            self.npc.loop("walk")
            self.isMoving = True
            self.isCurrentUser = status
            
    def stopChase(self):
        
        #self.AIbehaviors.pauseAi("pursue")
        if not self._is_dead:
            self.AIbehaviors.removeAi("pursue")
            p1 = LerpHprInterval(self.npc, 4, Point3(180,0,0))
            p2 = LerpPosInterval(self.npc, 4, Point3(self.anchorx, self.anchory, self.anchorz))
            animInterval = self.npc.actorInterval("walk", loop = 1, duration=4)
            p2.start()
            p1.start()
            animInterval.start()
            self.isMoving = False
            self.target = None
            self.isCurrentUser = False
        
    def givNPCDistance(self,charachter):
        x = self.npc.getX()
        y = self.npc.getY()
        z = self.npc.getZ()
        minDist = math.sqrt( (charachter.getX()-x)*(charachter.getX()-x) + (charachter.getY()-y)*(charachter.getY()-y) + (charachter.getZ()-z)*(charachter.getZ()-z) )
        return minDist
    
    def checkNpcIsAlive(self):
        if(self.health>0):
            return True
        else:
            return False
                         
    def shouldAttack(self,currentTime,cManager):
        if not self._is_dead:
            if self.isMoving:
                if self.attackTimer>0:
                    self.attackTimer = self.attackTimer-currentTime
                    #print self.attackTimer
                if self.AIbehaviors.behaviorStatus("pursue")=="done":
                    #self.npc.stop("walk")
                    #print self.npc.getAnimControl("walk")
                    if self.attackTimer<=0:
                            if self.npc.getAnimControl("walk").isPlaying():
                                self.npc.stop("walk")
                            if not self.npc.getAnimControl("attack").isPlaying():
                                #self.npc.loop("attack")
                                self.npc.play("attack")
                                self.attackTimer = 2
                                #myInterval = self.npc.actorInterval("attack")
                                #seq = Sequence(myInterval)
                                #seq.append(Wait(3))
                                #seq.start()
                            if self.isCurrentUser:
                                cManager.sendRequest(Constants.CMSG_NPCATTACK, [self.id, self.damage])
                
                if self.AIbehaviors.behaviorStatus("pursue")=="active":
                    if self.npc.getAnimControl("attack").isPlaying():
                        self.npc.stop("attack")
                    if not self.npc.getAnimControl("walk").isPlaying():
                        self.npc.loop("walk") 
Beispiel #23
0
class Lvl03(DirectObject):
    def start(self):
        base.disableMouse() #turn off mouse camera control
        base.enableParticles()
	
	self.music = loader.loadMusic("models/gamedev/DEC.mp3")
	self.music.play()
	
        camera.setPosHpr(Vec3(98,-390,90), Vec3(0,-5,0))
        self.ballNum = 10
	self.setupStage()
        self.loadModels()
        self.setupLighting()
        self.setupCollisions()
        self.setupIntervals()
	
	taskMgr.add(self.ballMovementTask,'ballMoveTask')
        
        self.gameLen = 30
        
	self.player1Weapon = ""
	self.player2Weapon = ""
	
        #hud = OnscreenImage(image = 'models/gamedev/lvl2hud.jpg', pos = (0,1,20),scale=5.0)
        #hud.reparentTo(render)
        
        globalClock.reset()
        
        self.timer = OnscreenText("%d" % (self.gameLen-globalClock.getRealTime(),), pos = (98,145), scale = 18.0)
        self.timer.setColor(1,1,1)
        taskMgr.add(self.clockTask,"clockTask")
        
        self.player1Score = 0
        self.player2Score = 0
        
        self.nodeCount1 = 0
        self.nodeCount2 = 0
	
	self.player1Invincible = 0
        self.player2Invincible = 0
	
	self.jNP = self.playerModel.exposeJoint(None,"modelRoot","ikHandle2")
	self.jNP2 = self.playerModel2.exposeJoint(None,"modelRoot","ikHandle2")
	
        self.climbing1 = 0
        self.climbing2 = 0
        
        self.speed1 = 3.0
        self.speed2 = 3.0
        
        self.ignoreColl= 0
        
        self.player1IsColliding = 0
        self.player2IsColliding = 0
        
        taskMgr.doMethodLater(self.gameLen, self.endGame,'gameFinished')
        
        #taskMgr.doMethodLater(self.gameLen/2.0,self.changeMusic,'musicSwitch')
        
        
        #setup key controls
        self.accept("escape",sys.exit)
        #self.acceptOnce("space",self.drop)
        # Player 1 movement
        
        self.acceptOnce("a",self.left)
        self.acceptOnce("d",self.right)
        
        self.accept("a-up",self.stopLeft)
        self.accept("d-up",self.stopRight)
        
        self.acceptOnce("w", self.jump)

        
        #Player 2 movement keys
        #self.accept("l",self.fall2)
        
        self.acceptOnce("k",self.left2)
        self.acceptOnce(";",self.right2)
        
        self.accept("k-up",self.stopLeft2)
        self.accept(";-up",self.stopRight2)
        
        self.acceptOnce("o", self.jumpT2)
        
    def setupStage(self):
	self.ball = []
	self.movement = []
	for i in range(self.ballNum+1):
		z=random.randint(1,2)
		if z ==1:
			z=-1
		else:
			z=1
		weapBalls.define(self.ball,i,render)
		self.movement.append(Vec3(random.random()*z,0,random.random()*z))
		#self.movement[i].Vec3(random.randint(1,3),0,random.randint(1,3))
		
	self.background2 = OnscreenImage(image = 'models/gamedev/frozenbg.JPG', pos = (98,10,0),scale=500)
	self.background2.detachNode()
        self.background = OnscreenImage(image = 'models/gamedev/moltenbg.JPG', pos = (98,10,0),scale=500)
        self.background.reparentTo(render)
        
        self.lava = loader.loadModel("models/gamedev/lava")
        self.lava.setPosHpr(Vec3(98,0,-18),Vec3(0,5,0))
        self.lava.setScale(50)
        self.lava.reparentTo(render)
        
        
        x1= 196
        x2 = 0
        m1 = 98
        m2 = 107.8
        len = 9.8
        h = 0
        a = 0
        p = 0
        
        for j in range(4):
            if j > 0:
                x1Old = x1
                x2Old = x2
                x1 = 196-(random.randint(0,3)*9.8)
                x2 = 0+random.randint(0,3)*9.8
                m1=98-(random.randint(0,3)*9.8)
                m2= 107.8+random.randint(0,3)*9.8
            
                for count in range(1):
                    l = random.randint(2,5)
                    r = random.randint(2,5)
                    c1 = random.randint(2,5)
                    c2 = random.randint(2,5)
                    if l+r < 4:
		        count = 0
			
            else:
                l = 4
                r = 4
                c1 = 2
                c2 = 2
            '''
            if j ==1 or j == 3:
                self.ladder = loader.loadModel("models/gamedev/ladder")
                self.ladder.reparentTo(render)
                self.ladder.setScale(1.5)
                self.ladder.setPos(x2+4.9,0,h-20)
                self.ladder2 = loader.loadModel("models/gamedev/ladder")
                self.ladder2.reparentTo(render)
                self.ladder2.setScale(1.5)
                self.ladder2.setPos(x1-4.9,0,h-20)
            
            if j == 2:
                self.ladder = loader.loadModel("models/gamedev/ladder")
                self.ladder.reparentTo(render)
                self.ladder.setScale(1.5)
                self.ladder.setPos(m1-4.9,0,h-20)
                self.ladder2 = loader.loadModel("models/gamedev/ladder")
                self.ladder2.reparentTo(render)
                self.ladder2.setScale(1.5)
                self.ladder2.setPos(m2+4.9,0,h-20)
            '''
            self.first = 1

            for i in range(r):
                '''Right half of stage'''
                self.environment = loader.loadModel("models/gamedev/platform")
                self.environment.reparentTo(render)
                self.environment.setScale(5)
                self.environment.setPos(x1,0,h)
                    
                if self.first == 1:
                    self.first = 0
                    bounds = self.environment.getChild(0).getBounds()
                    center = bounds.getCenter()
                    poly1 = Point3(center.getX()+1, center.getY()-.5, center.getZ()+.2)
                    poly2 = Point3(center.getX()-(2*r-1), center.getY()-.5, center.getZ()+.2)
                    poly3 = Point3(center.getX()+1, center.getY()+.5, center.getZ()+.2)
                    poly4 = Point3(center.getX()-(2*r-1), center.getY()+.5, center.getZ()+.2)
                    cPoly = CollisionPolygon(poly4, poly2, poly1, poly3)
                    cNode = CollisionNode("platform")
                    cNode.addSolid(cPoly)
                    cNodePath = self.environment.attachNewNode(cNode)
                    cNodePath.show()
                    
                x1 = x1 - len

            self.first = 1
            
            for i in range(l):
                '''Left Half of stage'''
                self.environment = loader.loadModel("models/gamedev/platform")
                self.environment.reparentTo(render)
                self.environment.setScale(5)
                self.environment.setPos(x2,0,h)
                
                if self.first == 1:
                    self.first = 0
                    bounds = self.environment.getChild(0).getBounds()
                    center = bounds.getCenter()
                    poly1 = Point3(center.getX()+(2*l-1), center.getY()-.5, center.getZ()+.2)
                    poly2 = Point3(center.getX()-1, center.getY()-.5, center.getZ()+.2)
                    poly3 = Point3(center.getX()+(2*l-1), center.getY()+.5, center.getZ()+.2)
                    poly4 = Point3(center.getX()-1, center.getY()+.5, center.getZ()+.2)
                    cPoly = CollisionPolygon(poly4, poly2, poly1, poly3)
                    cNode = CollisionNode("platform")
                    cNode.addSolid(cPoly)
                    cNodePath = self.environment.attachNewNode(cNode)
                    cNodePath.show()
                
                x2 = x2 + len
                
            self.first = 1
            
            for i in range(c1):
                '''Right half of stage'''
                self.environment = loader.loadModel("models/gamedev/platform")
                self.environment.reparentTo(render)
                self.environment.setScale(5)
                self.environment.setPos(m1,0,h)
                
                if self.first == 1:
                    self.first = 0
                    bounds = self.environment.getChild(0).getBounds()
                    center = bounds.getCenter()
                    poly1 = Point3(center.getX()+1, center.getY()-.5, center.getZ()+.2)
                    poly2 = Point3(center.getX()-(2*c1-1), center.getY()-.5, center.getZ()+.2)
                    poly3 = Point3(center.getX()+1, center.getY()+.5, center.getZ()+.2)
                    poly4 = Point3(center.getX()-(2*c1-1), center.getY()+.5, center.getZ()+.2)
                    cPoly = CollisionPolygon(poly4, poly2, poly1, poly3)
                    cNode = CollisionNode("platform")
                    cNode.addSolid(cPoly)
                    cNodePath = self.environment.attachNewNode(cNode)
                    cNodePath.show()
                
                m1 = m1 - len
                
            self.first = 1
            
            for i in range(c2):
                '''Left Half of stage'''
                self.environment = loader.loadModel("models/gamedev/platform")
                self.environment.reparentTo(render)
                self.environment.setScale(5)
                self.environment.setPos(m2,0,h)
                
                if self.first == 1:
                    self.first = 0
                    bounds = self.environment.getChild(0).getBounds()
                    center = bounds.getCenter()
                    poly1 = Point3(center.getX()+(2*c2-1), center.getY()-.5, center.getZ()+.2)
                    poly2 = Point3(center.getX()-1, center.getY()-.5, center.getZ()+.2)
                    poly3 = Point3(center.getX()+(2*c2-1), center.getY()+.5, center.getZ()+.2)
                    poly4 = Point3(center.getX()-1, center.getY()+.5, center.getZ()+.2)
                    cPoly = CollisionPolygon(poly4, poly2, poly1, poly3)
                    cNode = CollisionNode("platform")
                    cNode.addSolid(cPoly)
                    cNodePath = self.environment.attachNewNode(cNode)
                    cNodePath.show()
                
                m2 = m2 + len
            
            h = h+40
            a = 0

    def loadModels(self):
    
        # ** Load female character that will represent first player** #
        
        
        self.playerModel = Actor("models/gamedev/redguy-model",{"walk":"models/gamedev/redguy-run"})
        self.playerModel.reparentTo(render)
        self.playerModel.setScale(.6)
        self.playerModel.setH(90)
        
        # ** Position player at center of the field with it lying directly above the field. ** #
        
        self.playerModel.setPos(0,0,1.76)
        
        # ** Load female character that will represent second player** #
        
        self.playerModel2 = Actor("models/gamedev/bluegirl-model",{"walk2":"models/gamedev/bluegirl-run"})
        self.playerModel2.reparentTo(render)
        self.playerModel2.setScale(.6)
        self.playerModel2.setH(0)
        
        # ** Position player at center of the field with it lying directly above the field. ** #
        
        self.playerModel2.setPos(196,0,2.0)

    def reset(self):
	self.an1.getPhysicsObject().setVelocity(Vec3(0,0,0))
	self.an2.getPhysicsObject().setVelocity(Vec3(0,0,0))
	self.an1.getPhysicsObject().setPosition(Point3(0,0,11.76))
	self.an2.getPhysicsObject().setPosition(Point3(196,0,22.0))
	
	self.playerModel.setH(90)
	self.playerModel.detachNode()
	self.playerModel.setPos(0,0,1.76)
	self.anp.setFluidPos(Point3(0,0,1.76))
	self.playerModel.reparentTo(self.anp)
	
	self.playerModel2.setH(0)
	self.playerModel2.detachNode()
	self.playerModel2.setPos(196,0,22.0)
	self.anp2.setFluidPos(Point3(196,0,22.0))
	self.playerModel2.reparentTo(self.anp2)

    def setupLighting(self):
        ambientLight = AmbientLight('ambientLight')
        ambientLight.setColor(Vec4(0.55,0.55,0.55,1.0))
        ambientLightNP = render.attachNewNode(ambientLight)
        render.setLight(ambientLightNP)
        dirLight = DirectionalLight('dirLight')
        dirLight.setColor(Vec4(0.6,0.6,0.6,1))
        dirLightNP = render.attachNewNode(dirLight)
        dirLightNP.setHpr(Vec3(0.0,-26.0,0.0))
        render.setLight(dirLightNP)
        
    def setupIntervals(self):
        self.charWalk1l = self.playerModel.actorInterval("walk")
        self.charWalk1l.loop( )
        self.charWalk1l.pause( )
        
        self.charWalk1r = self.playerModel.actorInterval("walk")
        self.charWalk1r.loop( )
        self.charWalk1r.pause( )
        
        self.charWalk2l = self.playerModel2.actorInterval("walk2")
        self.charWalk2l.loop( )
        self.charWalk2l.pause( )
        
        self.charWalk2r = self.playerModel2.actorInterval("walk2")
        self.charWalk2r.loop( )
        self.charWalk2r.pause( )
        
        self.jump1 = self.playerModel.actorInterval("jump")
        self.jump1.loop()
        self.jump1.pause()
        
        self.jump2 = self.playerModel2.actorInterval("jump2")
        self.jump2.loop()
        self.jump2.pause()
        
        self.climb1 = self.playerModel.actorInterval("climb")
        self.climb1.loop()
        self.climb1.pause()
        
        self.climb2 = self.playerModel2.actorInterval("climb2")
        self.climb2.loop()
        self.climb2.pause()
        
        # end setupIntervals

        # ############################
        # Actual Working movement code
        # ############################

    def rise(self):
        dist = 40
        self.playerModel.setH(0)
        playerJump = self.playerModel.posInterval(1.0,Vec3(self.playerModel.getX(), self.playerModel.getY(),self.playerModel.getZ()+dist))
        playerJump.start()
        
    def rise2(self):
        dist = 40
        self.playerModel2.setH(90)
        playerJump2 = self.playerModel2.posInterval(1.0,Vec3(self.playerModel2.getX(), self.playerModel2.getY(),self.playerModel2.getZ()+dist))
        playerJump2.start()
        
    # PLAYER ONE #
        
    def left(self):
        taskMgr.add(self.leftTask,'leftTask')
        self.charWalk1l.loop()
        #end left
        
    def leftTask(self,task):
        if self.climbing1 == 0:
            self.playerModel.setH(270)
            self.playerModel.setPos(Vec3(self.playerModel.getX()-self.speed1, self.playerModel.getY(), self.playerModel.getZ()))
        return Task.cont
        
    def right(self):
        taskMgr.add(self.rightTask,'rightTask')
        self.charWalk1r.loop()
        #end right
        
    def rightTask(self,task):
        if self.climbing1 == 0:
            self.playerModel.setH(90)
            self.playerModel.setPos(Vec3(self.playerModel.getX()+self.speed1, self.playerModel.getY(), self.playerModel.getZ()))
        return Task.cont	

	def climbable(self,cEntry):
		self.nodeCount1+=1
		print self.nodeCount1
		self.ignore("w")
		self.ignore("w-up")
		self.ignore("s")
		self.ignore("s-up")
		self.acceptOnce("w",self.climb,[1])
		self.accept("w-up",self.noClimb)
		self.acceptOnce("s",self.climb,[-1])
		self.accept("s-up",self.noClimb)

	def climb(self,dir):
		self.dir1 = dir
		self.climbing1 = 1
		self.climbSpeed1 = 1
		self.ignore("a")
		self.ignore("a-up")
		self.ignore("d")
		self.ignore("d-up")
		taskMgr.add(self.climbTask,'climbTask')
		self.climb1.loop()
		
	def noClimb(self):
		taskMgr.remove('climbTask')
		self.climb1.pause()
		if self.nodeCount1 == 0:
			self.climbing = 0
		self.climbSpeed1 = 0
		self.acceptOnce("w",self.climb,[1])
		self.acceptOnce("s",self.climb,[-1])
		
	def jumpable(self,cEntry):
		self.nodeCount1+=-1
		print self.nodeCount1
		if self.nodeCount1 == 0:
			taskMgr.remove('climbTask')
			self.ignore("w")
			self.ignore("w-up")
			self.ignore("s")
			self.ignore("s-up")
			self.acceptOnce("w",self.jump)
			self.acceptOnce("a",self.left)
			self.acceptOnce("d",self.right)
			self.accept("a-up",self.stopLeft)
			self.accept("d-up",self.stopRight)
			self.climbing1 = 0
			self.climbSpeed1 = 0
			self.climb1.pause()
			
	def walkable(self,cEntry):
		self.ignore("w")
		self.ignore("w-up")
		self.ignore("s")
		self.ignore("s-up")
		self.acceptOnce("w",self.climb,[1])
		self.accept("w-up",self.noClimb)
		self.acceptOnce("s",self.climb,[-1])
		self.accept("s-up",self.noClimb)
		self.acceptOnce("a",self.left)
		self.acceptOnce("d",self.right)
		self.accept("a-up",self.stopLeft)
		self.accept("d-up",self.stopRight)
		self.climbing1 = 0
		self.climbSpeed1 = 0
		self.climb1.pause()
			
	def climbTask(self,task):
		if self.playerModel.getZ() >=0:
			self.playerModel.setH(0)
			self.playerModel.setPos(Vec3(self.playerModel.getX(), self.playerModel.getY(), self.playerModel.getZ()+self.climbSpeed1*self.dir1))
		return Task.cont	

    def jump(self):
        if self.nodeCount1 == 0:
            self.ignore("w")
            self.ignore("w-up")
            z = self.playerModel.getZ()
            j = ProjectileInterval(self.playerModel, startPos = self.playerModel.getPos(), startVel = Point3(5,0,30), duration = 2.0)
            j.start()
            taskMgr.doMethodLater(2,self.jumpTask,"jumpTask")
        else:
            self.acceptOnce("w",self.climb,[1])
        
    def jumpTask(self, task):
        if self.climbing1 == 0:
            self.jump1.pause()
            self.acceptOnce("w",self.jump)
        #return task.cont
    
    def allowRight(self):
        self.acceptOnce("d",self.right)
    
    def noRight(self):
        taskMgr.remove('rightTask')
        self.charWalk1r.pause()
        self.acceptOnce("d",self.right)

    def stopRight(self):
        self.noRight()
        #self.allowRight()

    def rightWall(self,cEntry):
	self.ignore("d")
	self.noRight()
		
    def rightEdge(self,cEntry):
	self.ignore("d")
	self.noRight()

    def rightOK(self,cEntry):
	self.allowRight()	
		
    def allowLeft(self):
	self.acceptOnce("a",self.left)

    def noLeft(self):
        taskMgr.remove('leftTask')
        self.charWalk1l.pause()
        self.acceptOnce("a",self.left)

    def stopLeft(self):
        self.noLeft()
        #self.allowLeft()
        
    def leftWall(self,cEntry):
        self.ignore("a")
        self.noLeft()
        
    def leftEdge(self,cEntry):
        self.ignore("a")
        self.noLeft()
        
    def leftOK(self,cEntry):
        self.allowLeft()

	# PLAYERTWO #

    def left2(self):
        taskMgr.add(self.leftTask2,'leftTask2')
        self.charWalk2l.loop()
    #end left

    def leftTask2(self,task):
        if self.climbing2 == 0:
            self.playerModel2.setH(0)
            self.playerModel2.setPos(Vec3(self.playerModel2.getX()-self.speed2, self.playerModel2.getY(), self.playerModel2.getZ()))
        return Task.cont

    def right2(self):
        taskMgr.add(self.rightTask2,'rightTask2')
        self.charWalk2r.loop()
        #end right

    def rightTask2(self,task):
        if self.climbing2 == 0:
            self.playerModel2.setH(180)
            self.playerModel2.setPos(Vec3(self.playerModel2.getX()+self.speed2, self.playerModel2.getY(), self.playerModel2.getZ()))
        return Task.cont	

	def climbable2(self,cEntry):
		self.nodeCount2+=1
		#print self.nodeCount1
		self.ignore("o")
		self.ignore("o-up")
		self.ignore("l")
		self.ignore("l-up")
		self.acceptOnce("o",self.climbT2,[1])
		self.accept("o-up",self.noClimb2)
		self.acceptOnce("l",self.climbT2,[-1])
		self.accept("l-up",self.noClimb2)

	def climbT2(self,dir):
		self.dir2 = dir
		self.climbing2 = 1
		self.climbSpeed2 = 1
		self.ignore("k")
		self.ignore("k-up")
		self.ignore(";")
		self.ignore(";-up")
		taskMgr.add(self.climbTask2,'climbTask2')
		self.climb2.loop()
		
	def noClimb2(self):
		taskMgr.remove('climbTask2')
		self.climb2.pause()
		if self.nodeCount2 == 0:
			self.climbing2 = 0
		self.climbSpeed2 = 0
		self.acceptOnce("o",self.climbT2,[1])
		self.acceptOnce("l",self.climbT2,[-1])
		
	def jumpable2(self,cEntry):
		self.nodeCount2+=-1
		#print self.nodeCount2
		if self.nodeCount2 == 0:
			taskMgr.remove('climbTask2')
			self.ignore("o")
			self.ignore("o-up")
			self.ignore("l")
			self.ignore("l-up")
			self.acceptOnce("o",self.jumpT2)
			self.acceptOnce("k",self.left2)
			self.acceptOnce(";",self.right2)
			self.accept("k-up",self.stopLeft2)
			self.accept(";-up",self.stopRight2)
			self.climbing2 = 0
			self.climbSpeed2 = 0
			self.climb2.pause()
			
	def walkable2(self,cEntry):
		self.ignore("o")
		self.ignore("o-up")
		self.ignore("l")
		self.ignore("l-up")
		self.acceptOnce("o",self.climbT2,[1])
		self.accept("o-up",self.noClimb2)
		self.acceptOnce("l",self.climbT2,[-1])
		self.accept("l-up",self.noClimb2)
		self.acceptOnce("k",self.left2)
		self.acceptOnce(";",self.right2)
		self.accept("k-up",self.stopLeft)
		self.accept(";-up",self.stopRight)
		self.climbing2 = 0
		self.climbSpeed2 = 0
		self.climb2.pause()
			
	def climbTask2(self,task):
		if self.playerModel2.getZ() >=0:
			self.playerModel2.setH(90)
			self.playerModel2.setPos(Vec3(self.playerModel2.getX(), self.playerModel2.getY(), self.playerModel2.getZ()+self.climbSpeed2*self.dir2))
		return Task.cont	

    def jumpT2(self):
        if self.nodeCount2 == 0:
            self.ignore("o")
            self.ignore("o-up")
            z = self.playerModel2.getZ()
            j = ProjectileInterval(self.playerModel2, startPos = self.playerModel2.getPos(), startVel = Point3(3,0,30), duration = 2.0)
            j.start()
            taskMgr.doMethodLater(3,self.jumpTask2,"jumpTask2")
        else:
            self.acceptOnce("w",self.climb,[1])
        
    def jumpTask2(self, task):
        if self.climbing2 == 0:
            self.jump2.pause()
            self.acceptOnce("o",self.jumpT2)
        #return task.cont

	def allowRight2(self):
		self.acceptOnce(";",self.right2)

    def noRight2(self):
        taskMgr.remove('rightTask2')
        self.charWalk2r.pause()
        self.acceptOnce(";",self.right2)

    def stopRight2(self):
        self.noRight2()
        #self.allowRight()
        
    def rightWall2(self,cEntry):
        self.ignore(";")
        self.noRight2()
        
    def rightEdge2(self,cEntry):
        self.ignore(";")
        self.noRight2()

    def rightOK2(self,cEntry):
        self.allowRight2()	
    
    def allowLeft2(self):
        self.acceptOnce("k",self.left2)

    def noLeft2(self):
        taskMgr.remove('leftTask2')
        self.charWalk2l.pause()
        self.acceptOnce("k",self.left2)

    def stopLeft2(self):
        self.noLeft2()
        #self.allowLeft()
        
    def leftWall2(self,cEntry):
        self.ignore("k")
        self.noLeft2()
        
    def leftEdge2(self,cEntry):
        self.ignore("k")
        self.noLeft2()
        
    def leftOK2(self,cEntry):
        self.allowLeft2()
    
    def setupCollisions(self):
	self.cHandler = PhysicsCollisionHandler()
        #self.cHandler.setInPattern("ate-%in")
        self.cHandler.addInPattern('%fn-into-%in')
	#self.cHandler2.addInPattern('%fn-into-%in')         
        self.cHandler.setAgainPattern('%fn-again-%in')          
        self.cHandler.setOutPattern('%fn-outof-%in')        
        self.cTrav = CollisionTraverser()
	#self.cTrav2 = CollisionTraverser()
        base.cTrav = self.cTrav
	
        #Player 1 collision solid
        bounds = self.playerModel.getChild(0).getBounds()
        center = bounds.getCenter()-Vec3(0,0,12)
        radius = bounds.getRadius()-18
        boundsB = self.playerModel.getChild(0).getBounds()
        centerB = bounds.getCenter()-Vec3(0,0,-4)
        radiusB = bounds.getRadius()-20
        cSphere = CollisionSphere(center,radius)
        cSphereB = CollisionSphere(centerB,radiusB)
        cNode = CollisionNode("player1")
        #print radius, radiusB
        cNode.addSolid(cSphere)
        cNode.addSolid(cSphereB)
        cNodePath = self.playerModel.attachNewNode(cNode)
        cNodePath.show()
        
        Node=NodePath(PandaNode("PhysicsNode"))
        Node.reparentTo(render)
        self.an1=ActorNode("player1-physics")
        self.anp=Node.attachNewNode(self.an1)
        base.physicsMgr.attachPhysicalNode(self.an1)
        self.playerModel.reparentTo(self.anp)
	#self.anp.reparentTo(self.playerModel)
	
        #Player 2 collision solid
        bounds2 = self.playerModel2.getChild(0).getBounds()
        center2 = bounds2.getCenter()-Vec3(0,0,-4)
        radius2 = bounds2.getRadius()-20
        cSphere2 = CollisionSphere(center2,radius2)
        bounds2B = self.playerModel2.getChild(0).getBounds()
        center2B = bounds2B.getCenter()-Vec3(0,0,12)
        radius2B = bounds2B.getRadius()-18
        cSphere2B = CollisionSphere(center2B,radius2B)
        cNode2 = CollisionNode("player2")
        #print radius2, radius2B
        cNode2.addSolid(cSphere2)
        cNode2.addSolid(cSphere2B)
        cNodePath2 = self.playerModel2.attachNewNode(cNode2)
        cNodePath2.show()
        
        Node2=NodePath(PandaNode("PhysicsNode"))
        Node2.reparentTo(render)
        self.an2=ActorNode("player2-physics")
        self.anp2=Node2.attachNewNode(self.an2)
        base.physicsMgr.attachPhysicalNode(self.an2)
        self.playerModel2.reparentTo(self.anp2)
        #self.anp2.reparentTo(self.playerModel2)
	
        gravityFN=ForceNode('world-forces')
        gravityFNP=render.attachNewNode(gravityFN)
        gravityForce=LinearVectorForce(0,0,-9.8) #gravity acceleration
        gravityFN.addForce(gravityForce)
        
        base.physicsMgr.addLinearForce(gravityForce)
	self.an1.getPhysicsObject().setMass(15)
	self.an2.getPhysicsObject().setMass(15)
	gravityForce.setMassDependent(1)
        
        self.cHandler.addCollider(cNodePath, self.anp)
        self.cHandler.addCollider(cNodePath2, self.anp2)
        self.cTrav.addCollider(cNodePath,self.cHandler)
        self.cTrav.addCollider(cNodePath2,self.cHandler)
        self.cTrav.addCollider(cNodePath,self.cHandler)
        self.cTrav.addCollider(cNodePath2,self.cHandler)
	#self.cTrav.addCollider(cNodePath,self.cHandler2)
        #self.cTrav.addCollider(cNodePath2,self.cHandler2)
        #self.cTrav2.addCollider(cNodePath,self.cHandler2)
        #self.cTrav2.addCollider(cNodePath2,self.cHandler2)
	
	#cHandler2 = CollisionHandlerEvent()
	#cHandler2.addInPattern('%fn-into-%in')
	#self.cTrav.addCollider(cNodePath1,cHandler2)
        #self.cTrav.addCollider(cNodePath2,cHandler2)
	
        for i in range(self.ballNum+1):
            boundsB = self.ball[i].getChild(0).getBounds()
            centerB = boundsB.getCenter()
            radiusB = boundsB.getRadius()*0.65
            cSphereB = CollisionSphere(centerB,radiusB)
            cNodeB = CollisionNode("ball")
            cNodeB.addSolid(cSphereB)
            cNodePathB = self.ball[i].attachNewNode(cNodeB)
	    #self.cTrav.addCollider(cNodePathB,self.cHandler)

            #cNodePathB.show()
	
	self.accept("player1-into-ball",self.acquire1)
	#self.accept("ball-into-player1",self.acquire1)
	self.accept("player2-into-ball",self.acquire2)
	#self.accept("ball-into-player2",self.acquire2)
	#self.accept( 'player1-into2-platform', self.wall1)
        #self.accept( 'player2-into2-platform', self.wall2)
        
    def wall1(self,cEntry):
	self.an1.getPhysicsObject().setVelocity(Vec3(0,0,0))
	
    def wall2(self,cEntry):
	self.an2.getPhysicsObject().setVelocity(Vec3(0,0,0))
	
    def player1Wins(self,cEntry):
	if self.player2Invincible == 0:
		self.player1Score+=10
		self.reset()
	
    def player2Wins(self,cEntry):
	if self.player1Invincible == 0:
		self.player2Score+=10
		self.reset()
		
    def acquire1(self,cEntry):
	self.playerModel.setY(0)
	if str(cEntry.getIntoNodePath().getParent()) == "render/sawball":
	    self.player1Weapon = "saw"
	    saw = loader.loadModel("models/gamedev/saw")
	    saw.setScale(2.5)
	    self.jNP.getChildren().detach()
	    saw.reparentTo(self.jNP)
	    self.acceptOnce("e",self.useWeapon1)
	    self.acceptOnce("q",self.useWeapon1)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/moltovball":
	    self.player1Weapon = "molotov"
	    molo = loader.loadModel("models/gamedev/moltov")
	    molo.setScale(2.5)
	    #self.jNP = self.playerModel.exposeJoint(None,"modelRoot","ikHandle2")
	    self.jNP.getChildren().detach()
	    molo.reparentTo(self.jNP)
	    self.acceptOnce("e",self.useWeapon1)
	    self.acceptOnce("q",self.useWeapon1)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/grenadeball":
	    self.player1Weapon = "grenade"
	    gren = loader.loadModel("models/gamedev/grenade")
	    gren.setScale(2.5)
	    #self.jNP = self.playerModel.exposeJoint(None,"modelRoot","ikHandle2")
	    self.jNP.getChildren().detach()
	    gren.reparentTo(self.jNP)
	    self.acceptOnce("e",self.useWeapon1)
	    self.acceptOnce("q",self.useWeapon1)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/pogo": #done
	    self.jNP.getChildren().detach()
	    self.player1Weapon = "jump"
	    self.acceptOnce("e",self.useWeapon1)
	    self.acceptOnce("q",self.useWeapon1)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/golden": #done
	    self.jNP.getChildren().detach()
	    self.player1Weapon = "speedUp"
	    self.acceptOnce("e",self.useWeapon1)
	    self.acceptOnce("q",self.useWeapon1)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/crystalball":
	    self.jNP.getChildren().detach()
	    self.player1Weapon = "icestage"
	    self.acceptOnce("e",self.useWeapon1)
	    self.acceptOnce("q",self.useWeapon1)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/fireball": #done
	    self.jNP.getChildren().detach()
	    self.player1Weapon = "meteo"
	    self.acceptOnce("e",self.useWeapon1)
	    self.acceptOnce("q",self.useWeapon1)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/blackball": #done
	    self.jNP.getChildren().detach()
	    self.player1Weapon = "blind"
	    self.acceptOnce("e",self.useWeapon1)
	    self.acceptOnce("q",self.useWeapon1)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/translucent":
	    self.jNP.getChildren().detach()
	    self.player1Weapon = "invis"
	    self.acceptOnce("e",self.useWeapon1)
	    self.acceptOnce("q",self.useWeapon1)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/superball": #done
	    self.jNP.getChildren().detach()
	    self.player1Weapon = "invincible"
	    self.acceptOnce("e",self.useWeapon1)
	    self.acceptOnce("q",self.useWeapon1)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/death": #done
	    self.jNP.getChildren().detach()
	    if self.player1Invincible == 0:
		self.player2Deaths+= 1
		self.reset()
	
	cEntry.getIntoNodePath().getParent().removeNode()
		
	#Drop a New Ball
	self.ballNum+=1
	z=random.randint(1,2)
	if z ==1:
		z=-1
	else:
		z=1
	self.movement.append(Vec3(random.random()*z,0,random.random()*z))
	weapBalls.define(self.ball,self.ballNum,render)
	
	boundsB = self.ball[self.ballNum].getChild(0).getBounds()
	centerB = boundsB.getCenter()
	radiusB = boundsB.getRadius()*.65
	cSphereB = CollisionSphere(centerB,radiusB)
	cNodeB = CollisionNode("ball")
	cNodeB.addSolid(cSphereB)
	cNodePathB = self.ball[self.ballNum].attachNewNode(cNodeB)
		
    def acquire2(self,cEntry):
	if str(cEntry.getIntoNodePath().getParent()) == "render/sawball":
	    self.player2Weapon = "saw"
	    saw = loader.loadModel("models/gamedev/saw")
	    saw.setScale(2.5)
	    self.jNP2.getChildren().detach()
	    saw.reparentTo(self.jNP2)
	    self.acceptOnce("e",self.useWeapon2)
	    self.acceptOnce("q",self.useWeapon2)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/moltovball":
	    self.player2Weapon = "molotov"
	    molo = loader.loadModel("models/gamedev/moltov")
	    molo.setScale(2.5)
	    #self.jNP = self.playerModel.exposeJoint(None,"modelRoot","ikHandle2")
	    self.jNP.getChildren().detach()
	    molo.reparentTo(self.jNP)
	    self.acceptOnce("e",self.useWeapon2)
	    self.acceptOnce("q",self.useWeapon2)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/grenadeball":
	    self.player2Weapon = "grenade"
	    gren = loader.loadModel("models/gamedev/grenade")
	    gren.setScale(2.5)
	    #self.jNP = self.playerModel.exposeJoint(None,"modelRoot","ikHandle2")
	    self.jNP.getChildren().detach()
	    gren.reparentTo(self.jNP)
	    self.acceptOnce("e",self.useWeapon2)
	    self.acceptOnce("q",self.useWeapon2)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/pogo": #done
	    self.jNP.getChildren().detach()
	    self.player2Weapon = "jump"
	    self.acceptOnce("e",self.useWeapon2)
	    self.acceptOnce("q",self.useWeapon2)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/golden": #done
	    self.jNP.getChildren().detach()
	    self.player2Weapon = "speedUp"
	    self.acceptOnce("e",self.useWeapon2)
	    self.acceptOnce("q",self.useWeapon2)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/crystalball":
	    self.jNP.getChildren().detach()
	    self.player2Weapon = "icestage"
	    self.acceptOnce("e",self.useWeapon2)
	    self.acceptOnce("q",self.useWeapon2)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/fireball": #done
	    self.jNP.getChildren().detach()
	    self.player2Weapon = "meteo"
	    self.acceptOnce("e",self.useWeapon2)
	    self.acceptOnce("q",self.useWeapon2)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/blackball": #done
	    self.jNP.getChildren().detach()
	    self.player2Weapon = "blind"
	    self.acceptOnce("e",self.useWeapon2)
	    self.acceptOnce("q",self.useWeapon2)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/translucent":
	    self.jNP.getChildren().detach()
	    self.player2Weapon = "invis"
	    self.acceptOnce("e",self.useWeapon2)
	    self.acceptOnce("q",self.useWeapon2)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/superball": #done
	    self.jNP.getChildren().detach()
	    self.player2Weapon = "invincible"
	    self.acceptOnce("e",self.useWeapon2)
	    self.acceptOnce("q",self.useWeapon2)
	elif str(cEntry.getIntoNodePath().getParent()) == "render/death": #done
	    self.jNP.getChildren().detach()
	    if self.player2Invincible == 0:
		self.player1Score+=3
		self.reset()
	
	cEntry.getIntoNodePath().getParent().removeNode()
		
	#Drop a New Ball
	self.ballNum+=1
	z=random.randint(1,2)
	if z ==1:
		z=-1
	else:
		z=1
	self.movement.append(Vec3(random.random()*z,0,random.random()*z))
	weapBalls.define(self.ball,self.ballNum,render)
	
	boundsB = self.ball[self.ballNum].getChild(0).getBounds()
	centerB = boundsB.getCenter()
	radiusB = boundsB.getRadius()*.65
	cSphereB = CollisionSphere(centerB,radiusB)
	cNodeB = CollisionNode("ball")
	cNodeB.addSolid(cSphereB)
	cNodePathB = self.ball[self.ballNum].attachNewNode(cNodeB)

    def useWeapon1(self):
	if self.player1Weapon == "meteo":
		fireRain = Sequence(Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), 
		Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain))
		fireRain.start()
	elif self.player1Weapon == "jump":
		self.playerModel.detachNode()
		self.playerModel.reparentTo(render)
		angle = (self.playerModel.getH())*math.pi/180.0
		ProjectileInterval(self.playerModel, startPos = Point3(self.playerModel.getPos()),startVel = Point3(math.sin(angle)*30,0,100), duration= 4.0).start()
	elif self.player1Weapon == "speedUp":
		self.speed1 = 6
		taskMgr.doMethodLater(5,self.restoreSpeedBG,"restoreStuff")
	elif self.player1Weapon == "blind":
		camera.setPos(Vec3(-50,0,0))
		taskMgr.doMethodLater(5,self.restoreCamera,"restoreCamera")
	elif self.player1Weapon == "invincible":
		self.player1Invincible = 1
		taskMgr.doMethodLater(5,self.notInvince1,"mortal1")
	elif self.player1Weapon == "grenade":
		self.jNP.getChildren().detach()
		gren = loader.loadModel("models/gamedev/grenade")
		gren.setScale(2.5)
		gren.reparentTo(render)
		angle = (self.playerModel.getH())*math.pi/180.0
		ProjectileInterval(gren, startPos = Point3(self.playerModel.getPos()),startVel = Point3(math.sin(angle)*30,0,10), endZ = -50).start()
		if gren.getZ() == -50:
			gren.removeNode()
		cHandler = CollisionHandlerEvent()
		cHandler.addInPattern('%fn-into-%in')
		boundsB = gren.getChild(0).getBounds()
		centerB = boundsB.getCenter()
		radiusB = boundsB.getRadius()*0.65
		cSphereB = CollisionSphere(centerB,radiusB)
		cNodeB = CollisionNode("grenade")
		cNodeB.addSolid(cSphereB)
		cNodePathB = gren.attachNewNode(cNodeB)
		self.cTrav.addCollider(cNodePathB,cHandler)
		
		self.acceptOnce("grenade-into-platform",self.explode)
		
	elif self.player1Weapon == "molotov":
		self.jNP.getChildren().detach()
	elif self.player1Weapon == "saw":
		self.jNP.getChildren().detach()
	elif self.player1Weapon == "invis":
		self.jNP.getChildren().detach()
		self.playerModel2.hide()
		taskMgr.doMethodLater(4.0,self.showPlayer,"showPlayer")
	elif self.player1Weapon == "icestage":
		self.jNP.getChildren().detach()
		self.speed1 = 6
		self.speed2 = 6
		self.background.detachNode()
		self.background2.reparentTo(render)
		taskMgr.doMethodLater(5,self.restoreSpeedBG,"restoreStuff")
		
    def restoreSpeedBG(self,task):
	self.speed1 = 3
	self.speed2 = 3
	self.background2.detachNode()
	self.background.reparentTo(render)
	
    def showPlayer(self,task):
	self.playerModel.show()
	self.playerModel2.show()
	
    def useWeapon2(self):
	if self.player2Weapon == "meteo":
		fireRain = Sequence(Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), 
		Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain), Wait(.5), Func(self.rain))
		fireRain.start()
	elif self.player2Weapon == "jump":
		angle = self.playerModel2.getH()/90
		ProjectileInterval(self.playerModel2, startPos = Point3(self.playerModel2.getPos()),startVel = Point3(angle*30,0,100), endZ = self.playerModel2.getZ()).start()
	elif self.player2Weapon == "speedUp":
		self.speed2 = 6
	elif self.player2Weapon == "blind":
		camera.setPos(Vec3(-50,0,0))
		taskMgr.doMethodLater(5,self.restoreCamera,"restoreCamera")
	elif self.player2Weapon == "invincible":
		self.player2Invincible = 1
		taskMgr.doMethodLater(5,self.notInvince2,"mortal2")
	elif self.player2Weapon == "grenade":
		self.jNP2.getChildren().detach()
		gren = loader.loadModel("models/gamedev/grenade")
		gren.setScale(2.5)
		gren.reparentTo(render)
		angle = (self.playerModel2.getH())*math.pi/180.0
		ProjectileInterval(gren, startPos = Point3(self.playerModel2.getPos()),startVel = Point3(math.sin(angle)*30,0,10), endZ = -50).start()
		if gren.getZ() == -50:
			gren.removeNode()
		cHandler = CollisionHandlerEvent()
		cHandler.addInPattern('%fn-into-%in')
		boundsB = gren.getChild(0).getBounds()
		centerB = boundsB.getCenter()
		radiusB = boundsB.getRadius()*0.65
		cSphereB = CollisionSphere(centerB,radiusB)
		cNodeB = CollisionNode("grenade")
		cNodeB.addSolid(cSphereB)
		cNodePathB = gren.attachNewNode(cNodeB)
		self.cTrav.addCollider(cNodePathB,cHandler)
		
		self.acceptOnce("grenade-into-platform",self.explode)
		
	elif self.player2Weapon == "molotov":
		self.jNP.getChildren().detach()
	elif self.player2Weapon == "saw":
		self.jNP.getChildren().detach()
	elif self.player2Weapon == "invis":
		self.jNP.getChildren().detach()
		self.playerModel1.hide()
		taskMgr.doMethodLater(4.0,self.showPlayer,"showPlayer")
	elif self.player2Weapon == "icestage":
		self.jNP2.getChildren().detach()
		self.speed1 = 6
		self.speed2 = 6
		self.background.detachNode()
		self.background2.reparentTo(render)
		taskMgr.doMethodLater(5,self.restoreSpeedBG,"restoreStuff")
		
    def rain(self):
	    meteoBall = Actor("models/gamedev/fireball")
	    meteoBall.reparentTo(render)
	    meteoBall.setScale(2)
	    meteoBall.setH(-15)
	    boundsB = meteoBall.getChild(0).getBounds()
            centerB = boundsB.getCenter()
            radiusB = boundsB.getRadius()*0.65
            cSphereB = CollisionSphere(centerB,radiusB)
            cNodeB = CollisionNode("meteor")
            cNodeB.addSolid(cSphereB)
            cNodePathB = meteoBall.attachNewNode(cNodeB)
	    #cNodePathB.show()
	    
	    ProjectileInterval(meteoBall, startPos = Point3(random.randint(15,211),0,170),startVel = Point3(-12,0,0), endZ = -50).start()
	    
	    cHandler = CollisionHandlerEvent()
	    cHandler.addInPattern('%fn-into-%in')
	    self.cTrav.addCollider(cNodePathB,cHandler)
	    self.accept("meteor-into-player1",self.player2Wins)
	    self.accept("meteor-into-player2",self.player1Wins)
	    
    def showBalls(self,task):
        for i in self.ball:
            i.show()
     
    def notInvince1(self,task):
	self.player1Invincible = 0
	
    def notInvince2(self,task):
        self.player2Invincible = 0

    def restoreCamera(self,task):
        camera.setPosHpr(Vec3(98,-390,90), Vec3(0,-5,0))
        
    def switch(self,task):
        self.environment.setColor(0,1,0.3)
        
    def colliding1( self, collEntry ): # accept a collision entry argument    
        if self.ignoreColl == 0:
            self.player1IsColliding = 1 # we are colliding        
            self.stopWalk( ) # pause all walking animation and movement        
            disp = ( collEntry.getSurfacePoint( render ) - collEntry.getInteriorPoint( render ) )
            newPos = self.playerModel2.getPos( ) + disp # get new position
            self.playerModel2.setPos( newPos ) # and set it to tiny's position
        # end colliding        
        
    def notColliding1( self, collEntry ): 
        self.player1IsColliding = 0    
        
    def colliding2( self, collEntry ): # accept a collision entry argument 
        if self.ignoreColl == 0:
            self.player2IsColliding = 1 # we are colliding        
            self.stopWalk2( ) # pause all walking animation and movement               
            disp = ( collEntry.getSurfacePoint( render ) - collEntry.getInteriorPoint( render ) )
            newPos = self.playerModel2B.getPos( ) + disp # get new position
            self.playerModel2B.setPos( newPos ) # and set it to tiny's position
        # end colliding        
        
    def notColliding2( self, collEntry ): 
        self.player2IsColliding = 0    
        
    def returnSpeeds(self,task):
        self.speed1 = 8.0
        self.speed2 = 8.0
        self.turnSpeed1 = 80.0
        self.turnSpeed2 = 80.0
        
    def returnSpeeds2(self,task):
        self.acceptOnce("w",self.walk)
        self.acceptOnce("o",self.walk2)
        self.speed1 = 8.0
        self.speed2 = 8.0
        self.turnSpeed1 = 80.0
        self.turnSpeed2 = 80.0
        
    def returnSpeeds3(self,task):
        self.speed1 = 8.0
        self.speed2 = 8.0
        self.turnSpeed1 = 80.0
        self.turnSpeed2 = 80.0
        
    def changeMusic(self,task):
        self.music.stop()
        self.music2  = loader.loadMusic("models/gamedev/ADRENALINE.mp3")
        self.music2.play()
        
    def clockTask(self,task):
        self.timer.detachNode()
        self.timer = OnscreenText("%d" % (self.gameLen-globalClock.getRealTime(),), pos = (98,145), scale = 18.0)
        self.timer.setColor(1,1,1)
        self.timer.reparentTo(render)
        return Task.cont
    
    def ballMovementTask(self,task):
	self.anp.setY(0)
	self.anp2.setY(0)
	for i in range(self.ballNum+1):
		if i < len(self.ball):
			if self.ball[i].getX() > 234 or self.ball[i].getX() < -38 or self.ball[i].getZ() < -10 or self.ball[i].getZ() > 132:
				self.ball[i].setPos(self.ball[i].getPos()/1.005)
				z=random.randint(1,2)
				if z ==1:
					z=-1
				else:
					z=1
				self.movement[i]=Vec3(random.random()*z,0,random.random()*z)
			else:
				self.ball[i].setPos(self.ball[i].getPos()+self.movement[i])
	return Task.cont
	
    def fire(self):
        
        self.fire = ParticleEffect()
        
        self.fire.reset()
        self.fire.setPos(0.000, 0.000, 0.000)
        self.fire.setHpr(0.000, 0.000, 0.000)
        self.fire.setScale(10.000, 10.000, 10.000)
        p0 = Particles('particles-1')
        # Particles parameters
        p0.setFactory("PointParticleFactory")
        p0.setRenderer("SpriteParticleRenderer")
        p0.setEmitter("DiscEmitter")
        p0.setPoolSize(1024)
        p0.setBirthRate(0.0200)
        p0.setLitterSize(10)
        p0.setLitterSpread(0)
        p0.setSystemLifespan(1200.0000)
        p0.setLocalVelocityFlag(1)
        p0.setSystemGrowsOlderFlag(0)
        # Factory parameters
        p0.factory.setLifespanBase(2.0000)
        p0.factory.setLifespanSpread(0.0000)
        p0.factory.setMassBase(1.0000)
        p0.factory.setMassSpread(0.0000)
        p0.factory.setTerminalVelocityBase(400.0000)
        p0.factory.setTerminalVelocitySpread(0.0000)
        # Point factory parameters
        # Renderer parameters
        p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAOUT)
        p0.renderer.setUserAlpha(0.22)
        # Sprite parameters
        p0.renderer.addTextureFromFile('models/gamedev/sparkle.png')
        p0.renderer.setColor(Vec4(1.00, 1.00, 1.00, 1.00))
        p0.renderer.setXScaleFlag(1)
        p0.renderer.setYScaleFlag(1)
        p0.renderer.setAnimAngleFlag(0)
        p0.renderer.setInitialXScale(0.5000)
        p0.renderer.setFinalXScale(2.0000)
        p0.renderer.setInitialYScale(1.0000)
        p0.renderer.setFinalYScale(2.0000)
        p0.renderer.setNonanimatedTheta(0.0000)
        p0.renderer.setAlphaBlendMethod(BaseParticleRenderer.PPNOBLEND)
        p0.renderer.setAlphaDisable(0)
        # Emitter parameters
        p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE)
        p0.emitter.setAmplitude(1.0000)
        p0.emitter.setAmplitudeSpread(0.0000)
        p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, 3.0000))
        p0.emitter.setExplicitLaunchVector(Vec3(1.0000, 0.0000, 0.0000))
        p0.emitter.setRadiateOrigin(Point3(0.0000, 0.0000, 0.0000))
        # Disc parameters
        p0.emitter.setRadius(0.5000)
        self.fire.addParticles(p0)
        
        self.fire.setPos(self.playerModel2.getPos())
        
        t = Sequence(Func(self.fire.start, render, render),Wait(20),Func(self.cleanFire))
        t.start()
 
    def cleanFire(self):
        self.fire.cleanup()

    def explode(self,cEntry):

        self.explosion = ParticleEffect()
        
        self.explosion.reset()
        self.explosion.setPos(cEntry.getIntoNodePath().getParent().getPos())
        self.explosion.setHpr(0.000, 0.000, 0.000)
        self.explosion.setScale(10.000, 10.000, 10.000)
        p0 = Particles('particles-1')
        # Particles parameters
        p0.setFactory("PointParticleFactory")
        p0.setRenderer("LineParticleRenderer")
        p0.setEmitter("SphereVolumeEmitter")
        p0.setPoolSize(10000)
        p0.setBirthRate(0.0500)
        p0.setLitterSize(10000)
        p0.setLitterSpread(0)
        p0.setSystemLifespan(2.0000)
        p0.setLocalVelocityFlag(1)
        p0.setSystemGrowsOlderFlag(1)
        # Factory parameters
        p0.factory.setLifespanBase(2.0000)
        p0.factory.setLifespanSpread(0.0000)
        p0.factory.setMassBase(.5000)
        p0.factory.setMassSpread(0.0500)
        p0.factory.setTerminalVelocityBase(400.0000)
        p0.factory.setTerminalVelocitySpread(0.0000)
        # Point factory parameters
        # Renderer parameters
        p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAOUT)
        p0.renderer.setUserAlpha(1.00)
        # Line parameters
        p0.renderer.setHeadColor(Vec4(1.00, 0.00, 0.00, 1.00))
        p0.renderer.setTailColor(Vec4(1.00, 1.00, 0.00, 1.00))
        p0.renderer.setLineScaleFactor(3.00)
        # Emitter parameters
        p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE)
        p0.emitter.setAmplitude(10.0000)
        p0.emitter.setAmplitudeSpread(0.0000)
        p0.emitter.setOffsetForce(Vec3(0.0000, 0.0000, -0.4930))
        p0.emitter.setExplicitLaunchVector(Vec3(1.0000, 0.0000, 0.0000))
        p0.emitter.setRadiateOrigin(Point3(0.0000, 0.0000, 0.0000))
        # Sphere Volume parameters
        p0.emitter.setRadius(0.5000)
        self.explosion.addParticles(p0)
        f0 = ForceGroup('gravity')
        # Force parameters
        self.explosion.addForceGroup(f0)
        
	cHandler = CollisionHandlerEvent()
	cHandler.addInPattern('%fn-into-%in')
	cSphereB = CollisionSphere(cEntry.getIntoNodePath().getParent().getPos(),1)
	cNodeB = CollisionNode("explosion")
	cNodeB.addSolid(cSphereB)
	cNodePathB = self.explosion.attachNewNode(cNodeB)
	self.cTrav.addCollider(cNodePathB,cHandler)
	cNodePathB.show()
        
	self.accept("player1-into-explosion",self.player2Wins)
	self.accept("player2-into-explosion",self.player1Wins)
        #f.reparentTo(self.playerModel)
        #self.explosion.setPos(self.playerModel.getPos())

        t = Sequence(Func(self.explosion.start, render, render),Wait(2),Func(self.cleanExplo))
        t.start()
	cEntry.getFromNodePath().getParent().removeNode()
        
    def cleanExplo(self):
        self.explosion.cleanup()

    def endGame(self,task):
        taskMgr.removeTasksMatching('returnSpeedsToNormal')
        taskMgr.removeTasksMatching('restoreCamera')
	taskMgr.removeTasksMatching('clockTask')
	taskMgr.removeTasksMatching('ballMoveTask')
	
	self.music.stop()

        self.music3  = loader.loadMusic("models/gamedev/CSTAR.mp3")
        self.music3.play()
        
        self.speed1 = 0
        self.speed2 = 0

    def getScores(self):
	return (self.player1Score, self.player2Score)
		
    def getGameLen(self):
	return self.gameLen
		
    def stopMusic(self):
	self.music3.stop()
	
    def destroy(self):
	self.playerModel.detachNode()
	self.playerModel2.detachNode()
	self.background.destroy()
	self.lava.detachNode()
	self.ladder.detachNode()
	self.ladder2.detachNode()
	
	for i in range(self.ballNum+1):
	    self.ball[i].detachNode()
	    
    def stopMusic(self):
        self.music3.stop()
        
#world = Lvl03()
#world.start()
#run()
Beispiel #24
0
class DBoard(DistributedObject):
    def __init__(self, cr):
        DistributedObject.__init__(self, cr)
        self.accept("checkBoardAnimationDone", self.checkBoardAnimationDone)

        base.messenger.send("registerLoadEvent", ["loadBoardDone"])
        base.messenger.send("registerLoadEvent", ["loadTableDone"])

        self.modelLoadList = {"board": False, "table": False}

        self.boardAnimation = None
        self.boardAnimationStarted = False

        self.lightSun = DirectionalLight('light_sun')
        self.lightSun.setColorTemperature(5300)
        self.lightSun.setShadowCaster(True, 2048, 2048)
        self.lightSunNP = render.attachNewNode(self.lightSun)
        self.lightSunNP.setPos(-2, 2, 2)
        self.lightSunNP.lookAt(2, -2, -0.5)

        self.lightAmb = AmbientLight('light_ambient')
        #self.lightAmb.setColor((0.1, 0.1, 0.1, 1))
        self.lightAmb.setColorTemperature(4500)
        c = self.lightAmb.getColor()
        self.lightAmb.setColor((c.x / 2, c.y / 2, c.z / 2, 1))
        self.lightAmbNP = render.attachNewNode(self.lightAmb)

        self.accept("loadDone", self.loadDone)

        self.boardSceneLoadTask = loader.loadModel(
            "assets/models/board/BoardScene.bam", callback=self.boardLoaded)
        self.tableLoadTask = loader.loadModel("assets/models/table/Table.bam",
                                              callback=self.tableLoaded)

        # render lights
        render.setLight(self.lightSunNP)
        render.setLight(self.lightAmbNP)

    def boardLoaded(self, boardScene):
        """Callback event for when the board model has fully loaded"""
        self.boardScene = boardScene
        self.boardFlip = Actor(self.boardScene.find("**/BoardArmature"),
                               copy=False)
        self.boardFlip.reparentTo(self.boardScene)

        self.camFly = Actor(self.boardScene.find("**/CameraArmature"),
                            copy=False)
        self.camFly.reparentTo(self.boardScene)

        bone = self.camFly.exposeJoint(None, "modelRoot", "CamHolder")
        base.camLens.setNear(0.01)
        base.camLens.setFar(100)
        base.camera.reparentTo(bone)
        base.camera.setP(-90)

        # render board
        self.boardSceneNP = self.boardScene.reparentTo(render)

        self.setupCollisions()

        base.messenger.send("loadBoardDone")
        base.messenger.send("loadDone", ["board"])

    def tableLoaded(self, table):
        """Callback event for when the table model has fully loaded"""
        self.table = table
        # render table
        self.tableNP = self.table.reparentTo(render)

        base.messenger.send("loadTableDone")
        base.messenger.send("loadDone", ["table"])

    def loadDone(self, model):
        """Check function to determine if all models have loaded. If all models
        have been loaded, the boardDone event will be fired."""
        self.modelLoadList[model] = True

        for key, value in self.modelLoadList.items():
            if value == False: return

        self.ignore("loadDone")
        base.messenger.send("boardDone")

    def announceGenerate(self):
        # tell everyone interested, that the board DO has been generated
        base.messenger.send(self.cr.uniqueName("board_generated"), [self.doId])
        # call the base class method
        DistributedObject.announceGenerate(self)

    def disable(self):
        self.ignoreAll()
        self.boardScene.detachNode()
        self.table.detachNode()
        DistributedObject.disable(self)

    def delete(self):
        """Cleanup just before deletion of the DO"""
        # cleanup events
        self.ignoreAll()

        # cleanup models
        self.boardFlip.cleanup()
        self.camFly.cleanup()
        self.boardFlip.removeNode()
        self.camFly.removeNode()
        self.table.removeNode()

        self.boardAnimation = None

        # cleanup light
        try:
            render.clearLight(self.lightSunNP)
            render.clearLight(self.lightAmbNP)
        except:
            print("clear lights failed.")
        self.lightSunNP.removeNode()
        self.lightAmbNP.removeNode()

        # cleanup collisions
        for field in BoardMap.gameMap:
            field.collisionNP.removeNode()

        # cleanup other variables
        self.modelLoadList = {"board": False, "table": False}

        self.boardAnimation = None
        self.boardAnimationStarted = False

        DistributedObject.delete(self)

    def start(self):
        """Start the board animation"""
        taskMgr.step()
        self.boardAnimationStarted = True
        self.boardAnimation = Sequence(
            Parallel(self.boardFlip.actorInterval("BoardFlipUp"),
                     self.camFly.actorInterval("CamFly")),
            Func(base.messenger.send, "BoardAnimationDone"))
        self.boardAnimation.start()

    def checkBoardAnimationDone(self):
        """Check if the board animation has been stopped and resend the
        respective event if it has."""
        # check if we have an animation and it has actually been started once
        if self.boardAnimation is not None and self.boardAnimationStarted:
            # now check if the animation is done
            if self.boardAnimation.isStopped():
                # resend the event
                base.messenger.send("BoardAnimationDone")

    def setupCollisions(self):
        """Setup the collision solids for all fields.

        NOTE: This can be removed once blend2bam supports invisible collision
        model export"""
        for field in BoardMap.gameMap:
            # create a sphere collision solid
            cs = CollisionSphere(0, 0, 0, 0.01)
            cn = CollisionNode("{}-collision".format(field.name))
            cn.addSolid(cs)
            fieldNP = self.boardScene.find("**/{}".format(field.name))
            field.collisionNP = fieldNP.attachNewNode(cn)
            field.collisionNP.setCollideMask(BitMask32(0x80))
Beispiel #25
0
class Npc():
    def __init__(self, controlPointId, id, anchorx, anchory, anchorz, render,
                 team):
        self.id = id
        self.anchorx = anchorx
        self.anchory = anchory
        self.anchorz = anchorz
        self.controlPointId = controlPointId
        self.target = None
        self.isMoving = False
        self.health = 200
        self.isCurrentUser = False
        self.damage = 8
        self.attackTimer = 0
        self._is_dead = False
        self._team = team

        self.render = render
        '''Initializing NPC actors'''
        self.npc = Actor(
            "models/priest", {
                "walk": "models/priest-walk",
                "attack": "models/priest-attack",
                "hurt": "models/priest-hit",
                "die": "models/priest-die"
            })
        if self._team == 0:
            self.npcTex = loader.loadTexture("models/tex/guard_red.png")
        else:
            self.npcTex = loader.loadTexture("models/tex/guard_blue.png")
        self.npc.setTexture(self.npcTex)
        self.npc.setScale(0.5, 0.5, 0.5)
        self.npc.clearColor()
        self.npc.clearColorScale()
        self.npc.setColor(255, 0, 0, 0)
        self.npc.setColorScale(255, 0, 0, 0)
        self.npc.reparentTo(self.render)
        self.npc.setPos(anchorx, anchory, anchorz)

        self.AIchar = AICharacter("npc" + str(self.id), self.npc, 100, 0.05, 5)
        self.AIbehaviors = self.AIchar.getAiBehaviors()

        self.hb = HealthBar(1.5, value=self.health)
        #self._floater = NodePath(PandaNode("char_info"))
        #self._floater.reparentTo(self.npc)
        self.hb.setPos(0, 0, 11.9)
        self.hb.reparentTo(self.npc)
        #self.hb.reparentTo(self.npc)

    def renderBlue(self, AIworld):
        if not self._is_dead:
            self.AIbehaviors.removeAi("pursue")
            self.npc.detachNode()

        print "Started delete procedure for npc ",
        print self.id
        self.npc.delete()
        self.npc = Actor(
            "models/priest", {
                "walk": "models/priest-walk",
                "attack": "models/priest-attack",
                "hurt": "models/priest-hit",
                "die": "models/priest-die"
            })
        self.npcTex = loader.loadTexture("models/tex/guard_blue.png")
        self.npc.setTexture(self.npcTex)
        self.npc.setScale(0.5, 0.5, 0.5)
        self.npc.clearColor()
        self.npc.clearColorScale()
        self.npc.setColor(255, 0, 0, 0)
        self.npc.setColorScale(255, 0, 0, 0)
        self.npc.reparentTo(self.render)
        self.npc.setPos(self.anchorx, self.anchory, self.anchorz)

        AIworld.removeAiChar("npc" + str(self.id))
        self.AIchar = AICharacter("npc" + str(self.id), self.npc, 100, 0.05, 5)
        self.AIbehaviors = self.AIchar.getAiBehaviors()
        AIworld.addAiChar(self.AIchar)

        self.hb = HealthBar(1.5, value=self.health)
        self.hb.setPos(0, 0, 18.1)
        self.hb.reparentTo(self.npc)
        #self.hb.reparentTo(self.npc)

    def renderRed(self, AIworld):
        if not self._is_dead:
            self.AIbehaviors.removeAi("pursue")
            self.npc.detachNode()

        self.npc.delete()
        self.npc = Actor(
            "models/priest", {
                "walk": "models/priest-walk",
                "attack": "models/priest-attack",
                "hurt": "models/priest-hit",
                "die": "models/priest-die"
            })
        self.npcTex = loader.loadTexture("models/tex/guard_red.png")
        self.npc.setTexture(self.npcTex)
        self.npc.setScale(0.5, 0.5, 0.5)
        self.npc.clearColor()
        self.npc.clearColorScale()
        self.npc.setColor(255, 0, 0, 0)
        self.npc.setColorScale(255, 0, 0, 0)
        self.npc.reparentTo(self.render)
        self.npc.setPos(self.anchorx, self.anchory, self.anchorz)

        AIworld.removeAiChar("npc" + str(self.id))
        self.AIchar = AICharacter("npc" + str(self.id), self.npc, 100, 0.05, 5)
        self.AIbehaviors = self.AIchar.getAiBehaviors()
        AIworld.addAiChar(self.AIchar)
        AIworld.update()

        self.hb = HealthBar(1.5, value=self.health)
        self.hb.setPos(0, 0, 8.1)
        self.hb.reparentTo(self.npc)

    def switchTeam(self, AIworld):
        print self.id,
        print " from team ",
        print self._team,
        print " getting deleted."
        if self._team == 0:
            self._team = 1
            self.renderBlue(AIworld)
        else:
            self._team = 0
            self.renderRed(AIworld)

        if self.isCurrentUser:
            main.freeDeadNpc(self.id)

        self.target = None
        self.isMoving = False
        self.health = 200
        self.isCurrentUser = False
        self.damage = 8
        self.attackTimer = 0
        self._is_dead = False

    def set_health(self, health):
        self.health = health

    def take_damage(self, health_change):
        health = self.health
        if health <= health_change and not self._is_dead:
            self.killNpc()
        else:
            health = health - health_change
            self.set_health(health)
            self.hb.setValue(self.health)
            self.npc.play("hurt")

    def killNpc(self):
        self.set_health(0)
        self.hb.setValue(0)
        self.AIbehaviors.removeAi("pursue")
        hurt_interval = self.npc.actorInterval("hurt")
        death_interval = self.npc.actorInterval("die")
        seq = Sequence(hurt_interval, death_interval)
        seq.start()
        self.npc.pose("die", 45)
        self._is_dead = True
        self.npc.detachNode()
        if self.isCurrentUser:
            main.freeDeadNpc(self.id)
            #main.cManager.sendRequest(Constants.CMSG_NPCDEATH, [self.id])
            print Constants.CMSG_NPCDEATH,
            print " + ",
            print self.id

    def chaseTarget(self, target, status=False):
        if (not self.isMoving):
            self.target = target
            self.AIbehaviors.pursue(self.target)
            self.npc.loop("walk")
            self.isMoving = True
            self.isCurrentUser = status

    def stopChase(self):

        #self.AIbehaviors.pauseAi("pursue")
        if not self._is_dead:
            self.AIbehaviors.removeAi("pursue")
            p1 = LerpHprInterval(self.npc, 4, Point3(180, 0, 0))
            p2 = LerpPosInterval(
                self.npc, 4, Point3(self.anchorx, self.anchory, self.anchorz))
            animInterval = self.npc.actorInterval("walk", loop=1, duration=4)
            p2.start()
            p1.start()
            animInterval.start()
            self.isMoving = False
            self.target = None
            self.isCurrentUser = False

    def givNPCDistance(self, charachter):
        x = self.npc.getX()
        y = self.npc.getY()
        z = self.npc.getZ()
        minDist = math.sqrt((charachter.getX() - x) * (charachter.getX() - x) +
                            (charachter.getY() - y) * (charachter.getY() - y) +
                            (charachter.getZ() - z) * (charachter.getZ() - z))
        return minDist

    def checkNpcIsAlive(self):
        if (self.health > 0):
            return True
        else:
            return False

    def shouldAttack(self, currentTime, cManager):
        if not self._is_dead:
            if self.isMoving:
                if self.attackTimer > 0:
                    self.attackTimer = self.attackTimer - currentTime
                    #print self.attackTimer
                if self.AIbehaviors.behaviorStatus("pursue") == "done":
                    #self.npc.stop("walk")
                    #print self.npc.getAnimControl("walk")
                    if self.attackTimer <= 0:
                        if self.npc.getAnimControl("walk").isPlaying():
                            self.npc.stop("walk")
                        if not self.npc.getAnimControl("attack").isPlaying():
                            #self.npc.loop("attack")
                            self.npc.play("attack")
                            self.attackTimer = 2
                            #myInterval = self.npc.actorInterval("attack")
                            #seq = Sequence(myInterval)
                            #seq.append(Wait(3))
                            #seq.start()
                        if self.isCurrentUser:
                            cManager.sendRequest(Constants.CMSG_NPCATTACK,
                                                 [self.id, self.damage])

                if self.AIbehaviors.behaviorStatus("pursue") == "active":
                    if self.npc.getAnimControl("attack").isPlaying():
                        self.npc.stop("attack")
                    if not self.npc.getAnimControl("walk").isPlaying():
                        self.npc.loop("walk")
class WindowSplash:
    def setup(self):
        x_size, y_size = base.win.get_x_size(), base.win.get_y_size()
        bg_buffer = base.win.makeTextureBuffer(
            "Background Scene",
            x_size,
            y_size,
        )
        bg_buffer.set_clear_color_active(True)
        bg_buffer.set_clear_color(VBase4(0, 1, 0, 1))
        bg_buffer.set_sort(-100)  # render buffer before main scene.

        bg_texture = bg_buffer.get_texture()
        self.bg_texture = bg_texture
        bg_camera = base.make_camera(bg_buffer)

        self.setup_background_scene(bg_camera)

        # Foreground Scene
        base.win.set_clear_color((0, 0, 0, 1))
        cam_dist = 2
        base.cam.set_pos(0, -2.2 * cam_dist, 0)
        base.cam.node().get_lens().set_fov(45/cam_dist)

        self.logo_animation = Actor(asset_path / "panda3d_logo.bam")
        self.logo_animation.reparent_to(render)
        self.logo_animation.set_two_sided(True)

        shader = Shader.load(
            Shader.SL_GLSL,
            vertex=asset_path / "splash_window.vert",
            fragment=asset_path / "splash_window.frag",
        )
        self.logo_animation.set_shader(shader)
        self.logo_animation.set_shader_input("background", bg_texture)
        self.logo_animation.set_shader_input("fade", 0.0)
        self.logo_sound = base.loader.loadSfx(asset_path / "panda3d_logo.wav")

        # Build interval
        def fade_background_to_white(t):
            base.win.set_clear_color((t,t,t,1))
            self.logo_animation.set_shader_input("fade", t)
        def set_background_texture(t):
            self.logo_animation.set_shader_input(
                "background",
                self.bg_texture,
            )
                    
        effects = Parallel(
            self.logo_animation.actorInterval(
                "splash",
                loop=False,
            ),
            SoundInterval(
                self.logo_sound,
                loop=False,
            ),
            Sequence(
                LerpFunc(
                    set_background_texture,
                    fromData=0,
                    toData=1,
                    duration=3.878,
                ),
                LerpFunc(
                    fade_background_to_white,
                    fromData=0,
                    toData=1,
                    duration=1.0,
                ),
            ),
        )
        return effects

    def teardown(self):
        self.teardown_background_scene()
        self.logo_animation.cleanup()
        # FIXME: Destroy self.logo_sound
        # FIXME: Destroy the extra buffer stuff

    def setup_background_scene(self, bg_camera):
        """
        Override this to set up the scene that will be seen through the
        splash's shards.

        bg_camera
          The camera watching the background scene
        """
        # The scene to be rendered to texture
        bg_scene = NodePath("My Scene")
        bg_camera.reparent_to(bg_scene)
        bg_camera.set_pos(0, -100, 50)
        bg_camera.look_at(0, 0, 0)

        model = base.loader.loadModel('models/environment')
        model.reparent_to(bg_scene)
        model.set_scale(0.25)

    def teardown_background_scene(self):
        """
        Override this to tear down your scene again.
        """
        pass
Beispiel #27
0
class Player(FSM, DirectObject):
    NormalMode = "Normal"
    FightMode = "Fight"

    GAMEPADMODE = "Gamepad"
    MOUSEANDKEYBOARD = "MouseAndKeyboard"

    def __init__(self):
        FSM.__init__(self, "FSM-Player")
        random.seed()

        #
        # PLAYER CONTROLS AND CAMERA
        #
        self.player = Actor(
            "Character",
            {
                "Idle": "Character-Idle",
                "Run": "Character-Run",
                "Activate": "Character-Activate",
                "Death": "Character-Death",
                "Jump": "Character-Jump",
                "Hit": "Character-Hit",
                "Fight_Attack": "Character-FightAttack",
                "Fight_Idle": "Character-FightIdle",
                "Fight_Left": "Character-FightLeft",
                "Fight_Right": "Character-FightRight",
            },
        )
        self.player.setBlend(frameBlend=True)
        # the initial cam distance
        self.fightCamDistance = 3.0
        # the next two vars will set the min and max distance the cam can have
        # to the node it is attached to
        self.maxCamDistance = 4.0
        self.minCamDistance = 1.2
        # the initial cam distance
        self.camDistance = (self.maxCamDistance - self.minCamDistance) / 2.0 + self.minCamDistance
        # the next two vars set the min and max distance on the Z-Axis to the
        # node the cam is attached to
        self.maxCamHeightDist = 3.0
        self.minCamHeightDist = 1.5
        # the average camera height
        self.camHeightAvg = (self.maxCamHeightDist - self.minCamHeightDist) / 2.0 + self.minCamHeightDist
        # an invisible object which will fly above the player and will be used to
        # track the camera on it
        self.camFloater = NodePath(PandaNode("playerCamFloater"))
        self.camFloater.setPos(0, 0, 1.5)
        self.camFloater.reparentTo(self.player)
        # screen sizes
        self.winXhalf = base.win.getXSize() / 2
        self.winYhalf = base.win.getYSize() / 2
        # Interval for the jump animation
        self.jumpInterval = None
        self.jumpstartFloater = NodePath(PandaNode("jumpstartFloater"))
        self.jumpstartFloater.reparentTo(render)
        self.deathComplete = None
        # Joystick/Gamepad support
        self.hasJoystick = False
        if gamepadSupport:
            # initialize controls
            joysticks = [pygame.joystick.Joystick(x) for x in range(pygame.joystick.get_count())]
            if len(joysticks) > 0:
                self.mainJoystick = joysticks[0]
                self.mainJoystick.init()
                self.hasJoystick = True

        #
        # WEAPONS AND ACCESSORIES
        #
        self.RightHandAttach = self.player.exposeJoint(None, "modelRoot", "HandAttach_R")
        self.spear = loader.loadModel("Spear")
        self.spear.setP(90)
        self.spear.setR(180)
        self.spear.reparentTo(self.RightHandAttach)
        self.LeftHandAttach = self.player.exposeJoint(None, "modelRoot", "HandAttach_L")
        self.shield = loader.loadModel("Shield")
        self.shield.setZ(0.05)
        self.shield.setH(-90)
        self.shield.reparentTo(self.LeftHandAttach)

        #
        # PLAYER COLLISION DETECTION AND PHYSICS
        #
        self.playerSphere = CollisionSphere(0, 0, 0.8, 0.7)
        self.playerCollision = self.player.attachNewNode(CollisionNode("playerCollision"))
        self.playerCollision.node().addSolid(self.playerSphere)
        base.pusher.addCollider(self.playerCollision, self.player)
        base.cTrav.addCollider(self.playerCollision, base.pusher)
        # The foot collision checks
        self.footRay = CollisionRay(0, 0, 0, 0, 0, -1)
        self.playerFootRay = self.player.attachNewNode(CollisionNode("playerFootCollision"))
        self.playerFootRay.node().addSolid(self.footRay)
        self.playerFootRay.node().setIntoCollideMask(0)
        self.lifter = CollisionHandlerFloor()
        self.lifter.addCollider(self.playerFootRay, self.player)
        self.lifter.setMaxVelocity(5)
        base.cTrav.addCollider(self.playerFootRay, self.lifter)
        # a collision segment slightly in front of the player to check for jump ledges
        self.jumpCheckSegment = CollisionSegment(0, -0.2, 0.5, 0, -0.2, -2)
        self.playerJumpRay = self.player.attachNewNode(CollisionNode("playerJumpCollision"))
        self.playerJumpRay.node().addSolid(self.jumpCheckSegment)
        self.playerJumpRay.node().setIntoCollideMask(0)
        self.jumper = CollisionHandlerEvent()
        self.jumper.addOutPattern("%fn-out")
        base.cTrav.addCollider(self.playerJumpRay, self.jumper)
        # a collision segment to check attacks
        self.attackCheckSegment = CollisionSegment(0, 0, 1, 0, -1.3, 1)
        self.playerAttackRay = self.player.attachNewNode(CollisionNode("playerAttackCollision"))
        self.playerAttackRay.node().addSolid(self.attackCheckSegment)
        self.playerAttackRay.node().setIntoCollideMask(0)
        self.attackqueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.playerAttackRay, self.attackqueue)

        #
        # SOUNDEFFECTS
        #
        self.footstep = loader.loadSfx("Footstep.ogg")
        self.footstep.setLoop(True)
        self.footstep.setPlayRate(1.5)
        self.footstep.setVolume(0.5)
        self.spearAttackSfx = loader.loadSfx("SpearAttack.ogg")
        self.spearAttackSfx.setVolume(0.5)

    #
    # START/STOP
    #
    def start(self, startPoint):
        self.player.setPos(startPoint.getPos())
        self.player.setHpr(startPoint.getHpr())
        self.player.reparentTo(render)
        self.jumpstartFloater.setPos(self.player.getPos())

        self.keyMap = {"horizontal": 0, "vertical": 0}

        self.health = 3
        self.trackedEnemy = None
        # this mode will be used to determine in which move mode the player currently is
        self.mode = Player.NormalMode
        # the initial cam height
        self.camHeight = self.camHeightAvg
        # a time to keep the cam zoom at a specific speed independent of
        # current framerate
        self.camElapsed = 0.0
        self.mouseSpeedX = 15.0 * base.mouseSensitivity
        self.mouseSpeedY = 0.2 * base.mouseSensitivity
        self.speed = 1.0

        self.camCenterEvents = ["centerCam", "home", "q"]
        self.camZoomInEvents = ["zoomIn", "+", "wheel_up"]
        self.camZoomOutEvents = ["zoomOut", "-", "wheel_down"]
        self.actionEvents = ["doAction", "enter", "e"]

        self.accept("arrow_left", self.setKey, ["horizontal", 1])
        self.accept("arrow_right", self.setKey, ["horizontal", -1])
        self.accept("arrow_up", self.setKey, ["vertical", -1])
        self.accept("arrow_down", self.setKey, ["vertical", 1])
        self.accept("arrow_left-up", self.setKey, ["horizontal", 0])
        self.accept("arrow_right-up", self.setKey, ["horizontal", 0])
        self.accept("arrow_up-up", self.setKey, ["vertical", 0])
        self.accept("arrow_down-up", self.setKey, ["vertical", 0])
        self.accept("a", self.setKey, ["horizontal", 1])
        self.accept("d", self.setKey, ["horizontal", -1])
        self.accept("w", self.setKey, ["vertical", -1])
        self.accept("s", self.setKey, ["vertical", 1])
        self.accept("a-up", self.setKey, ["horizontal", 0])
        self.accept("d-up", self.setKey, ["horizontal", 0])
        self.accept("w-up", self.setKey, ["vertical", 0])
        self.accept("s-up", self.setKey, ["vertical", 0])
        for event in self.camCenterEvents:
            self.acceptOnce(event, self.center)
        for event in self.camZoomInEvents:
            self.acceptOnce(event, self.zoom, [True])
        for event in self.camZoomOutEvents:
            self.acceptOnce(event, self.zoom, [False])
        for event in self.actionEvents:
            self.acceptOnce(event, self.request, ["Action"])
        self.accept("ActionDone", self.request, ["Idle"])

        self.accept("playerJumpCollision-out", self.jump)

        taskMgr.add(self.move, "task_movement", priority=-10)
        taskMgr.add(self.updateCam, "task_camActualisation", priority=-4)

        if self.hasJoystick:
            taskMgr.add(self.gamepadLoop, "task_gamepad_loop", priority=-5)

        camera.setPos(self.player, 0, self.camDistance, self.camHeightAvg)

        self.hasJumped = False
        self.isActionmove = False

        self.request("Idle")

    def stop(self):
        taskMgr.remove("task_movement")
        taskMgr.remove("task_camActualisation")
        taskMgr.remove("task_gamepad_loop")
        self.ignoreAll()
        self.player.hide()

    def cleanup(self):
        self.stop()
        if self.deathComplete is not None:
            self.deathComplete.finish()
        if self.jumpInterval is not None:
            self.jumpInterval.finish()
        self.spear.removeNode()
        self.shield.removeNode()
        self.player.cleanup()
        self.player.removeNode()
        self.jumpstartFloater.removeNode()
        self.camFloater.removeNode()

    #
    # BASIC FUNCTIONS
    #
    def die(self):
        self.health -= 1
        base.messenger.send("setHealth", [self.health])
        self.request("Death")

    def heal(self):
        if self.health >= 3:
            return
        self.health += 1
        base.messenger.send("setHealth", [self.health])

    def hit(self):
        self.health -= 1
        base.messenger.send("setHealth", [self.health])
        if self.health == 0:
            self.request("Death")
        else:
            self.request("Hit")

    def resetPlayerPos(self):
        self.player.setPos(self.jumpstartFloater.getPos())
        self.jumper.clear()
        self.request("Idle")

    def gameOver(self):
        base.messenger.send("GameOver", ["loose"])

    def enterFightMode(self, trackedEnemy):
        self.trackedEnemy = trackedEnemy
        self.mode = Player.FightMode
        base.messenger.send("EnterFightMode")

    def exitFightMode(self):
        self.trackedEnemy = None
        self.mode = Player.NormalMode
        base.messenger.send("ExitFightMode")

    def gamepadLoop(self, task):
        joymap = {0: "doAction", 5: "centerCam", 6: "zoomIn", 4: "zoomOut", 9: "escape"}
        for event in pygame.event.get():
            for button in range(self.mainJoystick.get_numbuttons()):
                if button in joymap and self.mainJoystick.get_button(button):
                    base.messenger.send(joymap[button])
            if event.type == pygame.JOYAXISMOTION:
                for axis in range(self.mainJoystick.get_numaxes()):
                    axisChange = 0.0
                    axisChange = self.mainJoystick.get_axis(axis)
                    if axis == 0:
                        self.setKey("horizontal", -axisChange)
                    if axis == 1:
                        self.setKey("vertical", axisChange)
        return task.cont

    def setAnimationSpeed(self, requestedState):
        if requestedState == "Run":
            self.player.setPlayRate(3 * self.speed, "Run")
        elif requestedState == "RunReverse":
            self.player.setPlayRate(-3 * self.speed, "Run")
        elif requestedState == "FightLeft":
            self.player.setPlayRate(2 * self.speed, "Fight_Left")
        elif requestedState == "FightRight":
            self.player.setPlayRate(2 * self.speed, "Fight_Right")

    #
    # MOVE FUNCTIONS
    #
    def setKey(self, key, value):
        self.keyMap[key] = value

    def move(self, task):
        dt = globalClock.getDt()
        resetMouse = False

        def resetMouse():
            if base.controlType == Player.MOUSEANDKEYBOARD:
                base.win.movePointer(0, self.winXhalf, self.winYhalf)

        if self.player.getAnimControl("Hit").isPlaying() or self.player.getAnimControl("Death").isPlaying():
            resetMouse()
            return task.cont
        if self.deathComplete is not None:
            if self.deathComplete.isPlaying():
                resetMouse()
                return task.cont
        if self.jumpInterval is not None:
            if self.jumpInterval.isPlaying():
                resetMouse()
                return task.cont
        if self.isActionmove:
            resetMouse()
            return task.cont

        if self.mode == Player.NormalMode:
            self.__normalMove(dt)
        else:
            self.__fightMove(dt)
        return task.cont

    def __normalMove(self, dt):
        requestState = "Idle"
        move = False
        if self.keyMap["horizontal"] != 0:
            requestState = "Run"
            move = True
        if self.keyMap["vertical"] != 0:
            requestState = "Run"
            move = True
        if move and base.controlType == Player.GAMEPADMODE:
            movementVec = Vec3(self.keyMap["horizontal"], self.keyMap["vertical"], 0)
            self.speed = max(abs(self.keyMap["horizontal"]), abs(self.keyMap["vertical"]))
            angle = math.atan2(-movementVec.getX(), movementVec.getY())
            rotation = angle * (180.0 / math.pi)
            self.player.setH(camera, rotation)
            self.player.setP(0)
            self.player.setR(0)
            self.player.setPos(self.player, (0, -2 * self.speed * dt, 0))
        elif base.controlType == Player.MOUSEANDKEYBOARD:
            if not base.mouseWatcherNode.hasMouse():
                return
            self.pointer = base.win.getPointer(0)
            mouseX = self.pointer.getX()
            mouseY = self.pointer.getY()

            if base.win.movePointer(0, self.winXhalf, self.winYhalf):
                z = camera.getZ() + (mouseY - self.winYhalf) * self.mouseSpeedY * dt
                camera.setZ(z)

                h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX * dt
                if h < -360:
                    h = 360
                elif h > 360:
                    h = -360
                self.player.setH(h)
                if move:
                    self.player.setPos(
                        self.player, (2 * dt * self.keyMap["horizontal"], 2 * dt * self.keyMap["vertical"], 0)
                    )
                self.center()
        if self.state != requestState:
            self.request(requestState)
        self.setAnimationSpeed(requestState)

    def __fightMove(self, dt):
        if self.trackedEnemy == None:
            return
        requestState = "Idle"
        self.player.lookAt(self.trackedEnemy)
        self.player.setH(self.player, 180)
        if self.keyMap["horizontal"] > 0:
            self.player.setX(self.player, 2 * self.speed * dt)
            requestState = "FightLeft"
        elif self.keyMap["horizontal"] < 0:
            self.player.setX(self.player, -2 * self.speed * dt)
            requestState = "FightRight"
        elif self.keyMap["vertical"] < 0:
            self.player.setY(self.player, -2 * self.speed * dt)
            requestState = "Run"
        elif self.keyMap["vertical"] > 0:
            self.player.setY(self.player, 2 * self.speed * dt)
            requestState = "RunReverse"
        if self.state != requestState:
            self.request(requestState)
        self.setAnimationSpeed(requestState)

    def jump(self, extraArg):
        intoName = extraArg.getIntoNode().getName().lower()
        if not "floor" in intoName and not "plate" in intoName:
            return
        # setup the projectile interval
        startPos = self.player.getPos()
        self.jumpstartFloater.setPos(self.player, 0, 0.5, 0)
        tempFloater = NodePath(PandaNode("tempJumpFloater"))
        tempFloater.setPos(self.player, 0, -3.2, 0.1)
        endPos = tempFloater.getPos()
        tempFloater.removeNode()
        self.jumpInterval = ProjectileInterval(
            self.player, startPos=startPos, endPos=endPos, duration=1.5, gravityMult=0.25
        )
        self.request("Jump")
        self.jumpInterval.start()

    #
    # CAMERA FUNCTIONS
    #
    def updateCam(self, task):
        if self.mode == Player.NormalMode:
            self.__normalCam()
        else:
            self.__fightCam()
        return task.cont

    def zoom(self, zoomIn):

        # Camera Movement Updates
        camvec = self.player.getPos() - camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()

        zoom = 0
        if zoomIn:
            if camdist > self.minCamDistance + 0.5:
                zoom = 0.5
            for event in self.camZoomInEvents:
                self.acceptOnce(event, self.zoom, [True])
        else:
            if camdist < self.maxCamDistance - 0.5:
                zoom = -0.5
            for event in self.camZoomOutEvents:
                self.acceptOnce(event, self.zoom, [False])
        camera.setPos(camera, 0, zoom, 0)

    def center(self):
        # Camera Movement Updates
        camvec = self.player.getPos() - camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()
        # get the cameras current offset to the player model on the z-axis
        offsetZ = camera.getZ() - self.player.getZ()
        camera.setPos(self.player, 0, camdist, offsetZ)
        for event in self.camCenterEvents:
            self.acceptOnce(event, self.center)

    def __normalCam(self):
        """This function will check the min and max distance of the camera to
        the defined model and will correct the position if the cam is to close
        or to far away"""

        # Camera Movement Updates
        camvec = self.player.getPos() - camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()
        camvec.normalize()

        # If far from player start following
        if camdist > self.maxCamDistance:
            camera.setPos(camera.getPos() + camvec * (camdist - self.maxCamDistance))
            camdist = self.maxCamDistance

        # If player to close move cam backwards
        if camdist < self.minCamDistance:
            camera.setPos(camera.getPos() - camvec * (self.minCamDistance - camdist))
            camdist = self.minCamDistance

        # get the cameras current offset to the player model on the z-axis
        offsetZ = camera.getZ() - self.player.getZ()
        # check if the camera is within the min and max z-axis offset
        if offsetZ < self.minCamHeightDist:
            camera.setZ(self.player.getZ() + self.minCamHeightDist)
            offsetZ = self.minCamHeightDist
        elif offsetZ > self.maxCamHeightDist:
            camera.setZ(self.player.getZ() + self.maxCamHeightDist)
            offsetZ = self.maxCamHeightDist

        if offsetZ != self.camHeightAvg and not base.controlType == Player.MOUSEANDKEYBOARD:
            # if we are not moving up or down, set the cam to an average position
            if offsetZ != self.camHeightAvg:
                if offsetZ > self.camHeightAvg:
                    # the cam is higher then the average cam height above the player
                    # so move it slowly down
                    camera.setZ(camera.getZ() - 5 * globalClock.getDt())
                    newOffsetZ = camera.getZ() - self.player.getZ()
                    # check if the cam has reached the desired offset
                    if newOffsetZ < self.camHeightAvg:
                        # set the cam z position to exactly the desired offset
                        camera.setZ(self.player.getZ() + self.camHeightAvg)
                else:
                    # the cam is lower then the average cam height above the player
                    # so move it slowly up
                    camera.setZ(camera.getZ() + 5 * globalClock.getDt())
                    newOffsetZ = camera.getZ() - self.player.getZ()
                    # check if the cam has reached the desired offset
                    if newOffsetZ > self.camHeightAvg:
                        # set the cam z position to exactly the desired offset
                        camera.setZ(self.player.getZ() + self.camHeightAvg)

        camera.lookAt(self.camFloater)

    def __fightCam(self):
        """This function will check the min and max distance of the camera to
        the defined model and will correct the position if the cam is to close
        or to far away"""
        camera.setX(self.player, 0)
        camera.setY(self.player, self.fightCamDistance)
        camera.setZ(0.5)

        camera.lookAt(self.camFloater)

    #
    # FSM FUNCTIONS
    #
    def enterIdle(self):
        if self.mode == Player.NormalMode:
            self.player.loop("Idle")
            self.footstep.stop()
        elif self.mode == Player.FightMode:
            self.player.loop("Fight_Idle")
            self.footstep.stop()

    def enterRun(self):
        self.player.loop("Run")
        self.footstep.play()

    def enterRunReverse(self):
        self.player.loop("Run")
        self.footstep.play()

    def enterAction(self):
        if self.player.getAnimControl("Hit").isPlaying() or self.player.getAnimControl("Death").isPlaying():
            self.__exitAction()
            return
        self.isActionmove = True
        if self.mode == Player.NormalMode:
            self.__enterActivate()
        elif self.mode == Player.FightMode:
            self.__enterFightAttack()
        self.accept("ActionDone", self.__exitAction)

    def __exitAction(self):
        self.isActionmove = False
        for event in self.actionEvents:
            self.acceptOnce(event, self.request, ["Action"])

    def __enterActivate(self):
        activateAnim = self.player.actorInterval("Activate", playRate=3)
        activateAnim.setDoneEvent("ActionDone")
        activateAnim.start()
        base.messenger.send("Player_Activate")
        self.footstep.stop()

    def enterDeath(self):
        self.footstep.stop()
        deathAnim = self.player.actorInterval("Death")
        deathComplete = None
        if self.health == 0:
            self.deathComplete = Sequence(deathAnim, Wait(2), Func(self.gameOver))
        else:
            self.deathComplete = Sequence(deathAnim, Wait(2), Func(self.resetPlayerPos))
        self.deathComplete.start()

    def enterJump(self):
        self.player.play("Jump")
        self.footstep.stop()

    def enterHit(self):
        self.player.setPlayRate(4, "Hit")
        self.player.play("Hit")
        self.footstep.stop()

    def __enterFightAttack(self):
        attackAnim = self.player.actorInterval("Fight_Attack", playRate=3)
        attackAnim.setDoneEvent("ActionDone")
        attackAnim.start()
        self.spearAttackSfx.play()
        for i in range(self.attackqueue.getNumEntries()):
            entry = self.attackqueue.getEntry(i)
            into = entry.getIntoNode()
            if "golemHitField" in into.getName():
                if random.random() > 0.15:
                    base.messenger.send("HitEnemy")
        self.footstep.stop()

    def enterFightLeft(self):
        self.player.loop("Fight_Left")
        self.footstep.play()

    def enterFightRight(self):
        self.player.loop("Fight_Right")
        self.footstep.play()
Beispiel #28
0
class CharGen(DirectObject):
    def __init__(self, common):
        self.common=common
        self.common['chargen']=self
        self.load()        
    def load(self):  
        self.font = loader.loadFont('Bitter-Bold.otf')
        self.currentLevel=0
        
        self.common['pc_stat1']=50
        self.common['pc_stat2']=50
        self.common['pc_stat3']=50
        #render.setShaderAuto()
        #base.disableMouse()  
        #render.setAntialias(AntialiasAttrib.MMultisample)
        #base.setBackgroundColor(0, 0, 0)
        wp = base.win.getProperties()
        winX = wp.getXSize()
        winY = wp.getYSize()
        
        
        self.campmap=loader.loadModel("models/camp3")
        self.campmap.reparentTo(render)
        
        #music       
        self.common['music']=MusicPlayer(self.common)
        self.common['music'].loop(0)
        #self.common['music']=base.loadMusic("music/LuridDeliusion.ogg")
        #self.common['music'].setLoop(True)
        #self.common['music'].play()        
        
        
        self.node=render.attachNewNode("node")
        
        self.cameraNode  = self.node.attachNewNode("cameraNode")         
        self.cameraNode.setZ(-1)
        base.camera.setY(-8)
        base.camera.setZ(5)
        base.camera.lookAt((0,3,0))
        base.camera.wrtReparentTo(self.cameraNode)  
        self.pointer=self.cameraNode.attachNewNode("pointerNode") 
        
        #light
        self.pLight = PointLight('plight')
        self.pLight.setColor(VBase4(1, .95, .9, 1))
        self.pLight.setAttenuation(Point3(.5, 0, 0.1))          
        self.pLightNode = self.node.attachNewNode(self.pLight) 
        self.pLightNode.setZ(1.0)
        render.setLight(self.pLightNode)
        
        self.sLight=Spotlight('sLight')
        self.sLight.setColor(VBase4(.4, .25, .25, 1))
        if self.common['extra_ambient']:            
            self.sLight.setColor(VBase4(.7, .5, .5, 1))        
        spot_lens = PerspectiveLens()
        spot_lens.setFov(40)        
        self.sLight.setLens(spot_lens)
        self.Ambient = self.cameraNode.attachNewNode( self.sLight)
        self.Ambient.setPos(base.camera.getPos(render))
        self.Ambient.lookAt((0,3,0))
        render.setLight(self.Ambient)
        
        self.fire_node=self.node.attachNewNode("fireNode")    
        self.fire=vfx(self.fire_node, texture='vfx/big_fire3.png',scale=.29, Z=.5, depthTest=True, depthWrite=True)
        self.fire.show()
        self.fire.loop(0.02) 
        
        self.character1=Actor("models/pc/male", {"attack":"models/pc/male_attack2","idle":"models/pc/male_ready2", "block":"models/pc/male_block"}) 
        self.character1.reparentTo(self.node)
        self.character1.setBlend(frameBlend = True)  
        self.character1.setPos(1,2, 0)
        self.character1.setScale(.025)
        self.character1.setH(-25.0)       
        self.character1.setBin("opaque", 10)
        self.character1.loop("idle")        
        self.swingSound = base.loader.loadSfx("sfx/swing2.ogg")
        
        
        coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere'))
        coll_sphere.node().addSolid(CollisionSphere(1, 2, 1, 1))   
        coll_sphere.setTag("class", "1") 
        coll_sphere.node().setIntoCollideMask(BitMask32.bit(1))
        
        
        if self.common['nude']:
            self.character2=Actor("models/pc/female_nude", {"attack":"models/pc/female_attack1","idle":"models/pc/female_idle"}) 
        else:    
            self.character2=Actor("models/pc/female", {"attack":"models/pc/female_attack1","idle":"models/pc/female_idle"}) 
        #self.character2.setPlayRate(.4, "attack")
        self.character2.reparentTo(self.node)
        self.character2.setBlend(frameBlend = True)  
        self.character2.setPos(-1,2, 0)
        self.character2.setScale(.026)
        self.character2.setH(25.0)       
        #self.character2.setBin("opaque", 10)
        self.character2.loop("idle")
        
        self.char2_magic= loader.loadModel('vfx/vfx3')
        self.char2_magic.setPos(self.character2.getPos())
        self.char2_magic.setH(self.character2.getH())
        self.char2_magic.setP(-10.0)
        self.char2_magic.setZ(0.71)
        self.char2_magic.setScale(1,2,1)
        self.char2_magic.wrtReparentTo(self.character2)
        self.char2_magic.setY(-10)        
        self.char2_magic.setDepthWrite(False)
        self.char2_magic.setDepthTest(False)
        self.char2_magic.setLightOff()
        self.char2_magic.hide()        
        self.vfxU=-0.125
        self.vfxV=0
        self.magicSound = base.loader.loadSfx("sfx/thunder3.ogg")
        
        coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere'))
        coll_sphere.node().addSolid(CollisionSphere(-1, 2, 1, 1))   
        coll_sphere.setTag("class", "2") 
        coll_sphere.node().setIntoCollideMask(BitMask32.bit(1))
        
        if self.common['nude']:
            self.character3=Actor("models/pc/female2_nude", {"attack":"models/pc/female2_arm","reset":"models/pc/female2_fire","idle":"models/pc/female2_idle"}) 
        else:    
            self.character3=Actor("models/pc/female2", {"attack":"models/pc/female2_arm","reset":"models/pc/female2_fire","idle":"models/pc/female2_idle"}) 
        #self.character2.setPlayRate(.4, "attack")
        self.character3.reparentTo(self.node)
        self.character3.setBlend(frameBlend = True)  
        self.character3.setPos(-1.8,0.9, 0)
        self.character3.setScale(.026)
        self.character3.setH(40.0)       
        #self.character2.setBin("opaque", 10)
        self.character3.loop("idle")
        
        coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere'))
        coll_sphere.node().addSolid(CollisionSphere(-1.8,0.9, 0, 1))   
        coll_sphere.setTag("class", "3") 
        coll_sphere.node().setIntoCollideMask(BitMask32.bit(1))
        
        self.arrow_bone=self.character3.exposeJoint(None, 'modelRoot', 'arrow_bone')
        self.arrow=loader.loadModel('models/arrow')        
        self.arrow.reparentTo(self.arrow_bone)
        self.arrow.setP(-45)
        self.movingArrow=None
        self.arrowTime=0.0
        self.drawSound = base.loader.loadSfx("sfx/draw_bow2.ogg")
        self.fireSound = base.loader.loadSfx("sfx/fire_arrow3.ogg")
        
        
        self.character4=Actor("models/pc/male2", {"attack":"models/pc/male2_aura","idle":"models/pc/male2_idle"}) 
        #self.character2.setPlayRate(.4, "attack")
        self.character4.reparentTo(self.node)
        self.character4.setBlend(frameBlend = True)  
        self.character4.setPos(1.8,0.9, 0)
        self.character4.setScale(.024)
        self.character4.setH(-60.0)       
        #self.character2.setBin("opaque", 10)
        self.character4.loop("idle")
        self.FFSound = base.loader.loadSfx("sfx/teleport.ogg")
        #self.FFSound = base.loader.loadSfx("sfx/walk_new3.ogg")
        
        coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere'))
        coll_sphere.node().addSolid(CollisionSphere(1.8,0.9, 0, 1))   
        coll_sphere.setTag("class", "4") 
        coll_sphere.node().setIntoCollideMask(BitMask32.bit(1))
        
        
        
        #gui
        self.mp_logo=DirectFrame(frameSize=(-512, 0, 0, 128),
                                    frameColor=(1,1,1, 1),
                                    frameTexture='mp_logo.png',
                                    state=DGG.NORMAL,
                                    parent=pixel2d)       
        self.mp_logo.setPos(256+winX/2, 0, -winY)
        self.mp_logo.setBin('fixed', 1)
        self.mp_logo.hide()
        self.mp_logo.setTransparency(TransparencyAttrib.MDual)
        self.mp_logo.bind(DGG.B1PRESS, self.open_www, ['http://www.matthewpablo.com/'])
        #self.mp_logo.bind(DGG.WITHIN, self.GUIOnEnter, ["MP"]) 
        #self.mp_logo.bind(DGG.WITHOUT, self.GUIOnExit)
        
        self.title = DirectFrame(frameSize=(-512, 0, 0, 128),
                                    frameColor=(1,1,1, 1),
                                    frameTexture='select.png',
                                    parent=pixel2d)       
        self.title.setPos(256+winX/2, 0, -128)
        self.title.setBin('fixed', 1)
        self.title.setTransparency(TransparencyAttrib.MDual)
        #self.title.hide()
        self.close=DirectFrame(frameSize=(-32, 0, 0, 32),
                                    frameColor=(1, 1, 1, 1),
                                    frameTexture='icon/close.png',
                                    state=DGG.NORMAL,
                                    parent=pixel2d)        
        self.close.setPos(winX, 0, -32)
        self.close.setBin('fixed', 1)
        self.close.bind(DGG.B1PRESS, self.exit) 
        
        self.start=DirectFrame(frameSize=(-256, 0, 0, 32),                                    
                                    frameTexture='icon/level_select.png',  
                                    frameColor=(1, 1, 1, 1),                                    
                                    parent=pixel2d)       
        self.start.setPos(128+winX/2, 0, -164)
        self.start.setTransparency(TransparencyAttrib.MDual)
        #self.start.bind(DGG.B1PRESS, self.onStart)
        self.start.setBin('fixed', 1)
        #self.start.hide()
        self.start_main=DirectFrame(frameSize=(-192, 0, 0, 32),
                                    frameColor=(1,1,1, 0),    
                                    text_font=self.font,
                                    text='Start in Level 1',
                                    text_pos = (-160, 12,0),
                                    text_scale = 16,
                                    text_fg=(0,0,0,1),
                                    text_align=TextNode.ALeft, 
                                    textMayChange=1,  
                                    state=DGG.NORMAL,
                                    parent=pixel2d)       
        self.start_main.setPos(96+winX/2, 0, -164)
        self.start_main.setTransparency(TransparencyAttrib.MDual)
        self.start_main.bind(DGG.B1PRESS, self.onStart)
        self.start_main.bind(DGG.WITHIN, self.GUIOnEnter, ["4A"]) 
        self.start_main.bind(DGG.WITHOUT, self.GUIOnExit)
        self.start_main.setBin('fixed', 1)
        self.start_main.wrtReparentTo(self.start)
        
        self.start_back=DirectFrame(frameSize=(-32, 0, 0, 32),
                                    frameColor=(1,0,0, 0),                                    
                                    state=DGG.NORMAL,
                                    parent=pixel2d)       
        self.start_back.setPos(128+winX/2, 0, -164)
        self.start_back.setTransparency(TransparencyAttrib.MDual)
        self.start_back.bind(DGG.B1PRESS, self.selectLevel, [1])
        self.start_back.bind(DGG.WITHIN, self.GUIOnEnter, ["4B"]) 
        self.start_back.bind(DGG.WITHOUT, self.GUIOnExit)
        self.start_back.setBin('fixed', 1)
        self.start_back.wrtReparentTo(self.start)
        
        self.start_next=DirectFrame(frameSize=(-32, 0, 0, 32),
                                    frameColor=(0,1,0, 0),                                    
                                    state=DGG.NORMAL,
                                    parent=pixel2d)       
        
        self.start_next.setPos(-96+winX/2, 0, -164)
        self.start_next.setTransparency(TransparencyAttrib.MDual)
        self.start_next.bind(DGG.B1PRESS, self.selectLevel, [-1])
        self.start_next.bind(DGG.WITHIN, self.GUIOnEnter, ["4C"]) 
        self.start_next.bind(DGG.WITHOUT, self.GUIOnExit)
        self.start_next.setBin('fixed', 1)
        self.start_next.wrtReparentTo(self.start)
        
        self.start.hide() 
        
        
       
        self.slider3 = DirectSlider(range=(0,100),
                                    value=50,
                                    pageSize=10,      
                                    thumb_relief=DGG.FLAT,
                                    thumb_frameTexture='glass1.png',
                                    #thumb_frameColor=(1,1,1, 1),
                                    frameTexture='glass2.png',
                                    scale=96,
                                    #frameSize=(-100, 0, 0, 100),
                                    command=self.set_slider,
                                    extraArgs=["3"],
                                    parent=pixel2d)  
        self.slider3.setPos(winX/2, 0, -16)
        self.slider3.setBin('fixed', 2)
        
        self.slider2 = DirectSlider(range=(0,100),
                                    value=50,
                                    pageSize=10,      
                                    thumb_relief=DGG.FLAT,
                                    thumb_frameTexture='glass1.png',
                                    #thumb_frameColor=(1,1,1, 1),
                                    frameTexture='glass2.png',
                                    scale=96,
                                    #frameSize=(-100, 0, 0, 100),
                                    command=self.set_slider,
                                    extraArgs=["2"],
                                    parent=pixel2d)  
        self.slider2.setPos(winX/2, 0, -64)
        self.slider2.setBin('fixed', 2)
        
        self.slider1 = DirectSlider(range=(0,100),
                                    value=50,
                                    pageSize=10,      
                                    thumb_relief=DGG.FLAT,
                                    thumb_frameTexture='glass1.png',
                                    #thumb_frameColor=(1,1,1, 1),
                                    frameTexture='glass2.png',
                                    scale=96,
                                    #frameSize=(-100, 0, 0, 100),
                                    command=self.set_slider,
                                    extraArgs=["1"],
                                    parent=pixel2d)  
        self.slider1.setPos(winX/2, 0, -112)
        self.slider1.setBin('fixed', 2)
        self.slider1.hide()
        self.slider2.hide()
        self.slider3.hide()
        
        self.cursor=DirectFrame(frameSize=(-32, 0, 0, 32),
                                    frameColor=(1, 1, 1, 1),
                                    frameTexture='icon/cursor1.png',
                                    parent=pixel2d)        
        self.cursor.setPos(32,0, -32)
        self.cursor.flattenLight()
        self.cursor.setBin('fixed', 10)
        self.cursor.setTransparency(TransparencyAttrib.MDual)
        
        self.button1A=DirectFrame(frameSize=(-32, 0, 0, 32),
                                    frameColor=(1, 1, 1, 1),
                                    frameTexture='icon/armor.png',
                                    state=DGG.NORMAL,
                                    parent=pixel2d)        
        self.button1A.setPos(128+winX/2, 0, -128)
        self.button1A.setBin('fixed', 1)
        
        self.button1B=DirectFrame(frameSize=(-32, 0, 0, 32),
                                    frameColor=(1, 1, 1, 1),
                                    frameTexture='icon/armor.png',
                                    state=DGG.NORMAL,
                                    parent=pixel2d)        
        self.button1B.setPos(-96+winX/2, 0, -128)
        self.button1B.setBin('fixed', 1)
        
        self.button2A=DirectFrame(frameSize=(-32, 0, 0, 32),
                                    frameColor=(1, 1, 1, 1),
                                    frameTexture='icon/armor.png',
                                    state=DGG.NORMAL,
                                    parent=pixel2d)        
        self.button2A.setPos(128+winX/2, 0, -79)
        self.button2A.setBin('fixed', 1)
        
        self.button2B=DirectFrame(frameSize=(-32, 0, 0, 32),
                                    frameColor=(1, 1, 1, 1),
                                    frameTexture='icon/armor.png',
                                    state=DGG.NORMAL,
                                    parent=pixel2d)        
        self.button2B.setPos(-96+winX/2, 0, -79)
        self.button2B.setBin('fixed', 1)
        
        self.button3A=DirectFrame(frameSize=(-32, 0, 0, 32),
                                    frameColor=(1, 1, 1, 1),
                                    frameTexture='icon/armor.png',
                                    state=DGG.NORMAL,
                                    parent=pixel2d)        
        self.button3A.setPos(128+winX/2, 0, -32)
        self.button3A.setBin('fixed', 1)
        
        self.button3B=DirectFrame(frameSize=(-32, 0, 0, 32),
                                    frameColor=(1, 1, 1, 1),
                                    frameTexture='icon/armor.png',
                                    state=DGG.NORMAL,
                                    parent=pixel2d)        
        self.button3B.setPos(-96+winX/2, 0, -32)
        self.button3B.setBin('fixed', 1)
        
        self.button1A.hide()
        self.button1B.hide()
        self.button2A.hide()
        self.button2B.hide()
        self.button3A.hide()
        self.button3B.hide()
        self.button1A.bind(DGG.WITHIN, self.GUIOnEnter, ["1A"]) 
        self.button1A.bind(DGG.WITHOUT, self.GUIOnExit)
        self.button2A.bind(DGG.WITHIN, self.GUIOnEnter, ["2A"]) 
        self.button2A.bind(DGG.WITHOUT, self.GUIOnExit)
        self.button3A.bind(DGG.WITHIN, self.GUIOnEnter, ["3A"]) 
        self.button3A.bind(DGG.WITHOUT, self.GUIOnExit)
        self.button1B.bind(DGG.WITHIN, self.GUIOnEnter, ["1B"]) 
        self.button1B.bind(DGG.WITHOUT, self.GUIOnExit)
        self.button2B.bind(DGG.WITHIN, self.GUIOnEnter, ["2B"]) 
        self.button2B.bind(DGG.WITHOUT, self.GUIOnExit)
        self.button3B.bind(DGG.WITHIN, self.GUIOnEnter, ["3B"]) 
        self.button3B.bind(DGG.WITHOUT, self.GUIOnExit)
        
        #tooltip
        
        #self.font.setPixelsPerUnit(16)
        #self.font.setMinfilter(Texture.FTNearest )
        #self.font.setMagfilter(Texture.FTNearest )
        #self.font.setAnisotropicDegree(4)        
        #self.font.setNativeAntialias(False) 
        #self.font.setPageSize(1024,1024)
        
        self.Tooltip=DirectLabel(frameColor=(0, 0, 0, 0),
                                text_font=self.font,
                                text='Lorem ipsum dolor sit amet,\n consectetur adipisicing elit,\n sed do eiusmod tempor incididunt \nut labore et dolore magna aliqua.',
                                #pos = (0, 0,-35),
                                text_scale = 16,
                                text_fg=(1,1,1,1),                                
                                text_align=TextNode.ALeft , 
                                textMayChange=1,
                                parent=pixel2d
                                )
        self.Tooltip.flattenLight()                        
        self.Tooltip.setBin('fixed', 300)
        self.Tooltip.hide()
        
        self.tooltip_text=[None, 
                           {"1A":"ARMOR:\nYou have more Hit Points\n",
                           "1B":"REGENERATION:\nYou heal over time\n",
                           "2A":"BLOCK:\nYour block is more effective\n",
                           "2B":"SPEED:\nYour move faster\n",
                           "3A":"DAMAGE:\nYou deal more damage\n",
                           "3B":"CRITICAL HIT:\nChance for a critical hit\n"},
                          {"1A":"BLAST:\nBigger Magic Bolt explosion\n",
                           "1B":"DAMAGE:\nMagic Bolt deals more damage\n",
                           "2A":"LIGHTNING:\nMore damage to far targets\n",
                           "2B":"THUNDER:\nMore damage to near targets\n",
                           "3A":"RAPID CHARGE:\nExponential damage increase\n",
                           "3B":"STATIC CHARGE:\nLinear damage increase\n"},                           
                          {"1A":"BARBS:\nOne hit counts as two\n",
                           "1B":"PIERCE:\nArrows pass through targets\n",
                           "2A":"BLEED:\nDamage over time\n",
                           "2B":"CRIPPLE:\nSlow down enemies\n",
                           "3A":"FINESSE:\nMore critical hits\n",
                           "3B":"PROWESS:\nMore damage\n"},                           
                          {"1A":"BURNING DEATH:\nMagma deals more damage\n",
                           "1B":"MAGMA FLOW:\nMore magma at once\n",
                           "2A":"HEART OF FIRE:\nMagma lasts longer\n",
                           "2B":"VOLCANIC ACTIVITY:\nMagma is bigger\n",
                           "3A":"PHASESHIFT:\nYou can teleport more often\n",
                           "3B":"WARP FIELD:\nFaster recovery after teleport\n"} ]
        #collisions
        #self.traverser=CollisionTraverser("playerTrav")
        #self.traverser.setRespectPrevTransform(True)        
        #self.queue = CollisionHandlerQueue() 
        self.MousePickerNode = CollisionNode('mouseRay')        
        self.pickerNP = base.camera.attachNewNode(self.MousePickerNode)        
        self.MousePickerNode.setFromCollideMask(BitMask32.bit(1))
        self.MousePickerNode.setIntoCollideMask(BitMask32.allOff())
        self.pickerRay = CollisionSegment()               #Make our ray
        self.MousePickerNode.addSolid(self.pickerRay)      #Add it to the collision node        
        self.common['traverser'].addCollider(self.pickerNP, self.common['queue'])
        
        self.accept("mouse1", self.onClick)
        
        taskMgr.doMethodLater(0.2, self.flicker,'flicker')
        #taskMgr.add(self.camera_spin, "camera_spin")  
        taskMgr.add(self.__getMousePos, "chargenMousePos")  
        
        self.current_class=None
        
        self.camLoop=Sequence(LerpHprInterval(self.cameraNode, 10.0, VBase3(-20,0, 0), bakeInStart=0),LerpHprInterval(self.cameraNode, 10.0, VBase3(20,0, 0),bakeInStart=0))
        self.camLoop.loop()
        self.accept( 'window-event', self.windowEventHandler)
    
    def selectLevel(self, next, event=None):
        self.currentLevel+=next
        if self.currentLevel<0:
            self.currentLevel=0
        if self.currentLevel>self.common['max_level']:
            self.currentLevel=self.common['max_level']
        self.start_main['text']="Start in Level "+str(self.currentLevel+1)    
    
    def moveArrow(self, task):
        if self.movingArrow:
            self.arrowTime+=task.time
            if self.arrowTime>3.0:
                self.movingArrow.removeNode()
                self.arrowTime=0.0
                return task.done
            dt = globalClock.getDt()    
            self.movingArrow.setX(self.movingArrow, 400*dt)    
            return task.again
        else:
            return task.done
            
    def fireArrow(self):
        self.movingArrow=loader.loadModel('models/arrow')        
        self.movingArrow.reparentTo(self.arrow_bone)
        self.movingArrow.setP(-45)
        self.movingArrow.wrtReparentTo(render)
        self.arrow.hide()
        self.fireSound.play()
        taskMgr.add(self.moveArrow, "moveArrowTask") 
        Sequence(Wait(0.5),Func(self.arrow.show)).start()
        
    def onStart(self, event=None):
        #unload stuff        
        self.camLoop.pause()
        self.camLoop=None
        base.camera.reparentTo(render)
        self.campmap.removeNode()
        self.node.removeNode()
        self.fire.remove_loop()
        if taskMgr.hasTaskNamed('flicker'):
            taskMgr.remove('flicker') 
        if taskMgr.hasTaskNamed('chargenMousePos'):
            taskMgr.remove('chargenMousePos')  
        self.common['traverser'].removeCollider(self.pickerNP)
        self.pickerNP.removeNode() 
        self.Ambient.removeNode()
                
        self.button1A.destroy()
        self.button1B.destroy()
        self.button2A.destroy()
        self.button2B.destroy()
        self.button3A.destroy()
        self.button3B.destroy()
        self.Tooltip.destroy()
        self.cursor.destroy()
        self.slider1.destroy()
        self.slider2.destroy()
        self.slider3.destroy()
        self.start.destroy()
        self.start_back.destroy()
        self.start_next.destroy()
        self.close.destroy()
        self.title.destroy()
        self.mp_logo.destroy()
        
        render.setLightOff()
        self.ignoreAll()
        
        #self.common['music'].stop()
        
        #self.common['spawner']=Spawner(self.common)
        #self.common['levelLoader']=LevelLoader(self.common)
        
        self.common['levelLoader'].load(self.currentLevel, PCLoad=False)
        #render.ls()
        if self.current_class=="1":
            self.common['PC']=PC1(self.common)
            #self.common['PC'].node.setPos(-12, 0, 0)
        elif self.current_class=="2": 
            self.common['PC']=PC2(self.common)
            #self.common['PC'].node.setPos(-12, 0, 0)
        elif self.current_class=="3": 
            self.common['PC']=PC3(self.common)
            #self.common['PC'].node.setPos(-12, 0, 0)    
        elif self.current_class=="4": 
            self.common['PC']=PC4(self.common)
            #self.common['PC'].node.setPos(-12, 0, 0)
        pos=(data.levels[self.currentLevel]["enter"][0], data.levels[self.currentLevel]["enter"][1], data.levels[self.currentLevel]["enter"][2])     
        self.common['PC'].node.setPos(pos)
        self.common['music'].loop(1, fadeIn=True)
        
    def open_www(self, url, event=None):
        webbrowser.open_new(url)
    
    def windowEventHandler( self, window=None ): 
        #print "resize"
        if window is not None: # window is none if panda3d is not started
            wp = base.win.getProperties()
            X= wp.getXSize()/2
            Y= wp.getYSize()
            self.slider3.setPos(X, 0, -16)
            self.slider2.setPos(X, 0, -64)
            self.slider1.setPos(X, 0, -112)
            self.button1A.setPos(128+X, 0, -128)
            self.button1B.setPos(-96+X, 0, -128)
            self.button2A.setPos(128+X, 0, -79)
            self.button2B.setPos(-96+X, 0, -79)
            self.button3A.setPos(128+X, 0, -32)
            self.button3B.setPos(-96+X, 0, -32)
            self.start.setPos(128+X, 0, -164)
            self.title.setPos(256+X, 0, -128)
            self.close.setPos(X*2, 0, -32)
            self.mp_logo.setPos(256+X, 0, -Y) 
            
    def getSliderValue(self, option):        
        value=0        
        if option[0]=="1":
            value=int(self.slider1['value'])
        elif option[0]=="2":
            value=int(self.slider2['value'])
        elif option[0]=="3":
            value=int(self.slider3['value'])
            
        if self.current_class=="2":    
            if option=="1A":
                return "{0}% blast size".format(value+50)
            elif option=="1B":
                return "{0}% damage".format(75+(101-value)/2)
            elif option=="2A":
                return "{0}% damage to far targets".format(value*2)
            elif option=="2B":
                return "{0}% damage to near targets\n".format(2*(100-value))
            elif option=="3A":
                return "{0}-{1} Lightning damage\n{2}-{3} Magic Bolt damage".format(
                                                                                    int(round(value/100.0+8*(101-value)/100.0)),
                                                                                    int(round(15*value/100.0+8*(101-value)/100)),
                                                                                    2*int(round(2*value/100.0+6*(101-value)/100.0)),
                                                                                    2*int(round(26*value/100.0+20*(101-value)/100))
                                                                                    )
            elif option=="3B":
                return "{0}-{1} Lightning damage\n{2}-{3} Magic Bolt damage".format(
                                                                                    int(round(value/100.0+8*(101-value)/100.0)),
                                                                                    int(round(15*value/100.0+8*(101-value)/100)),
                                                                                    2*int(round(2*value/100.0+6*(101-value)/100.0)),
                                                                                    2*int(round(26*value/100.0+20*(101-value)/100))
                                                                                    )
        elif self.current_class=="1":    
            if option=="1A":
                return "{0} total HP".format(value+50)
            elif option=="1B":
                return "+{0}HP/second".format(round((101-value)/100.0, 1))
            elif option=="2A":
                return "{0}% damage blocked".format(50+(value+1)/2)
            elif option=="2B":
                return "{0}% movement speed".format(75+(101-value)/2)
            elif option=="3A":
                return "{0}-{1} damage".format( int(round(1.0+(value+1.0)/100.0)), int(round(15.0*(1.0+(value+1.0)/50.0))))
            elif option=="3B":
                return "{0}% chance for +{1} damage".format(5+(101-value)/2,5+(101-value)/5)
                
        elif self.current_class=="3":    
            if option=="1A":
                return "{0}% chance to activate".format(int(value/2))
            elif option=="1B":
                return "{0}%chance to pierce".format(int((100-value)/2))
            elif option=="2A":
                return "{0}% of critical hits".format(int(value))
            elif option=="2B":
                return "{0}% of critical hits".format(int(100-value))
            elif option=="3A":
                return "{0}% chance for critical hit".format(25+ int(value/2))
            elif option=="3B":
                return "{0}% damage".format(50+int(100-value))   
        elif self.current_class=="4":    
            if option=="1A":
                return "{0}% damage".format(50+int(value))
            elif option=="1B":
                v=1+int((100-value)/20)
                if v<2:
                    return "Control 1 orb of magma"                    
                return "Control {0} orbs of magma".format(v)
            elif option=="2A":
                return "{0}% time".format(50+int(value))
            elif option=="2B":
                return "{0}% size".format(50+int(100-value))
            elif option=="3A":
                return "Teleport every {0} seconds".format(16.0*((100-value)/1000.0)+0.8)
            elif option=="3B":
                return "{0}% recovery time".format(50+int(value))
                
        return "???"
        
    def GUIOnEnter(self, object, event=None):       
        if object[0]=="4":            
            if object[1]=="A":
                self.Tooltip['text']="Click to start!"    
            elif object[1]=="B":
                self.Tooltip['text']="Next level"        
            elif object[1]=="C":
                self.Tooltip['text']="Previous level"        
            self.Tooltip['text_pos'] = (10, -40,0)
            self.Tooltip['text_align'] =TextNode.ACenter 
            self.Tooltip.show()    
            return
        if not self.current_class:
            return            
        #print int(self.current_class)
        self.Tooltip['text']=self.tooltip_text[int(self.current_class)][object]+self.getSliderValue(object)    
        if object[1]=="A":            
            self.Tooltip['text_pos'] = (30, -10,0)
            self.Tooltip['text_align'] =TextNode.ALeft
        else:            
            self.Tooltip['text_pos'] = (-20, -10,0)
            self.Tooltip['text_align'] =TextNode.ARight
        self.Tooltip.show()
        #print "in"
        
    def GUIOnExit(self, event=None):
        self.Tooltip.hide()
        #print "out"
        
    def start_lightning(self, time=0.03):
        taskMgr.doMethodLater(time, self.lightning,'vfx')
        self.magicSound.play()
        
    def lightning(self, task):
        self.char2_magic.show()
        self.vfxU=self.vfxU+0.5   
        if self.vfxU>=1.0:
            self.vfxU=0
            self.vfxV=self.vfxV-0.125
        if self.vfxV <=-1:
            self.char2_magic.hide()
            self.vfxU=0
            self.vfxV=0
            return task.done
        self.char2_magic.setTexOffset(TextureStage.getDefault(), self.vfxU, self.vfxV)
        return task.again   
        
    def loopAnim(self, actor, anim):
        actor.loop(anim)
    
    def set_slider(self, id):
        #self.current_class=id
        #print id, 
        if id=="1":
            self.common['pc_stat1']=int(self.slider1['value'])
            #print self.common['pc_stat1']
        elif id=="2":
            self.common['pc_stat2']=int(self.slider2['value'])
            #print self.common['pc_stat2']
        elif id=="3":
            self.common['pc_stat3']=int(self.slider3['value'])        
            #print self.common['pc_stat3']
            
    def onClick(self):
        self.common['traverser'].traverse(render) 
        my_class=None
        for entry in self.common['queue'].getEntries():
            if entry.getIntoNodePath().hasTag("class"):
                my_class=entry.getIntoNodePath().getTag("class")
                
        if my_class=="1":
            self.slider1['value']=50        
            self.slider2['value']=50        
            self.slider3['value']=50
            self.current_class=my_class
            self.title.hide()
            self.start.show()
            self.button1A.show()
            self.button1B.show()
            self.button2A.show()
            self.button2B.show()
            self.button3A.show()
            self.button3B.show()
            
            self.button1A['frameTexture']='icon/armor.png'
            self.button1B['frameTexture']='icon/heart.png'
            self.button2A['frameTexture']='icon/shield2.png'
            self.button2B['frameTexture']='icon/move.png'
            self.button3A['frameTexture']='icon/power.png'
            self.button3B['frameTexture']='icon/critical.png'
            
            #self.skills.show()
            self.slider1.show()
            self.slider2.show()
            self.slider3.show()            
            Sequence(self.character1.actorInterval("attack"),self.character1.actorInterval("block"), Func(self.loopAnim, self.character1, "idle")).start()
            self.swingSound.play()
            #self.character1.play("attack")
            self.character2.loop("idle")
        elif my_class=="2":
            self.slider1['value']=50        
            self.slider2['value']=50        
            self.slider3['value']=50
            self.current_class=my_class
            self.title.hide()
            self.start.show()
            self.button1A.show()
            self.button1B.show()
            self.button2A.show()
            self.button2B.show()
            self.button3A.show()
            self.button3B.show()
            
            self.button1A['frameTexture']='icon/blast.png'
            self.button1B['frameTexture']='icon/damage.png'
            self.button2A['frameTexture']='icon/lightning.png'
            self.button2B['frameTexture']='icon/thunder.png'
            self.button3A['frameTexture']='icon/amp.png'
            self.button3B['frameTexture']='icon/volt.png'
            
            
            self.slider1.show()
            self.slider2.show()
            self.slider3.show()                
            Sequence(self.character2.actorInterval("attack", playRate=0.8),Func(self.loopAnim, self.character2, "idle")).start()
            Sequence(Wait(0.3), Func(self.start_lightning, 0.05)).start()
            #self.character2.play("attack")
            self.character1.loop("idle")
            #RayVfx(self.character2, texture='vfx/lightning.png').start()
        elif my_class=="3":
            self.slider1['value']=50        
            self.slider2['value']=50        
            self.slider3['value']=50
            self.current_class=my_class
            self.title.hide()
            self.start.show()
            self.button1A.show()
            self.button1B.show()
            self.button2A.show()
            self.button2B.show()
            self.button3A.show()
            self.button3B.show()
            
            self.button1A['frameTexture']='icon/barbs.png'
            self.button1B['frameTexture']='icon/pierce.png'
            self.button2A['frameTexture']='icon/bleed.png'
            self.button2B['frameTexture']='icon/cripple.png'
            self.button3A['frameTexture']='icon/finese.png'
            self.button3B['frameTexture']='icon/bow_damage.png'
            
            
            self.slider1.show()
            self.slider2.show()
            self.slider3.show()
            self.drawSound.play()
            self.character3.play("attack")
            Sequence(Wait(1.5),Func(self.fireArrow), Func(self.character3.play, "reset"),Wait(1.0),Func(self.loopAnim, self.character3, "idle")).start()
        elif my_class=="4":
            self.slider1['value']=50        
            self.slider2['value']=50        
            self.slider3['value']=50
            self.current_class=my_class
            self.title.hide()
            self.start.show()
            self.button1A.show()
            self.button1B.show()
            self.button2A.show()
            self.button2B.show()
            self.button3A.show()
            self.button3B.show()
            
            self.button1A['frameTexture']='icon/hand_o_fate.png'
            self.button1B['frameTexture']='icon/magma_flow.png'
            self.button2A['frameTexture']='icon/heart_o_fire.png'
            self.button2B['frameTexture']='icon/vulcanic.png'
            self.button3A['frameTexture']='icon/warp.png'
            self.button3B['frameTexture']='icon/thorns.png'
            
            #self.skills.show()
            self.slider1.show()
            self.slider2.show()
            self.slider3.show()
            self.character4.loop("attack")
            aura=vfx(self.character4, texture='vfx/tele2.png',scale=.5, Z=.85, depthTest=False, depthWrite=False)
            aura.show()
            aura.start()
            self.FFSound.play()
            Sequence(Wait(2.2), Func(self.loopAnim, self.character4, "idle")).start()
               
    def exit(self, event=None):
        self.common['root'].save_and_exit()
        #sys.exit()
    
    def __getMousePos(self, task):
        if base.mouseWatcherNode.hasMouse():  
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())        
            pos2d=Point3(mpos.getX() ,0, mpos.getY())
            self.cursor.setPos(pixel2d.getRelativePoint(render2d, pos2d)) 
            self.Tooltip.setPos(self.cursor.getPos())    
        return task.again  
        
    def flicker(self, task):
        self.pLight.setAttenuation(Point3(1, 0, random.uniform(.1, 0.15)))  
        self.pLightNode.setZ(random.uniform(.9, 1.1))
        #self.pLight.setColor(VBase4(random.uniform(.9, 1.0), random.uniform(.9, 1.0), .9, 1))        
        return task.again  
        
    def camera_spin(self, task):
        H=self.cameraNode.getH()
        #Z=self.cameraNode.getZ()
        #print H
        if H<=-20.0 or H>=20.0:
            if self.reverse_spin:
                self.reverse_spin=False
            else:
                self.reverse_spin=True
        if self.reverse_spin:        
            self.cameraNode.setH(self.cameraNode, 4*globalClock.getDt())
            #self.cameraNode.setZ(Z+0.1*globalClock.getDt())
        else:
            self.cameraNode.setH(self.cameraNode, -4*globalClock.getDt())
            #self.cameraNode.setZ(Z-0.1*globalClock.getDt())
        return task.again  
#c=Camp()
#run()        
Beispiel #29
0
class Tricker(object):
    def __init__(self):
        ## tricker-model taken from tutorial files from
        # https://www.digitaltutors.com/tutorial/1478-Animating-an-Acrobatic-Fight-Scene-in-Maya
        self.actor = Actor(
            "tp/models/tricker-model", {
                "gainer": "tp/anims/tricker-gainer",
                "gainer_bad": "tp/anims/tricker-gainer-bad",
                "gswitch": "tp/anims/tricker-gswitch",
                "gswitch_bad": "tp/anims/tricker-gswitch-bad",
                "btwist": "tp/anims/tricker-btwist",
                "btwist_bad": "tp/anims/tricker-btwist",
                "cork": "tp/anims/tricker-cork",
                "cork_bad": "tp/anims/tricker-cork-bad",
                "doublecork": "tp/anims/tricker-dubcork",
                "doublecork_bad": "tp/anims/tricker-dubcork",
                "fall_swing": "tp/anims/tricker-fall-left",
                "initial_swing": "tp/anims/tricker-initial-swing",
                "end_swing": "tp/anims/tricker-end-swing",
                "fall_reversal": "tp/anims/tricker-fall-right",
                "raiz": "tp/anims/tricker-raiz",
                "raiz_bad": "tp/anims/tricker-raiz-bad",
                "fiveForty": "tp/anims/tricker-540",
                "fiveForty_bad": "tp/anims/tricker-540-bad"
            })

        #saveDict contains all info to be saved to json
        self.saveDict = {
            'name': '',
            'level': 0,
            'totalStam': 100,
            'skills': {
                "gainer": 1,
                "gswitch": 1,
                "btwist": 1,
                "cork": 1,
                "doublecork": 1,
                "raiz": 1,
                "fiveForty": 1
            }
        }
        self.updateAttributes()

        # trickMap is different - this shit maps trick names to their classes
        # in order to get class data just given an animation name
        self.trickMap = {
            'gainer': self.gainer,
            'gswitch': self.gswitch,
            'btwist': self.btwist,
            'cork': self.cork,
            'doublecork': self.doublecork,
            'raiz': self.raiz,
            'fiveForty': self.fiveForty
        }

        # runtime traits, to be reset with reset function
        # NOTE: You MUST add any vals here to the reset function below
        self.prevTrick = None
        self.stamina = self.totalStam
        self.grade = ''
        self.timing = ''
        self.score = 0
        self.comboLength = 0
        self.comboEnded = False
        self.comboContinuing = False
        self.falling = False
        self.midTrick = False

    def comboHasEnded(self):
        return self.comboEnded

    def hasName(self):
        return self.name != ''

    def isFalling(self):
        return self.falling

    def isMidTrick(self):
        return self.midTrick

    def getName(self):
        if self.hasName(): return self.name
        else: return "NewPlayer"

    def getLevel(self):
        return str(self.saveDict['level'])

    def getTotalStam(self):
        return str(self.totalStam)

    def getSaveDict(self):
        return self.saveDict

    def getSkillDict(self):
        return self.skillDict

    def getComboLength(self):
        return str(int(self.comboLength))

    def getScore(self):
        return str(int(self.score))

    def getTiming(self):
        return self.timing

    def updateStamina(self, stamCost):
        self.stamina -= stamCost

    def updateComboLength(self):
        self.comboLength += 1

    def updateScore(self, trick, goodPercentage, comboLength):
        b = trick.getDifficulty() * 100
        score = b + (b * goodPercentage) + (b * (comboLength / 5))
        self.score += score

    def getTimingBarPercentage(self):
        currAnim = self.actor.getCurrentAnim()

        if currAnim and 'fall' not in currAnim and 'initial' not in currAnim and 'end' not in currAnim:
            trick = self.trickMap[currAnim.split('_')[0]]
            sweetspot = trick.getSweetSpot()
            currFrame = self.actor.getCurrentFrame()
            dist = abs(sweetspot - currFrame)
            eMargin = trick.getDuration() * .2 / trick.getDifficulty()

            if dist > eMargin: gp = 0
            else: gp = 1 - (dist / eMargin)

            return gp
        else:
            return 0

    def getTrueStam(self):
        return self.stamina

    def stamPercentage(self):
        sp = self.stamina / self.totalStam
        if sp < 0: sp = 0
        return sp

    def getGrade(self):
        return self.grade

    def increaseSkill(self, trick, grade):
        if grade == 0: b = 2
        elif grade == 1: b = 1.66
        elif grade == 2: b = 1.33
        elif grade == 3: b = 1
        elif grade == 4: b = 1

        # This line makes the exp curve and prevents leveling over 100
        exp = b - math.log(self.saveDict['skills'][str(trick)])

        if exp < 0: exp = 0

        self.saveDict['skills'][str(trick)] += exp
        self.updateAttributes()

    """
    debug animation procedure:
    comment out:
    return under if self.comboEnded in self.tryTrick
    both moveInterval.start() in self.doTrickTask
    
    
    """

    def tryTrick(self, trick, taskMgr):
        if self.midTrick:
            print("already received an input")
            return
        self.midTrick = True
        if self.comboEnded:
            print("combo ended - no more tricking 4 u")
            return

        if self.falling:
            print("can't trick once you've fallen boi")
            return

        if self.stamina <= 0:
            self.comboEnded = True
            print("no stamina to throw trick!! ending combo")
            return

        self.comboContinuing = True
        distance = (0, 0, 0)

        self.grade = 0
        currAnim = self.actor.getCurrentAnim()
        goodPercentage = trick.getGoodPercentage(self.grade)

        if self.prevTrick: distance = self.prevTrick.getDistance()

        if currAnim and self.prevTrick:
            if (self.prevTrick.getExitTransition() !=
                    trick.getEntryTransition()):
                self.comboEnded = True
                print("invalid transition - ended combo")
                return

            distance = self.prevTrick.getDistance()

            currFrame = self.actor.getCurrentFrame(currAnim)
            numFrames = self.actor.getNumFrames(currAnim)
            framesLeft = numFrames - currFrame

            (self.grade, self.timing) = self.prevTrick.getGrade(currFrame)
            if self.grade == 4:
                self.falling = True
                print("Combo failed - falling")
                self.prevTrick = None

            stamCost = trick.getStamCost(self.grade)
            self.updateStamina(stamCost)

            goodPercentage = trick.getGoodPercentage(self.grade)

            # 0.06 is the time it takes for 2 frames - smooth blending
            delayTime = framesLeft / 30 - 0.09
            taskMgr.doMethodLater(
                delayTime,
                self.doTrickTask,
                'doTrick',
                extraArgs=[str(trick), goodPercentage, distance, taskMgr],
                appendTask=True)
        else:
            stamCost = trick.getStamCost(self.grade)
            self.updateStamina(stamCost)

            if trick.entryTransition == 'swing':
                self.actor.play('initial_swing')
                distance = (-2, 2, 0)
                taskMgr.doMethodLater(
                    21 / 30,
                    self.doTrickTask,
                    'doTrick',
                    extraArgs=[str(trick), goodPercentage, distance, taskMgr],
                    appendTask=True)
            else:
                taskMgr.add(
                    self.doTrickTask,
                    'doTrick',
                    extraArgs=[str(trick), goodPercentage, distance, taskMgr],
                    appendTask=True)

        if self.getTrueStam() < 0:
            self.falling = True
            return ("Ran out of stamina mid-trick - falling!")

        if not self.falling:
            self.updateScore(trick, goodPercentage, self.comboLength)
            self.updateComboLength()
            self.prevTrick = trick

        # this is tricking - you still learn from your falls!
        self.increaseSkill(trick, self.grade)

    def doTrickTask(self, animation, goodPercentage, distance, taskMgr, task):
        print("goodp:", goodPercentage)
        self.actor.setPos(self.actor, distance)
        badAnim = str(animation + "_bad")

        if not self.isFalling():
            self.actor.enableBlend()
            self.actor.setControlEffect(badAnim, 1 - goodPercentage)
            self.actor.setControlEffect(animation, goodPercentage)
            self.actor.play(badAnim)
            self.actor.play(animation)
            self.actor.disableBlend()

            self.comboContinuing = False
            self.midTrick = False
            taskMgr.add(self.checkTrickStateTask,
                        'checkTrickState',
                        extraArgs=[animation],
                        appendTask=True)

        elif self.isFalling():
            trick = self.trickMap[animation]
            fallDist = trick.getDistance()
            exitTrans = trick.getExitTransition()
            fallingAnim = "fall_" + exitTrans

            fallStartFrame = trick.getDuration() - trick.getSweetSpot()
            regFrames = self.actor.getNumFrames(animation) - fallStartFrame

            fallSeq = Sequence(
                self.actor.actorInterval(badAnim, endFrame=regFrames),
                Func(self.playFall, fallingAnim, fallDist, exitTrans))
            fallSeq.start()

    # if moveInterval: moveInterval.start()
        return Task.done

    def playFall(self, fallingAnim, distance, exitTrans):
        # if fallingAnim == 'fall_swing':
        #     self.actor.enableBlend()
        #     self.actor.setControlEffect(badAnim, .5)
        #     self.actor.setControlEffect(fallingAnim, .5)
        #     self.actor.play(badAnim, fromFrame=startFrame)
        #     self.actor.play(fallingAnim)
        #     self.actor.disableBlend()
        # elif fallingAnim == 'fall_reversal':
        if exitTrans == 'swing':
            self.actor.setPos(self.actor, distance)
        self.actor.play(fallingAnim)

    def playSwingExit(self, distance):
        self.actor.setPos(self.actor, distance)
        self.actor.play('end_swing')

    def checkTrickStateTask(self, animation, task):
        # has to be -1 otherwise the currFrame never gets to the last frame. IDK why
        totalFrames = self.actor.getNumFrames(animation) - 1
        currFrame = self.actor.getCurrentFrame(animation)

        if self.comboContinuing or self.falling:
            print("comboContinuing or falling")
            return Task.done
        self.comboContinuing = False
        if currFrame == totalFrames:
            self.comboEnded = True
            print("no input received - combo ended")
            trick = self.trickMap[animation]
            distance = trick.getDistance()
            if trick.getExitTransition() == 'swing':
                self.playSwingExit(distance)
            return Task.done
        return Task.cont

    def reset(self):
        self.prevTrick = None
        self.stamina = 100
        self.grade = None
        self.timing = ''
        self.score = 0
        self.comboLength = 0
        self.comboEnded = False
        self.comboContinuing = False
        self.falling = False
        self.midTrick = False

    def setName(self, name):
        self.saveDict['name'] = name
        self.updateAttributes()

    def loadToSaveDict(self, indata):
        self.saveDict = indata
        self.updateAttributes()

    def updateAttributes(self):
        self.name = self.saveDict['name']
        self.totalStam = self.saveDict['totalStam']
        self.skillDict = self.saveDict['skills']

        # set tricker's level based on proficiency in all skills
        numTricks = totalSP = 0
        for trick in self.skillDict:
            numTricks += 1
            totalSP += self.skillDict[trick]
        self.level = int(totalSP / numTricks)
        self.saveDict['level'] = self.level

        # Load tricks
        self.gainer = Gainer(self)
        self.gswitch = Gswitch(self)
        self.btwist = Btwist(self)
        self.cork = Cork(self)
        self.doublecork = DoubleCork(self)
        self.raiz = Raiz(self)
        self.fiveForty = FiveForty(self)
class World(DirectObject):
    def __init__(self):
        # Preliminary capabilities check.

        if not ape.base().win.getGsg().getSupportsBasicShaders():
            self.t = addTitle(
                "Shadow Demo: Video driver reports that shaders are not supported."
            )
            return
        if not ape.base().win.getGsg().getSupportsDepthTexture():
            self.t = addTitle(
                "Shadow Demo: Video driver reports that depth textures are not supported."
            )
            return

        self.inst_p = addInstructions(0.06,
                                      'P : stop/start the Panda Rotation')
        self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle')
        self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot')
        self.inst_l = addInstructions(0.24,
                                      'L : move light source far or close')
        self.inst_v = addInstructions(0.30,
                                      'V : View the Depth-Texture results')
        self.inst_u = addInstructions(0.36,
                                      'U : toggle updating the shadow map')
        self.inst_x = addInstructions(
            0.42, 'Left/Right Arrow : switch camera angles')

        ape.base().setBackgroundColor(0, 0, 0.2, 1)

        ape.base().camLens.setNearFar(1.0, 10000)
        ape.base().camLens.setFov(75)
        ape.base().disableMouse()

        # Load the scene.
        floorTex = ape.loader().loadTexture('maps/envir-ground.jpg')

        cm = p3dc.CardMaker('')
        cm.setFrame(-2, 2, -2, 2)
        floor = ape.render().attachNewNode(p3dc.PandaNode("floor"))
        for y in range(12):
            for x in range(12):
                nn = floor.attachNewNode(cm.generate())
                nn.setP(-90)
                nn.setPos((x - 6) * 4, (y - 6) * 4, 0)
        floor.setTexture(floorTex)
        floor.flattenStrong()

        self.pandaAxis = ape.render().attachNewNode('panda axis')
        self.pandaModel = Actor('panda-model', {'walk': 'panda-walk4'})
        self.pandaModel.reparentTo(self.pandaAxis)
        self.pandaModel.setPos(9, 0, 0)
        self.pandaModel.setScale(0.01)
        self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8)
        self.pandaWalk.loop()
        self.pandaMovement = self.pandaAxis.hprInterval(
            20.0, p3dc.LPoint3(-360, 0, 0), startHpr=p3dc.LPoint3(0, 0, 0))
        self.pandaMovement.loop()

        self.teapot = ape.loader().loadModel('teapot')
        self.teapot.reparentTo(ape.render())
        self.teapot.setPos(0, -20, 10)
        self.teapotMovement = self.teapot.hprInterval(
            50, p3dc.LPoint3(0, 360, 360))
        self.teapotMovement.loop()

        self.accept('escape', sys.exit)

        self.accept("arrow_left", self.incrementCameraPosition, [-1])
        self.accept("arrow_right", self.incrementCameraPosition, [1])
        self.accept("p", self.toggleInterval, [self.pandaMovement])
        self.accept("t", self.toggleInterval, [self.teapotMovement])
        self.accept("w", self.toggleInterval, [self.pandaWalk])
        self.accept("v", ape.base().bufferViewer.toggleEnable)
        self.accept("u", self.toggleUpdateShadowMap)
        self.accept("l", self.incrementLightPosition, [1])
        self.accept("o", ape.base().oobe)

        self.light = ape.render().attachNewNode(p3dc.Spotlight("Spot"))
        self.light.node().setScene(ape.render())
        self.light.node().setShadowCaster(True)
        self.light.node().showFrustum()
        self.light.node().getLens().setFov(40)
        self.light.node().getLens().setNearFar(10, 100)
        ape.render().setLight(self.light)

        self.alight = ape.render().attachNewNode(p3dc.AmbientLight("Ambient"))
        self.alight.node().setColor(p3dc.LVector4(0.2, 0.2, 0.2, 1))
        ape.render().setLight(self.alight)

        # Important! Enable the shader generator.
        ape.render().setShaderAuto()

        # default values
        self.cameraSelection = 0
        self.lightSelection = 0

        self.incrementCameraPosition(0)
        self.incrementLightPosition(0)

    def toggleInterval(self, ival):
        if ival.isPlaying():
            ival.pause()
        else:
            ival.resume()

    def toggleUpdateShadowMap(self):
        buffer = self.light.node().getShadowBuffer(ape.base().win.gsg)
        buffer.active = not buffer.active

    def incrementCameraPosition(self, n):
        self.cameraSelection = (self.cameraSelection + n) % 6
        if (self.cameraSelection == 0):
            ape.base().cam.reparentTo(ape.render())
            ape.base().cam.setPos(30, -45, 26)
            ape.base().cam.lookAt(0, 0, 0)
            self.light.node().hideFrustum()
        if (self.cameraSelection == 1):
            ape.base().cam.reparentTo(self.pandaModel)
            ape.base().cam.setPos(7, -3, 9)
            ape.base().cam.lookAt(0, 0, 0)
            self.light.node().hideFrustum()
        if (self.cameraSelection == 2):
            ape.base().cam.reparentTo(self.pandaModel)
            ape.base().cam.setPos(-7, -3, 9)
            ape.base().cam.lookAt(0, 0, 0)
            self.light.node().hideFrustum()
        if (self.cameraSelection == 3):
            ape.base().cam.reparentTo(ape.render())
            ape.base().cam.setPos(7, -23, 12)
            ape.base().cam.lookAt(self.teapot)
            self.light.node().hideFrustum()
        if (self.cameraSelection == 4):
            ape.base().cam.reparentTo(ape.render())
            ape.base().cam.setPos(-7, -23, 12)
            ape.base().cam.lookAt(self.teapot)
            self.light.node().hideFrustum()
        if (self.cameraSelection == 5):
            ape.base().cam.reparentTo(ape.render())
            ape.base().cam.setPos(1000, 0, 195)
            ape.base().cam.lookAt(0, 0, 0)
            self.light.node().showFrustum()

    def incrementLightPosition(self, n):
        self.lightSelection = (self.lightSelection + n) % 2
        if (self.lightSelection == 0):
            self.light.setPos(0, -40, 25)
            self.light.lookAt(0, -10, 0)
            self.light.node().getLens().setNearFar(10, 100)
        if (self.lightSelection == 1):
            self.light.setPos(0, -600, 200)
            self.light.lookAt(0, -10, 0)
            self.light.node().getLens().setNearFar(10, 1000)

    def shaderSupported(self):
        return ape.base().win.getGsg().getSupportsBasicShaders() and \
               ape.base().win.getGsg().getSupportsDepthTexture() and \
               ape.base().win.getGsg().getSupportsShadowFilter()
class World(DirectObject):
    def __init__(self):
        # Preliminary capabilities check.

        if not ape.base().win.getGsg().getSupportsBasicShaders():
            self.t = addTitle(
                "Shadow Demo: Video driver reports that shaders are not supported."
            )
            return
        if not ape.base().win.getGsg().getSupportsDepthTexture():
            self.t = addTitle(
                "Shadow Demo: Video driver reports that depth textures are not supported."
            )
            return

        # creating the offscreen buffer.

        winprops = p3dc.WindowProperties(size=(512, 512))
        props = p3dc.FrameBufferProperties()
        props.setRgbColor(1)
        props.setAlphaBits(1)
        props.setDepthBits(1)
        LBuffer = ape.base().graphicsEngine.makeOutput(
            ape.base().pipe, "offscreen buffer", -2, props, winprops,
            p3dc.GraphicsPipe.BFRefuseWindow,
            ape.base().win.getGsg(),
            ape.base().win)
        self.buffer = LBuffer

        if not LBuffer:
            self.t = addTitle(
                "Shadow Demo: Video driver cannot create an offscreen buffer.")
            return

        Ldepthmap = p3dc.Texture()
        LBuffer.addRenderTexture(Ldepthmap, p3dc.GraphicsOutput.RTMBindOrCopy,
                                 p3dc.GraphicsOutput.RTPDepthStencil)
        if ape.base().win.getGsg().getSupportsShadowFilter():
            Ldepthmap.setMinfilter(p3dc.Texture.FTShadow)
            Ldepthmap.setMagfilter(p3dc.Texture.FTShadow)

        # Adding a color texture is totally unnecessary, but it helps with
        # debugging.
        Lcolormap = p3dc.Texture()
        LBuffer.addRenderTexture(Lcolormap, p3dc.GraphicsOutput.RTMBindOrCopy,
                                 p3dc.GraphicsOutput.RTPColor)

        self.inst_p = addInstructions(0.06,
                                      'P : stop/start the Panda Rotation')
        self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle')
        self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot')
        self.inst_l = addInstructions(0.24,
                                      'L : move light source far or close')
        self.inst_v = addInstructions(0.30,
                                      'V : View the Depth-Texture results')
        self.inst_u = addInstructions(0.36,
                                      'U : toggle updating the shadow map')
        self.inst_x = addInstructions(
            0.42, 'Left/Right Arrow : switch camera angles')
        self.inst_a = addInstructions(0.48,
                                      'Something about A/Z and push bias')

        ape.base().setBackgroundColor(0, 0, 0.2, 1)

        ape.base().camLens.setNearFar(1.0, 10000)
        ape.base().camLens.setFov(75)
        ape.base().disableMouse()

        # Load the scene.

        floorTex = ape.loader().loadTexture('maps/envir-ground.jpg')
        cm = p3dc.CardMaker('')
        cm.setFrame(-2, 2, -2, 2)
        floor = ape.render().attachNewNode(p3dc.PandaNode("floor"))
        for y in range(12):
            for x in range(12):
                nn = floor.attachNewNode(cm.generate())
                nn.setP(-90)
                nn.setPos((x - 6) * 4, (y - 6) * 4, 0)
        floor.setTexture(floorTex)
        floor.flattenStrong()

        self.pandaAxis = ape.render().attachNewNode('panda axis')
        self.pandaModel = Actor('panda-model', {'walk': 'panda-walk4'})
        self.pandaModel.reparentTo(self.pandaAxis)
        self.pandaModel.setPos(9, 0, 0)
        self.pandaModel.setShaderInput("scale", (0.01, 0.01, 0.01, 1.0))
        self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8)
        self.pandaWalk.loop()
        self.pandaMovement = self.pandaAxis.hprInterval(
            20.0, p3dc.LPoint3(-360, 0, 0), startHpr=p3dc.LPoint3(0, 0, 0))
        self.pandaMovement.loop()

        self.teapot = ape.loader().loadModel('teapot')
        self.teapot.reparentTo(ape.render())
        self.teapot.setPos(0, -20, 10)
        self.teapot.setShaderInput("texDisable", (1, 1, 1, 1))
        self.teapotMovement = self.teapot.hprInterval(
            50, p3dc.LPoint3(0, 360, 360))
        self.teapotMovement.loop()

        self.accept('escape', sys.exit)

        self.accept("arrow_left", self.incrementCameraPosition, [-1])
        self.accept("arrow_right", self.incrementCameraPosition, [1])
        self.accept("p", self.toggleInterval, [self.pandaMovement])
        self.accept("t", self.toggleInterval, [self.teapotMovement])
        self.accept("w", self.toggleInterval, [self.pandaWalk])
        self.accept("v", ape.base().bufferViewer.toggleEnable)
        self.accept("u", self.toggleUpdateShadowMap)
        self.accept("l", self.incrementLightPosition, [1])
        self.accept("o", ape.base().oobe)
        self.accept('a', self.adjustPushBias, [1.1])
        self.accept('z', self.adjustPushBias, [0.9])

        self.LCam = ape.base().makeCamera(LBuffer)
        self.LCam.node().setScene(ape.render())
        self.LCam.node().getLens().setFov(40)
        self.LCam.node().getLens().setNearFar(10, 100)

        # default values
        self.pushBias = 0.04
        self.ambient = 0.2
        self.cameraSelection = 0
        self.lightSelection = 0

        # setting up shader
        ape.render().setShaderInput('light', self.LCam)
        ape.render().setShaderInput('Ldepthmap', Ldepthmap)
        ape.render().setShaderInput('ambient', (self.ambient, 0, 0, 1.0))
        ape.render().setShaderInput('texDisable', (0, 0, 0, 0))
        ape.render().setShaderInput('scale', (1, 1, 1, 1))

        # Put a shader on the Light camera.
        lci = p3dc.NodePath(p3dc.PandaNode("Light Camera Initializer"))
        lci.setShader(ape.loader().loadShader('shadows_caster.sha'))
        self.LCam.node().setInitialState(lci.getState())

        # Put a shader on the Main camera.
        # Some video cards have special hardware for shadow maps.
        # If the card has that, use it.  If not, use a different
        # shader that does not require hardware support.

        mci = p3dc.NodePath(p3dc.PandaNode("Main Camera Initializer"))
        if ape.base().win.getGsg().getSupportsShadowFilter():
            mci.setShader(ape.loader().loadShader('shadows_shadow.sha'))
        else:
            mci.setShader(
                ape.loader().loadShader('shadows_shadow-nosupport.sha'))
        ape.base().cam.node().setInitialState(mci.getState())

        self.incrementCameraPosition(0)
        self.incrementLightPosition(0)
        self.adjustPushBias(1.0)

    def toggleInterval(self, ival):
        if ival.isPlaying():
            ival.pause()
        else:
            ival.resume()

    def toggleUpdateShadowMap(self):
        self.buffer.active = not self.buffer.active

    def incrementCameraPosition(self, n):
        self.cameraSelection = (self.cameraSelection + n) % 6
        if (self.cameraSelection == 0):
            ape.base().cam.reparentTo(ape.render())
            ape.base().cam.setPos(30, -45, 26)
            ape.base().cam.lookAt(0, 0, 0)
            self.LCam.node().hideFrustum()
        if (self.cameraSelection == 1):
            ape.base().cam.reparentTo(self.pandaModel)
            ape.base().cam.setPos(7, -3, 9)
            ape.base().cam.lookAt(0, 0, 0)
            self.LCam.node().hideFrustum()
        if (self.cameraSelection == 2):
            ape.base().cam.reparentTo(self.pandaModel)
            ape.base().cam.setPos(-7, -3, 9)
            ape.base().cam.lookAt(0, 0, 0)
            self.LCam.node().hideFrustum()
        if (self.cameraSelection == 3):
            ape.base().cam.reparentTo(ape.render())
            ape.base().cam.setPos(7, -23, 12)
            ape.base().cam.lookAt(self.teapot)
            self.LCam.node().hideFrustum()
        if (self.cameraSelection == 4):
            ape.base().cam.reparentTo(ape.render())
            ape.base().cam.setPos(-7, -23, 12)
            ape.base().cam.lookAt(self.teapot)
            self.LCam.node().hideFrustum()
        if (self.cameraSelection == 5):
            ape.base().cam.reparentTo(ape.render())
            ape.base().cam.setPos(1000, 0, 195)
            ape.base().cam.lookAt(0, 0, 0)
            self.LCam.node().showFrustum()

    def incrementLightPosition(self, n):
        self.lightSelection = (self.lightSelection + n) % 2
        if (self.lightSelection == 0):
            self.LCam.setPos(0, -40, 25)
            self.LCam.lookAt(0, -10, 0)
            self.LCam.node().getLens().setNearFar(10, 100)
        if (self.lightSelection == 1):
            self.LCam.setPos(0, -600, 200)
            self.LCam.lookAt(0, -10, 0)
            self.LCam.node().getLens().setNearFar(10, 1000)

    def shaderSupported(self):
        return ape.base().win.getGsg().getSupportsBasicShaders() and \
               ape.base().win.getGsg().getSupportsDepthTexture() and \
               ape.base().win.getGsg().getSupportsShadowFilter()

    def adjustPushBias(self, inc):
        self.pushBias *= inc
        self.inst_a.setText('A/Z: Increase/Decrease the Push-Bias [%F]' %
                            self.pushBias)
        ape.render().setShaderInput('push', self.pushBias)
Beispiel #32
0
class SimpleWeapon:
    """Provides a simple weapon system - not very sophisticaed, but good enough to test shooting things."""
    def __init__(self, manager, xml):
        self.gunView = render.attachNewNode('gun-view')
        self.ray = None

        self.reload(manager, xml)

    def destroy(self):
        self.gunView.removeNode()

        if self.ray != None:
            self.ray.destroy()

    def reload(self, manager, xml):
        # Get the path to load weapons from...
        basePath = manager.get('paths').getConfig().find('weapons').get('path')

        # Variables to manage the firing state (Used G36 as reference for defaults.)...
        bullet = xml.find('bullet')
        if bullet != None:
            self.bulletRate = float(bullet.get('rate', 1.0 / 12.5))
            self.bulletSpeed = float(bullet.get('speed', 920.0))
            self.bulletWeight = float(bullet.get('mass', 0.004))
        else:
            self.bulletRate = 1.0 / 12.5
            self.bulletSpeed = 920.0
            self.bulletWeight = 0.004

        # Determine the weapon meshes path...
        self.meshPath = posixpath.join(basePath, xml.find('egg').get('file'))

        # Get the camera interface, so we can zoom in when the player aims...
        self.camera = manager.get(xml.find('camera').get('plugin'))

        # Create our gun node - both the gun and the ray used for shooting track this - allows for gun jitter, kick back etc...
        parent = xml.find('parent')
        self.gunView.reparentTo(
            manager.get(parent.get('plugin')).getNode(parent.get('node')))

        # Create a ray cast to detect what the player is looking at... and what will be shot...
        self.space = manager.get('ode').getSpace()

        if self.ray != None:
            self.ray.destroy()

        self.ray = OdeRayGeom(100.0)
        self.ray.setCategoryBits(BitMask32(0xfffffffe))
        self.ray.setCollideBits(BitMask32(0xfffffffe))

        # Get all the stuff we need to do the muzzle flash particle effect...
        flash = xml.find('muzzle_flash')
        self.flashManager = manager.get(flash.get('plugin'))
        self.flashEffect = flash.get('effect')
        self.flashBone = flash.get(
            'bone')  # Will be swapped out for the actual node latter.
        self.flashPos = csp.getPos(flash.get('pos'))

        # Get all the stuff we need to do the bullet hit sparks effect...
        sparks = xml.find('sparks')
        self.sparksManager = manager.get(sparks.get('plugin'))
        self.sparksEffect = sparks.get('effect')

        # Create a quaternion that rotates +ve z to +ve y - used to point it in the weapon direction rather than up...
        self.zToY = Quat()
        self.zToY.setFromAxisAngle(-90.0, Vec3(1.0, 0.0, 0.0))

        # State for the animation...
        self.state = False  # False==casual, True==aim.
        self.nextState = False

        # Firing state...
        self.firing = False  # True if the trigger is being held.
        self.triggerTime = 0.0  # How long the trigger has been held for, so we know when to eject ammo.

        # For bullet holes
        bh = xml.find('bullet_holes')
        if bh != None:
            self.bulletHoles = manager.get(bh.get('plugin'))
        else:
            self.bulletHoles = None

    def postInit(self):
        for i in self.postReload():
            yield i

    def postReload(self):
        # Load the actor...
        self.mesh = Actor(self.meshPath)
        yield

        # Shader generator makes it shiny, plus we need it in the right places in the render graph...
        self.mesh.setShaderAuto()
        self.mesh.reparentTo(self.gunView)
        self.mesh.hide()
        yield

        # Set its animation going... except we pause it until needed...
        self.nextAni()
        self.interval.pause()

        # Gun flash requires an exposed bone...
        self.flashBone = self.mesh.exposeJoint(None, "modelRoot",
                                               self.flashBone)
        yield

    def gunControl(self, task):
        # Update the gun direction ray to follow the players view...
        self.ray.setPosition(self.gunView.getPos(render))
        self.ray.setQuaternion(self.zToY.multiply(
            self.gunView.getQuat(render)))

        # If the gun is firing update the trigger time, if a bullet is ejected do the maths...
        if self.firing:
            dt = globalClock.getDt()
            self.triggerTime += dt
            while self.triggerTime > self.bulletRate:
                self.triggerTime -= self.bulletRate
                hit, pos, norm = ray_cast.nearestHit(self.space, self.ray)

                # Create a muzzle flash effect...
                self.flashManager.doEffect(self.flashEffect, self.flashBone,
                                           True, self.flashPos)

                if hit:
                    # Create an impact sparks effect...
                    # Calculate the reflection direction...
                    rd = self.ray.getDirection()
                    sparkDir = (norm * (2.0 * norm.dot(rd))) - rd

                    # Convert the reflection direction into a quaternion that will rotate +ve z to the required direction...
                    try:
                        ang = -math.acos(sparkDir[2])
                    except:
                        print 'Angle problem', sparkDir
                        ang = 0.0
                    axis = Vec3(0.0, 0.0, 1.0).cross(sparkDir)
                    axis.normalize()
                    sparkQuat = Quat()
                    sparkQuat.setFromAxisAngleRad(ang, axis)

                    # Set it going...
                    self.sparksManager.doEffect(self.sparksEffect, render,
                                                False, pos, sparkQuat)

                    # Make a bullet hole
                    if hit.hasBody() and isinstance(hit.getBody().getData(),
                                                    NodePath):
                        self.bulletHoles.makeNew(pos, norm,
                                                 hit.getBody().getData())
                    else:
                        self.bulletHoles.makeNew(pos, norm, None)

                # Impart some energy on the object...
                if hit and hit.hasBody():
                    body = hit.getBody()

                    # Calculate the force required to supply the energy the bullet contains to the body...
                    force = self.bulletWeight * self.bulletSpeed / 0.05

                    # Get the direction of travel of the bullet, multiply by force...
                    d = self.ray.getDirection()
                    d *= force

                    # If the object is asleep awaken it...
                    if not body.isEnabled():
                        body.enable()

                    # Add the force to the object...
                    body.addForceAtPos(d, pos)

        return task.cont

    def start(self):
        # Make the gun visible...
        self.mesh.show()

        # Set the gun animation going...
        self.interval.finish()

        # Weapon task - this primarily makes it shoot...
        self.task = taskMgr.add(self.gunControl, 'GunControl')

    def stop(self):
        self.interval.pause()
        self.mesh.hide()
        taskMgr.remove(self.task)

    def nextAni(self):
        self.state = self.nextState
        if self.state:
            ani = random.choice(
                ('aim_wiggle_a', 'aim_wiggle_b', 'aim_wiggle_c'))
        else:
            ani = random.choice(
                ('casual_wiggle_a', 'casual_wiggle_b', 'casual_wiggle_c'))
        self.mesh.pose(ani, 0)
        self.interval = Sequence(self.mesh.actorInterval(ani),
                                 Func(self.nextAni))
        self.interval.start()

    def setAiming(self, s):
        if self.nextState != s:
            self.interval.pause()
            self.nextState = s
            self.camera.setZoomed(s)

            def wib():
                self.interval.finish()

            if s: ani = 'casual_aim'
            else: ani = 'aim_casual'
            transition = Sequence(self.mesh.actorInterval(ani), Func(wib))
            transition.start()

    def setFiring(self, s):
        self.firing = s
        if self.firing:
            self.triggerTime = 0.0
Beispiel #33
0
class Golem(FSM, DirectObject):
    def __init__(self):
        FSM.__init__(self, "FSM-Golem")
        random.seed()
        self.golem = loader.loadModel("Golem")
        self.golem = Actor(
            "Golem", {
                "Idle": "Golem-Idle",
                "Walk": "Golem-Walk",
                "Attack": "Golem-Attack",
                "Destroyed": "Golem-Destroyed"
            })
        self.golem.setBlend(frameBlend=True)
        golemViewSphere = CollisionSphere(0, 0, 0.5, 6)
        golemViewSphere.setTangible(False)
        golemViewColNP = self.golem.attachNewNode(
            CollisionNode('golemViewField'))
        golemViewColNP.node().addSolid(golemViewSphere)
        golemHitSphere = CollisionSphere(0, 0, 0.5, 1)
        golemHitColNP = self.golem.attachNewNode(
            CollisionNode('golemHitField'))
        golemHitColNP.node().addSolid(golemHitSphere)

        # a collision segment to check attacks
        self.attackCheckSegment = CollisionSegment(0, 0, 1, 0, -1.3, 1)
        self.golemAttackRay = self.golem.attachNewNode(
            CollisionNode("golemAttackCollision"))
        self.golemAttackRay.node().addSolid(self.attackCheckSegment)
        self.golemAttackRay.node().setIntoCollideMask(0)
        self.attackqueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.golemAttackRay, self.attackqueue)

        attackAnim = self.golem.actorInterval("Attack", playRate=2)
        self.AttackSeq = Parallel(attackAnim,
                                  Sequence(Wait(0.5), Func(self.ceckAttack)))

        self.lookatFloater = NodePath(PandaNode("golemTracker"))
        self.lookatFloater.setPos(self.golem, 0, 0, 3.4)
        self.lookatFloater.hide()
        self.lookatFloater.reparentTo(render)
        self.trackerObject = loader.loadModel("misc/Pointlight")
        self.trackerObject.setColor(0, 1, 0)
        self.trackerObject.setScale(0.25)
        self.trackerObject.reparentTo(self.lookatFloater)

    def start(self, startPos):
        self.golem.setPos(startPos.getPos())
        self.golem.setHpr(startPos.getHpr())
        self.golem.reparentTo(render)
        self.trackedEnemy = None
        self.health = 5
        self.accept(
            "playerCollision-in-golemViewField", lambda extraArgs: base.
            messenger.send("golemSeesPlayer", [self.golem]))

    def stop(self):
        self.trackedEnemy = None
        taskMgr.remove("GolemAI_task")
        self.golem.hide()
        self.ignoreAll()

    def cleanup(self):
        self.stop()
        self.lookatFloater.removeNode()
        self.golem.cleanup()
        self.golem.removeNode()

    def activate(self, trackedEnemy):
        self.trackedEnemy = trackedEnemy
        taskMgr.add(self.aiTask, "GolemAI_task")
        self.lookatFloater.show()

    def aiTask(self, task):
        dt = globalClock.getDt()
        if self.AttackSeq.isPlaying(): return task.cont

        self.lookatFloater.setPos(self.golem, 0, 0, 3.4)
        self.lookatFloater.lookAt(self.trackedEnemy)
        self.lookatFloater.setH(self.lookatFloater.getH() + 180)
        self.lookatFloater.setP(0)
        self.lookatFloater.setR(0)

        self.golem.lookAt(self.trackedEnemy)
        self.golem.setH(self.golem.getH() + 180)

        distanceVec = self.golem.getPos() - self.trackedEnemy.getPos()
        enemyDist = distanceVec.length()

        if enemyDist < 2.0:
            # close enough for combat
            action = random.choice(["Attack", "Idle"])
            if action == "Attack":
                self.request("Attack")
            else:
                if self.state != "Idle":
                    self.request("Idle")
        else:
            self.golem.setY(self.golem, -0.5 * dt)
            if self.state != "Walk":
                self.request("Walk")

        return task.cont

    def hit(self):
        hitInterval = Sequence(Func(self.golem.setColorScale, 1, 0, 0, 0.75),
                               Wait(0.15), Func(self.golem.clearColorScale),
                               Wait(0.15),
                               Func(self.golem.setColorScale, 1, 0, 0, 0.75),
                               Wait(0.15), Func(self.golem.clearColorScale),
                               Wait(0.15),
                               Func(self.golem.setColorScale, 1, 0, 0, 0.75),
                               Wait(0.15), Func(self.golem.clearColorScale),
                               Wait(0.15),
                               Func(self.golem.setColorScale, 1, 0, 0, 0.75),
                               Wait(0.15), Func(self.golem.clearColorScale),
                               Wait(0.15))
        self.health -= 1
        if self.health == 4:
            self.trackerObject.setColor(0, 1, 0)
            hitInterval.start()
        elif self.health == 3:
            self.trackerObject.setColor(0.25, 0.75, 0)
            hitInterval.start()
        elif self.health == 2:
            self.trackerObject.setColor(0.5, .5, 0)
            hitInterval.start()
        elif self.health == 1:
            self.trackerObject.setColor(0.75, 0.25, 0)
            hitInterval.start()
        elif self.health == 0:
            self.trackerObject.setColor(0, 0, 0)
            self.request("Destroyed")

    def ceckAttack(self):
        for i in range(self.attackqueue.getNumEntries()):
            entry = self.attackqueue.getEntry(i)
            into = entry.getIntoNode()
            if "playerCollision" in into.getName():
                if random.random() > .5:
                    base.messenger.send("HitPlayer")

    def enterIdle(self):
        self.golem.loop("Idle")

    def enterWalk(self):
        self.golem.setPlayRate(2, "Walk")
        self.golem.loop("Walk")

    def enterAttack(self):
        self.AttackSeq.start()

    def enterDestroyed(self):
        self.ignoreAll()
        taskMgr.remove("GolemAI_task")
        self.AttackSeq.finish()
        self.golem.play("Destroyed")
        self.lookatFloater.hide()
        base.messenger.send("GolemDestroyed")