Пример #1
0
    def set_controls(self):
        """Configure common game controls.

        Configure major keys, collisions system
        and controls to manipulate characters.
        """
        base.accept("f1", self._show_keys)  # noqa: F821
        base.accept("escape", base.main_menu.show)  # noqa: F821
        base.accept("r", self._show_char_relations)  # noqa: F821
        base.accept("m", base.world.rails_scheme.show)  # noqa: F821
        base.accept("j", base.journal.show)  # noqa: F821

        # configure mouse collisions
        col_node = CollisionNode("mouse_ray")
        col_node.setIntoCollideMask(NO_MASK)
        col_node.setFromCollideMask(MOUSE_MASK)
        self._mouse_ray = CollisionRay()
        col_node.addSolid(self._mouse_ray)

        # set common collisions handler
        handler = CollisionHandlerEvent()
        handler.addInPattern("%fn-into")
        handler.addAgainPattern("%fn-again")
        handler.addOutPattern("%fn-out")

        self.traverser = CollisionTraverser("traverser")
        self.traverser.addCollider(
            base.cam.attachNewNode(col_node), handler  # noqa: F821
        )
        self.set_mouse_events()

        taskMgr.doMethodLater(0.03, self._collide_mouse, "collide_mouse")  # noqa: F821
        taskMgr.doMethodLater(0.04, self._traverse, name="main_traverse")  # noqa: F821
Пример #2
0
class CollisionBase(ShowBase):
    def __init__(self):
        self.cTrav = CollisionTraverser()
        self.mchandler = CollisionHandlerEvent()
        self.mchandler.addInPattern('into-%in')
        self.mchandler.addAgainPattern('%fn-again-%in')
        self.mchandler.addOutPattern('out-%in')
Пример #3
0
 def __init__(self, model = "cube_nocol", texture = "lava", pos = (0,0,0), scale = (1,1,1), cubetype = "A"):
     super(LavaCube, self).__init__(model, texture, pos, scale)
     cn = CollisionNode('lava')
     cn.setFromCollideMask(COLLISIONMASKS['lava'])
     cn.setIntoCollideMask(BitMask32.allOff())
     np = self.node.attachNewNode(cn)
     cn.addSolid(CollisionSphere(0,0,0,1.1))
     h = CollisionHandlerEvent()
     h.addInPattern('%fn-into-%in')
     h.addOutPattern('%fn-outof-%in')
     base.cTrav.addCollider(np, h)
 def __initCollisions(self):
     collSphere = CollisionSphere(0, 0, 0, Globals.PlayerCollisionRadius)
     collSphere.setTangible(0)
     self.mazeCollisionName = Globals.LocalPlayerCollisionName
     collNode = CollisionNode(self.mazeCollisionName)
     collNode.addSolid(collSphere)
     collNodePath = self.toon.attachNewNode(collNode)
     collNodePath.hide()
     handler = CollisionHandlerEvent()
     handler.addInPattern('%fn-into-%in')
     base.cTrav.addCollider(collNodePath, handler)
     self.handler = handler
     self._collNodePath = collNodePath
Пример #5
0
 def __init__(self, model = "models/sphere", texture = "exit", pos = (0,0,0), scale = (1,1,1), cubetype = "A"):
     super(LevelExit, self).__init__(model, texture, pos, scale)
     #self.node.setTransparency(TransparencyAttrib.MAlpha)
     self.node.setTag('noportals', '1')
     self.node.setTag('isexit', '1')
     cn = CollisionNode('levelExit')
     cn.setFromCollideMask(COLLISIONMASKS['exit'])
     cn.setIntoCollideMask(BitMask32.allOff())
     np = self.node.attachNewNode(cn)
     cn.addSolid(CollisionSphere(0,0,0,1.1))
     h = CollisionHandlerEvent()
     h.addInPattern('%fn-into-%in')
     h.addOutPattern('%fn-outof-%in')
     base.cTrav.addCollider(np, h)
Пример #6
0
class SmartCar(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        # Override defaults
        self.disableMouse()
        self.setBackgroundColor(VBase3(160, 200, 150) / 255.0)
        self.setFrameRateMeter(True)

        # Lights
        dlight = DirectionalLight("dlight")
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(180.0, -70.0, 0)
        self.render.setLight(dlnp)

        alight = AmbientLight("alight")
        alnp = self.render.attachNewNode(alight)
        alight.setColor(VBase4(0.4, 0.4, 0.4, 1))
        self.render.setLight(alnp)

        # Collision traverser
        self.cTrav = CollisionTraverser("collisionTraverser")

        # Collision handlers
        self.carCollisionHandler = CollisionHandlerEvent()
        self.carCollisionHandler.addInPattern("%fn-into-%in")

        # Camera controls
        self.cameraController = CameraController(self, 400, math.pi / 4.0, math.pi / 4.0)

        # Load the track
        self.track = self.loader.loadModel("models/trackValencia")
        checkpointsCollision = self.track.find("checkpoints").node()
        checkpointsCollision.setIntoCollideMask(BitMask32(0xF0))
        self.numCheckpoints = checkpointsCollision.getNumSolids()
        self.track.reparentTo(self.render)

        # Load the car
        self.car = NeuralNetworkCar(self)
        self.cameraController.follow(self.car.getNodePath())

        # Reposition the car
        # self.car.getNodePath().setH(180.0)

        # Register car collisions with track
        self.cTrav.addCollider(self.car.carCollider, self.carCollisionHandler)
        self.accept("carCollider-into-trackCollision", self.car.onCrash)
        self.accept("carCollider-into-checkpoints", self.car.onCheckpoint)
Пример #7
0
 def createPortalCollisions(self):
     # Enter the portals
     cn = CollisionNode('bluePortal')
     cn.setFromCollideMask(COLLISIONMASKS['portals'])
     cn.setIntoCollideMask(BitMask32.allOff())
     np = self.bluePortal.attachNewNode(cn)
     cn.addSolid(CollisionSphere(0,0,0,2))
     h = CollisionHandlerEvent()
     h.addInPattern('%fn-into-%in')
     h.addOutPattern('%fn-outof-%in')
     self.base.cTrav.addCollider(np, h)
     cn = CollisionNode('orangePortal')
     cn.setFromCollideMask(COLLISIONMASKS['portals'])
     cn.setIntoCollideMask(BitMask32.allOff())
     np = self.orangePortal.attachNewNode(cn)
     cn.addSolid(CollisionSphere(0,0,0,2))
     h = CollisionHandlerEvent()
     h.addInPattern('%fn-into-%in')
     h.addOutPattern('%fn-outof-%in')
     self.base.cTrav.addCollider(np, h)
Пример #8
0
class Pickup(DirectObject):

    #Creates health pickup object
    def __init__(self, idappend, spawn):
        
        self.id = "pick"+str(idappend)
        self.deletePickup = False          
        self.projectileNode = NodePath('heal'+str(self.id))

        self.projectileNode.setScale(1)
        self.projectileModel = loader.loadModel("./resources/healthPickup.egg")
        self.projectileModel.setColorScale(200, 0, 0, 100)
        self.projectileModel.reparentTo(self.projectileNode)
        self.projectileNode.reparentTo(render)
        self.projectileNode.setPos(spawn)
        cs = CollisionSphere(0, 0, 0, .5)
        cnode = CollisionNode('heal')
        self.colNode = self.projectileModel.attachNewNode(cnode)
        self.colNode.node().addSolid(cs)
        self.collHand = CollisionHandlerEvent()
        self.collHand.addInPattern('pickupin'+str(self.id))
        self.collHand.addOutPattern('oot')
        base.cTrav.addCollider(self.colNode, self.collHand)
        self.accept('pickupin'+str(self.id), self.pickup)
   
    #Detects if the player has picked up the health
    def pickup(self, col):
        
        if col.getIntoNodePath().getName() == "cnode":

            messenger.send("pickuphealth")
            self.deletePickup = True

    #Destroys the health pickups from the scene graph
    def destroy(self):

        self.projectileNode.removeNode()
        self.projectileModel.removeNode()
        self.colNode.node().clearSolids()
        
        del self
class DonkeyKong(ShowBase):
    def __init__(self):
        super().__init__(self)
        self.angle = 0
        self.taskMgr.add(self.setup, "setup")
        self.taskMgr.add(self.update, "update")

        self.scene = self.loader.loadModel('models/DKSet')
        self.scene.reparentTo(self.render)

        self.arcadeTexture = self.loader.loadTexture('models/dk-arcade.png')
        self.scene.setTexture(self.arcadeTexture)
        self.scene.setTransparency(1)

        self.blocksTexture = self.loader.loadTexture('models/block.png')
        self.stairsTexture = self.loader.loadTexture('models/stairs.png')

        #messenger.toggleVerbose()

    def setup(self, task):
        lens = OrthographicLens()
        lens.setFilmSize(25, 20)
        base.camNode.setLens(lens)

        self.player = self.scene.attachNewNode("Player")

        self.marioGfx = self.scene.find('root/mario')
        self.marioGfx.reparentTo(self.player)

        self.jumpAvailable = False
        self.gravity = -.5
        self.verticalTime = 0
        self.v0 = 0
        self.floorZ = 0
        self.onStairs = False
        self.jumpCounter = 1
        # input setup

        self.input = {
            'up': False,
            'down': False,
            'left': False,
            'right': False,
            'space': False
        }

        key_list = ['up', 'down', 'left', 'right']
        for k in key_list:
            self.accept(f'raw-arrow_{k}', self.buildPress(k))
            self.accept(f'raw-arrow_{k}-up', self.buildRelease(k))

        self.accept(f'raw-space', self.buildPress('space'))
        self.accept(f'raw-space-up', self.buildRelease('space'))

        # collision set up
        base.cTrav = CollisionTraverser()
        self.collisionHandlerEvent = CollisionHandlerEvent()
        self.collisionHandlerEvent.addInPattern('into-%in')
        self.collisionHandlerEvent.addOutPattern('outof-%in')

        ray = CollisionSegment(0, 0, 0, 0, 0, -.6)
        cNodePath = self.player.attachNewNode(CollisionNode('marioRay'))
        cNodePath.node().addSolid(ray)
        cNodePath.node().setIntoCollideMask(0x03)
        cNodePath.node().setFromCollideMask(0x03)
        cNodePath.show()
        base.cTrav.addCollider(cNodePath, self.collisionHandlerEvent)

        self.floor1 = self.createSquareCollider(-1.8, -5.5, 9.3, .5, 'floor0',
                                                'floor1HitBox', 'Floor1',
                                                self.enableJump,
                                                self.disableJump,
                                                self.blocksTexture, 0x1)
        self.floor2 = self.createSquareCollider(2.08, -2.5, 8.0, .5, 'floor1',
                                                'floor2HitBox', 'Floor2',
                                                self.enableJump,
                                                self.disableJump,
                                                self.blocksTexture, 0x1)
        self.floor3_1 = self.createSquareCollider(3.6, 0.5, 3.8, .5, 'floor2',
                                                  'floor3_1HitBox', 'Floor3_1',
                                                  self.enableJump,
                                                  self.disableJump,
                                                  self.blocksTexture, 0x1)
        self.floor3_2 = self.createSquareCollider(-6.3, 0.5, 5, .5, 'pCube4',
                                                  'floor3_2HitBox', 'Floor3_2',
                                                  self.enableJump,
                                                  self.disableJump,
                                                  self.blocksTexture, 0x1)
        self.floor4 = self.createSquareCollider(1.8, 3.5, 8.0, .5, 'floors',
                                                'floor4HitBox', 'Floor4',
                                                self.enableJump,
                                                self.disableJump,
                                                self.blocksTexture, 0x1)

        self.topStair = self.createSquareCollider(
            -6.8, 3.5, 0.5, 2.5, 'topstair', 'topStairHitBox', 'TopStair',
            self.enableStairs, self.disableStairs, self.stairsTexture, 0x2)
        self.middleStair = self.createSquareCollider(
            -0.86, 0.1, 0.5, 2.5, 'middlestair', 'middleStairHitBox',
            'MiddleStair', self.enableStairs, self.disableStairs,
            self.stairsTexture, 0x2)
        self.bottomStair = self.createSquareCollider(
            -6.8, -2.5, 0.5, 2.5, 'bottomstair', 'bottomStairHitBox',
            'BottomStair', self.enableStairs, self.disableStairs,
            self.stairsTexture, 0x2)

        #self.createInvisibleSquareCollider(0,0,8,3,"NewCollision","NewNode")
        #self.createInvisibleSquareCollider(-6,0,4,5,"NewCollisio2","NewNode2")
        base.cTrav.showCollisions(self.render)

        # self.player.setPos(3,0,-3.5)
        self.player.setPos(-8, 0, -1.5)
        return Task.done

    def enableJump(self, evt):
        print(f'IN----> {evt}')
        self.floorZ = evt.getIntoNodePath().node().getParent(
            0).getTransform().getPos().z + 1
        self.jumpAvailable = True

    def disableJump(self, evt):
        print(f'Out----> {evt}')
        self.jumpAvailable = False

    def enableStairs(self, evt):
        print(f'IN----> {evt}')
        self.onStairs = True

    def disableStairs(self, evt):
        print(f'Out----> {evt}')
        self.onStairs = False

    def createSquareCollider(self, px, pz, w, h, modelName, collisionNodeName,
                             nodeName, intoFunction, outFunction, texture,
                             mask):
        obj = self.scene.attachNewNode(nodeName)
        hitBox = CollisionBox(Point3(0, 0, 0), w, 5, h)
        cNodePath = obj.attachNewNode(CollisionNode(collisionNodeName))
        cNodePath.node().addSolid(hitBox)
        cNodePath.node().setIntoCollideMask(mask)
        cNodePath.node().setFromCollideMask(mask)
        #cNodePath.show()
        base.cTrav.addCollider(cNodePath, self.collisionHandlerEvent)

        self.scene.find(f'root/{modelName}').reparentTo(obj)
        obj.setPos(px, 0, pz)
        obj.setTexture(texture)

        self.accept(f'into-{collisionNodeName}', intoFunction)
        self.accept(f'outof-{collisionNodeName}', outFunction)

        return obj

    def createInvisibleSquareCollider(self, px, pz, w, h, collisionNodeName,
                                      nodeName, mask):
        obj = self.scene.attachNewNode(nodeName)
        hitBox = CollisionBox(Point3(0, 0, 0), w, 5, h)
        cNodePath = obj.attachNewNode(CollisionNode(collisionNodeName))
        cNodePath.node().addSolid(hitBox)
        cNodePath.node().setIntoCollideMask(mask)
        cNodePath.node().setFromCollideMask(mask)
        cNodePath.show()
        base.cTrav.addCollider(cNodePath, self.collisionHandlerEvent)
        obj.setPos(px, 0, pz)

    def buildPress(self, key):
        def pressKey():
            self.input[key] = True

        return pressKey

    def buildRelease(self, key):
        def releaseKey():
            self.input[key] = False

        return releaseKey

    def applyMove(self):

        mv = Vec3(0, 0, 0)
        p = self.player.getPos()

        if (self.input["right"]):
            mv.x = -.1

        if (self.input["left"]):
            mv.x = .1
        """
        if( self.input["space"]):
            playerPos.z += .1
            
        if( self.input["down"]):
            playerPos.z -= .1
        """

        if (self.jumpAvailable and not self.onStairs):
            self.jumpCounter = 1
            self.verticalTime = 0
            self.v0 = 0
            p.z = self.floorZ
            if (self.input["space"]):
                self.v0 = .165
                self.jumpAvailable = False

        if (not self.jumpAvailable and not self.onStairs):
            self.verticalTime += globalClock.getDt()
            mv.z = self.v0 + self.gravity * self.verticalTime

        if (self.onStairs):
            self.jumpCounter = 0
            self.v0 = 0
            if (self.input["down"]):
                mv.z = -.1
            if (self.input["up"]):
                mv.z = .1

        if (not self.onStairs):
            if (not self.jumpAvailable):
                if (self.input["space"] and self.jumpCounter == 0):
                    self.v0 = .165
                    self.jumpAvailable = False
                    self.jumpCounter = 1

        p.x += mv.x
        p.z += mv.z

        self.player.setPos(p)

        # hacer que se pueda agarrar el martillo, cuando suceda : self.marioGfx.setSx(self.player  , -1)
        # self.hammer = self.createSquareCollider(6,1.5,.5,.5,'hammer','hammerHitbox', 'hammer', self.enableHammer, self.disableHammer, self.arcadeTexture, 0x02)

    def update(self, task):
        self.camera.setPos(0, 35, 0)
        self.camera.lookAt(self.scene)

        self.applyMove()

        return Task.cont
Пример #10
0
class CogdoFlyingCollisions(GravityWalker):
    wantFloorSphere = 0

    def __init__(self):
        GravityWalker.__init__(self, gravity=0.0)

    def initializeCollisions(self, collisionTraverser, avatarNodePath, avatarRadius = 1.4, floorOffset = 1.0, reach = 1.0):
        self.cHeadSphereNodePath = None
        self.cFloorEventSphereNodePath = None
        self.setupHeadSphere(avatarNodePath)
        self.setupFloorEventSphere(avatarNodePath, ToontownGlobals.FloorEventBitmask, avatarRadius)
        GravityWalker.initializeCollisions(self, collisionTraverser, avatarNodePath, avatarRadius, floorOffset, reach)
        return

    def setupWallSphere(self, bitmask, avatarRadius):
        self.avatarRadius = avatarRadius
        cSphere = CollisionSphere(0.0, 0.0, self.avatarRadius + 0.75, self.avatarRadius)
        cSphereNode = CollisionNode('Flyer.cWallSphereNode')
        cSphereNode.addSolid(cSphere)
        cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
        cSphereNode.setFromCollideMask(bitmask)
        cSphereNode.setIntoCollideMask(BitMask32.allOff())
        if config.GetBool('want-fluid-pusher', 0):
            self.pusher = CollisionHandlerFluidPusher()
        else:
            self.pusher = CollisionHandlerPusher()
        self.pusher.addCollider(cSphereNodePath, self.avatarNodePath)
        self.cWallSphereNodePath = cSphereNodePath

    def setupEventSphere(self, bitmask, avatarRadius):
        self.avatarRadius = avatarRadius
        cSphere = CollisionSphere(0.0, 0.0, self.avatarRadius + 0.75, self.avatarRadius * 1.04)
        cSphere.setTangible(0)
        cSphereNode = CollisionNode('Flyer.cEventSphereNode')
        cSphereNode.addSolid(cSphere)
        cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
        cSphereNode.setFromCollideMask(bitmask)
        cSphereNode.setIntoCollideMask(BitMask32.allOff())
        self.event = CollisionHandlerEvent()
        self.event.addInPattern('enter%in')
        self.event.addOutPattern('exit%in')
        self.cEventSphereNodePath = cSphereNodePath

    def setupRay(self, bitmask, floorOffset, reach):
        cRay = CollisionRay(0.0, 0.0, 3.0, 0.0, 0.0, -1.0)
        cRayNode = CollisionNode('Flyer.cRayNode')
        cRayNode.addSolid(cRay)
        self.cRayNodePath = self.avatarNodePath.attachNewNode(cRayNode)
        cRayNode.setFromCollideMask(bitmask)
        cRayNode.setIntoCollideMask(BitMask32.allOff())
        self.lifter = CollisionHandlerGravity()
        self.lifter.setLegacyMode(self._legacyLifter)
        self.lifter.setGravity(self.getGravity(0))
        self.lifter.addInPattern('%fn-enter-%in')
        self.lifter.addAgainPattern('%fn-again-%in')
        self.lifter.addOutPattern('%fn-exit-%in')
        self.lifter.setOffset(floorOffset)
        self.lifter.setReach(reach)
        self.lifter.addCollider(self.cRayNodePath, self.avatarNodePath)

    def setupHeadSphere(self, avatarNodePath):
        collSphere = CollisionSphere(0, 0, 0, 1)
        collSphere.setTangible(1)
        collNode = CollisionNode('Flyer.cHeadCollSphere')
        collNode.setFromCollideMask(ToontownGlobals.CeilingBitmask)
        collNode.setIntoCollideMask(BitMask32.allOff())
        collNode.addSolid(collSphere)
        self.cHeadSphereNodePath = avatarNodePath.attachNewNode(collNode)
        self.cHeadSphereNodePath.setZ(base.localAvatar.getHeight() + 1.0)
        self.headCollisionEvent = CollisionHandlerEvent()
        self.headCollisionEvent.addInPattern('%fn-enter-%in')
        self.headCollisionEvent.addOutPattern('%fn-exit-%in')
        base.cTrav.addCollider(self.cHeadSphereNodePath, self.headCollisionEvent)

    def setupFloorEventSphere(self, avatarNodePath, bitmask, avatarRadius):
        cSphere = CollisionSphere(0.0, 0.0, 0.0, 0.75)
        cSphereNode = CollisionNode('Flyer.cFloorEventSphere')
        cSphereNode.addSolid(cSphere)
        cSphereNodePath = avatarNodePath.attachNewNode(cSphereNode)
        cSphereNode.setFromCollideMask(bitmask)
        cSphereNode.setIntoCollideMask(BitMask32.allOff())
        self.floorCollisionEvent = CollisionHandlerEvent()
        self.floorCollisionEvent.addInPattern('%fn-enter-%in')
        self.floorCollisionEvent.addAgainPattern('%fn-again-%in')
        self.floorCollisionEvent.addOutPattern('%fn-exit-%in')
        base.cTrav.addCollider(cSphereNodePath, self.floorCollisionEvent)
        self.cFloorEventSphereNodePath = cSphereNodePath

    def deleteCollisions(self):
        GravityWalker.deleteCollisions(self)
        if self.cHeadSphereNodePath != None:
            base.cTrav.removeCollider(self.cHeadSphereNodePath)
            self.cHeadSphereNodePath.detachNode()
            self.cHeadSphereNodePath = None
            self.headCollisionsEvent = None
        if self.cFloorEventSphereNodePath != None:
            base.cTrav.removeCollider(self.cFloorEventSphereNodePath)
            self.cFloorEventSphereNodePath.detachNode()
            self.cFloorEventSphereNodePath = None
            self.floorCollisionEvent = None
        self.cRayNodePath.detachNode()
        del self.cRayNodePath
        self.cEventSphereNodePath.detachNode()
        del self.cEventSphereNodePath
        return

    def setCollisionsActive(self, active = 1):
        if self.collisionsActive != active:
            if self.cHeadSphereNodePath != None:
                base.cTrav.removeCollider(self.cHeadSphereNodePath)
                if active:
                    base.cTrav.addCollider(self.cHeadSphereNodePath, self.headCollisionEvent)
            if self.cFloorEventSphereNodePath != None:
                base.cTrav.removeCollider(self.cFloorEventSphereNodePath)
                if active:
                    base.cTrav.addCollider(self.cFloorEventSphereNodePath, self.floorCollisionEvent)
        GravityWalker.setCollisionsActive(self, active)
        return

    def enableAvatarControls(self):
        pass

    def disableAvatarControls(self):
        pass

    def handleAvatarControls(self, task):
        pass
Пример #11
0
class Game(DirectObject):
    def __init__(self, showbase, usersData, gameData):
        DirectObject.__init__(self)

        self.showbase = showbase
        self.usersData = usersData
        self.gameData = gameData

        random.seed(self.gameData.randSeed)

        # Initialize the collision traverser.
        self.cTrav = CollisionTraverser()

        # Initialize the handler.
        self.collHandEvent = CollisionHandlerEvent()
        self.collHandEvent.addInPattern('into-%in')

        self.world = World(showbase)

        self.ambientLight = showbase.render.attachNewNode(
            AmbientLight("ambientLight"))
        # Set the color of the ambient light
        self.ambientLight.node().setColor((.1, .1, .1, 1))
        # add the newly created light to the lightAttrib
        # showbase.render.setLight(self.ambientLight)

        self.spotlight = None

        numberOfPlayers = len(self.usersData)
        for index, user in enumerate(self.usersData):
            user.centipede = Centipede(showbase, index, numberOfPlayers,
                                       self.addToCollisions)
            if user.thisPlayer:
                self.centipede = user.centipede
                self.centipede.attachRing(showbase)

                self.spotlight = self.centipede.head.attachNewNode(
                    PointLight("playerSpotlight"))
                self.spotlight.setPos(LVector3(0, 0, 8))
                # Now we create a spotlight. Spotlights light objects in a given cone
                # They are good for simulating things like flashlights
                self.spotlight.node().setAttenuation(
                    LVector3(.025, 0.0005, 0.0001))
                self.spotlight.node().setColor((0.35, 0.35, .35, 1))
                self.spotlight.node().setSpecularColor((0.01, 0.01, 0.01, 1))

                showbase.render.setLight(self.spotlight)

        self.perPixelEnabled = True
        self.shadowsEnabled = True
        #if self.spotlight:
        #    self.spotlight.node().setShadowCaster(True, 512, 512)
        showbase.render.setShaderAuto()

        self.foods = []
        for i in range(self.gameData.maxFoods):
            self.foods.append(Food(self.showbase, i, self.addToCollisions))

    def destroy(self):
        self.ignoreAll()
        self.collHandEvent.clear()
        self.ambientLight.removeNode()
        if self.spotlight:
            self.showbase.render.clearLight(self.spotlight)
            self.spotlight.removeNode()
        self.world.destroy()
        for user in self.usersData:
            user.centipede.destroy()
        for food in self.foods:
            food.destroy()

    def runTick(self, dt, tick):
        # run each of the centipedes simulations
        for user in self.usersData:
            user.centipede.update(dt)
            headPosition = user.centipede.head.getPos()
            if abs(headPosition.x) > 123 or abs(headPosition.y) > 123:
                user.centipede.reset()
            if len(user.centipede.body) > 10:
                return False

        for food in self.foods:
            food.update(dt)

        self.cTrav.traverse(self.showbase.render)

        # Return true if game is still not over (false to end game)
        return True

    def collideInto(self, collEntry):
        print "collide into"
        fromInto = collEntry.getFromNodePath().node().getIntoCollideMask()
        intoInto = collEntry.getIntoNodePath().node().getIntoCollideMask()
        fromIntoIndex = fromInto.getLowestOnBit() - 1
        intoIntoIndex = intoInto.getLowestOnBit() - 1

        # Collision was with a Food!
        if intoIntoIndex == -1:
            # TODO: Get food better
            for food in self.foods:
                if collEntry.getIntoNodePath() == food.model.collisionNode[0]:
                    user = self.usersData[fromIntoIndex]
                    user.centipede.addLength(self.showbase)
                    food.reset()
                    print "om nommed a food"
                    return

        # Centipede eating themself
        if fromIntoIndex == intoIntoIndex:
            print "hitting self"
            user = self.usersData[fromIntoIndex]
            if len(user.centipede.body) > 2:
                if collEntry.getIntoNodePath(
                ) == user.centipede.tail.collisionNode[0]:
                    user.centipede.reset()
                    print "dieded self tail"
                    return
                for i in range(len(user.centipede.body) - 1 - 2):
                    if collEntry.getIntoNodePath() == user.centipede.body[
                            i + 2].collisionNode[0]:
                        user.centipede.reset()
                        print "dieded self body", i
                        return
        else:
            # TODO: Check for both heads
            # if bothHeads:
            # one will survive if it's angle to the other node is greater than 90degrees from straight ahead

            # Centipede eating another centipede
            crasher = self.usersData[fromIntoIndex]
            crasher.centipede.reset()

            # Give crashee a point on behalf of crasher
            crashee = self.usersData[intoIntoIndex]
            print "Player", intoIntoIndex, " gets a point!"
            # crashee.point += 1

    def addToCollisions(self, item):
        # Add this object to the traverser.
        self.cTrav.addCollider(item[0], self.collHandEvent)

        # Accept the events sent by the collisions.
        self.accept('into-' + str(item[1]), self.collideInto)
class CogdoMazeLocalPlayer(CogdoMazePlayer):
    notify = directNotify.newCategory('CogdoMazeLocalPlayer')

    def __init__(self, id, toon, game, guiMgr):
        CogdoMazePlayer.__init__(self, id, toon)
        self.disableGagCollision()
        self.game = game
        self.maze = self.game.maze
        self._guiMgr = guiMgr
        self.cameraMgr = CogdoMazeCameraManager(self.toon, self.maze, camera,
                                                render)
        self._proximityRadius = self.maze.cellWidth * Globals.CameraRemoteToonRadius
        orthoDrive = OrthoDrive(
            Globals.ToonRunSpeed,
            maxFrameMove=self.maze.cellWidth / 2,
            customCollisionCallback=self.maze.doOrthoCollisions,
            wantSound=True)
        self.orthoWalk = OrthoWalk(orthoDrive)
        self._audioMgr = base.cogdoGameAudioMgr
        self._getMemoSfx = self._audioMgr.createSfx('getMemo',
                                                    source=self.toon)
        self._waterCoolerFillSfx = self._audioMgr.createSfx('waterCoolerFill',
                                                            source=self.toon)
        self._hitByDropSfx = self._audioMgr.createSfx('toonHitByDrop',
                                                      source=self.toon)
        self._winSfx = self._audioMgr.createSfx('win')
        self._loseSfx = self._audioMgr.createSfx('lose')
        self.enabled = False
        self.pickupCount = 0
        self.numEntered = 0
        self.throwPending = False
        self.coolDownAfterHitInterval = Sequence(
            Wait(Globals.HitCooldownTime),
            Func(self.setInvulnerable, False),
            name='coolDownAfterHitInterval-%i' % self.toon.doId)
        self.invulnerable = False
        self.gagHandler = CollisionHandlerEvent()
        self.gagHandler.addInPattern('%fn-into-%in')
        self.exited = False
        self.hints = {
            'find': False,
            'throw': False,
            'squashed': False,
            'boss': False,
            'minion': False
        }
        self.accept('control', self.controlKeyPressed)

    def destroy(self):
        self.toon.showName()
        self.ignoreAll()
        self.coolDownAfterHitInterval.clearToInitial()
        del self.coolDownAfterHitInterval
        del self._getMemoSfx
        del self._waterCoolerFillSfx
        del self._hitByDropSfx
        del self._winSfx
        self.orthoWalk.stop()
        self.orthoWalk.destroy()
        del self.orthoWalk
        CogdoMazePlayer.destroy(self)

    def __initCollisions(self):
        collSphere = CollisionSphere(0, 0, 0, Globals.PlayerCollisionRadius)
        collSphere.setTangible(0)
        self.mazeCollisionName = Globals.LocalPlayerCollisionName
        collNode = CollisionNode(self.mazeCollisionName)
        collNode.addSolid(collSphere)
        collNodePath = self.toon.attachNewNode(collNode)
        collNodePath.hide()
        handler = CollisionHandlerEvent()
        handler.addInPattern('%fn-into-%in')
        base.cTrav.addCollider(collNodePath, handler)
        self.handler = handler
        self._collNodePath = collNodePath

    def clearCollisions(self):
        self.handler.clear()

    def __disableCollisions(self):
        self._collNodePath.removeNode()
        del self._collNodePath

    def _isNearPlayer(self, player):
        return self.toon.getDistance(player.toon) <= self._proximityRadius

    def update(self, dt):
        if self.getCurrentOrNextState() != 'Off':
            self._updateCamera(dt)

    def _updateCamera(self, dt):
        numPlayers = 0.0
        for player in self.game.players:
            if player != self and player.toon and self._isNearPlayer(player):
                numPlayers += 1

        d = clamp(
            Globals.CameraMinDistance + numPlayers /
            (CogdoGameConsts.MaxPlayers - 1) *
            (Globals.CameraMaxDistance - Globals.CameraMinDistance),
            Globals.CameraMinDistance, Globals.CameraMaxDistance)
        self.cameraMgr.setCameraTargetDistance(d)
        self.cameraMgr.update(dt)

    def enterOff(self):
        CogdoMazePlayer.enterOff(self)

    def exitOff(self):
        CogdoMazePlayer.exitOff(self)
        self.toon.hideName()

    def enterReady(self):
        CogdoMazePlayer.enterReady(self)
        self.cameraMgr.enable()

    def exitReady(self):
        CogdoMazePlayer.enterReady(self)

    def enterNormal(self):
        CogdoMazePlayer.enterNormal(self)
        self.orthoWalk.start()

    def exitNormal(self):
        CogdoMazePlayer.exitNormal(self)
        self.orthoWalk.stop()

    def enterHit(self, elapsedTime=0.0):
        CogdoMazePlayer.enterHit(self, elapsedTime)
        self.setInvulnerable(True)

    def exitHit(self):
        CogdoMazePlayer.exitHit(self)
        self.coolDownAfterHitInterval.clearToInitial()
        self.coolDownAfterHitInterval.start()

    def enterDone(self):
        CogdoMazePlayer.enterDone(self)
        self._guiMgr.hideQuestArrow()
        self.ignore('control')
        self._guiMgr.setMessage('')
        if self.exited == False:
            self.lostMemos()

    def exitDone(self):
        CogdoMazePlayer.exitDone(self)

    def hitByDrop(self):
        if self.equippedGag is not None and not self.hints['squashed']:
            self._guiMgr.setMessageTemporary(TTLocalizer.CogdoMazeSquashHint,
                                             Globals.HintTimeout)
            self.hints['squashed'] = True
        self._hitByDropSfx.play()
        CogdoMazePlayer.hitByDrop(self)
        return

    def equipGag(self):
        CogdoMazePlayer.equipGag(self)
        self._waterCoolerFillSfx.play()
        messenger.send(Globals.WaterCoolerHideEventName, [])
        if not self.hints['throw']:
            self._guiMgr.setMessage(TTLocalizer.CogdoMazeThrowHint)
            self.hints['throw'] = True

    def hitSuit(self, suitType):
        if suitType == Globals.SuitTypes.Boss and not self.hints['boss']:
            self._guiMgr.setMessageTemporary(TTLocalizer.CogdoMazeBossHint,
                                             Globals.HintTimeout)
            self.hints['boss'] = True
        if suitType != Globals.SuitTypes.Boss and not self.hints['minion']:
            self._guiMgr.setMessageTemporary(TTLocalizer.CogdoMazeMinionHint,
                                             Globals.HintTimeout)
            self.hints['minion'] = True

    def createThrowGag(self, gag):
        throwGag = CogdoMazePlayer.createThrowGag(self, gag)
        collSphere = CollisionSphere(0, 0, 0, 0.5)
        collSphere.setTangible(0)
        name = Globals.GagCollisionName
        collNode = CollisionNode(name)
        collNode.setFromCollideMask(ToontownGlobals.PieBitmask)
        collNode.addSolid(collSphere)
        colNp = throwGag.attachNewNode(collNode)
        base.cTrav.addCollider(colNp, self.gagHandler)
        return throwGag

    def showToonThrowingGag(self, heading, pos):
        self._guiMgr.clearMessage()
        return CogdoMazePlayer.showToonThrowingGag(self, heading, pos)

    def removeGag(self):
        if self.equippedGag is None:
            return
        CogdoMazePlayer.removeGag(self)
        self.throwPending = False
        messenger.send(Globals.WaterCoolerShowEventName, [])
        return

    def controlKeyPressed(self):
        if self.game.finished or self.throwPending or self.getCurrentOrNextState(
        ) == 'Hit' or self.equippedGag == None:
            return
        self.throwPending = True
        heading = self.toon.getH()
        pos = self.toon.getPos()
        self.game.requestUseGag(pos.getX(), pos.getY(), heading)
        return

    def completeThrow(self):
        self.clearCollisions()
        CogdoMazePlayer.completeThrow(self)

    def shakeCamera(self, strength):
        self.cameraMgr.shake(strength)

    def getCameraShake(self):
        return self.cameraMgr.shakeStrength

    def setInvulnerable(self, bool):
        self.invulnerable = bool

    def handleGameStart(self):
        self.numEntered = len(self.game.players)
        self.__initCollisions()
        self._guiMgr.startGame(TTLocalizer.CogdoMazeFindHint)
        self.hints['find'] = True
        self.notify.info(
            'toonId:%d laff:%d/%d  %d player(s) started maze game' %
            (self.toon.doId, self.toon.hp, self.toon.maxHp,
             len(self.game.players)))

    def handleGameExit(self):
        self.cameraMgr.disable()
        self.__disableCollisions()

    def handlePickUp(self, toonId):
        if toonId == self.toon.doId:
            self.pickupCount += 1
            self._guiMgr.setPickupCount(self.pickupCount)
            if self.pickupCount == 1:
                self._guiMgr.showPickupCounter()
            self._getMemoSfx.play()

    def handleOpenDoor(self, door):
        self._guiMgr.setMessage(TTLocalizer.CogdoMazeGameDoorOpens)
        self._guiMgr.showQuestArrow(self.toon, door,
                                    Point3(0, 0,
                                           self.toon.getHeight() + 2))

    def handleTimeAlert(self):
        self._guiMgr.setMessageTemporary(TTLocalizer.CogdoMazeGameTimeAlert)

    def handleToonRevealsDoor(self, toonId, door):
        if toonId == self.toon.doId:
            self._guiMgr.setMessageTemporary(
                TTLocalizer.CogdoMazeGameLocalToonFoundExit)

    def handleToonEntersDoor(self, toonId, door):
        self.exited = True
        message = ''
        if door.getPlayerCount() < len(self.game.players):
            message = TTLocalizer.CogdoMazeGameWaitingForToons
        if toonId == self.toon.doId:
            self._guiMgr.setMessage(message)
            self._winSfx.play()
            self._audioMgr.stopMusic()
        self.notify.info(
            'toonId:%d laff:%d/%d  %d player(s) succeeded in maze game. Going to the executive suit building.'
            % (toonId, self.toon.hp, self.toon.maxHp, len(self.game.players)))
        if self.numEntered > len(self.game.players):
            self.notify.info('%d player(s) failed in maze game' %
                             (self.numEntered - len(self.game.players)))

    def lostMemos(self):
        self.pickupCount = 0
        self._guiMgr.setMessageTemporary(TTLocalizer.CogdoMazeGameTimeOut)
        self._guiMgr.setPickupCount(self.pickupCount)
        self.notify.info(
            'toonId:%d laff:%d/%d  %d player(s) failed in maze game' %
            (self.toon.doId, self.toon.hp, self.toon.maxHp,
             len(self.game.players)))
Пример #13
0
class World(DirectObject):
    def __init__(self):
        #--Collision Handler------------------------------------------------------
        self.collHandler = CollisionHandlerEvent()
        self.collHandler.addInPattern('%fn-into-%in')
        base.cTrav = CollisionTraverser('world traverser')

        #--Mouse Control----------------------------------------------------------
        base.disableMouse()
        self.properties = WindowProperties()
        self.properties.setCursorHidden(True)
        base.win.requestProperties(self.properties)

        #--Register Hud Elements--------------------------------------------------
        self.instruction1 = self.addInstruction("[click] to Shoot", 2)
        self.instruction2 = self.addInstruction("[a] to accelerate", 1)
        self.instruction3 = self.addInstruction("[esc] to quit", 0)

        self.scoreHud = self.addHudElement("", 0)
        self.accuracy = self.addHudElement("", 1)
        self.speedHud = self.addHudElement("", 2)

        self.bigHud = OnscreenText(text="",
                                   style=1,
                                   fg=(1, 1, 1, 1),
                                   pos=(0, 0),
                                   align=TextNode.ACenter,
                                   scale=.1)

        #--Load Objects and Models------------------------------------------------
        self.ship = Ship(self.collHandler)
        self.loadSkyBox()
        game.camera.reparentTo(self.ship.getModel())

        #--Start Game-------------------------------------------------------------
        self.asteroids = []
        self.resetGame()

        #--Controls --------------------------------------------------------------
        self.keysDown = {'a': 0}

        self.controlTask = taskMgr.add(self.gameLoop, "game-control-task")
        self.controlTask.lastTime = 0

        self.accept("escape", sys.exit, [0])
        self.accept("a", self.keyDown, ['a'])
        self.accept("a-up", self.keyUp, ['a'])
        self.accept("mouse1", self.shoot)
        self.accept("space", self.shoot)
        self.accept("resetgame", self.gameOver)

        if (DEBUG_CONTROLS):
            self.accept("0", self.ship.stop)
            self.accept("9", self.ship.getModel().setHpr, [0, 0, 0])

        #--Register CollisionEvent Handlers---------------------------------------
        self.accept('asteroid-into-bullet', self.bulletAsteroidCollision)

    ###
    # World.shoot:
    #
    # Dispatch method that overloads the use of the mouse button
    ##
    def shoot(self):
        if (self.ship.isAlive()):
            self.ship.fireBullet()
            self.shots += 1
        else:
            self.resetGame()

    ###
    # World.gameOver()
    #
    #  Displays "Game Over: <SCORE>" then resets game after 5 seconds
    def gameOver(self):
        self.bigHud.setText("GAME OVER: " + str(self.score))
        taskMgr.doMethodLater(GAME_OVER_DELAY, self.resetGame, "reset_game",
                              [])

    ###
    # World.resetGame
    #
    # Resets anything that might change during play essentially reloading
    ##
    def resetGame(self):
        for asteroid in self.asteroids:
            asteroid.remove()
        self.score = 0
        self.shots = 0
        self.hits = 0
        self.lifeLength = 0
        self.ship.reset()
        self.scoreHud.setText("Score     : " + str(self.score))
        self.accuracy.setText("Hit/Fired : 0/0")
        self.speedHud.setText("Speed     : 0")
        self.bigHud.setText("")
        self.loadAsteroids()

    ###
    # World.bulletAsteroidCollision:
    #
    # Event Handler for collision From Asteroid Into Bullet
    # Triggers the "explosion" of an Asteroid and appends replacments
    ##
    def bulletAsteroidCollision(self, entry):
        bullet = entry.getIntoNodePath().getParent().getPythonTag("owner")
        asteroid = entry.getFromNodePath().getParent().getPythonTag("owner")
        self.ship.removeBullet(bullet)
        self.asteroids.extend(asteroid.registerHit())
        self.asteroids.remove(asteroid)
        self.score += 100
        self.hits += 1
        asteroid.remove()

    ###
    # World.keyDown:
    #
    # Register the given key as being held down
    ##
    def keyDown(self, key):
        self.keysDown[key] = 1

    ###
    # World.keyUp:
    #
    # Register the given key as no longer being held down
    ##
    def keyUp(self, key):
        self.keysDown[key] = 0

    ###
    # World.addHudElement(msg, row)
    #
    # Displays the given string msg in the top left with a row offset of row
    ##
    def addHudElement(self, msg, row):
        return OnscreenText(text=msg,
                            style=1,
                            fg=(1, 1, 1, 1),
                            pos=(-1.3, .95 - (.05 * row)),
                            align=TextNode.ALeft,
                            scale=.05)

    ###
    # World.addInstruction(msg, row)
    #
    # Displays the given string msg in the top right with a row offset of row
    ##
    def addInstruction(self, msg, row):
        return OnscreenText(text=msg,
                            style=1,
                            fg=(1, 1, 1, 1),
                            pos=(1.3, .95 - (.05 * row)),
                            align=TextNode.ARight,
                            scale=.05)

    ###
    # World.loadSkyBox:
    #
    # Helper method that loads the skybox, sets size and other factors and
    # parents to ship, while keeping a compass effect so it will spin around the
    # ship
    ##
    def loadSkyBox(self):
        self.skybox = game.loader.loadModel("Models/skybox.egg")
        self.skybox.setScale(100.0, 100.0, 100.0)
        self.skybox.setPos(0, 0, 0)
        self.skybox.reparentTo(self.ship.getModel())
        # Roots the skybox with relation to the render node, making it stationary
        # even though its parented to the ship
        self.skybox.setEffect(CompassEffect.make(render, CompassEffect.PRot))

    ###
    # gameLoop
    #
    # Task for managing the input from the mouse and keys. In addition updating
    # the game world.
    ##
    def gameLoop(self, task):
        md = base.win.getPointer(0)
        x = md.getX()
        y = md.getY()

        # Get the delta in time since last frame (allows us to ratelimit rotation
        #   and acceleration
        dt = task.time - task.lastTime
        task.lastTime = task.time
        self.lifeLength += dt

        # Calculate how far the mouse moved, generate a rotation offest and send
        #  to the ship to rotate
        if base.win.movePointer(0, MOUSE_OFFSET, MOUSE_OFFSET):
            self.ship.rotate(
                Vec3(-((x - MOUSE_OFFSET) * ROTATION_RATE),
                     INVERTED_MOUSE * ((y - MOUSE_OFFSET) * ROTATION_RATE), 0))

        #--Allows Holding of A key------------------------------------------------

        if (self.keysDown['a'] == 1):
            self.ship.accelerate(dt)

        #--Update Asteroid Positions----------------------------------------------
        for asteroid in self.asteroids:
            asteroid.updatePos(dt)

        #--Update HUD-------------------------------------------------------------
        if (self.shots != 0):
            self.accuracy.setText("Hit/Fired : " + str(self.hits) + "/" +
                                  str(self.shots))

        self.scoreHud.setText("Score     : " + str(self.score))
        self.speedHud.setText("Speed     : " + str(self.ship.getVel()))

        return Task.cont

    ###
    # World.loadAsteroids
    #
    # Helper method for creating the asteroids
    ##
    def loadAsteroids(self):
        self.asteroids = []
        for i in range(ASTEROID_START_COUNT):
            x = choice([-1, 1]) * choice(
                range(ASTEROID_SPAWN_MIN, ASTEROID_SPAWN_MAX))
            y = choice([-1, 1]) * choice(
                range(ASTEROID_SPAWN_MIN, ASTEROID_SPAWN_MAX))
            z = choice([-1, 1]) * choice(
                range(ASTEROID_SPAWN_MIN, ASTEROID_SPAWN_MAX))
            self.asteroids.append(Asteroid(Vec3(x, y, z), self.collHandler))
Пример #14
0
class Game:
    def __init__(self, base, game_quit_cb):
        self.base = base
        self.game_quit_cb = game_quit_cb

    def run(self, root_node, restart_scene_cb):
        self.restart_scene_cb = restart_scene_cb
        self.root_node = root_node
        self.base.accept("escape", sys.exit)  # Escape quits
        self.base.camera.set_pos(0, 0, 90)
        self.base.camera.set_hpr(0, -90, 0)
        self.score = Scores(self.game_end, self.game_quit_cb,
                            self.restart_game)
        self.game_ended = False
        lens = OrthographicLens()
        lens.set_film_size(40 * win_aspect, 40)
        self.base.cam.node().setLens(lens)
        self.gc = GameControls(self.base, self.move_player, mouse_magnitude=7)

        self.base.disable_mouse()
        # debug camera movement
        # self.fm = FlyMove(self)
        # self.camera.set_pos(-20, 0, 10)
        # self.camera.set_hpr(-90, -50, 0)

        self.base.cTrav = CollisionTraverser()
        self.coll_hand_event = CollisionHandlerEvent()
        self.coll_hand_event.addInPattern('into-%in')

        paddle_path = 'models/paddle'
        self.player_paddle = pp = self.load_and_render(paddle_path)
        pp.set_pos(-20, 0, 0)
        pp.set_hpr((90, 0, 0))
        self.ai_paddle = aip = self.load_and_render(paddle_path, copy=True)
        aip.set_pos(20, 0, 0)
        aip.set_hpr((90, 0, 0))

        self.ball = self.load_and_render('models/ball')
        collision_ball = CollisionSphere(0, 0, 0, 1)
        cnodePath = self.ball.attachNewNode(CollisionNode('ball'))
        cnodePath.node().addSolid(collision_ball)
        self.base.cTrav.add_collider(cnodePath, self.coll_hand_event)

        # ball movement
        self.reset_ball()
        self.ball_speed_scale = 0.30
        self.base.task_mgr.add(self.ball_move_task, 'ball-move')

        # set up boundaries on the top and bottom
        self.border_distance = border_distance = 20
        self.top_boundary = self.load_and_render(paddle_path, copy=True)
        self.top_boundary.set_sx(5)
        self.top_boundary.set_y(border_distance)
        self.bottom_boundary = self.load_and_render(paddle_path, copy=True)
        self.bottom_boundary.set_sx(5)
        self.bottom_boundary.set_y(-1 * border_distance)

        horizontal_distance = 30
        self.player_side_plane = CollisionPlane(
            Plane(LVector3f(1, 0, 0), LPoint3f(-1 * horizontal_distance, 0,
                                               0)))
        self.player_side_cnode = self.root_node.attachNewNode(
            CollisionNode('pplane'))
        self.player_side_cnode.node().add_solid(self.player_side_plane)
        self.ai_side_plane = CollisionPlane(
            Plane(LVector3f(-1, 0, 0), LPoint3f(horizontal_distance, 0, 0)))
        self.ai_side_cnode = self.root_node.attachNewNode(
            CollisionNode('aiplane'))
        self.ai_side_cnode.node().add_solid(self.ai_side_plane)

        # add collision to paddles and walls, everything the ball can reflect off of
        for np in [pp, aip, self.bottom_boundary, self.top_boundary]:
            cs = CollisionBox((0, 0, 0), 5, 0.25, 8)
            cnodePath = np.attachNewNode(CollisionNode('wall'))
            cnodePath.node().addSolid(cs)
            self.base.cTrav.add_collider(cnodePath, self.coll_hand_event)
        self.base.accept('into-wall', self.ball_collision)
        self.base.accept('into-pplane', self.player_side_goal)
        self.base.accept('into-aiplane', self.ai_side_goal)

        self.ai = PongAI(self.base, self.ai_paddle, self.ball, border_distance)

    def game_end(self):
        self.game_ended = True
        self.base.task_mgr.remove("ball-move")
        self.gc.stop()
        self.ai.stop()

    def player_side_goal(self, entry):
        self.score.ai_scored()
        self.reset_ball()

    def ai_side_goal(self, entry):
        self.score.player_scored()
        self.reset_ball()

    def restart_game(self):
        self.restart_scene_cb()

    def reset_ball(self):
        if self.game_ended:
            return

        side = randint(0, 1)
        angle = randint(0, 90)
        angle += side * 180  # possibly flip which player it's going to
        angle = (angle - 45) * (pi / 180)
        self.ai_paddle.set_y(0)
        self.player_paddle.set_y(0)

        self.ball_v = LVector3f(cos(angle), sin(angle), 0)
        self.ball.set_pos((0, 0, 0))

    def ball_collision(self, entry):
        norm = entry.get_surface_normal(self.root_node) * -1
        in_vec = self.ball_v / self.ball_v.length()
        self.ball_v = (norm * norm.dot(in_vec * -1) * 2) + in_vec

    def ball_move_task(self, task):
        self.ball.set_pos(self.ball.get_pos() +
                          self.ball_v * self.ball_speed_scale)
        return task.cont

    def load_and_render(self, model_path, copy=False):
        if copy:
            model = self.base.loader.loadModelCopy(model_path)
        else:
            model = self.base.loader.loadModel(model_path)
        model.reparent_to(self.root_node)
        return model

    def move_player(self, dy):
        self.player_paddle.set_y(
            max(-1 * self.border_distance,
                min(self.border_distance,
                    self.player_paddle.get_y() + dy)))
Пример #15
0
class GameContainer(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)

        ########## Window configuration #########

        wp = WindowProperties()
        wp.setSize(1024, 860)

        self.win.requestProperties(wp)

        ########## Gameplay settings #########

        self.GAME_MODE = PLAY
        self.play_mode = SPACE

        self.level = 1.5

        self.mode_initialized = False

        ######### Camera #########

        self.disableMouse()

        self.mainCamera = Camera(self.camera)

        self.mainCamera.camObject.setHpr(0, 0, 0)

        #Trigger game chain

        self.loadLevel(LEVEL)

        ######### Events #########

        self.taskMgr.add(self.gameLoop, "gameLoop", priority = 35)

        self.keys = {"w" : 0, "s" : 0, "a" : 0, "d" : 0, "space" : 0}

        self.accept("w", self.setKey, ["w", 1])
        self.accept("w-up", self.setKey, ["w", 0])
        self.accept("s", self.setKey, ["s", 1])
        self.accept("s-up", self.setKey, ["s", 0])
        self.accept("a", self.setKey, ["a", 1])
        self.accept("a-up", self.setKey, ["a", 0])
        self.accept("d", self.setKey, ["d", 1])
        self.accept("d-up", self.setKey, ["d", 0])
        self.accept("space", self.setKey, ["space", 1])
        self.accept("space-up", self.setKey, ["space", 0])
        self.accept("wheel_up", self.zoomCamera, [-1])
        self.accept("wheel_down", self.zoomCamera, [1])
        self.accept("escape", self.switchGameMode, [IN_GAME_MENU])

        self.accept("window-event", self.handleWindowEvent)

        self.accept("playerGroundRayJumping-in", self.avatar.handleCollisionEvent, ["in"])
        self.accept("playerGroundRayJumping-out", self.avatar.handleCollisionEvent, ["out"])

        ######### GUI #########

        self.gui_elements = []

    def loadSpaceTexture(self, level):

        if level < 10: return 'textures/space#.jpg'
        elif level < 15: pass  

    def loadLevel(self, level):

        #Resets

        self.avatarActor = Actor("models/panda",
                                {"walk": "models/panda-walk"})
        self.avatarActor.setScale(.5, .5, .5)
        self.avatarActor.setHpr(180, 0, 0)
        self.avatarActor.setCollideMask(BitMask32.allOff())

        self.asteroidManager = AsteroidManager()

        #Alternate modes

        if int(self.level) == self.level: self.play_mode = TERRAIN

        else: self.play_mode = SPACE

        #Specifics

        if self.play_mode == SPACE:

            self.avatar = Avatar(self.avatarActor)
            self.avatar.objectNP.reparentTo(render)

            ########## Sky #########

            cubeMap = loader.loadCubeMap(self.loadSpaceTexture(self.level))
            self.spaceSkyBox = loader.loadModel('models/box')

            self.spaceSkyBox.setScale(100)
            self.spaceSkyBox.setBin('background', 0)
            self.spaceSkyBox.setDepthWrite(0)
            self.spaceSkyBox.setTwoSided(True)
            self.spaceSkyBox.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldCubeMap)
            self.spaceSkyBox.setTexture(cubeMap, 1)
            #self.spaceSkyBox.setEffect(CompassEffect.make(render))

            parentNP = render.attachNewNode('parent')

            self.spaceSkyBox.reparentTo(parentNP)
            self.spaceSkyBox.setPos(-self.spaceSkyBox.getSx()/2, -self.spaceSkyBox.getSy()/2, 
                                    -self.spaceSkyBox.getSz()/2)

            self.asteroidManager.initialize(self.level)

        elif self.play_mode == TERRAIN:

            ########## Terrain #########

            #self.environ = loader.loadModel("../mystuff/test.egg")
            self.environ = loader.loadModel("models/environment")
            self.environ.setName("terrain")
            self.environ.reparentTo(render)
            self.environ.setPos(0, 0, 0)
            self.environ.setCollideMask(BitMask32.bit(0))

            ######### Models #########

            ######### Physics #########

            base.enableParticles()

            gravityForce = LinearVectorForce(0, 0, -9.81)
            gravityForce.setMassDependent(False)
            gravityFN = ForceNode("world-forces")
            gravityFN.addForce(gravityForce)
            render.attachNewNode(gravityFN)
            base.physicsMgr.addLinearForce(gravityForce)

            self.avatarPhysicsActorNP = render.attachNewNode(ActorNode("player"))
            self.avatarPhysicsActorNP.node().getPhysicsObject().setMass(50.)
            self.avatarActor.reparentTo(self.avatarPhysicsActorNP)
            base.physicsMgr.attachPhysicalNode(self.avatarPhysicsActorNP.node())

            self.avatarPhysicsActorNP.setPos(15, 10, 5)

            ######### Game objects #########

            self.avatar = Avatar(self.avatarPhysicsActorNP)

            ######### Collisions #########

            self.cTrav = CollisionTraverser()

            #Make player rigid body

            self.pandaBodySphere = CollisionSphere(0, 0, 4, 3)

            self.pandaBodySphereNode = CollisionNode("playerBodyRay")
            self.pandaBodySphereNode.addSolid(self.pandaBodySphere)
            self.pandaBodySphereNode.setFromCollideMask(BitMask32.bit(0))
            self.pandaBodySphereNode.setIntoCollideMask(BitMask32.allOff())

            self.pandaBodySphereNodepath = self.avatar.objectNP.attachNewNode(self.pandaBodySphereNode)
            self.pandaBodySphereNodepath.show()

            self.pandaBodyCollisionHandler = PhysicsCollisionHandler()
            self.pandaBodyCollisionHandler.addCollider(self.pandaBodySphereNodepath, self.avatar.objectNP)

            #Keep player on ground

            self.pandaGroundSphere = CollisionSphere(0, 0, 1, 1)

            self.pandaGroundSphereNode = CollisionNode("playerGroundRay")
            self.pandaGroundSphereNode.addSolid(self.pandaGroundSphere)
            self.pandaGroundSphereNode.setFromCollideMask(BitMask32.bit(0))
            self.pandaGroundSphereNode.setIntoCollideMask(BitMask32.allOff())

            self.pandaGroundSphereNodepath = self.avatar.objectNP.attachNewNode(self.pandaGroundSphereNode)
            self.pandaGroundSphereNodepath.show()

            self.pandaGroundCollisionHandler = PhysicsCollisionHandler()
            self.pandaGroundCollisionHandler.addCollider(self.pandaGroundSphereNodepath, self.avatar.objectNP)

            #Notify when player lands

            self.pandaGroundRayJumping = CollisionSphere(0, 0, 1, 1)

            self.pandaGroundRayNodeJumping = CollisionNode("playerGroundRayJumping")
            self.pandaGroundRayNodeJumping.addSolid(self.pandaGroundRayJumping)
            self.pandaGroundRayNodeJumping.setFromCollideMask(BitMask32.bit(0))
            self.pandaGroundRayNodeJumping.setIntoCollideMask(BitMask32.allOff())

            self.pandaGroundRayNodepathJumping = self.avatar.objectNP.attachNewNode(self.pandaGroundRayNodeJumping)
            self.pandaGroundRayNodepathJumping.show()

            self.collisionNotifier = CollisionHandlerEvent()
            self.collisionNotifier.addInPattern("%fn-in")
            self.collisionNotifier.addOutPattern("%fn-out")

            self.cTrav.addCollider(self.pandaGroundSphereNodepath, self.pandaGroundCollisionHandler)
            self.cTrav.addCollider(self.pandaGroundRayNodepathJumping, self.collisionNotifier)
            self.cTrav.addCollider(self.pandaBodySphereNodepath, self.pandaBodyCollisionHandler)

    def maintainTurrets(self):

        pass

    def setKey(self, key, value):

        self.keys[key] = value

    def zoomCamera(self, direction):

        Camera.AVATAR_DIST += direction

    def b(self, hey):

        self.avatarLanded = True

    def handleWindowEvent(self, window=None):

        wp = window.getProperties()

        self.win_center_x = wp.getXSize() / 2
        self.win_center_y = wp.getYSize() / 2

    def switchGameMode(self, newGameMode=None):

        self.cleanupGUI()

        if self.GAME_MODE == IN_GAME_MENU: 

            if newGameMode == PLAY:

                render.clearFog()

            elif newGameMode == MAIN_MENU:

                pass

        elif True:

            pass

        self.GAME_MODE = newGameMode

        self.mode_initialized = False

    def cleanupGUI(self):

        for gui_element in self.gui_elements:

            gui_element.destroy()

    def evenButtonPositions(self, button_spacing, button_height, num_buttons):

        center_offset = (button_spacing/(2.0) if (num_buttons % 2 == 0) else 0)

        button_positions = []

        current_pos = center_offset + ((num_buttons - 1)/2) * button_spacing

        for i in range(0, num_buttons):

            button_positions.append(current_pos + (button_height/2.0))

            current_pos -= button_spacing

        return button_positions

    def buildInGameMenu(self):

        props = WindowProperties()
        props.setCursorHidden(False) 
        base.win.requestProperties(props)

        resume_button = DirectButton(text = "Resume", scale = .1, command = (lambda: self.switchGameMode(PLAY)),
                                    rolloverSound=None)

        main_menu_button = DirectButton(text = "Main Menu", scale = .1, command = self.b,
                                    rolloverSound=None)

        options_button = DirectButton(text = "Options", scale = .1, command = self.b,
                                    rolloverSound=None)

        exit_button = DirectButton(text = "Exit", scale = .1, command = exit,
                                    rolloverSound=None)

        BUTTON_SPACING = .2
        BUTTON_HEIGHT = resume_button.getSy()

        button_positions = self.evenButtonPositions(BUTTON_SPACING, BUTTON_HEIGHT, 4)

        resume_button.setPos(Vec3(0, 0, button_positions[0]))
        main_menu_button.setPos(Vec3(0, 0, button_positions[1]))
        options_button.setPos(Vec3(0, 0, button_positions[2]))
        exit_button.setPos(Vec3(0, 0, button_positions[3]))

        self.gui_elements.append(resume_button)
        self.gui_elements.append(main_menu_button)
        self.gui_elements.append(options_button)
        self.gui_elements.append(exit_button)

    def buildMainMenu(self):

        props = WindowProperties()
        props.setCursorHidden(False) 
        base.win.requestProperties(props)

        start_game_button = DirectButton(text = "Start", scale = .1,
                            command = self.b)

        select_level_button = DirectButton(text = "Select Level", scale = .1,
                            command = self.b)

        game_options_button = DirectButton(text = "Options", scale = .1,
                            command = self.b)

        exit_button = DirectButton(text = "Exit", scale = .1,
                            command = exit)

        BUTTON_SPACING = .2
        BUTTON_HEIGHT = start_game_button.getSy()

        button_positions = self.evenButtonPositions(BUTTON_SPACING, BUTTON_HEIGHT)

        start_game_button.setPos(Vec3(0, 0, button_positions[0]))
        select_level_button.setPos(Vec3(0, 0, button_positions[1]))
        game_options_button.setPos(Vec3(0, 0, button_positions[2]))
        exit_button.setPos(Vec3(0, 0, button_positions[3]))

        self.gui_elements.append(start_game_button)
        self.gui_elements.append(select_level_button)
        self.gui_elements.append(game_options_button)
        self.gui_elements.append(exit_button)

    def gameLoop(self, task):

        #Compensate for inconsistent update intervals

        dt = globalClock.getDt()

        if self.GAME_MODE == MAIN_MENU:

            if not self.mode_initialized:

                self.buildMainMenu()

                self.mode_initialized = True

        if self.GAME_MODE == IN_GAME_MENU:

            if not self.mode_initialized:

                #Fog out background

                inGameMenuFogColor = (50, 150, 50)

                inGameMenuFog = Fog("inGameMenuFog")

                inGameMenuFog.setMode(Fog.MExponential)
                inGameMenuFog.setColor(*inGameMenuFogColor)
                inGameMenuFog.setExpDensity(.01)

                render.setFog(inGameMenuFog)

                self.buildInGameMenu()

                self.mode_initialized = True

        if self.GAME_MODE == PLAY:

            if not self.mode_initialized:

                props = WindowProperties()
                props.setCursorHidden(True) 
                base.win.requestProperties(props)

                self.last_mouse_x = self.win.getPointer(0).getX()
                self.last_mouse_y = self.win.getPointer(0).getY()

                self.mode_initialized = True

            if self.play_mode == TERRAIN:

                self.maintainTurrets()
                self.avatar.move(dt)

            elif self.play_mode == SPACE:

                self.asteroidManager.maintainAsteroidField(self.avatar.objectNP.getPos(), 
                                                           self.avatar.speed, dt)

            #Handle keyboard input

            self.avatar.handleKeys(self.keys, self.play_mode)

            ########## Mouse-based viewpoint rotation ##########

            mouse_pos = self.win.getPointer(0)

            current_mouse_x = mouse_pos.getX()
            current_mouse_y = mouse_pos.getY()

            #Side to side

            if self.play_mode == TERRAIN:

                mouse_shift_x = current_mouse_x - self.last_mouse_x
                self.last_mouse_x = current_mouse_x

                if current_mouse_x < 5 or current_mouse_x >= (self.win_center_x * 1.5):

                    base.win.movePointer(0, self.win_center_x, current_mouse_y)
                    self.last_mouse_x = self.win_center_x

                yaw_shift = -((mouse_shift_x) * Camera.ROT_RATE[0])

                self.avatar.yawRot += yaw_shift

                self.avatar.objectNP.setH(self.avatar.yawRot)

            #Up and down

            mouse_shift_y = current_mouse_y - self.last_mouse_y
            self.last_mouse_y = current_mouse_y

            if current_mouse_y < 5 or current_mouse_y >= (self.win_center_y * 1.5):

                base.win.movePointer(0, current_mouse_x, self.win_center_y)
                self.last_mouse_y = self.win_center_y

            pitch_shift = -((mouse_shift_y) * Camera.ROT_RATE[1])

            self.mainCamera.pitchRot += pitch_shift

            if self.mainCamera.pitchRot > Camera.FLEX_ROT_MAG[0]:

                self.mainCamera.pitchRot = Camera.FLEX_ROT_MAG[0]

            elif self.mainCamera.pitchRot < -Camera.FLEX_ROT_MAG[0]:

                self.mainCamera.pitchRot = -Camera.FLEX_ROT_MAG[0]

            xy_plane_cam_dist = Camera.AVATAR_DIST

            cam_x_adjust = xy_plane_cam_dist*sin(radians(self.avatar.yawRot))  
            cam_y_adjust = xy_plane_cam_dist*cos(radians(self.avatar.yawRot))
            cam_z_adjust = Camera.ELEVATION

            self.mainCamera.camObject.setH(self.avatar.yawRot)
            self.mainCamera.camObject.setP(self.mainCamera.pitchRot)

            self.mainCamera.camObject.setPos(self.avatar.objectNP.getX() + cam_x_adjust, self.avatar.objectNP.getY() - cam_y_adjust, 
                            self.avatar.objectNP.getZ() + cam_z_adjust)

            #Find collisions

            #self.cTrav.traverse(render)

            #print self.environ.getBounds()

        return Task.cont
Пример #16
0
class DonkeyKong(ShowBase):
    def __init__(self):
        super().__init__(self)
        self.angle = 0
        self.taskMgr.add(self.setup, "setup")
        self.taskMgr.add(self.update, "update")

        self.scene = self.loader.loadModel('models/DKSet')
        self.scene.reparentTo(self.render)
        
        self.arcadeTexture = self.loader.loadTexture('models/dk-arcade.png')
        self.scene.setTexture(self.arcadeTexture)
        self.scene.setTransparency(1)
        
        self.blocksTexture = self.loader.loadTexture('models/block.png')
        self.stairsTexture = self.loader.loadTexture('models/stairs.png')
        
        self.dkTimer = -1
        self.lifeCounter = 3
        self.playerLost = False
        self.playerWon = False
        #messenger.toggleVerbose()
        
        self.barrels_frames = []
        self.barrels_frames.append(0)
        self.barrels_frames.append( 0.410573 - 0.375774)
        self.barrels_frames.append( 0.444913 - 0.375774)
        self.barrels_frames.append( 0.479941 - 0.375774)
        
    def setup(self,task):
        lens = OrthographicLens()
        lens.setFilmSize(23,19)
        base.camNode.setLens(lens)
        
        self.player = self.scene.attachNewNode("Player")
        
        self.marioGfx = self.scene.find('root/mario')
        self.marioGfx.reparentTo(self.player)
        self.marioGfx.setTwoSided(True)
        
        self.lifes = [
        self.scene.attachNewNode("life1"),
        self.scene.attachNewNode("life2"),
        self.scene.attachNewNode("life3")
        ]
        self.marioGfx.instanceTo(self.lifes[0])
        self.marioGfx.instanceTo(self.lifes[1])
        self.marioGfx.instanceTo(self.lifes[2])
        
        self.lifes[0].setPos(-9,0,7.5)
        self.lifes[1].setPos(-10,0,7.5)
        self.lifes[2].setPos(-11,0,7.5)

        
        self.hammerTime = False
        
        self.hammerDown = self.scene.find('root/hammerdowm')
        self.hammerDown.reparentTo(self.marioGfx)
        self.hammerDown.setPos(1,0,0)
        
        self.hammerUp = self.scene.find('root/hammerup')
        self.hammerUp.reparentTo(self.marioGfx)
        self.hammerUp.setPos(0,0,1)
        
        frame1 = Func(self.hammerFrame1)
        frame2 = Func(self.hammerFrame2)
        delay = Wait(0.1)
        self.hammerSequence = Sequence(frame1, delay, frame2, delay)
        # self.hammerSequence.loop()
        
        self.hammerUp.hide()
        self.hammerDown.hide()
        
        self.scene.find('root/walls').hide()
        self.scene.find('root/rightWall').hide()
        self.scene.find('root/barrel').setPos(0,100,0)
        
        self.jumpAvailable = False
        self.gravity = -.5
        self.verticalTime = 0
        self.v0 = 0
        self.floorZ = 0
        self.onStairs = False
        self.jumpCounter = 1
        # input setup 
        
        self.input = {
        'up':False,
        'down': False,
        'left': False , 
        'right': False,
        'space': False
        }
        
        key_list = ['up','down','left','right']
        for k in key_list:
            self.accept(f'raw-arrow_{k}' , self.buildPress(k) )
            self.accept(f'raw-arrow_{k}-up', self.buildRelease(k) )
        
        self.accept(f'raw-space' , self.buildPress('space') )
        self.accept(f'raw-space-up', self.buildRelease('space') )
        
        
        # collision set up
        base.cTrav = CollisionTraverser()
        self.collisionHandlerEvent = CollisionHandlerEvent()
        self.collisionHandlerEvent.addInPattern('into-%in')
        self.collisionHandlerEvent.addOutPattern('outof-%in')

        ray = CollisionSegment(0,0,0,0,0,-.6)
        cNodePath = self.player.attachNewNode( CollisionNode('marioRay') )
        cNodePath.node().addSolid(ray)
        cNodePath.node().setIntoCollideMask(0x03)
        cNodePath.node().setFromCollideMask(0x03)
        #cNodePath.show()
        base.cTrav.addCollider(cNodePath, self.collisionHandlerEvent)

        self.donkeykong = self.scene.find('root/donkeykong')
        self.donkeykonghit = self.createSquareCollider(8.7,5,1,1,'donkeykong','dkhitbox', 'DK' , self.reachedDK, self.exitDK , self.arcadeTexture, 0x02)
        self.createDkSequence()
        self.dk_sequence.start()
        
        self.floor1 = self.createSquareCollider(-1.8, -5.5 , 9.3, .5, 'floor0' , 'floor1HitBox', 'Floor1', self.enableJump, self.disableJump , self.blocksTexture, 0x1)
        self.floor2 = self.createSquareCollider(2.08, -2.5 , 8.0, .5, 'floor1' , 'floor2HitBox', 'Floor2', self.enableJump, self.disableJump , self.blocksTexture, 0x1)
        self.floor3_1 = self.createSquareCollider(3.6, 0.5 , 3.8, .5, 'floor2' , 'floor3_1HitBox', 'Floor3_1', self.enableJump, self.disableJump , self.blocksTexture, 0x1)
        self.floor3_2 = self.createSquareCollider(-6.3, 0.5 , 5, .5, 'pCube4' , 'floor3_2HitBox', 'Floor3_2', self.enableJump, self.disableJump , self.blocksTexture, 0x1)
        self.floor4 = self.createSquareCollider(1.8, 3.5 , 8.0, .5, 'floors' , 'floor4HitBox', 'Floor4', self.enableJump, self.disableJump , self.blocksTexture, 0x1)
        
        self.hammer = self.createSquareCollider(6,1.5,0.5,0.5,'hammer', 'hammerHitBox', 'hammer', self.enableHammer, self.disableHammer, self.arcadeTexture, 0x02) 
        self.topStair = self.createSquareCollider(-6.8, 3.5 , 0.5, 2.5, 'topstair' , 'topStairHitBox', 'TopStair', self.enableStairs, self.disableStairs , self.stairsTexture, 0x2)
        self.middleStair= self.createSquareCollider(-0.86, 0.1 , 0.5, 2.5, 'middlestair' , 'middleStairHitBox', 'MiddleStair', self.enableStairs, self.disableStairs , self.stairsTexture, 0x2)
        self.bottomStair = self.createSquareCollider(-6.8, -2.5 , 0.5, 2.5, 'bottomstair' , 'bottomStairHitBox', 'BottomStair', self.enableStairs, self.disableStairs , self.stairsTexture, 0x2)
        
        self.leftWall = self.createInvisibleSquareCollider(-12.5, 0, 1, 10 , 'leftWallHitBox','leftWall',0x1)
        self.rightWall = self.createInvisibleSquareCollider(11.3, 0, 1, 20 , 'rightWallHitBox','rightWall',0x1)
        
        self.barrelDestroyer = self.createInvisibleSquareCollider(-.5,-10,10.5,1, 'barrelDestroyerHitBox' , 'barrelDestroyer'  ,0x1) 
        self.barrelBridge = self.createInvisibleSquareCollider(-0.4,0.5,2,0.5, 'barrelBridgeHitBox' , 'barrelBridge'  ,0x4)
        self.accept('into-barrelCollider', self.barrelCrash)
        base.enableParticles()
        
        self.physicsCollisionPusher = PhysicsCollisionHandler()
        gravity = ForceNode('world-forces')
        gravityP = render.attachNewNode(gravity)
        gravityForce = LinearVectorForce(0,0,-9.81)
        gravity.addForce(gravityForce)
        base.physicsMgr.addLinearForce(gravityForce)
        
        
        #self.createInvisibleSquareCollider(0,0,8,3,"NewCollision","NewNode")
        #self.createInvisibleSquareCollider(-6,0,4,5,"NewCollisio2","NewNode2")
        #base.cTrav.showCollisions(self.render)
        
        # self.accept('raw-a', self.throwBarrel)
        # self.player.setPos(3,0,-3.5)
        self.player.setPos(-8,0,-1.5)
        return Task.done

    def reachedDK(self, evt):
        if self.hammerTime:
            self.playerWon = True
        else:
            self.playerLost = True
        pass
    
    def exitDK(self, evt):
        pass

    def calcNextBarrelThrow(self):
        self.dkTimer = random()*3+3

    def changeDkFrame(self, dk,new_u, new_v):
        self.dkTimer = -1
        dk.setTexOffset( TextureStage.getDefault() , new_u , new_v )

    def createDkSequence(self):
        f1 = Func(self.changeDkFrame, self.donkeykong , 0.1408067 - 0.0446603 , 0 )
        f2 = Func(self.changeDkFrame, self.donkeykong , 0.0431023 - 0.0446603 , 0.806672 - 0.703844 )
        f3 = Func(self.changeDkFrame, self.donkeykong , 0 , 0 )
        th = Func(self.throwBarrel)
        reset = Func(self.calcNextBarrelThrow)
        d = Wait(0.2)
        
        self.dk_sequence = Sequence(f1,d,f2,d,f3,th,d,f1,reset)


    def barrelCrash(self, evt):
        physicalBarrel = evt.getIntoNodePath().node().getParent(0).getParent(0)
        other = evt.getFromNodePath().node().getParent(0)
        
    
        if( other.name == 'leftWall' or other.name == 'rightWall'):
            forceNode = physicalBarrel.getChildren()[1]
            force = forceNode.getForce(0)
            force.setVector( force.getLocalVector().x*-1 , 0 ,0 )
            forceNode.clear()
            forceNode.addForce(force)
            
        if( other.name == 'barrelDestroyer' ):
            self.scene.node().removeChild( physicalBarrel.getParent(0) )
        
        
        if( other.name == 'Player' ):
            if(self.hammerTime):
                self.scene.node().removeChild( physicalBarrel.getParent(0) )
            else:
                self.minusLife()
    
    def minusLife(self):
        self.lifes[self.lifeCounter-1].hide()
        self.lifeCounter -= 1
        
        if( self.lifeCounter <= 0):
            self.playerLost = True

    def hammerFrame1(self):
        self.hammerUp.show()
        self.hammerDown.hide()

    
    def hammerFrame2(self):
        self.hammerUp.hide()
        self.hammerDown.show()
    

    def enableHammer(self, evt):
        self.hammerTime = True
        self.scene.node().removeChild( evt.getIntoNodePath().node().getParent(0) )
        self.hammerSequence.loop()
                
    def disableHammer(self, evt):
        pass

    def enableJump(self, evt):
        #print(f'IN----> {evt}')
        self.floorZ = evt.getIntoNodePath().node().getParent(0).getTransform().getPos().z + 1
        self.jumpAvailable = True
    
    def disableJump(self, evt):
        #print(f'Out----> {evt}')
        self.jumpAvailable = False

    def enableStairs(self, evt):
        #print(f'IN----> {evt}')
        self.onStairs = True
    
    def disableStairs(self, evt):
        #print(f'Out----> {evt}')
        self.onStairs = False



    def throwBarrel(self):
        barrelNode = self.scene.attachNewNode("PhysicalBarrel")
        physicalBarrel = ActorNode("physics_barrel")
        physicalBarrel.getPhysicsObject().setMass(0.01)
        
        barrel = barrelNode.attachNewNode(physicalBarrel)
        base.physicsMgr.attachPhysicalNode(physicalBarrel)
        
        visualBarrel = barrel.attachNewNode("BarrelCopy")
        originalBarrel = self.scene.find('root/barrel')
        originalBarrel.instanceTo(visualBarrel)
        visualBarrel.setPos(0,-100,0)
        
        sphere = CollisionSphere(0.16,100,0,0.5)
        cNodePath = visualBarrel.attachNewNode( CollisionNode("barrelCollider") )
        cNodePath.node().addSolid(sphere)
        cNodePath.node().setIntoCollideMask(0x05)
        cNodePath.node().setFromCollideMask(0x05)
        #cNodePath.show()
        
        self.physicsCollisionPusher.addCollider(cNodePath, barrel)
        base.cTrav.addCollider(cNodePath, self.physicsCollisionPusher)
        
        barrelForceNode = ForceNode("barrelForce")
        barrel.attachNewNode(barrelForceNode)
        barrelForce = LinearVectorForce(-8,0,0,1,False)
        barrelForceNode.addForce(barrelForce)
        physicalBarrel.getPhysical(0).addLinearForce(barrelForce)
        
        barrelNode.setPos(self.scene,7 , 0 , 4.5)
        
        dataNode = AuxNode("sequenceData")
        seq = self.createBarrelSequence(visualBarrel , physicalBarrel, dataNode )
        dataNode.setSequence(seq)
        barrelNode.attachNewNode(dataNode)
    
    def createBarrelSequence(self, vBarrel, pBarrel, dNode ):
        
        def updateBarrel():
            vel = pBarrel.getPhysicsObject().getVelocity()
            
            frame = dNode.frame
            
            if( vel.x > 0 ):
                frame = (frame+1)%4
            if( vel.x < 0):
                frame = (frame-1)%4
                
            dNode.frame = frame
            vBarrel.setTexOffset( TextureStage.getDefault() , self.barrels_frames[frame] , 0 )
            
        f1 = Func(updateBarrel)
        d = Wait(0.1)
        
        seq = Sequence(f1,d)
        seq.loop()
        return seq
        
    def createSquareCollider(self, px,pz, w, h, modelName, collisionNodeName, nodeName , intoFunction, outFunction, texture, mask ):
        obj = self.scene.attachNewNode(nodeName)
        hitBox = CollisionBox( Point3(0,0,0), w, 5, h )
        cNodePath = obj.attachNewNode( CollisionNode(collisionNodeName) )
        cNodePath.node().addSolid(hitBox)
        cNodePath.node().setIntoCollideMask(mask)
        cNodePath.node().setFromCollideMask(mask)
        #cNodePath.show()
        base.cTrav.addCollider(cNodePath, self.collisionHandlerEvent)
        
        self.scene.find(f'root/{modelName}').reparentTo(obj)
        obj.setPos(px,0,pz)
        obj.setTexture(texture)
        
        self.accept(f'into-{collisionNodeName}' , intoFunction)
        self.accept(f'outof-{collisionNodeName}' , outFunction)
        
        
        return obj
    

    def createInvisibleSquareCollider(self, px,pz, w, h, collisionNodeName, nodeName , mask ):
        obj = self.scene.attachNewNode(nodeName)
        hitBox = CollisionBox( Point3(0,0,0), w, 5, h )
        cNodePath = obj.attachNewNode( CollisionNode(collisionNodeName) )
        cNodePath.node().addSolid(hitBox)
        cNodePath.node().setIntoCollideMask(mask)
        cNodePath.node().setFromCollideMask(mask)
        #cNodePath.show()
        base.cTrav.addCollider(cNodePath, self.collisionHandlerEvent)
        obj.setPos(px,0,pz)
        
    
    def buildPress(self,key):
        def pressKey():
            self.input[key] = True
        return pressKey
        
    def buildRelease(self, key):
        def releaseKey():
            self.input[key] = False
        return releaseKey

    def applyMove(self):
        
        mv = Vec3(0,0,0)
        p = self.player.getPos()
        
        if( self.input["right"]):
            mv.x = -.1
            self.marioGfx.setSx(self.player , -1)        
            self.lifes[0].setSx(-1)
            self.lifes[1].setSx(-1)
            self.lifes[2].setSx(-1)
                    
            
        if( self.input["left"]):
            mv.x = .1
            self.marioGfx.setSx(self.player , 1)
            self.lifes[0].setSx(1)
            self.lifes[1].setSx(1)
            self.lifes[2].setSx(1)
            
        """
        if( self.input["space"]):
            playerPos.z += .1
            
        if( self.input["down"]):
            playerPos.z -= .1
        """
        
        if( self.jumpAvailable and not self.onStairs ):
            self.jumpCounter = 1
            self.verticalTime = 0
            self.v0 = 0
            p.z = self.floorZ
            if(self.input["space"]):
                self.v0 = .165
                self.jumpAvailable = False
            
        if(not self.jumpAvailable and not self.onStairs):
            self.verticalTime += globalClock.getDt()
            mv.z = self.v0  + self.gravity*self.verticalTime
            
        if( self.onStairs):
            self.jumpCounter = 0
            self.v0 = 0
            if( self.input["down"]):
                mv.z = -.1
            if( self.input["up"]):
                mv.z = .1
            
        if( not self.onStairs ):
            if(not self.jumpAvailable):
                if(self.input["space"] and self.jumpCounter == 0):
                    self.v0 = .165
                    self.jumpAvailable = False
                    self.jumpCounter = 1
            
        p.x += mv.x
        p.z += mv.z
        
        self.player.setPos(p)
        
        # hacer que se pueda agarrar el martillo, cuando suceda : self.marioGfx.setSx(self.player  , -1)
        # self.hammer = self.createSquareCollider(6,1.5,.5,.5,'hammer','hammerHitbox', 'hammer', self.enableHammer, self.disableHammer, self.arcadeTexture, 0x02)
        
        
    def update(self, task):
        self.camera.setPos(0,35,0)
        self.camera.lookAt(self.scene)
        
        if( self.dkTimer > -1):
            self.dkTimer -= globalClock.getDt()
            if(self.dkTimer <= 0):
                self.dk_sequence.start()
        
        if( self.playerLost):
            text = DirectLabel(text="Player Lost" , text_scale=(0.5,0.5) )
            return Task.done
            
        if( self.playerWon):
            text = DirectLabel(text="Player Won" , text_scale=(0.5,0.5) )
            return Task.done
            
                    
        self.applyMove()
            
        return Task.cont  
Пример #17
0
        if status == 'up':
            pickingEnabledOject.setScale(1.0)


#** This is a task function called each frame, where the collision ray position is syncronized with the mouse pointer position
def rayupdate(task):
    if base.mouseWatcherNode.hasMouse():
        mpos = base.mouseWatcherNode.getMouse()
        # this function will set our ray to shoot from the actual camera lenses off the 3d scene, passing by the mouse pointer position, making  magically hit what is pointed by it in the 3d space
        pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
    return task.cont


#** Now the tricky part: we have here a particular kind of pattern that react firing a task event when a collider, tagged as 'rays', whatever the value is stored into, hit an object tagged as 'balls', no matter what value is stored into its tag. The resulting event strings sent to the panda3D event manager will be the result of the FROM collider (ray) and the tag value owned by the INTO object being hit (a ball), provided that was settled with a tag key 'balls'.
# That said, these two lines will catch all the events for either smiles and frowneys because we both tagged 'em as 'balls', for all IN events...
collisionHandler.addInPattern("%(rays)ft-into-%(balls)it")
# ...and here for the OUT events
collisionHandler.addOutPattern("%(rays)ft-out-%(balls)it")

#** To complicate things a little, this time we'll going to use the addAgainPattern method, that will raise an event while the mouse ponter is keeping over a ball of any group. Note that the 'ray_again_all' chunk will be used by the CollisionHandlerEvent to fire the event. See the related accept below.
collisionHandler.addAgainPattern("ray_again_all%("
                                 "rays"
                                 ")fh%("
                                 "balls"
                                 ")ih")
""" Note that we could have been done the same using this form as well:

collisionHandler.addAgainPattern("%(rays)ft-again-%(balls)it")

but then we should have used 2 accepts like this:
Пример #18
0
class SillyWorld(DirectObject):

    def __init__(self):
        # start Panda3d
        base = ShowBase()
        # CollisionTraverser instance must be attached to base,
        # and must be called cTrav
        base.cTrav = CollisionTraverser()
        self.cHand = CollisionHandlerEvent()
        self.cHand.addInPattern('into-%in')
        
        # load smiley, which we will control
        # notice this is a little trickery. If we parent everything except smiley
        # to the camera, and the player is controlling the camera, then everything 
        # stays fixed in the same place relative to the camera, and when the camera
        # moves, the player is given the illusion that he is moving smiley, rather than 
        # the camera and the rest of the scene.
        self.smiley = base.loader.loadModel('smiley')
        self.smiley.reparentTo(render)
        self.smiley.setName('Smiley')
        
        # Setup a collision solid for this model. Our initCollisionSphere method returns
        # the cNodepath and the string representing it. We will use the cNodepath for 
        # adding to the traverser, and the string to accept it for event handling.
        #sColl = self.initCollisionSphere(self.smiley)
        sColl = self.initCollisionSphere(self.smiley, True)
        print 'smiley', sColl[0]
        print 'smiley', sColl[1]

        # Add this object to the traverser.
        base.cTrav.addCollider(sColl[0], self.cHand)

        # load frowney
        self.frowney = base.loader.loadModel('frowney')
        self.frowney.setName('Frowney')
        self.frowney.reparentTo(camera)
        
        # Setup a collision solid for this model.
        fColl = self.initCollisionSphere(self.frowney, True)
        #print 'frowney', fColl[0]
        #print 'frowney', fColl[1]
        
        # Add this object to the traverser.
        base.cTrav.addCollider(fColl[0], self.cHand)

        # Accept the events sent by the collisions.
        # smiley is the object we are 'moving', so by convention
        # it is the from object.
        # If we instead put smiley as the into object here,
        # it would work fine, but then smiley would disappear
        # when we collided them.
        self.accept('into-' + fColl[1], self.collide)        

        # set the initial positions of smiley and frowney
        self.set_initial_positions()
        
    def set_initial_positions(self):
        self.smiley.setPos(0, 25, 0)
        self.frowney.setPos(5, 25, 0)

    def collide(self, collEntry):
        #print('collision')
        #print collEntry.getIntoNodePath().getParent()
        collEntry.getIntoNodePath().getParent().stash()
        #print self.frowney.isStashed()
        # if instead of making frowney disappear, you wanted to 
        # change some aspect of one or both colliding objects,
        # you could do soemthing like this:
        colliderFROM = collEntry.getFromNodePath().getParent()
        #colliderINTO = collEntry.getIntoNodePath().getParent()
        # Note that for it to work, you have to 
        # we now may change the aspect of the two colliding objects
        #colliderINTO.setColor(1,1,1,1)
        colliderFROM.setScale(1.5)

    def initCollisionSphere(self, obj, show=False):
        # Get the size of the object for the collision sphere.
        bounds = obj.getChild(0).getBounds()
        center = bounds.getCenter()
        # We are making our radius bigger than our object. It will look strange
        # if we don't show the collision sphere, because frowney will disappear 
        # before the objects appear to touch, but this shows you how you can 
        # change the sphere separately from the actual object. Of course, you 
        # can make it the same size as the object if you want.
        radius = bounds.getRadius() * 1.1
 
        # Create a collision sphere and name it something understandable.
        collSphereStr = 'CollisionHull' + "_" + obj.getName()
        cNode = CollisionNode(collSphereStr)
        cNode.addSolid(CollisionSphere(center, radius))
 
        cNodepath = obj.attachNewNode(cNode)
        if show:
            cNodepath.show()
 
        # Return a tuple with the collision node and its corrsponding string so
        # that the bitmask can be set.
        return (cNodepath, collSphereStr)
Пример #19
0
class Player(DirectObject):
    def __init__(self, _main):
        self.main = _main
        self.name = ""
        self.points = 0
        self.health = 100.0
        self.runSpeed = 1.8
        self.keyMap = {
            "left":False,
            "right":False,
            "up":False,
            "down":False
            }
        base.camera.setPos(0,0,0)
        self.model = loader.loadModel("Player")
        self.model.find('**/+SequenceNode').node().stop()
        self.model.find('**/+SequenceNode').node().pose(0)
        base.camera.setP(-90)
        self.playerHud = Hud()
        self.playerHud.hide()
        self.model.hide()

        # Weapons: size=2, 0=main, 1=offhand
        self.mountSlot = []
        self.activeWeapon = None
        self.isAutoActive = False
        self.trigger = False
        self.lastShot = 0.0
        self.fireRate = 0.0

        self.playerTraverser = CollisionTraverser()
        self.playerEH = CollisionHandlerEvent()
        ## INTO PATTERNS
        self.playerEH.addInPattern('intoPlayer-%in')
        #self.playerEH.addInPattern('colIn-%fn')
        self.playerEH.addInPattern('intoHeal-%in')
        self.playerEH.addInPattern('intoWeapon-%in')
        ## OUT PATTERNS
        self.playerEH.addOutPattern('outOfPlayer-%in')
        playerCNode = CollisionNode('playerSphere')
        playerCNode.setFromCollideMask(BitMask32.bit(1))
        playerCNode.setIntoCollideMask(BitMask32.bit(1))
        self.playerSphere = CollisionSphere(0, 0, 0, 0.6)
        playerCNode.addSolid(self.playerSphere)
        self.playerNP = self.model.attachNewNode(playerCNode)
        self.playerTraverser.addCollider(self.playerNP, self.playerEH)
        #self.playerNP.show()

        self.playerPusher = CollisionHandlerPusher()
        self.playerPusher.addCollider(self.playerNP, self.model)
        self.playerPushTraverser = CollisionTraverser()
        self.playerPushTraverser.addCollider(self.playerNP, self.playerPusher)

    def acceptKeys(self):
        self.accept("w", self.setKey, ["up", True])
        self.accept("w-up", self.setKey, ["up", False])
        self.accept("a", self.setKey, ["left", True])
        self.accept("a-up", self.setKey, ["left", False])
        self.accept("s", self.setKey, ["down", True])
        self.accept("s-up", self.setKey, ["down", False])
        self.accept("d", self.setKey, ["right", True])
        self.accept("d-up", self.setKey, ["right", False])

        # Add mouse btn for fire()
        self.accept("mouse1", self.setWeaponTrigger, [True])
        self.accept("mouse1-up", self.setWeaponTrigger, [False])

        # Killed enemies
        self.accept("killEnemy", self.addPoints)

        # Game states
        self.accept("doDamageToPlayer", self.doDamage)

    def ignoreKeys(self):
        self.ignore("w")
        self.ignore("a")
        self.ignore("s")
        self.ignore("d")
        self.ignore("killEnemy")
        self.ignore("mouse1")
        self.ignore("mouse1-up")

        for item in self.main.itemList:
            if item.type == "heal":
                self.ignore("intoHeal-" + "itemHeal" + str(item.id))
            elif item.type == "gun":
                self. ignore("intoWeapon-" + "itemWeapon" + str(item.id))

        for enemy in self.main.enemyList:
            self.ignore("intoPlayer-" + "colEnemy" + str(enemy.id))

        # Add mouse btn for fire to ignore

    def setKey(self, action, pressed):
        self.keyMap[action] = pressed

    def start(self, startPos, playerName):
        self.name = playerName
        self.points = 0
        self.health = 100
        self.model.reparentTo(render)
        self.model.setPos(startPos.x,
                          startPos.y,
                          0)
        for slot in self.mountSlot[:]:
            self.mountSlot.remove(slot)
        # Create a basic weapon
        self.mountSlot.append(Weapon(self.main, "Pistol", 0.30, 25, weaponType="Pistol"))
        # Mount the players default weapon
        self.mountWeapon(self.mountSlot[0])
        self.playerHud.setWeapon("Pistol")

        self.acceptKeys()
        self.playerHud.show()

        taskMgr.add(self.move, "moveTask")

    def stop(self):
        taskMgr.remove("moveTask")
        self.ignoreKeys()
        self.unmountWeapon()
        self.playerHud.hide()
        self.model.hide()

    def addPoints(self, args):
        self.points += 10
        base.messenger.send("setHighscore", [self.points])

    def move(self, task):
        elapsed = globalClock.getDt()
        #self.playerTraverser.traverse(self.main.enemyParent)
        #self.playerTraverser.traverse(self.main.itemParent)

        # set headding
        pos = self.main.mouse.getMousePos()
        pos.setZ(0)
        self.model.lookAt(pos)
        self.model.setP(-90)

        # new player position
        if self.keyMap["up"]:
            # follow mouse mode
            #self.model.setZ(self.model, 5 * elapsed * self.runSpeed)
            # axis move mode
            self.model.setY(self.model.getY() + elapsed * self.runSpeed)
        elif self.keyMap["down"]:
            #self.model.setZ(self.model, -5 * elapsed * self.runSpeed)
            self.model.setY(self.model.getY() - elapsed * self.runSpeed)

        if self.keyMap["left"]:
            # follow mouse mode
            #self.model.setX(self.model, -5 * elapsed * self.runSpeed)
            # axis move mode
            self.model.setX(self.model.getX() - elapsed * self.runSpeed)
        elif self.keyMap["right"]:
            #self.model.setX(self.model, 5 * elapsed * self.runSpeed)
            self.model.setX(self.model.getX() + elapsed * self.runSpeed)

        # actualize cam position
        base.camera.setPos(self.model.getPos())
        base.camera.setZ(20)
        return task.cont

    def mountWeapon(self, _weaponToMount):
        self.activeWeapon = _weaponToMount # self.mountSlot[0]
        if self.activeWeapon.style == "TwoHand":
            self.model.find('**/+SequenceNode').node().pose(0)
        else:
            self.model.find('**/+SequenceNode').node().pose(1)
        self.activeWeapon.model.reparentTo(self.model)
        self.activeWeapon.model.setY(self.model.getY() - 0.1)
        self.model.show()
        self.activeWeapon.model.show()
        self.fireRate = self.activeWeapon.fireRate

    def unmountWeapon(self):
        self.activeWeapon.model.hide()

    def setWeaponTrigger(self, _state):
        self.trigger = _state

        if _state:
            mpos = self.main.mouse.getMousePos()
            self.activeWeapon.doFire(mpos)
            if self.activeWeapon.weaponType == "MG":
                self.fireActiveWeapon()
            else:
                self.activeWeapon.stopFire()
        else:
            self.activeWeapon.stopFire()
            taskMgr.remove("Fire")

    def fireActiveWeapon(self):
        if self.activeWeapon:
            #mpos = self.main.mouse.getMousePos()
            taskMgr.add(self.fireUpdate, "Fire")
            #self.activeWeapon.doFire(mpos)

    def fireUpdate(self, task):
        dt = globalClock.getDt()
        self.lastShot += dt
        mpos = self.main.mouse.getMousePos()
        #print self.lastShot
        if self.lastShot >= self.fireRate:
            self.lastShot -= self.fireRate

            if self.trigger:
                self.activeWeapon.doFire(mpos)
                #task.delayTime += self.fireRate
        return task.again

    def setMouseBtn(self):
        self.trigger = False

        print "Mouse Released"

    def addEnemyDmgEvent(self, _id):
        self.accept("intoPlayer-" + "colEnemy" + str(_id), self.setEnemyAttack)
        #self.accept("outOfPlayer-" + "colEnemy" + str(_id), self.setEnemyAttackOutOfRange)

    def setEnemyAttack(self, _entry):
        enemyColName = _entry.getIntoNodePath().node().getName()
        base.messenger.send("inRange-" + enemyColName, [True])

    def setEnemyAttackOutOfRange(self, _entry):
        enemyColName = _entry.getIntoNodePath().node().getName()
        base.messenger.send("inRange-" + enemyColName, [False])

    def doDamage(self, _dmg):

        if self.health <= 0:
            #print "KILLED IN ACTION"
            self.main.stop()
        else:
            self.health -= _dmg
            #print "Remaining Health: ", self.health
        base.messenger.send("setHealth", [self.health])

    def addHealItemEvent(self, _id):
        self.accept("intoHeal-" + "itemHeal" + str(_id), self.healPlayer)

    def healPlayer(self, _entry):
        itemColName = _entry.getIntoNodePath().node().getName()

        if self.health == 100:
            pass

        else:
            self.health += 50
            base.messenger.send("into-" + itemColName)
            if self.health > 100:
                self.health = 100

        print self.health

    def addWeaponItemEvent(self, _id):
        self.accept("intoWeapon-" + "itemWeapon" + str(_id), self.changeWeapon)

    def changeWeapon(self, _entry):
        itemColName = _entry.getIntoNodePath().node().getName()
        base.messenger.send("into-" + itemColName)
        for weapon in self.mountSlot:
            if weapon.name == "MachineGun":
                return
        self.unmountWeapon()
        self.mountSlot.append(Weapon(self.main, "MachineGun", 0.15, 50, weaponType="MG"))
        self.playerHud.setWeapon("MG")
        self.mountWeapon(self.mountSlot[len(self.mountSlot) - 1])
        self.activeWeapon.model.show()
class Starfox(ShowBase):
    def __init__(self):
        self.height = 500
        super().__init__(self)
        self.scene = self.loader.loadModel("./models/world.egg")
        playerTexture = loader.loadTexture("models/starfoxShip.jpg")
        enemyTexture = loader.loadTexture("models/enemyShip.jpg")
        bulletTexture = loader.loadTexture("models/shot.png")
        self.scene.reparentTo(self.render)

        base.setBackgroundColor(0.1, 0.1, 0.1, 1)

        self.player = self.scene.find("player")
        self.player.setPythonTag("ObjectController", Player(self.player))
        self.player.setTexture(playerTexture)

        self.building_enemy = self.scene.find("building_enemy")
        self.dynamic_enemy = self.scene.find("enemy1")
        self.dynamic_enemy.setTexture(enemyTexture)
        self.bullet = self.scene.find("bullet")
        self.bullet.setTexture(bulletTexture)

        base.cTrav = CollisionTraverser()
        self.CollisionHandlerEvent = CollisionHandlerEvent()
        base.enableParticles()
        self.CollisionHandlerEvent.addInPattern('into-%in')
        self.CollisionHandlerEvent.addOutPattern('out-%in')

        self.accept('into-collision_player', self.crash)
        self.accept('into-collision_plane', self.crash)
        self.accept('into-collision_enemy', self.crash)

        base.cTrav.addCollider(self.scene.find("player/collision**"),
                               self.CollisionHandlerEvent)
        base.cTrav.addCollider(self.scene.find("basePlane/collision**"),
                               self.CollisionHandlerEvent)

        self.player.find("**collision**").node().setFromCollideMask(0x3)
        self.player.find("**collision**").node().setIntoCollideMask(0x3)

        self.dynamic_enemy.find("**collision**").node().setFromCollideMask(0x5)
        self.dynamic_enemy.find("**collision**").node().setIntoCollideMask(0x5)

        self.building_enemy.find("**collision**").node().setFromCollideMask(
            0x5)
        self.building_enemy.find("**collision**").node().setIntoCollideMask(
            0x5)

        #base.cTrav.showCollisions(self.render)

        self.taskMgr.add(self.update, "update")
        InputManager.initWith(self, [
            InputManager.arrowUp, InputManager.arrowDown,
            InputManager.arrowLeft, InputManager.arrowRight,
            InputManager.space, InputManager.keyX, InputManager.keyV
        ])

        self.rails = self.scene.attachNewNode("rails")
        self.scene.find("basePlane").setHpr(70, 0, 0)
        self.rails.setPos(self.scene, 0, 0, 0)
        self.player.reparentTo(self.rails)
        self.player.setPos(self.rails, 0, 0, 0)
        self.rails_y = -50

        self.createStaticEnemy(self.building_enemy, 0, 50, 0)
        self.createStaticEnemy(self.building_enemy, -50, 50, 0)
        self.createStaticEnemy(self.building_enemy, -100, 50, 0)
        self.createStaticEnemy(self.building_enemy, -70, 130, 0)
        self.createStaticEnemy(self.building_enemy, -120, 80, 0)
        self.createStaticEnemy(self.building_enemy, -220, 130, 0)

        DynamicEnemy(self.dynamic_enemy,
                     self.scene,
                     Vec3(-230, 140, 10),
                     base.cTrav,
                     self.CollisionHandlerEvent,
                     type=ENEMY_TYPE.CHASER)
        #DynamicEnemy(self.dynamic_enemy, self.scene, Vec3(-240,160,10) ,  base.cTrav, self.CollisionHandlerEvent)
        #DynamicEnemy(self.dynamic_enemy, self.scene, Vec3(-250,200,10) ,  base.cTrav, self.CollisionHandlerEvent)
        #DynamicEnemy(self.dynamic_enemy, self.scene, Vec3(-270,160,10) ,  base.cTrav, self.CollisionHandlerEvent)
        #DynamicEnemy(self.dynamic_enemy, self.scene, Vec3(-250,200,10) ,  base.cTrav, self.CollisionHandlerEvent)

        self.building_enemy.hide()
        self.dynamic_enemy.hide()

        self.fog = Fog("fog")
        self.fog.setColor(0.1, 0.1, 0.1)
        self.fog.setExpDensity(.3)
        self.fog.setLinearRange(50, 150)
        self.fog.setLinearFallback(45, 160, 320)
        self.render.setFog(self.fog)

        self.dirLight = DirectionalLight("dir light")
        self.dirLight.color = (0.7, 0.7, 1, 1)
        self.dirLightPath = self.render.attachNewNode(self.dirLight)
        self.dirLightPath.setHpr(45, -45, 0)
        self.dirLight.setShadowCaster(True, 512, 512)
        render.setLight(self.dirLightPath)

        filters = CommonFilters(base.win, base.cam)
        filters.setBloom(size="large", mintrigger=0.2)

        self.render.setShaderAuto()

        self.initSounds()
        self.initUI()
        self.onGame = False

    def initUI(self):
        self.font = loader.loadFont('./fonts/Magenta.ttf')

        self.lifes = [
            OnscreenImage(image='./UI/fox-icon-png-8.png',
                          pos=(1.1, 0, 0.8),
                          scale=0.05),
            OnscreenImage(image='./UI/fox-icon-png-8.png',
                          pos=(1.2, 0, 0.8),
                          scale=0.05)
        ]

        self.lifes[0].setTransparency(True)
        self.lifes[1].setTransparency(True)

        self.dialogScreen = DirectDialog(frameSize=(-0.7, 0.7, -0.7, 0.7),
                                         relief=DGG.FLAT)

        s = OnscreenImage(image='./UI/fox-icon-png-8.png',
                          pos=(0, 0, -0.2),
                          scale=0.20,
                          parent=self.dialogScreen)
        s.setTransparency(True)

        self.titleUI = DirectLabel(text="Starfox Region 4",
                                   parent=self.dialogScreen,
                                   scale=0.1,
                                   pos=(0, 0, .2),
                                   text_font=self.font)

        self.btn = DirectButton(text="Start",
                                command=self.startGame,
                                pos=(0, 0, 0),
                                parent=self.dialogScreen,
                                scale=0.07)

    def startGame(self):
        self.dialogScreen.hide()
        self.flyingSound.play()
        self.onGame = True
        self.btn.hide()

    def initSounds(self):
        self.audio3d = Audio3DManager.Audio3DManager(base.sfxManagerList[0],
                                                     self.camera)

        self.flyingSound = self.audio3d.loadSfx(
            "./sounds/great fox flying.mp3")
        self.flyingSound.setLoop(True)

        self.audio3d.attachSoundToObject(self.flyingSound, self.player)
        self.audio3d.setSoundVelocityAuto(self.flyingSound)
        self.audio3d.setListenerVelocityAuto()
        #self.audio3d.setDistanceFactor(100)
        self.audio3d.setDropOffFactor(0)

        self.fireSound = self.audio3d.loadSfx(
            "./sounds/arwing double laser one shot.mp3")
        self.crashSound = self.audio3d.loadSfx("./sounds/break.mp3")

    def createStaticEnemy(self, original, px, py, pz):
        be = original.copyTo(self.scene)
        be.setPos(px, py, pz)
        base.cTrav.addCollider(be.find("**collision**"),
                               self.CollisionHandlerEvent)
        """
        self.pointLight = PointLight("point light")
        self.pointLight.color = (1,1,1,1)
        self.pointLightPath = self.render.attachNewNode(self.pointLight)
        self.pointLightPath.setPos(px,py,pz)
        self.pointLight.attenuation = (1,0,0)
        #self.pointLight.setShadowCaster(True,1024,1024)
        self.render.setLight(self.pointLightPath)
        """

    def crash(self, evt):

        self.crashSound.play()
        objectInto = evt.getIntoNodePath().node().getParent(0).getPythonTag(
            "ObjectController")
        objectFrom = evt.getFromNodePath().node().getParent(0).getPythonTag(
            "ObjectController")

        if (objectInto != None):
            objectInto.crash(objectFrom)

        if (objectFrom != None):
            objectFrom.crash(objectInto)

        lifes = self.player.getPythonTag("ObjectController").getLifes()
        if (lifes <= 0):
            self.onGame = False
            self.dialogScreen.show()
            self.flyingSound.stop()

    def update(self, evt):
        #self.camera.setPos(0,-100,100)

        lifes = self.player.getPythonTag("ObjectController").getLifes()

        if (lifes > 2):
            self.lifes[0].show()
            self.lifes[1].show()
        elif (lifes > 1):
            self.lifes[0].show()
            self.lifes[1].hide()
        elif (lifes > 0):
            self.lifes[0].hide()
            self.lifes[1].hide()

        self.camera.lookAt(self.player)
        self.rails.setPos(self.scene, Path.getXOfY(self.rails_y), self.rails_y,
                          12.4)
        self.rails.setHpr(Path.getHeading(self.rails_y), 0, 0)
        self.dirLight.color = (self.rails_y / 600, 0.7, 1, 1)
        self.camera.setHpr(Path.getHeading(self.rails_y), 0, 0)

        if (self.onGame):
            self.rails_y = self.rails_y + globalClock.getDt() * 10
            #self.player.setPos(self.rails, 0, 0, sin(self.z/10.0)*40 )
            relX, relZ, isShooting = self.player.getPythonTag(
                "ObjectController").update(self.rails, globalClock.getDt())
            self.camera.setPos(self.rails, relX, -30, relZ)
            if (isShooting):
                self.fireSound.play()
                b = Bullet(
                    self.bullet, self.scene, self.player.getPos(self.scene),
                    base.cTrav, self.CollisionHandlerEvent,
                    self.scene.getRelativeVector(self.player,
                                                 Vec3(0, 1, 0)), 40, 0x4)
            enemies = self.scene.findAllMatches("dynamicEnemy")
            for e in enemies:
                enemy = e.getPythonTag("ObjectController")
                enemy.update(self.scene, globalClock.getDt(), self.player,
                             self.bullet)

            bullets = self.scene.findAllMatches("bulletC")
            for b in bullets:
                bullet = b.getPythonTag("ObjectController")
                bullet.update(self.scene, globalClock.getDt(), self.player)

        return Task.cont
Пример #21
0
class MyApp(ShowBase):
    def center_mouse(self):
        self.win.movePointer(0,self.win.getXSize()/2,self.win.getYSize()/2)
    def __init__(self):
        #Game variables
        self.health = 100
        self.panda_kill_count = 0
        self.level = 0
        
        #Implementation variables
        #self.color = [Vec4((204.0/255), (255.0/255), (204/255), 0.1),Vec4((0/255), (255.0/255), (255.0/255), 0.1),Vec4((255.0/255), (51.0/255), (255.0/255), 0.1),Vec4((153.0/255), (255.0/255), (153.0/255), 0.1),Vec4((255.0/255), (178.0/255), (102.0/255), 0.1),Vec4((229.0/255), (204.0/255), (255.0/255), 0.1)]
        self.color = [Vec4(0.4,0.4,0.4,0.1)]
        self.mirror=False
        self.paused=False
        self.displayed=False
        self.game_started=False
        self.randomthings_ = randomthings.RandomThings(self)
        self.shifted_cam=False
        self.is_firstP=False
        self.old_anim2 = None
        self.old_anim=None
        self.timeout=False
        (self.r,self.f,self.b,self.l)=(0,0,0,0)
        self.inside_level=False
        self.move_anim_queue=[]
        self.anim_queue=[]
        self.prev_time=0.0
        self.bullets = []
        self.rightspeed=0
        self.forwardspeed=0
        ShowBase.__init__(self)
        self.makeDefaultPipe()
        bb=self.pipe.getDisplayHeight()
        aa=self.pipe.getDisplayWidth()
        
        self.openDefaultWindow(size=(aa, bb))
        import layer2d
        self.layer2d = layer2d
        self.layer2d.update_info('Loading...')
        self.keyreader= ReadKeys(self,layer2d)
        
        #Sounds
        self.gunshot = self.loader.loadSfx("sounds/gunshot_se.ogg")
        self.gunshot.setLoop(False)
        
        self.music = self.loader.loadSfx("sounds/music.ogg")
        self.music.setLoop(True)
        
        
        self.zombie_die = self.loader.loadSfx('sounds/zombie_die.ogg')
        self.zombie_die.setLoop(False)
        
        self.kicked = self.loader.loadSfx('sounds/kicked.ogg')
        self.kicked.setLoop(False)
        
        self.hurt_sound = self.loader.loadSfx('sounds/hurt.ogg')
        self.hurt_sound.setLoop(False)
        
        self.dead_sound = self.loader.loadSfx('sounds/dead.ogg')
        self.dead_sound.setLoop(False)
        
        self.intro_sound = self.loader.loadSfx('sounds/intro.ogg')
        self.intro_sound.setLoop(False)
        self.intro_sound.play()
        
        
        self.enableParticles()
        self.center_mouse()
        #self.disableMouse()
        self.prev_pos = None
        if base.mouseWatcherNode.hasMouse():
            x=base.mouseWatcherNode.getMouseX()
            y=base.mouseWatcherNode.getMouseY()
            self.prev_pos = (x,y)
        #Hide cursor
        props = WindowProperties()
        props.setCursorHidden(True) 
        self.win.requestProperties(props)
        
        
        self.environ = self.loader.loadModel('models/ourworld')
        self.environ.setPos(0,0,0)
        self.environ.reparentTo(self.render)
        
        
        self.pandaActor = Actor("models/hero_anim", {'kick':'models/hero_anim-kick','unready_to_shoot':'models/hero_anim-unready_to_shoot','jump':'models/hero_anim-jump',"shooting":"models/hero_anim-shooting","ready_to_shoot":"models/hero_anim-ready_to_shoot","ready_to_walk":"models/hero_anim-ready_to_run","ready_to_run":"models/hero_anim-ready_to_run","walk4":"models/hero_anim-walk1", "breathe": "models/hero_anim-breathe", "run": "models/hero_anim-walk"})
        self.pandaActor.setPlayRate(3,'ready_to_shoot')
        self.pandaActor.setPlayRate(-1.0,"ready_to_walk")
        self.pandaActor.setPlayRate(1.5,'run')
        self.pandaActor.setPlayRate(1.5,'ready_to_run')
        self.pandaActor.reparentTo(self.render)
        self.pandaActor.setPos(self.environ,0,0,100)
        self.pandaActor.loop("breathe")
        
        self.phy = NodePath("PhysicsNode")
        self.phy.reparentTo(self.render)
        
        self.pandaAN = ActorNode("PandaActor")
        self.pandaActorPhysicsP = self.phy.attachNewNode(self.pandaAN)
        
        self.physicsMgr.attachPhysicalNode(self.pandaAN)
        self.pandaActor.reparentTo(self.pandaActorPhysicsP)
        
        
        #set mass of panda
        self.pandaAN.getPhysicsObject().setMass(100)
        
        #apply gravity
        self.gravityFN=ForceNode('world-forces')
        self.gravityFNP=self.environ.attachNewNode(self.gravityFN)
        self.gravityForce=LinearVectorForce(0,0,-30.81) #gravity acceleration
        self.gravityFN.addForce(self.gravityForce)
        self.physicsMgr.addLinearForce(self.gravityForce)
        
        
        #camera stuff
        self.camera.reparentTo(self.pandaActor)
        self.camera.lookAt(self.pandaActor)
        self.taskMgr.add(self.spinCameraTask, "zombieTask_SpinCameraTask")
        self.taskMgr.doMethodLater(0.01,self.movePandaTask,"zombieTask_movePandaTask")
        
        
        #Collision Handling
        self.cTrav = CollisionTraverser()
        self.collisionHandler = CollisionHandlerEvent()
        
        #Add collider for terrain
        self.groundCollider = self.environ.find("**/terrain")
        
        #Add walker for panda
        self.collision_sphere = CollisionSphere(0,0,1,1)
        self.collNode = CollisionNode('pandaWalker')
        self.cnodePath = self.pandaActor.attachNewNode(self.collNode)
        self.cnodePath.node().addSolid(self.collision_sphere)
        
        #AddZombieDetector for panda
        self.zombie_sphere = CollisionSphere(0,0,3,1)
        self.zomb_detector_node = CollisionNode('zombieDetector')
        self.zomb_detector_NP = self.pandaActor.attachNewNode(self.zomb_detector_node)
        self.zomb_detector_NP.node().addSolid(self.zombie_sphere)
        #self.zomb_detector_NP.show()
        
        #Add pusher against gravity
        self.pusher = PhysicsCollisionHandler()
        self.pusher.addCollider(self.cnodePath, self.pandaActorPhysicsP)
        self.pusher.addCollider(self.zomb_detector_NP,self.pandaActorPhysicsP)
        self.cTrav.addCollider(self.cnodePath,self.pusher)
        self.cTrav.addCollider(self.zomb_detector_NP,self.pusher)
        
        self.pusher.addInPattern('%fn-into-%in')
        self.pusher.addAgainPattern('%fn-again-%in')
        
        #Add collision handler patterns
        self.collisionHandler.addInPattern('%fn-into-%in')
        self.collisionHandler.addAgainPattern('%fn-again-%in')
        
        self.abientLight = AmbientLight("ambientLight")
        self.abientLight.setColor(Vec4(0.1, 0.1, 0.1, 1))
        self.directionalLight = DirectionalLight("directionalLight")
        self.directionalLight.setDirection(Vec3(-5, -5, -5))
        self.directionalLight.setColor(Vec4((229.0/255), (204.0/255), (255.0/255), 0.7))
        self.directionalLight.setSpecularColor(Vec4(0.4, 0.4, 0.4, 0.1))
        self.directionalLight.setShadowCaster(True,512,512)
        self.render.setLight(self.render.attachNewNode(self.abientLight))
        self.render.setLight(self.render.attachNewNode(self.directionalLight))
        self.render.setShaderAuto()
        
        #create zombie land
        self.zombieland = zombie.Zombies(self)
        self.taskMgr.doMethodLater(0.01,self.zombieland.moveZombie, "zombieTask_ZombieMover")
        layer2d.incBar(self.health)
        self.taskMgr.add(self.game_monitor,"zombieTask_gameMonitor")
        self.taskMgr.doMethodLater(2.7,self.music_play, "zombieTask_music")
        
        #Add random useless things:
        self.randomthings_.add_random_things()
    def music_play(self,task):
        self.music.play()
        return Task.done
    #def get_color(self):
     #   return self.color[min(len(self.color)-1,self.level)]
    
    #GameMonitor
    def game_monitor(self,task):
        if self.paused:
            return Task.cont
        #Update Score
        self.layer2d.update_score(self.panda_kill_count)
        #Check for health of actor
        if self.health <= 0:
            self.dead_sound.play()
            self.pandaActor.detachNode()
            print "LOL u ded"
            self.info = """Game Over..
    Score: """ + str(self.panda_kill_count) + """
    Press alt+f4 to quit the game.
    
    """
            self.layer2d.update_info(self.info)
            self.taskMgr.removeTasksMatching('zombieTask_*')
        
        if self.game_started<>True:
            if not self.displayed:
                self.display_information()
            self.pandaActor.setPos(self.pandaActorPhysicsP.getRelativePoint(self.render,Point3(10,10,100)))
            return Task.cont
        
        #Check if user is inside some level. if yes, pass.
        if self.inside_level or self.timeout:
            return Task.cont
        self.inside_level = True
        #self.health=100
        self.timeout=True
        print ".."
        #The next lines will be executed only when the user is in between two levels (or at the beginning of the game)
        #Display information based on game level
        self.display_information()
        print "HUEHUEHUEHUE"    
        #Schedule wave of zombies
        self.taskMgr.doMethodLater(10,self.addWave, "zombieTask_ZombieAdder")
        
        return Task.cont
        
            
    
    def addWave(self,task):
        ##add a wave of 5 zombies, depending on the level.
        ##speed of zombie increases with each level
        ##durability of zombie increases with each level.
        ##Wave ends when all zombies die.
        self.directionalLight.setSpecularColor(Vec4(0.4, 0.4, 0.4, 0.1))
        self.layer2d.update_info("level"+str(self.level))
        self.timeout=False
        self.zombieland.add(5)
        return Task.done
        
    
    #information displayer
    def display_information(self):
        #display information based on levels.
        print self.game_started
        self.displayed=True
        if self.game_started==False:
            info = """
    Welcome to PandaLand. Once upon a time, there used to be these cute

    little creatures called Pandas. They were lazy, funny, and

    adorable. But that is what we humans thought. Pandas are

    actually an evil alien race that spread from planet to planet,

    spreading destruction and terror everywhere. They ruled earth

    several billion years ago. But our super ancestors (Dinosaurs)

    fought agaisnt them with great valour and selflessness; and managed

    to save planet Earth from doom. But the pandas went into hiding

    (and became cute); until few days back! Now they seek to kill all.

    You, the Joker, are our only hope,since Batman has retired.

    Go Kill Pandas.For Mother Earth!
    
    

    """
            self.layer2d.information['bg'] = (0,0,0,0.8)
        else:
            self.layer2d.update_info('')
            if self.level==0:
                info="""
    Your game will start in a few seconds.
    This is the first level. Pandas will spawn
    and follow you. Shoot to kill.

    Test out your controls while
    they are still cute and harmless :)
    
    Jump: Space
    Shoot: LeftClick
    Kick: RightClick
    Walk: A/W/S/D
    
    For more information, press P.

"""
                
                self.layer2d.information['bg'] = (0,0,0,0.6)
            elif self.level==1:
                info="""
    Level 0 Completed!
    Starting Level 1.
    
    Pandas have turned evil
    and stronger. They will try
    to eat you up.

    To run:
    Press Shift + A/S/W/D

"""
            elif self.level==2:
                info="""
    Level 1 Completed!
    Starting Level 2.
    
    Pandas are even stronger now.
    They will get stronger by
    each level.

    Your automatic shooting speed has
    also improved due to experience
    gained.

"""
            elif self.level==3:
                info="""
    Level 2 Completed!
    Starting Level 3.
    
    Pandas also move faster
    by each level. They really
    want to eat you.

    But don't worry, you also 
    run faster as the levels
    proceed.
    
"""
            else:
                info = """
    Level """ + str(self.level-1) + """ Completed!
    Starting """ + str(self.level) + """ .
    
    Well done!
    Keep fighting, our fate lies
    in your hands.
    
"""
        self.layer2d.update_info(info)
    #self.create_bullet()
    def create_bullet(self):
        self.bullet = self.loader.loadModel('models/gun/bullet')
        self.gunshot.play()
        self.bulletAN = ActorNode("BulletNode")
        self.bulletActorPhysicsP = self.phy.attachNewNode(self.bulletAN)
        
        self.physicsMgr.attachPhysicalNode(self.bulletAN)
        self.bullet.reparentTo(self.bulletActorPhysicsP)
        self.bulletAN.getPhysicsObject().setMass(1)
        self.bullet.setPos(self.pandaActor,0,-3,3.5)
        self.bullet.setScale(0.1,0.1,0.1)
        self.bullet.setHpr(self.pandaActor,0,90,0)
        self.bullet.setP(self.camera.getP()+90)
        self.bullet_sphere = CollisionSphere(0,0,0,0.2)
        self.bullet_collNode = CollisionNode('bullet')
        self.bullet_cnodePath = self.bullet.attachNewNode(self.bullet_collNode)
        self.bullet_cnodePath.node().addSolid(self.bullet_sphere)
        
        #self.pusher.addCollider(self.bullet_cnodePath,self.bulletActorPhysicsP)
        self.cTrav.addCollider(self.bullet_cnodePath,self.collisionHandler)
        
        #self.bullet_cnodePath.show()
        self.bullets += [self.bullet]
    def bulletKiller(self,task):
        if self.paused:
            return Task.cont
        self.bullets[0].remove_node()
        self.bullets = self.bullets[1:]
        return Task.done
    
    
    def bulletThrower(self,task):
        if self.paused:
            return Task.cont
        #make bullet move
        if self.pandaActor.getCurrentAnim()<>'shooting' and self.pandaActor.getCurrentAnim()<>'ready_to_shoot':
            self.pandaActor.play('shooting')
        print "loL"
        self.create_bullet()
        
        self.bulletAN.getPhysicsObject().setVelocity(self.render.getRelativeVector(self.camera,Vec3(0,200,0)))
        
        self.taskMgr.doMethodLater(max(0.05,0.1*(5-self.level)),self.bulletThrower, "zombieTask_bulletThrower")
        self.taskMgr.doMethodLater(0.5,self.bulletKiller, "zombieTask_bulletKiller")
        
        self.prev=True
        
        if self.old_anim2==None:
            self.old_anim2='breathe'
        if self.old_anim2 not in ['run','walk4']:
            self.old_anim2='breathe'
        self.anim_queue = [(self.pandaActor,True,'unready_to_shoot'),(self.pandaActor,False,self.old_anim2)]
        return Task.done
        
    def movePandaTask(self,task):
        
        if self.paused:
            return Task.cont
        tempos = self.pandaActor.getPos()
        speed = 0.1
        if self.run_:
            speed+=0.3*self.level
        self.rightspeed = -(self.r-self.l)*speed
        self.forwardspeed = -(self.f-self.b)*speed
        if (self.r-self.l)<>0 and (self.f-self.b)<>0:
            #print self.forwardspeed
            #print self.rightspeed
            #sys.exit(0)
            self.rightspeed *= 0.7
            self.forwardspeed *= 0.7
        self.pandaActor.setPos(self.pandaActor,self.rightspeed, self.forwardspeed,0)
        return Task.again
    def spinCameraTask(self, task):
        if self.paused:
           
            return Task.cont
        if self.render.getRelativePoint(self.pandaActorPhysicsP,self.pandaActor.getPos())[2] < -10:
            self.pandaAN.getPhysicsObject().setVelocity(0,0,30)
            #self.pandaActor.setPos(self.pandaActorPhysicsP.getRelativePoint(self.render,Point3(10,10,100)))
        self.prev_time=task.time
        
            
            
        #play queued animations:
        for x in self.move_anim_queue+self.anim_queue:
            if x[0].getCurrentAnim()==None:
                if x[1]:
                    x[0].play(x[2])
                else:
                    x[0].loop(x[2])
                if x in self.move_anim_queue:
                    self.move_anim_queue.remove(x)
                elif x in self.anim_queue:
                    self.anim_queue.remove(x)
                    
        
        #Do other stuff
        if self.mouseWatcherNode.hasMouse():
            x=base.mouseWatcherNode.getMouseX()
            y=base.mouseWatcherNode.getMouseY()
            if self.prev_pos==None:
                self.prev_pos = (x,y)
            xx = self.prev_pos[0] - x
            yy = self.prev_pos[1] + y
            self.prev_pos = (xx,yy)
            
            self.pandaActor.setHpr(self.pandaActor,-20*(pi/2.0)*x,0,0)
            
            #self.camera.setHpr(self.pandaActor, 20*(pi/2.0)*x, 20*(pi/2.0)*yy, 0)
            if self.is_firstP:
                self.camera.lookAt(self.pandaActor)
                self.camera.setPos(self.pandaActor,0,0,4)
                self.camera.setHpr(self.camera,180,0,0)
                
            else:
                self.camera.setPos(self.pandaActor,0,8,5)
                self.camera.lookAt(self.pandaActor)
                if self.mirror:
                    self.camera.setY(-self.camera.getY())
                    self.camera.lookAt(self.pandaActor)
            self.camera.setHpr(self.camera,0,20*(pi/2.0)*yy,0)
        self.center_mouse()
        
        #zombie collisions
        return Task.cont
    
    #User Actions:
    def meelee(self):
        #Make actor stomp here. or something
        #Load animation
        self.zombieland.meelee()
        self.anim_queue += [(self.pandaActor,True,self.pandaActor.getCurrentAnim())]
        self.pandaActor.play('kick')
        #pass
    def ranged_start(self):
        #put animation here
        self.old_anim = self.pandaActor.getCurrentAnim()
        if self.old_anim not in  ['shooting','unready_to_shoot','ready_to_shoot'] :
            self.old_anim2 = self.old_anim
        if self.old_anim not in ['ready_to_shoot','shooting','unready_to_shoot']:
            self.pandaActor.play('ready_to_shoot')
        
        self.taskMgr.add(self.bulletThrower, "zombieTask_bulletThrower")
    def ranged_stop(self,task=None):
        if self.paused:
            return Task.cont
        #stop animation here
        if self.pandaActor.getCurrentAnim()<>'shooting' and task==None:
            self.pandaActor.play('shooting')
            self.taskMgr.remove("zombieTask_bulletThrower")
            self.taskMgr.doMethodLater(0.5,self.ranged_stop,'zombieTask_rangedStop')
            return Task.done
        self.taskMgr.remove("zombieTask_bulletThrower")
        return Task.done
Пример #22
0
class PinchTask(ShowBase, GripStateMachine):
    DATA_DIR = 'data'
    
    def __init__(self, id, session, hand, block, mode, wrist):
        ShowBase.__init__(self)
        GripStateMachine.__init__(self)
        base.disableMouse()
        wp = WindowProperties()
        wp.setSize(1920,1080)
        wp.setFullscreen(True)
        base.win.requestProperties(wp)

        self.sub_id = str(id)
        self.sess_id = str(session)
        self.hand = str(hand)
        self.block = str(block)
        self.mode = str(mode)
        self.wrist = str(wrist)
        
        self.prev_blk = os.path.join(self.DATA_DIR,'exp_1',self.sub_id,self.sess_id,self.wrist,self.hand,"B0")
        if self.wrist == 'pron':
            self.table = np.loadtxt('src/pinch_task/trialtable_pron.csv',dtype='str',delimiter=',',skiprows=1)
        elif self.wrist == 'flex':
            self.table = np.loadtxt('src/pinch_task/trialtable_flex.csv',dtype='str',delimiter=',',skiprows=1)
        else:
            raise NameError('Wrist position not found')

        try:
            self.prev_table = np.loadtxt(os.path.join(self.prev_blk, 'final_targets.csv'),dtype='str',delimiter=',',skiprows=1)
            indices = {}
            for i in range(self.prev_table.shape[0]):
                indices[self.prev_table[i,1]] = int(self.prev_table[i,0])-1
            for i in range(self.table.shape[0]):
                self.table[i,11] = self.prev_table[indices[self.table[i,1].strip()],11]
                self.table[i,12] = self.prev_table[indices[self.table[i,1].strip()],12]
                self.table[i,13] = self.prev_table[indices[self.table[i,1].strip()],13]
        except:
            print('Previous target file not found')
        
        self.table = np.array([[item.strip() for item in s] for s in self.table])

        ##################################################
        #only use rows relevant to this block
        #HARDCODED! NOTE IN LOG SHEET
        spec_table = []
        for i in range(self.table.shape[0]):
            if int(self.block)%4 == 0:
                if "(p)" in self.table[i,2]:
                    spec_table.append(self.table[i])
            elif int(self.block)%4 == 1:
                if "(t)" in self.table[i,2]:
                    spec_table.append(self.table[i])
            elif int(self.block)%4 == 2:
                if "(s)" in self.table[i,2]:
                    spec_table.append(self.table[i])
            elif int(self.block)%4 == 3:
                if "(t+s)" in self.table[i,2]:
                    spec_table.append(self.table[i])
        ###################################################
        self.table = np.array(spec_table)

        self.session_dir = os.path.join(self.DATA_DIR,'exp_1',self.sub_id,self.sess_id,self.wrist,self.hand)
        self.subjinfo = self.sub_id + '_' + self.sess_id + '_' + self.hand + '_log.yml'
        self.p_x,self.p_y,self.p_a = GET_POS(self.session_dir,self.subjinfo,self.hand,self.wrist)

        self.rotmat = ROT_MAT(self.p_a,self.hand)

        self.setup_text()
        self.setup_lights()
        self.setup_camera()
        
        self.trial_counter = 0
        self.load_models()
        self.load_audio()
        self.update_trial_command()
        self.countdown_timer = CountdownTimer()
        self.hold_timer = CountdownTimer()

        self.cTrav = CollisionTraverser()
        self.chandler = CollisionHandlerEvent()
        self.chandler.addInPattern('%fn-into-%in')
        self.chandler.addAgainPattern('%fn-again-%in')
        self.chandler.addOutPattern('%fn-outof-%in')
        self.attachcollnodes()

        taskMgr.add(self.read_data, 'read')
        for i in range(5):
            taskMgr.add(self.move_player, 'move%d' % i, extraArgs = [i], appendTask=True)
        taskMgr.add(self.log_data, 'log data')
        taskMgr.add(self.update_state, 'update_state', sort=1)

        self.accept('space', self.space_on)
        self.accept('escape', self.clean_up)
        self.space = False
        self.statenum = list()

        self.max_time = 20
        self.med_data = None

        self.grip_dir = os.path.join(self.DATA_DIR,'exp_1',self.sub_id,self.sess_id,self.wrist,self.hand,"B"+self.block)
        if not os.path.exists(self.grip_dir):
           print('Making new folders: ' + self.grip_dir)
           os.makedirs(self.grip_dir)

        self.dev = MpDevice(RightHand(calibration_files=['calibs/cal_mat_15.mat',  # thumb
                                               'calibs/cal_mat_31.mat',
                                               'calibs/cal_mat_8.mat',
                                               'calibs/cal_mat_21.mat',
                                               'calibs/cal_mat_13.mat'], clock=mono_clock.get_time))

        self.init_ser()

    ############
    #SET UP HUD#
    ############
    def setup_text(self):
        #OnscreenImage(parent=self.cam2dp, image='models/background.jpg')
        self.bgtext = OnscreenText(text='Not recording.', pos=(-0.8, 0.8),
                                 scale=0.08, fg=(0, 0, 0, 1),
                                 bg=(1, 1, 1, 1), frame=(0.2, 0.2, 0.8, 1),
                                 align=TextNode.ACenter)
        self.bgtext.reparentTo(self.aspect2d)

        self.dirtext = OnscreenText( pos=(-0.6, 0.65),
                                 scale=0.08, fg=(0, 0, 0, 1),
                                 bg=(1, 1, 1, 1), frame=(0.2, 0.2, 0.8, 1),
                                 align=TextNode.ACenter)
        self.dirtext.reparentTo(self.aspect2d)

    ##########################
    #SET UP SCENE AND PLAYERS#
    ##########################
    def setup_lights(self):
        pl = PointLight('pl')
        pl.setColor((1, 1, 1, 1))
        plNP = self.render.attachNewNode(pl)
        plNP.setPos(-10, -10, 10)
        self.render.setLight(plNP)
        pos = [[[0, 0, 50], [0, 0, -10]],
               [[0, -50, 0], [0, 10, 0]],
               [[-50, 0, 0], [10, 0, 0]]]
        for i in pos:
            dl = Spotlight('dl')
            dl.setColor((1, 1, 1, 1))
            dlNP = self.render.attachNewNode(dl)
            dlNP.setPos(*i[0])
            dlNP.lookAt(*i[1])
            dlNP.node().setShadowCaster(False)
            self.render.setLight(dlNP)

    def setup_camera(self):
        self.cam.setPos(0, -4, 12)
        self.cam.lookAt(0, 2, 0)
        self.camLens.setFov(90)

    def load_models(self):
        self.back_model = self.loader.loadModel('models/back')
        self.back_model.setScale(10, 10, 10)
        if self.hand == "Left":
            self.back_model.setH(90)
        self.back_model.reparentTo(self.render)

        self.player_offsets = [[self.p_x[0]-5, self.p_y[0]+3, 0], [self.p_x[1]-2.5, self.p_y[1]+4.5, 0], [self.p_x[2], self.p_y[2]+5, 0],
                                [self.p_x[3]+2.5, self.p_y[3]+4.5, 0], [self.p_x[4]+5, self.p_y[4]+3, 0]]
        self.p_col =[[0,0,250],[50,0,200],[125,0,125],[200,0,50],[250,0,0]]
        if self.hand == 'Left':
            self.p_col = self.p_col[::-1]

        self.players = list()
        self.contacts = list()        
        for counter, value in enumerate(self.player_offsets):
            self.players.append(self.loader.loadModel('models/target'))
            self.contacts.append(False)

            self.players[counter].setPos(*value)
            self.players[counter].setScale(0.2, 0.2, 0.2)
            self.players[counter].setColorScale(
                self.p_col[counter][0]/255, self.p_col[counter][1]/255, self.p_col[counter][2]/255, 1)
            self.players[counter].reparentTo(self.render)
            self.players[counter].show()

        self.target_select()

    def load_audio(self):
        self.pop = self.loader.loadSfx('audio/Blop.wav')
        self.buzz = self.loader.loadSfx('audio/Buzzer.wav')


    ############################
    #SET UP COLLISION MECHANICS#
    ############################
    def attachcollnodes(self):
        for i in range(5):
            self.fromObject = self.players[i].attachNewNode(CollisionNode('colfromNode'+str(i)))
            self.fromObject.node().addSolid(CollisionSphere(0,0,0,1))
            self.cTrav.addCollider(self.fromObject, self.chandler)

        for i in range(5):
            self.accept('colfromNode%d-into-colintoNode' % i, self.collide1,[i])
            self.accept('colfromNode%d-again-colintoNode' % i, self.collide2,[i])
            self.accept('colfromNode%d-outof-colintoNode' % i, self.collide3,[i])

    def collide1(self,f,collEntry):
        if f in self.highlighted_indices:
            self.players[f].setColorScale(0,1,0,0)
            self.tar.setColorScale(0.2,0.2,0.2,1)
            self.tar.setAlphaScale(0.7)
            self.contacts[f] = True
            taskMgr.doMethodLater(self.delay,self.too_long,'too_long%d' % f,extraArgs = [f])
            self.sendsig(1,f,100)
                
    def collide2(self,f,collEntry):
        if f in self.highlighted_indices:
            dist = np.sqrt(self.distances[f][1]^2+self.distances[f][2]^2+self.distances[f][3]^2)
            self.sendsig(2,f,int(10/dist)+100)
        for i in self.highlighted_indices:
            if self.contacts[i] == False:
                return
        taskMgr.remove('too_long%d' % f)

    def collide3(self,f,collEntry):
        taskMgr.remove('too_long%d' % f)
        self.reset_fing(f)
        self.tar.setColorScale(0.1,0.1,0.1,1)
        self.tar.setAlphaScale(0.7)

    def too_long(self,f):
        self.reset_fing(f)
        self.tar.setColorScale(0.5,0.2,0.2,1)
        self.tar.setAlphaScale(0.7)

    def reset_fing(self,f):
        self.players[f].setColorScale(
                self.p_col[f][0]/255, self.p_col[f][1]/255, self.p_col[f][2]/255, 1)
        self.contacts[f] = False
        self.sendsig(3,f,0)

    ###############
    #TARGET THINGS#
    ###############
    def show_target(self):
        self.target_select()
        self.intoObject = self.tar.attachNewNode(CollisionNode('colintoNode'))

        if self.table[self.trial_counter,7] == "sphere":
            self.intoObject.node().addSolid(CollisionSphere(0,0,0,1))
        elif self.table[self.trial_counter,7] == "cylinder":
            self.intoObject.node().addSolid(CollisionTube(0,0,-2,0,0,2,1))
        else:
            raise NameError("No such collision type")

        self.tar.show()

        #hide players not related to target
        for i in range(5):
            if i not in self.highlighted_indices:
                self.players[i].hide()
        
    def target_select(self):
        self.tgtscx=float(self.table[self.trial_counter,14])
        self.tgtscy=float(self.table[self.trial_counter,15])
        self.tgtscz=float(self.table[self.trial_counter,16])
        tgttsx=float(self.table[self.trial_counter,11])
        tgttsy=float(self.table[self.trial_counter,12])
        tgttsz=float(self.table[self.trial_counter,13])
        tgtrx=float(self.table[self.trial_counter,17])
        tgtry=float(self.table[self.trial_counter,18])
        tgtrz=float(self.table[self.trial_counter,19])
        if self.hand == 'Left':
            tgttsx *= -1
            tgtrx *= -1

        self.static_task = (str(self.table[self.trial_counter,5]) == "True")
        self.target_model = str(self.table[self.trial_counter,6])
        self.highlighted_indices=[int(s)-1 for s in self.table[self.trial_counter,4].split(' ')]
        if self.hand == 'Left':
            self.highlighted_indices=[4-i for i in self.highlighted_indices]

        #NOTE:this position finding is present in all three tasks
        #     it is somewhat hacky and can be improved upon
        self.tgtposx = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][[-2,-1],0]) + tgttsx
        self.tgtposy = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][[0,1],1]) + tgttsy
        if len(self.highlighted_indices) > 3: #for sphere, return to just average of all fingers
            self.tgtposx = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][:,0]) + tgttsx
            #self.tgtposy = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][:,1])
        self.tgtposz = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][:,2]) + tgttsz

        self.tar = self.loader.loadModel(self.target_model)
        self.tar.setScale(self.tgtscx,self.tgtscy,self.tgtscz)
        self.tar.setPos(self.tgtposx,self.tgtposy,self.tgtposz)
        self.tar.setHpr(tgtrx,tgtry,tgtrz)
        self.tar.setColorScale(0.1, 0.1, 0.1, 1)
        self.tar.setAlphaScale(0.7)
        self.tar.setTransparency(TransparencyAttrib.MAlpha) 
        self.tar.reparentTo(self.render)
        self.tar.hide()

        self.delay=float(self.table[self.trial_counter,8])
        self.loc_angle=math.radians(float(self.table[self.trial_counter,9]))
        self.invf=float(self.table[self.trial_counter,10])
        
        self.distances = [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]

    ##############
    #MOVE FINGERS#
    ##############
    def read_data(self,task):
        error, data = self.dev.read()
        if data is not None:
            data *= 0.001
            self.ts = data.time
            data = np.dot(data,self.rotmat)
            self.data = data
            if self.med_data is None:
                self.med_data = np.median(data, axis=0)

            if self.space:
                self.statenum.extend(([self.checkstate()])*len(data.time))
                
        return task.cont
        
    def move_player(self,p,task):
        if self.data is not None :
            k = p*3
            new_x = 10*np.mean(self.data[-1,k]) + self.player_offsets[p][0] - 10*self.med_data[k]
            new_y = 10*np.mean(self.data[-1,k + 1]) + self.player_offsets[p][1] - 10*self.med_data[k + 1]
            new_z = 10*np.mean(self.data[-1,k + 2]) + self.player_offsets[p][2] - 10*self.med_data[k + 2]

            #make sure digits do not cross each other
            if ((p in range(1,3) and p+1 in self.highlighted_indices and new_x > self.players[p+1].getX())
                or (p in range(2,4) and p-1 in self.highlighted_indices and new_x < self.players[p-1].getX())):
                    new_x = self.players[p].getX()
            
            #make sure digits do not cross into target
            if self.space == True and p in self.highlighted_indices:
                self.distances[p][0] = new_x - self.tar.getX()
                self.distances[p][1] = new_y - self.tar.getY()
                self.distances[p][2] = new_z - self.tar.getZ()
                self.check_pos(p)
                
            self.players[p].setPos(new_x, new_y, new_z)
            
        return task.cont
    
    def check_pos(self,p):
        if (abs(self.distances[p][0]) < self.invf*self.tgtscx
            and abs(self.distances[p][1]) < self.invf*self.tgtscy
            and abs(self.distances[p][2]) < self.invf*self.tgtscz):
                self.too_long(p)

    ##################
    #CHECK COMPLETION#
    ##################
    def close_to_target(self):
        for i in self.highlighted_indices:
            if self.contacts[i] == False:
                return False

        if not self.check_angle():
            self.tar.setColorScale(0.1,0.1,0.1,1)
            self.tar.setAlphaScale(0.7)
            return False

        self.tar.setColorScale(0,1,1,1)
        return True

    def check_hold(self):
        if not self.close_to_target():
            self.hold_timer.reset(0.5)
            return False
        return self.hold_timer.elapsed() < 0

    def check_angle(self):
        #hardcoded condition may be able to be assimilated into old angle method somehow
        if self.table[self.trial_counter,1] == 'pts':
            vec = np.subtract(self.players[self.highlighted_indices[1]].getPos(), self.players[self.highlighted_indices[0]].getPos())
            xvec = [1,0,0]
            if self.hand == 'Left':
                xvec = [-1,0,0]
            print(math.degrees(math.acos(np.dot(vec,xvec)/(np.linalg.norm(vec)*np.linalg.norm(xvec)))))
            if math.acos(np.dot(vec,xvec)/(np.linalg.norm(vec)*np.linalg.norm(xvec))) < self.loc_angle:
                return True
            else: return False
        thumbindx = 0
        if self.hand == "Left": thumbindx = 4
        for i in self.highlighted_indices:
            if i == thumbindx:
                continue
            th = self.distances[thumbindx]
            fg = self.distances[i]
            if math.acos(np.dot(th,fg)/(np.linalg.norm(th)*np.linalg.norm(fg))) > self.loc_angle:
                return True
        return False

    def adjust_targets(self):
        #no adjustment if more than 2 fingers or position is prone
        if len(self.highlighted_indices) > 2 or self.wrist == 'pron':
            return

        xadj,yadj,zadj = np.mean(np.asarray(self.distances)[self.highlighted_indices],0)
        #yadj = np.mean(np.asarray(self.distances)[self.highlighted_indices][1])
        #zadj = np.mean(np.asarray(self.distances)[self.highlighted_indices][2])

        #do adjustment on all tasks with same name
        if self.hand == 'Left':
            xadj = -xadj
        for i in range(self.trial_counter+1,self.table.shape[0]):
            if self.table[i,1] == self.table[self.trial_counter,1]:
                self.table[i,11] = float(self.table[i,11]) + xadj
                self.table[i,12] = float(self.table[i,12]) + yadj
                self.table[i,13] = float(self.table[i,13]) + zadj


    #########
    #LOGGING#
    #########
    def play_success(self):
        if int(self.block) == 0:
            self.adjust_targets()
        self.pop.play()
        self.tar.hide()
        self.highlighted_indices = [0,1,2,3,4]

    def log_text(self):
        self.bgtext.setText('Now logging...')

    def log_data(self, task):
        if (self.trial_counter + 1) <= self.table.shape[0]:
            if self.space:
                self.log_file_name = os.path.join(self.grip_dir,
                                          self.sub_id+"_"+self.sess_id+"_"+self.hand+"_"+
                                              str(self.table[self.trial_counter,1])+"_"+str(self.table[self.trial_counter,0])+".csv" )
                self.movvars = np.column_stack((self.ts, self.statenum, self.data))
                self.statenum = []
                if self.mode=='task':
                    with open(self.log_file_name, 'ab') as f:
                        np.savetxt(f, self.movvars, fmt='%10.5f', delimiter=',')
            return task.cont
        else:
            pass

    def stoplog_text(self):
        self.dirtext.clearText()
        self.bgtext.setText('Done logging!')
        for i in range(5):
            self.players[i].show()

    #######
    #RESET#
    #######
    def delete_file(self):
        if (self.trial_counter + 1) <= self.table.shape[0]:
            self.log_file_name = os.path.join(self.grip_dir,
                                      self.sub_id+"_"+self.sess_id+"_"+self.hand+"_"+
                                          str(self.table[self.trial_counter,1])+"_"+str(self.table[self.trial_counter,0])+".csv" )
            try:
                os.remove(self.log_file_name)
            except OSError:
                pass
        else:
            pass

    def reset_baseline(self):
       self.med_data = None
                   
    def reset_keyboard_bool(self):
        self.space = False

    def hide_target(self):
        self.tar.hide()
        self.intoObject.removeNode()
        self.imageObject.destroy()

    def update_trial_command(self):
        self.dirtext.setText(str(self.table[self.trial_counter,2]))
        if self.hand == 'Left':
            xfac = -0.25
        else:
            xfac = 0.25
        self.imageObject = OnscreenImage(image = str(self.table[self.trial_counter,3]),scale=(xfac,0.25,0.25),pos=(-1.2, 0, 0.3))

    def increment_trial_counter(self):
        self.trial_counter += 1
        self.update_trial_command()

    ########
    #TIMERS#
    ########
    def start_trial_countdown(self):
        self.countdown_timer.reset(self.max_time)

    def start_hold_countdown(self):
        self.hold_timer.reset(0.5)

    def start_post_countdown(self):
        self.countdown_timer.reset(2)

    def time_elapsed(self):
        return self.countdown_timer.elapsed() < 0

    #########
    #MACHINE#
    #########
    def update_state(self, task):
        self.step()
        return task.cont

    def wait_for_space(self):
        return self.space

    def space_on(self):
        self.space = True

    #####
    #END#
    #####
    def trial_counter_exceeded(self):
        return (self.trial_counter+1) > self.table.shape[0]-1

    def clean_up(self):
        #write last known positions to 'final_targets' file
        f = open('src/pinch_task/trialtable_flex.csv')
        header = f.readline().rstrip()
        np.savetxt(self.grip_dir + '/final_targets.csv',self.table,fmt='%s',header = header, delimiter=',')
        f.close()
        sys.exit()

    ########
    #SERIAL#
    ########
    def init_ser(self):
        #CONNECT TO HAPTIC DEVICE
        ports = list_ports.comports()
        mydev = next((p.device for p in ports if p.pid == 1155))
        self.ser = serial.Serial(mydev,9600,timeout=.1)

    def sendsig(self,signal,finger,intensity):
        #would read from table, but table not available yet
        if intensity > 255:
            intensity = 255
        dur_int = [signal,finger,intensity]
        data = struct.pack('3B',*dur_int)
        self.ser.write(data)
Пример #23
0
class SmartCar(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        # Override defaults
        self.disableMouse()
        self.setBackgroundColor(VBase3(160, 200, 150) / 255.0)
        self.setFrameRateMeter(True)

        # Lights
        dlight = DirectionalLight("dlight")
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(180.0, -70.0, 0)
        self.render.setLight(dlnp)

        alight = AmbientLight("alight")
        alnp = self.render.attachNewNode(alight)
        alight.setColor(VBase4(0.4, 0.4, 0.4, 1))
        self.render.setLight(alnp)

        # Collision traverser
        self.cTrav = CollisionTraverser("collisionTraverser")
        #self.cTrav.showCollisions(self.render)

        # Collision handlers
        self.carCollisionHandler = CollisionHandlerEvent()
        self.carCollisionHandler.addInPattern("%fn-into-%in")

        # Camera controls
        self.cameraController = CameraController(self, 250, math.pi / 4.0, math.pi / 4.0)
        #self.cameraController = CameraController(self, 300, -math.pi, math.pi / 4.0)

        # Load the track
        self.track = self.loader.loadModel("models/trackMotegi")
        checkpointsCollision = self.track.find("checkpoints").node()
        checkpointsCollision.setIntoCollideMask(BitMask32(0xF0))
        self.numCheckpoints = checkpointsCollision.getNumSolids()
        self.track.reparentTo(self.render)

        # Load the car
        #self.car = KeyboardCar(self)
        self.car = NeuralNetworkCar(self)
        self.cameraController.follow(self.car.getNodePath())
        #self.cameraController.setTarget(self.car.getNodePath())

        # Reposition the car
        #self.car.getNodePath().setH(180.0)

        # Register car collisions with track
        self.cTrav.addCollider(self.car.carCollider, self.carCollisionHandler)
        self.accept("carCollider-into-trackCollision", self.car.onCrash)
        self.accept("carCollider-into-checkpoints", self.car.onCheckpoint)

        # State logger
        self.loggingActive = False
        self.log = []
        self.accept("l", self.toggleStateLogger)

    def toggleStateLogger(self):
        if not self.loggingActive:
            print "LOG: started."
            self.taskMgr.add(self.stateLogger, "StateLoggerTask")
        else:
            self.taskMgr.remove("StateLoggerTask")
            self.writeLog("data/log.csv")
        self.loggingActive = not self.loggingActive

    def stateLogger(self, task):
        row = [self.car.speed, self.car.steerAngle]
        row.extend(self.car.sensorDistances)
        row.append(float(self.car.arrowUpDown))
        row.append(float(self.car.arrowLeftDown))
        row.append(float(self.car.arrowRightDown))
        self.log.append(row)
        return task.again

    def writeLog(self, filename):
        with open(filename, 'wb') as file:
            wr = csv.writer(file)
            wr.writerows(self.log)
        print "LOG: written."
Пример #24
0
    def __init__(self):
	global collide
        ShowBase.__init__(self)

	self.traverser = CollisionTraverser('traverser1')
	base.cTrav = self.traverser
	#traverser.addCollider(cnode1, handler)

	entry = 1

	imageObject = OnscreenImage(image = '/Users/devanshi/Downloads/sky.png', pos = (0, 0, 0), scale = 2)
	imageObject.setTransparency(TransparencyAttrib.MAlpha)
	base.cam.node().getDisplayRegion(0).setSort(20)
		
	self.forest=NodePath(PandaNode("Forest Root"))
        self.forest.reparentTo(render)
        loader.loadModel("models/background").reparentTo(self.forest)
        loader.loadModel("models/foliage01").reparentTo(self.forest)
        loader.loadModel("models/foliage02").reparentTo(self.forest)
        loader.loadModel("models/foliage03").reparentTo(self.forest)
        loader.loadModel("models/foliage04").reparentTo(self.forest)
        loader.loadModel("models/foliage05").reparentTo(self.forest)
        loader.loadModel("models/foliage06").reparentTo(self.forest)
        loader.loadModel("models/foliage07").reparentTo(self.forest)
        loader.loadModel("models/foliage08").reparentTo(self.forest)
        loader.loadModel("models/foliage09").reparentTo(self.forest)
	
	
	self.forest1=NodePath(PandaNode("Forest Root"))
        self.forest1.reparentTo(render)
        
        loader.loadModel("models/foliage01").reparentTo(self.forest1)
        loader.loadModel("models/foliage02").reparentTo(self.forest1)
        loader.loadModel("models/foliage03").reparentTo(self.forest1)
        loader.loadModel("models/foliage04").reparentTo(self.forest1)
        loader.loadModel("models/foliage05").reparentTo(self.forest1)
        loader.loadModel("models/foliage06").reparentTo(self.forest1)
        loader.loadModel("models/foliage07").reparentTo(self.forest1)
        loader.loadModel("models/foliage08").reparentTo(self.forest1)
        loader.loadModel("models/foliage09").reparentTo(self.forest1)

        self.forest.hide(BitMask32.bit(1))
	
        self.forest.setScale(2.5, 2.5, 2.5)
        self.forest.setPos(0, 0, -2)

        self.forest1.hide(BitMask32.bit(1))
	
        self.forest1.setScale(1.5, 1.5, 1.5)
        self.forest1.setPos(-1,-1, 0)

	self.forest2=NodePath(PandaNode("Forest Root"))
        self.forest2.reparentTo(render)
        
        loader.loadModel("models/foliage01").reparentTo(self.forest2)
        loader.loadModel("models/foliage02").reparentTo(self.forest2)
        loader.loadModel("models/foliage03").reparentTo(self.forest2)
        loader.loadModel("models/foliage04").reparentTo(self.forest2)
        loader.loadModel("models/foliage05").reparentTo(self.forest2)
        loader.loadModel("models/foliage06").reparentTo(self.forest2)
        loader.loadModel("models/foliage07").reparentTo(self.forest2)
        loader.loadModel("models/foliage08").reparentTo(self.forest2)
        loader.loadModel("models/foliage09").reparentTo(self.forest2)

        self.forest2.hide(BitMask32.bit(1))

        self.forest1.setScale(1.5, 1.5, 1.5)
        self.forest1.setPos(1,1, 0)

	self.stall = self.loader.loadModel("models/patch/cornfield")
	self.stall.reparentTo(self.render)
	self.stall.setScale(0.5)
	self.stall.setPos(40,0,1)
	self.stall.setHpr(0,0,0)
	self.tex1=self.loader.loadTexture("models/water.png")
	self.stall.setTexture(self.tex1,1)

	self.flock = Actor("models/goose/goosemodelonly",  {"gfly":"models/goose/gooseanimationonly"
                       })

        self.flock.setScale(0.05, 0.05, 0.05)
	self.flock.setPos(0,-30,13)
        self.flock.reparentTo(self.render)
	self.flock.loop("gfly")
	self.tex2=self.loader.loadTexture("models/orange.jpg")
	self.flock.setTexture(self.tex2,1)

	self.camera.setPos(0,0,0)
	self.camera.setHpr(90,0,0)

       # Create the four lerp intervals needed for the panda to
        # walk back and forth.
        pandaPosInterval1 = self.flock.posInterval(13,
                                                        Point3(-5, -30, 13),
                                                        startPos=Point3(5, -30, 13))
        pandaPosInterval2 = self.flock.posInterval(13,
                                                        Point3(5, -30, 13),
                                                        startPos=Point3(-5, -30, 13))
        pandaHprInterval1 = self.flock.hprInterval(3,
                                                        Point3(0, 0, 0),
                                                        startHpr=Point3(180, 0, 0))
        pandaHprInterval2 = self.flock.hprInterval(3,
                                                        Point3(180, 0, 0),
                                                        startHpr=Point3(0, 0, 0))
 
        # Create and play the sequence that coordinates the intervals.
        self.pandaPace = Sequence(pandaPosInterval1,
                                  pandaHprInterval1,
                                  pandaPosInterval2,
                                  pandaHprInterval2,
                                  name="pandaPace")
        self.pandaPace.loop()

		
	
	
        # Disable the camera trackball controls.
        #self.disableMouse()
 
        # Load the environment model.
        self.environ = self.loader.loadModel("models/environment1")
        # Reparent the model to render.
        self.environ.reparentTo(self.render)
        # Apply scale and position transforms on the model.
        self.environ.setScale(0.25, 0.25, 0.25)
        self.environ.setPos(-8, 42, 0)

	self.boy =  Actor("models/trex/trex",  {"run":"models/trex/trex-run",
                                  "eat":"models/trex/trex-eat"})
	self.boy.reparentTo(self.render)
	self.boy.setPos(0,0,0)
	self.boy.setScale(0.5)
	self.isMoving = False
	self.myAnimControl = self.boy.getAnimControl('run')
				
	base.camera.setPos(self.boy.getX(),self.boy.getY()+10,20)
	self.floater = NodePath(PandaNode("floater"))
	self.floater.reparentTo(render)
		
	self.cBoy = self.boy.attachNewNode(CollisionNode('cBoyNode'))
	self.cBoy.node().addSolid(CollisionSphere(0, 0, 3, 8.5))
	#self.cBoy.show()
		
	#self.cPond = self.stall.attachNewNode(CollisionNode('cPond'))
	#self.cPond.node().addSolid(CollisionSphere(40, 0, 1, 70))
	#self.cPond.show()
	
 
        # Add the spinCameraTask procedure to the task manager.
        #self.taskMgr.add(self.spinCameraTask,"asdsad")
	self.keyMap = {"left":0, "right":0, "forward":0, "cam-left":0, "cam-right":0}

	cs1 = CollisionSphere(0, 0, 0, 2)
	self.cnodePath1 = render.attachNewNode(CollisionNode('cnode1'))
	self.cnodePath1.node().addSolid(cs1)
	#self.cnodePath1.setCollideMask(BitMask32(0x10))
	#self.cnodePath1.show()

	
	self.taskMgr.add(self.moveSphere1, "sfasdasf")
 

	cs2 = CollisionSphere(0, 0, 0, 1)
	self.cnodePath2 = render.attachNewNode(CollisionNode('cnode2'))
	self.cnodePath2.node().addSolid(cs2)
	#self.cnodePath2.reparentTo(self.render)
	#self.cnodePath2.node().setFromCollideMask(BitMask32.bit(0))
        #self.cnodePath2.node().setIntoCollideMask(BitMask32.allOff())
	#self.cnodePath2.show()

	self.taskMgr.add(self.moveSphere2, "sfasd")


	handler = CollisionHandlerEvent()
	handler.addInPattern('cnode1-into-cnode2')
	handler.addAgainPattern('cnode1-again-cnode2')
	handler.addOutPattern('cs1-out-cs2')


	self.accept('cnode1-into-cnode2', self.collide)
	#self.accept('cs1-out-cs2', self.collide)
	#self.accept('cnode1-again-cnode2', self.collide)


	self.traverser.addCollider(self.cnodePath1, handler)

        # Load and transform the panda actor.
        self.pandaActor = Actor("models/panda-model",
                                {"walk": "models/panda-walk4"})
        self.pandaActor.setScale(0.005, 0.005, 0.005)
        self.pandaActor.reparentTo(self.render)
        # Loop its animation.
        self.pandaActor.loop("walk")

	self.taskMgr.add(self.movePanda, "Sasdas")
	
	self.pandaActor2 = Actor("models/panda-model",{"walk": "models/panda-walk4"})
        self.pandaActor2.setScale(0.003, 0.003, 0.003)
        self.pandaActor2.reparentTo(self.render)
        # Loop its animation.
        self.pandaActor2.loop("walk")

	self.taskMgr.add(self.movePanda2, "Sak")

	self.camera.setPos(0,0,0)
	self.camera.setHpr(90,0,0)

	self.cTrav1=CollisionTraverser()
	self.collisionHandler1 = CollisionHandlerQueue()
	self.cTrav1.addCollider(self.cBoy, self.collisionHandler1)

	self.taskMgr.add(self.boyMoveTask, "BoyMoveTask")
		
	#self.accept("v",self.switchView)
	self.accept("escape", sys.exit)
	self.accept("arrow_left", self.setKey, ["left",1])
	self.accept("arrow_right", self.setKey, ["right",1])
	self.accept("arrow_up", self.setKey, ["forward",1])
	#self.accept("a", self.setKey, ["cam-left",1])
	#self.accept("s", self.setKey, ["cam-right",1])
	self.accept("arrow_left-up", self.setKey, ["left",0])
	self.accept("arrow_right-up", self.setKey, ["right",0])
	self.accept("arrow_up-up", self.setKey, ["forward",0])
	#self.accept("a-up", self.setKey, ["cam-left",0])
	#self.accept("s-up", self.setKey, ["cam-right",0])

	self.cTrav2=CollisionTraverser()
	self.collisionHandler2 = CollisionHandlerQueue()
Пример #25
0
class CBShield(DirectObject):
    
    #Property stuff
    creaTime = time.clock()
    dur = 5
    vec = 0
    delta = .15
    prevtime = 0
    flag = False
    
    #defining the thing fired by whatever gun we have
    def __init__(self, camera, look, id):
        
        #nodepath of the projectile, give it a trajectory
        self.projectileNode = NodePath('projectile'+str(id))
        self.projectileNode.setTransparency(TransparencyAttrib.MAlpha)
        self.projectileNode.reparentTo(render)
        
        #by passing the camera node form the camMov object, all projectiles are spawned 5 units in front of the camera
        self.projectileNode.setHpr(look, 0, 0, 0)
        self.projectileNode.setPos(camera,-1,10, 3)
        
        #fix z position to line up with gun
        self.projectileNode.setScale(.1)
        projectileModel = loader.loadModel("./resources/cubeShot.egg")
        projectileModel.setColorScale(0, 0, 0, .5)
        projectileModel.setSz(50)
        projectileModel.setSy(1)
        projectileModel.setSx(50)
        projectileModel.reparentTo(self.projectileNode)
    	
        #must calculate unit vector based on direction
        dir = render.getRelativeVector(look, Vec3(0, 1, 0))
    	
        #speed up or slow down projectiles here
        dir = dir*10
        self.vec = dir
        
        #base.cTrav = CollisionTraverser()
        cs = CollisionSphere(0, 0, 0, 25)
        cnodepath = self.projectileNode.attachNewNode(CollisionNode('projNode'))
        cnodepath.node().addSolid(cs)
        self.collHand = CollisionHandlerEvent()
        self.collHand.addInPattern('into'+str(id))
        self.collHand.addOutPattern('outof')
        
        #cTrav has the distinction of global colider handler
        base.cTrav.addCollider(cnodepath, self.collHand)
        self.acceptOnce('into'+str(id), self.hit)
      
	    #deal with colliding or special effects here.
	    #wanted projectiles to be short lived
	    #so i will make them delete themselves after impact or time expired
        #writing a task that will rek the projectiles at the end of time
        self.damage = 20
    
    def placeTask(self, task):
        
        #curtime = time.clock()
        #self.delta = curtime-self.prevtime
        
        if self.flag:
            return task.done
        
        #prevtime = time.clock()
            
        
        if task.time < self.dur:
        
            return task.cont
        else:
            
            self.flag = True
            return task.done
        

    def hit(self, collEntry):
        #throw out a custom message for what hit
        if collEntry.getIntoNodePath().getName() != 'projNode':
           
            temp = collEntry.getIntoNodePath().getName()
            messenger.send(temp, [self.damage]) 
            
            #remove the impacting projectile
            collEntry.getFromNodePath().getParent().getParent().removeNode()
            self.flag =  True
            del self
Пример #26
0
class LearnNeuroevolution(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        # Override defaults
        self.disableMouse()
        self.setBackgroundColor(VBase3(160, 200, 150) / 255.0)
        self.setFrameRateMeter(True)

        # Lights
        dlight = DirectionalLight("dlight")
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(180.0, -70.0, 0)
        self.render.setLight(dlnp)

        alight = AmbientLight("alight")
        alnp = self.render.attachNewNode(alight)
        alight.setColor(VBase4(0.4, 0.4, 0.4, 1))
        self.render.setLight(alnp)

        # Collision traverser
        self.cTrav = CollisionTraverser("collisionTraverser")

        # Collision handlers
        self.carCollisionHandler = CollisionHandlerEvent()
        self.carCollisionHandler.addInPattern("%fn-into-%in")

        # Camera controls
        self.cameraController = CameraController(self, 600, math.radians(45),
                                                 math.radians(60))

        # Load the track
        self.track = self.loader.loadModel("models/trackMotegi")
        # self.track = self.loader.loadModel("models/trackValencia")
        checkpointsCollision = self.track.find("checkpoints").node()
        checkpointsCollision.setIntoCollideMask(BitMask32(0xF0))
        self.numCheckpoints = checkpointsCollision.getNumSolids()
        self.track.reparentTo(self.render)

        # Neuroevolution
        self.inputLayerSize = 9
        self.hiddenLayer1Size = 5
        self.hiddenLayer2Size = 5
        self.numLabels = 2
        self.thetaSizes = [(5, 10), (5, 6), (2, 6)]

        self.generationSize = 20
        self.weightInit = 0.12
        self.replaceRatio = 0.05
        self.scaleRatio = 0.05
        self.addRatio = 0.05

        self.generationCount = 1
        self.cars = []
        for i in range(self.generationSize):
            car = NeuroevolutionCar(self, i, 9)
            # Register car collisions with track
            self.cTrav.addCollider(car.carCollider, self.carCollisionHandler)
            self.accept("carCollider{}-into-trackCollision".format(i),
                        car.onCrash)
            self.accept("carCollider{}-into-checkpoints".format(i),
                        car.onCheckpoint)
            self.cars.append(car)

        # Initial generation
        np.random.seed(3)
        for i in range(self.generationSize):
            theta1 = self.randWeights(5, 10, self.weightInit)
            theta2 = self.randWeights(5, 6, self.weightInit)
            theta3 = self.randWeights(2, 6, self.weightInit)
            self.cars[i].startSimulation(theta1, theta2, theta3)

        # Run learning task
        self.taskMgr.add(self.neuroevolution, "NeuroevolutionTask")

        # DEBUG
        self.txtGen = OnscreenText(text='',
                                   pos=(0.0, -0.04),
                                   scale=0.05,
                                   align=TextNode.ALeft,
                                   fg=(1, 1, 1, 1),
                                   bg=(0, 0, 0, .4))
        self.txtGen.reparentTo(self.a2dTopLeft)

    def neuroevolution(self, task):
        generationDone = True
        for car in self.cars:
            if not car.simulationDone:
                generationDone = False

        if generationDone:
            # Compute fitness scores
            fitness = np.zeros(self.generationSize)
            for i in range(self.generationSize):
                fitness[i] = self.fitnessFunction(self.cars[i].checkpointCount,
                                                  self.cars[i].timeAlive)
            prob = fitness / np.sum(fitness)

            # Generate new generation
            nextGenTheta1 = []
            nextGenTheta2 = []
            nextGenTheta3 = []
            for i in range(self.generationSize):
                # Selection
                (p1_i, p2_i) = np.random.choice(self.generationSize,
                                                2,
                                                replace=False,
                                                p=prob)
                if fitness[p1_i] < fitness[p2_i]:
                    p1_i, p2_i = p2_i, p1_i

                # Crossover
                fit1 = fitness[p1_i]
                fit2 = fitness[p2_i]
                crossoverRatio = fit2 / (fit1 + fit2)

                theta1 = np.copy(self.cars[p1_i].theta1)
                mask1 = np.random.rand(5, 10) < crossoverRatio
                theta1[mask1] = self.cars[p2_i].theta1[mask1]

                theta2 = np.copy(self.cars[p1_i].theta2)
                mask2 = np.random.rand(5, 6) < crossoverRatio
                theta2[mask2] = self.cars[p2_i].theta2[mask2]

                theta3 = np.copy(self.cars[p1_i].theta3)
                mask3 = np.random.rand(2, 6) < crossoverRatio
                theta3[mask3] = self.cars[p2_i].theta3[mask3]

                # Mutation
                # replace
                maskReplace = np.random.rand(5, 10) < self.replaceRatio
                sz = np.sum(maskReplace)
                theta1[maskReplace] = np.random.rand(
                    sz) * 2 * self.weightInit - self.weightInit

                maskReplace = np.random.rand(5, 6) < self.replaceRatio
                sz = np.sum(maskReplace)
                theta2[maskReplace] = np.random.rand(
                    sz) * 2 * self.weightInit - self.weightInit

                maskReplace = np.random.rand(2, 6) < self.replaceRatio
                sz = np.sum(maskReplace)
                theta3[maskReplace] = np.random.rand(
                    sz) * 2 * self.weightInit - self.weightInit

                # scale
                maskScale = np.random.rand(5, 10) < self.scaleRatio
                sz = np.sum(maskScale)
                theta1[maskScale] = theta1[maskScale] * (np.random.rand(sz) +
                                                         0.5)

                maskScale = np.random.rand(5, 6) < self.scaleRatio
                sz = np.sum(maskScale)
                theta2[maskScale] = theta2[maskScale] * (np.random.rand(sz) +
                                                         0.5)

                maskScale = np.random.rand(2, 6) < self.scaleRatio
                sz = np.sum(maskScale)
                theta3[maskScale] = theta3[maskScale] * (np.random.rand(sz) +
                                                         0.5)

                # add
                maskAdd = np.random.rand(5, 10) < self.addRatio
                sz = np.sum(maskAdd)
                theta1[maskAdd] = theta1[maskAdd] + (np.random.rand(sz) -
                                                     0.5) * 2.0

                maskAdd = np.random.rand(5, 6) < self.addRatio
                sz = np.sum(maskAdd)
                theta2[maskAdd] = theta2[maskAdd] + (np.random.rand(sz) -
                                                     0.5) * 2.0

                maskAdd = np.random.rand(2, 6) < self.addRatio
                sz = np.sum(maskAdd)
                theta3[maskAdd] = theta3[maskAdd] + (np.random.rand(sz) -
                                                     0.5) * 2.0

                nextGenTheta1.append(theta1)
                nextGenTheta2.append(theta2)
                nextGenTheta3.append(theta3)

            # Run new generation
            for i in range(self.generationSize):
                self.cars[i].startSimulation(nextGenTheta1[i],
                                             nextGenTheta2[i],
                                             nextGenTheta3[i])

            self.generationCount += 1
            self.txtGen.setText('Gen: {}'.format(self.generationCount))

        return task.cont

    def fitnessFunction(self, checkpointCount, timeAlive):
        f = 100 * checkpointCount + timeAlive + 1
        return f

    def randWeights(self, rows, cols, weightInit):
        w = np.random.rand(rows, cols) * 2 * weightInit - weightInit
        return w
Пример #27
0
class DistributedIceGame(DistributedMinigame.DistributedMinigame,
                         DistributedIceWorld.DistributedIceWorld):
    notify = directNotify.newCategory('DistributedIceGame')
    MaxLocalForce = 100
    MaxPhysicsForce = 25000

    def __init__(self, cr):
        DistributedMinigame.DistributedMinigame.__init__(self, cr)
        DistributedIceWorld.DistributedIceWorld.__init__(self, cr)
        self.gameFSM = ClassicFSM.ClassicFSM('DistributedIceGame', [
            State.State('off', self.enterOff, self.exitOff, ['inputChoice']),
            State.State(
                'inputChoice', self.enterInputChoice, self.exitInputChoice,
                ['waitServerChoices', 'moveTires', 'displayVotes', 'cleanup']),
            State.State('waitServerChoices', self.enterWaitServerChoices,
                        self.exitWaitServerChoices, ['moveTires', 'cleanup']),
            State.State('moveTires', self.enterMoveTires, self.exitMoveTires,
                        ['synch', 'cleanup']),
            State.State('synch', self.enterSynch, self.exitSynch,
                        ['inputChoice', 'scoring', 'cleanup']),
            State.State('scoring', self.enterScoring, self.exitScoring,
                        ['cleanup', 'finalResults', 'inputChoice']),
            State.State('finalResults', self.enterFinalResults,
                        self.exitFinalResults, ['cleanup']),
            State.State('cleanup', self.enterCleanup, self.exitCleanup, [])
        ], 'off', 'cleanup')
        self.addChildGameFSM(self.gameFSM)
        self.cameraThreeQuarterView = (0, -22, 45, 0, -62.89, 0)
        self.tireDict = {}
        self.forceArrowDict = {}
        self.canDrive = False
        self.timer = None
        self.timerStartTime = None
        self.curForce = 0
        self.curHeading = 0
        self.headingMomentum = 0.0
        self.forceMomentum = 0.0
        self.allTireInputs = None
        self.curRound = 0
        self.curMatch = 0
        self.controlKeyWarningLabel = DirectLabel(
            text=TTLocalizer.IceGameControlKeyWarning,
            text_fg=VBase4(1, 0, 0, 1),
            relief=None,
            pos=(0.0, 0, 0),
            scale=0.15)
        self.controlKeyWarningLabel.hide()
        self.waitingMoveLabel = DirectLabel(
            text=TTLocalizer.IceGameWaitingForPlayersToFinishMove,
            text_fg=VBase4(1, 1, 1, 1),
            relief=None,
            pos=(-0.6, 0, -0.75),
            scale=0.075)
        self.waitingMoveLabel.hide()
        self.waitingSyncLabel = DirectLabel(
            text=TTLocalizer.IceGameWaitingForAISync,
            text_fg=VBase4(1, 1, 1, 1),
            relief=None,
            pos=(-0.6, 0, -0.75),
            scale=0.075)
        self.waitingSyncLabel.hide()
        self.infoLabel = DirectLabel(text='',
                                     text_fg=VBase4(0, 0, 0, 1),
                                     relief=None,
                                     pos=(0.0, 0, 0.7),
                                     scale=0.075)
        self.updateInfoLabel()
        self.lastForceArrowUpdateTime = 0
        self.sendForceArrowUpdateAsap = False
        self.treasures = []
        self.penalties = []
        self.obstacles = []
        self.controlKeyPressed = False
        self.controlKeyWarningIval = None
        return

    def delete(self):
        DistributedIceWorld.DistributedIceWorld.delete(self)
        DistributedMinigame.DistributedMinigame.delete(self)
        if self.controlKeyWarningIval:
            self.controlKeyWarningIval.finish()
            self.controlKeyWarningIval = None
        self.controlKeyWarningLabel.destroy()
        del self.controlKeyWarningLabel
        self.waitingMoveLabel.destroy()
        del self.waitingMoveLabel
        self.waitingSyncLabel.destroy()
        del self.waitingSyncLabel
        self.infoLabel.destroy()
        del self.infoLabel
        for treasure in self.treasures:
            treasure.destroy()

        del self.treasures
        for penalty in self.penalties:
            penalty.destroy()

        del self.penalties
        for obstacle in self.obstacles:
            obstacle.removeNode()

        del self.obstacles
        del self.gameFSM
        return

    def announceGenerate(self):
        DistributedMinigame.DistributedMinigame.announceGenerate(self)
        DistributedIceWorld.DistributedIceWorld.announceGenerate(self)
        self.debugTaskName = self.uniqueName('debugTask')

    def getTitle(self):
        return TTLocalizer.IceGameTitle

    def getInstructions(self):
        szId = self.getSafezoneId()
        numPenalties = IceGameGlobals.NumPenalties[szId]
        result = TTLocalizer.IceGameInstructions
        if numPenalties == 0:
            result = TTLocalizer.IceGameInstructionsNoTnt
        return result

    def getMaxDuration(self):
        return 0

    def load(self):
        self.notify.debug('load')
        DistributedMinigame.DistributedMinigame.load(self)
        self.music = base.loader.loadMusic('phase_4/audio/bgm/MG_IceGame.ogg')
        self.gameBoard = loader.loadModel(
            'phase_4/models/minigames/ice_game_icerink')
        background = loader.loadModel('phase_4/models/minigames/ice_game_2d')
        backgroundWide = loader.loadModel(
            'phase_4/models/minigames/iceslide_ground')
        background.reparentTo(self.gameBoard)
        backgroundWide.reparentTo(self.gameBoard)
        backgroundWide.setPos(0, -0.3, -0.5)
        self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0)
        self.gameBoard.setScale(1.0)
        self.setupSimulation()
        index = 0
        for avId in self.avIdList:
            self.setupTire(avId, index)
            self.setupForceArrow(avId)
            index += 1

        for index in xrange(len(self.avIdList), 4):
            self.setupTire(-index, index)
            self.setupForceArrow(-index)

        self.showForceArrows(realPlayersOnly=True)
        self.westWallModel = NodePath()
        if not self.westWallModel.isEmpty():
            self.westWallModel.reparentTo(self.gameBoard)
            self.westWallModel.setPos(IceGameGlobals.MinWall[0],
                                      IceGameGlobals.MinWall[1], 0)
            self.westWallModel.setScale(4)
        self.eastWallModel = NodePath()
        if not self.eastWallModel.isEmpty():
            self.eastWallModel.reparentTo(self.gameBoard)
            self.eastWallModel.setPos(IceGameGlobals.MaxWall[0],
                                      IceGameGlobals.MaxWall[1], 0)
            self.eastWallModel.setScale(4)
            self.eastWallModel.setH(180)
        self.arrowKeys = ArrowKeys.ArrowKeys()
        self.target = loader.loadModel('phase_3/models/misc/sphere')
        self.target.setScale(0.01)
        self.target.reparentTo(self.gameBoard)
        self.target.setPos(0, 0, 0)
        self.scoreCircle = loader.loadModel(
            'phase_4/models/minigames/ice_game_score_circle')
        self.scoreCircle.setScale(0.01)
        self.scoreCircle.reparentTo(self.gameBoard)
        self.scoreCircle.setZ(IceGameGlobals.TireRadius / 2.0)
        self.scoreCircle.setAlphaScale(0.5)
        self.scoreCircle.setTransparency(1)
        self.scoreCircle.hide()
        self.treasureModel = loader.loadModel(
            'phase_4/models/minigames/ice_game_barrel')
        self.penaltyModel = loader.loadModel(
            'phase_4/models/minigames/ice_game_tnt2')
        self.penaltyModel.setScale(0.75, 0.75, 0.7)
        szId = self.getSafezoneId()
        obstacles = IceGameGlobals.Obstacles[szId]
        index = 0
        cubicObstacle = IceGameGlobals.ObstacleShapes[szId]
        for pos in obstacles:
            newPos = Point3(pos[0], pos[1], IceGameGlobals.TireRadius)
            newObstacle = self.createObstacle(newPos, index, cubicObstacle)
            self.obstacles.append(newObstacle)
            index += 1

        self.countSound = loader.loadSfx(
            'phase_3.5/audio/sfx/tick_counter.ogg')
        self.treasureGrabSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_sfx_vine_game_bananas.ogg')
        self.penaltyGrabSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_cannon_fire_alt.ogg')
        self.tireSounds = []
        for tireIndex in xrange(4):
            tireHit = loader.loadSfx(
                'phase_4/audio/sfx/Golf_Hit_Barrier_1.ogg')
            wallHit = loader.loadSfx('phase_4/audio/sfx/MG_maze_pickup.ogg')
            obstacleHit = loader.loadSfx(
                'phase_4/audio/sfx/Golf_Hit_Barrier_2.ogg')
            self.tireSounds.append({
                'tireHit': tireHit,
                'wallHit': wallHit,
                'obstacleHit': obstacleHit
            })

        self.arrowRotateSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_sfx_ice_force_rotate.ogg')
        self.arrowUpSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_sfx_ice_force_increase_3sec.ogg')
        self.arrowDownSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_sfx_ice_force_decrease_3sec.ogg')
        self.scoreCircleSound = loader.loadSfx(
            'phase_4/audio/sfx/MG_sfx_ice_scoring_1.ogg')

    def unload(self):
        self.notify.debug('unload')
        DistributedMinigame.DistributedMinigame.unload(self)
        del self.music
        self.gameBoard.removeNode()
        del self.gameBoard
        for forceArrow in self.forceArrowDict.values():
            forceArrow.removeNode()

        del self.forceArrowDict
        self.scoreCircle.removeNode()
        del self.scoreCircle
        del self.countSound

    def onstage(self):
        self.notify.debug('onstage')
        DistributedMinigame.DistributedMinigame.onstage(self)
        self.gameBoard.reparentTo(render)
        self.__placeToon(self.localAvId)
        self.moveCameraToTop()
        self.scorePanels = []
        base.playMusic(self.music, looping=1, volume=0.8)

    def offstage(self):
        self.notify.debug('offstage')
        self.music.stop()
        self.gameBoard.hide()
        self.infoLabel.hide()
        for avId in self.tireDict:
            self.tireDict[avId]['tireNodePath'].hide()

        for panel in self.scorePanels:
            panel.cleanup()

        del self.scorePanels
        for obstacle in self.obstacles:
            obstacle.hide()

        for treasure in self.treasures:
            treasure.nodePath.hide()

        for penalty in self.penalties:
            penalty.nodePath.hide()

        for avId in self.avIdList:
            av = self.getAvatar(avId)
            if av:
                av.dropShadow.show()
                av.resetLOD()

        taskMgr.remove(self.uniqueName('aimtask'))
        self.arrowKeys.destroy()
        del self.arrowKeys
        DistributedMinigame.DistributedMinigame.offstage(self)

    def handleDisabledAvatar(self, avId):
        self.notify.debug('handleDisabledAvatar')
        self.notify.debug('avatar ' + str(avId) + ' disabled')
        DistributedMinigame.DistributedMinigame.handleDisabledAvatar(
            self, avId)

    def setGameReady(self):
        if not self.hasLocalToon:
            return
        self.notify.debug('setGameReady')
        if DistributedMinigame.DistributedMinigame.setGameReady(self):
            return
        for index in xrange(self.numPlayers):
            avId = self.avIdList[index]
            toon = self.getAvatar(avId)
            if toon:
                toon.reparentTo(render)
                self.__placeToon(avId)
                toon.forwardSpeed = 0
                toon.rotateSpeed = False
                toon.dropShadow.hide()
                toon.setAnimState('Sit')
                if avId in self.tireDict:
                    tireNp = self.tireDict[avId]['tireNodePath']
                    toon.reparentTo(tireNp)
                    toon.setY(1.0)
                    toon.setZ(-3)
                toon.startLookAround()

    def setGameStart(self, timestamp):
        if not self.hasLocalToon:
            return
        self.notify.debug('setGameStart')
        DistributedMinigame.DistributedMinigame.setGameStart(self, timestamp)
        for avId in self.remoteAvIdList:
            toon = self.getAvatar(avId)
            if toon:
                toon.stopLookAround()

        self.scores = [0] * self.numPlayers
        spacing = 0.4
        for i in xrange(self.numPlayers):
            avId = self.avIdList[i]
            avName = self.getAvatarName(avId)
            scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel(
                avId, avName)
            scorePanel.setScale(0.9)
            scorePanel.setPos(-0.583 - spacing * (self.numPlayers - 1 - i),
                              0.0, -0.15)
            scorePanel.reparentTo(base.a2dTopRight)
            scorePanel.makeTransparent(0.75)
            self.scorePanels.append(scorePanel)

        self.arrowKeys.setPressHandlers([
            self.__upArrowPressed, self.__downArrowPressed,
            self.__leftArrowPressed, self.__rightArrowPressed,
            self.__controlPressed
        ])

    def isInPlayState(self):
        if not self.gameFSM.getCurrentState():
            return False
        if not self.gameFSM.getCurrentState().getName() == 'play':
            return False
        return True

    def enterOff(self):
        self.notify.debug('enterOff')

    def exitOff(self):
        pass

    def enterInputChoice(self):
        self.notify.debug('enterInputChoice')
        self.forceLocalToonToTire()
        self.controlKeyPressed = False
        if self.curRound == 0:
            self.setupStartOfMatch()
        else:
            self.notify.debug('self.curRound = %s' % self.curRound)
        self.timer = ToontownTimer.ToontownTimer()
        self.timer.hide()
        if self.timerStartTime != None:
            self.startTimer()
        self.showForceArrows(realPlayersOnly=True)
        self.localForceArrow().setPosHpr(0, 0, -1.0, 0, 0, 0)
        self.localForceArrow().reparentTo(self.localTireNp())
        self.localForceArrow().setY(IceGameGlobals.TireRadius)
        self.localTireNp().headsUp(self.target)
        self.notify.debug('self.localForceArrow() heading = %s' %
                          self.localForceArrow().getH())
        self.curHeading = self.localTireNp().getH()
        self.curForce = 25
        self.updateLocalForceArrow()
        for avId in self.forceArrowDict:
            forceArrow = self.forceArrowDict[avId]
            forceArrow.setPosHpr(0, 0, -1.0, 0, 0, 0)
            tireNp = self.tireDict[avId]['tireNodePath']
            forceArrow.reparentTo(tireNp)
            forceArrow.setY(IceGameGlobals.TireRadius)
            tireNp.headsUp(self.target)
            self.updateForceArrow(avId, tireNp.getH(), 25)

        taskMgr.add(self.__aimTask, self.uniqueName('aimtask'))
        if base.localAvatar.laffMeter:
            base.localAvatar.laffMeter.stop()
        self.sendForceArrowUpdateAsap = False
        return

    def exitInputChoice(self):
        if not self.controlKeyPressed:
            if self.controlKeyWarningIval:
                self.controlKeyWarningIval.finish()
                self.controlKeyWarningIval = None
            self.controlKeyWarningIval = Sequence(
                Func(self.controlKeyWarningLabel.show),
                self.controlKeyWarningLabel.colorScaleInterval(
                    10, VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1,
                                                                   1)),
                Func(self.controlKeyWarningLabel.hide))
            self.controlKeyWarningIval.start()
        if self.timer != None:
            self.timer.destroy()
            self.timer = None
        self.timerStartTime = None
        self.hideForceArrows()
        self.arrowRotateSound.stop()
        self.arrowUpSound.stop()
        self.arrowDownSound.stop()
        taskMgr.remove(self.uniqueName('aimtask'))
        return

    def enterWaitServerChoices(self):
        self.waitingMoveLabel.show()
        self.showForceArrows(True)

    def exitWaitServerChoices(self):
        self.waitingMoveLabel.hide()
        self.hideForceArrows()

    def enterMoveTires(self):
        for key in self.tireDict:
            body = self.tireDict[key]['tireBody']
            body.setAngularVel(0, 0, 0)
            body.setLinearVel(0, 0, 0)

        for index in xrange(len(self.allTireInputs)):
            input = self.allTireInputs[index]
            avId = self.avIdList[index]
            body = self.getTireBody(avId)
            degs = input[1] + 90
            tireNp = self.getTireNp(avId)
            tireH = tireNp.getH()
            self.notify.debug('tireH = %s' % tireH)
            radAngle = deg2Rad(degs)
            foo = NodePath('foo')
            dirVector = Vec3(math.cos(radAngle), math.sin(radAngle), 0)
            self.notify.debug('dirVector is now=%s' % dirVector)
            inputForce = input[0]
            inputForce /= self.MaxLocalForce
            inputForce *= self.MaxPhysicsForce
            force = dirVector * inputForce
            self.notify.debug('adding force %s to %d' % (force, avId))
            body.addForce(force)

        self.enableAllTireBodies()
        self.totalPhysicsSteps = 0
        self.startSim()
        taskMgr.add(self.__moveTiresTask, self.uniqueName('moveTiresTtask'))

    def exitMoveTires(self):
        self.forceLocalToonToTire()
        self.disableAllTireBodies()
        self.stopSim()
        self.notify.debug('total Physics steps = %d' % self.totalPhysicsSteps)
        taskMgr.remove(self.uniqueName('moveTiresTtask'))

    def enterSynch(self):
        self.waitingSyncLabel.show()

    def exitSynch(self):
        self.waitingSyncLabel.hide()

    def enterScoring(self):
        sortedByDistance = []
        for avId in self.avIdList:
            np = self.getTireNp(avId)
            pos = np.getPos()
            pos.setZ(0)
            sortedByDistance.append((avId, pos.length()))

        def compareDistance(x, y):
            if x[1] - y[1] > 0:
                return 1
            elif x[1] - y[1] < 0:
                return -1
            else:
                return 0

        sortedByDistance.sort(cmp=compareDistance)
        self.scoreMovie = Sequence()
        curScale = 0.01
        curTime = 0
        self.scoreCircle.setScale(0.01)
        self.scoreCircle.show()
        self.notify.debug('newScores = %s' % self.newScores)
        circleStartTime = 0
        for index in xrange(len(sortedByDistance)):
            distance = sortedByDistance[index][1]
            avId = sortedByDistance[index][0]
            scorePanelIndex = self.avIdList.index(avId)
            time = (distance - curScale) / IceGameGlobals.ExpandFeetPerSec
            if time < 0:
                time = 0.01
            scaleXY = distance + IceGameGlobals.TireRadius
            self.notify.debug('circleStartTime = %s' % circleStartTime)
            self.scoreMovie.append(
                Parallel(
                    LerpScaleInterval(self.scoreCircle, time,
                                      Point3(scaleXY, scaleXY, 1.0)),
                    SoundInterval(self.scoreCircleSound,
                                  duration=time,
                                  startTime=circleStartTime)))
            circleStartTime += time
            startScore = self.scorePanels[scorePanelIndex].getScore()
            destScore = self.newScores[scorePanelIndex]
            self.notify.debug('for avId %d, startScore=%d, newScores=%d' %
                              (avId, startScore, destScore))

            def increaseScores(t,
                               scorePanelIndex=scorePanelIndex,
                               startScore=startScore,
                               destScore=destScore):
                oldScore = self.scorePanels[scorePanelIndex].getScore()
                diff = destScore - startScore
                newScore = int(startScore + diff * t)
                if newScore > oldScore:
                    base.playSfx(self.countSound)
                self.scorePanels[scorePanelIndex].setScore(newScore)
                self.scores[scorePanelIndex] = newScore

            duration = (destScore -
                        startScore) * IceGameGlobals.ScoreCountUpRate
            tireNp = self.tireDict[avId]['tireNodePath']
            self.scoreMovie.append(
                Parallel(
                    LerpFunctionInterval(increaseScores, duration),
                    Sequence(
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 0, 0, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 1, 1, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 0, 0, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 1, 1, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 0, 0, 1)),
                        LerpColorScaleInterval(tireNp, duration / 6.0,
                                               VBase4(1, 1, 1, 1)))))
            curScale += distance

        self.scoreMovie.append(
            Func(self.sendUpdate, 'reportScoringMovieDone', []))
        self.scoreMovie.start()

    def exitScoring(self):
        self.scoreMovie.finish()
        self.scoreMovie = None
        self.scoreCircle.hide()
        return

    def enterFinalResults(self):
        lerpTrack = Parallel()
        lerpDur = 0.5
        tY = 0.6
        bY = -.05
        lX = -.5
        cX = 0
        rX = 0.5
        scorePanelLocs = (((cX, bY), ), ((lX, bY), (rX, bY)),
                          ((cX, tY), (lX, bY), (rX, bY)), ((lX, tY), (rX, tY),
                                                           (lX, bY), (rX, bY)))
        scorePanelLocs = scorePanelLocs[self.numPlayers - 1]
        for i in xrange(self.numPlayers):
            panel = self.scorePanels[i]
            pos = scorePanelLocs[i]
            panel.wrtReparentTo(aspect2d)
            lerpTrack.append(
                Parallel(
                    LerpPosInterval(panel,
                                    lerpDur,
                                    Point3(pos[0], 0, pos[1]),
                                    blendType='easeInOut'),
                    LerpScaleInterval(panel,
                                      lerpDur,
                                      Vec3(panel.getScale()) * 2.0,
                                      blendType='easeInOut')))

        self.showScoreTrack = Parallel(
            lerpTrack,
            Sequence(Wait(IceGameGlobals.ShowScoresDuration),
                     Func(self.gameOver)))
        self.showScoreTrack.start()

    def exitFinalResults(self):
        self.showScoreTrack.pause()
        del self.showScoreTrack

    def enterCleanup(self):
        self.notify.debug('enterCleanup')
        if base.localAvatar.laffMeter:
            base.localAvatar.laffMeter.start()

    def exitCleanup(self):
        pass

    def __placeToon(self, avId):
        toon = self.getAvatar(avId)
        if toon:
            toon.setPos(0, 0, 0)
            toon.setHpr(0, 0, 0)

    def moveCameraToTop(self):
        camera.reparentTo(render)
        p = self.cameraThreeQuarterView
        camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5])

    def setupTire(self, avId, index):
        tireNp, tireBody, tireOdeGeom = self.createTire(index)
        self.tireDict[avId] = {
            'tireNodePath': tireNp,
            'tireBody': tireBody,
            'tireOdeGeom': tireOdeGeom
        }
        if avId <= 0:
            tireBlocker = tireNp.find('**/tireblockermesh')
            if not tireBlocker.isEmpty():
                tireBlocker.hide()
        if avId == self.localAvId:
            tireNp = self.tireDict[avId]['tireNodePath']
            self.treasureSphereName = 'treasureCollider'
            self.treasureCollSphere = CollisionSphere(
                0, 0, 0, IceGameGlobals.TireRadius)
            self.treasureCollSphere.setTangible(0)
            self.treasureCollNode = CollisionNode(self.treasureSphereName)
            self.treasureCollNode.setFromCollideMask(
                ToontownGlobals.PieBitmask)
            self.treasureCollNode.addSolid(self.treasureCollSphere)
            self.treasureCollNodePath = tireNp.attachNewNode(
                self.treasureCollNode)
            self.treasureHandler = CollisionHandlerEvent()
            self.treasureHandler.addInPattern('%fn-intoTreasure')
            base.cTrav.addCollider(self.treasureCollNodePath,
                                   self.treasureHandler)
            eventName = '%s-intoTreasure' % self.treasureCollNodePath.getName()
            self.notify.debug('eventName = %s' % eventName)
            self.accept(eventName, self.toonHitSomething)

    def setupForceArrow(self, avId):
        arrow = loader.loadModel('phase_4/models/minigames/ice_game_arrow')
        priority = 0
        if avId < 0:
            priority = -avId
        else:
            priority = self.avIdList.index(avId)
            if avId == self.localAvId:
                priority = 10
        self.forceArrowDict[avId] = arrow

    def hideForceArrows(self):
        for forceArrow in self.forceArrowDict.values():
            forceArrow.hide()

    def showForceArrows(self, realPlayersOnly=True):
        for avId in self.forceArrowDict:
            if realPlayersOnly:
                if avId > 0:
                    self.forceArrowDict[avId].show()
                else:
                    self.forceArrowDict[avId].hide()
            else:
                self.forceArrowDict[avId].show()

    def localForceArrow(self):
        if self.localAvId in self.forceArrowDict:
            return self.forceArrowDict[self.localAvId]
        else:
            return None
        return None

    def setChoices(self, input0, input1, input2, input3):
        pass

    def startDebugTask(self):
        taskMgr.add(self.debugTask, self.debugTaskName)

    def stopDebugTask(self):
        taskMgr.remove(self.debugTaskName)

    def debugTask(self, task):
        if self.canDrive and localAvatar.doId in self.tireDict:
            dt = globalClock.getDt()
            forceMove = 25000
            forceMoveDt = forceMove
            tireBody = self.tireDict[localAvatar.doId]['tireBody']
            if self.arrowKeys.upPressed() and not tireBody.isEnabled():
                x = 0
                y = 1
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.downPressed() and not tireBody.isEnabled():
                x = 0
                y = -1
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.leftPressed() and not tireBody.isEnabled():
                x = -1
                y = 0
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.rightPressed() and not tireBody.isEnabled():
                x = 1
                y = 0
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
        return task.cont

    def __upArrowPressed(self):
        pass

    def __downArrowPressed(self):
        pass

    def __leftArrowPressed(self):
        pass

    def __rightArrowPressed(self):
        pass

    def __controlPressed(self):
        if self.gameFSM.getCurrentState().getName() == 'inputChoice':
            self.sendForceArrowUpdateAsap = True
            self.updateLocalForceArrow()
            self.controlKeyPressed = True
            self.sendUpdate('setAvatarChoice',
                            [self.curForce, self.curHeading])
            self.gameFSM.request('waitServerChoices')

    def startTimer(self):
        now = globalClock.getFrameTime()
        elapsed = now - self.timerStartTime
        self.timer.posInTopRightCorner()
        self.timer.setTime(IceGameGlobals.InputTimeout)
        self.timer.countdown(IceGameGlobals.InputTimeout - elapsed,
                             self.handleChoiceTimeout)
        self.timer.show()

    def setTimerStartTime(self, timestamp):
        if not self.hasLocalToon:
            return
        self.timerStartTime = globalClockDelta.networkToLocalTime(timestamp)
        if self.timer != None:
            self.startTimer()
        return

    def handleChoiceTimeout(self):
        self.sendUpdate('setAvatarChoice', [0, 0])
        self.gameFSM.request('waitServerChoices')

    def localTireNp(self):
        ret = None
        if self.localAvId in self.tireDict:
            ret = self.tireDict[self.localAvId]['tireNodePath']
        return ret

    def localTireBody(self):
        ret = None
        if self.localAvId in self.tireDict:
            ret = self.tireDict[self.localAvId]['tireBody']
        return ret

    def getTireBody(self, avId):
        ret = None
        if avId in self.tireDict:
            ret = self.tireDict[avId]['tireBody']
        return ret

    def getTireNp(self, avId):
        ret = None
        if avId in self.tireDict:
            ret = self.tireDict[avId]['tireNodePath']
        return ret

    def updateForceArrow(self, avId, curHeading, curForce):
        forceArrow = self.forceArrowDict[avId]
        tireNp = self.tireDict[avId]['tireNodePath']
        tireNp.setH(curHeading)
        tireBody = self.tireDict[avId]['tireBody']
        tireBody.setQuaternion(tireNp.getQuat())
        self.notify.debug('curHeading = %s' % curHeading)
        yScale = curForce / 100.0
        yScale *= 1
        headY = yScale * 15
        xScale = (yScale - 1) / 2.0 + 1.0
        shaft = forceArrow.find('**/arrow_shaft')
        head = forceArrow.find('**/arrow_head')
        shaft.setScale(xScale, yScale, 1)
        head.setPos(0, headY, 0)
        head.setScale(xScale, xScale, 1)

    def updateLocalForceArrow(self):
        avId = self.localAvId
        self.b_setForceArrowInfo(avId, self.curHeading, self.curForce)

    def __aimTask(self, task):
        if not hasattr(self, 'arrowKeys'):
            return task.done
        dt = globalClock.getDt()
        headingMomentumChange = dt * 60.0
        forceMomentumChange = dt * 160.0
        arrowUpdate = False
        arrowRotating = False
        arrowUp = False
        arrowDown = False
        if self.arrowKeys.upPressed() and not self.arrowKeys.downPressed():
            self.forceMomentum += forceMomentumChange
            if self.forceMomentum < 0:
                self.forceMomentum = 0
            if self.forceMomentum > 50:
                self.forceMomentum = 50
            oldForce = self.curForce
            self.curForce += self.forceMomentum * dt
            arrowUpdate = True
            if oldForce < self.MaxLocalForce:
                arrowUp = True
        elif self.arrowKeys.downPressed() and not self.arrowKeys.upPressed():
            self.forceMomentum += forceMomentumChange
            if self.forceMomentum < 0:
                self.forceMomentum = 0
            if self.forceMomentum > 50:
                self.forceMomentum = 50
            oldForce = self.curForce
            self.curForce -= self.forceMomentum * dt
            arrowUpdate = True
            if oldForce > 0.01:
                arrowDown = True
        else:
            self.forceMomentum = 0
        if self.arrowKeys.leftPressed() and not self.arrowKeys.rightPressed():
            self.headingMomentum += headingMomentumChange
            if self.headingMomentum < 0:
                self.headingMomentum = 0
            if self.headingMomentum > 50:
                self.headingMomentum = 50
            self.curHeading += self.headingMomentum * dt
            arrowUpdate = True
            arrowRotating = True
        elif self.arrowKeys.rightPressed(
        ) and not self.arrowKeys.leftPressed():
            self.headingMomentum += headingMomentumChange
            if self.headingMomentum < 0:
                self.headingMomentum = 0
            if self.headingMomentum > 50:
                self.headingMomentum = 50
            self.curHeading -= self.headingMomentum * dt
            arrowUpdate = True
            arrowRotating = True
        else:
            self.headingMomentum = 0
        if arrowUpdate:
            self.normalizeHeadingAndForce()
            self.updateLocalForceArrow()
        if arrowRotating:
            if not self.arrowRotateSound.status(
            ) == self.arrowRotateSound.PLAYING:
                base.playSfx(self.arrowRotateSound, looping=True)
        else:
            self.arrowRotateSound.stop()
        if arrowUp:
            if not self.arrowUpSound.status() == self.arrowUpSound.PLAYING:
                base.playSfx(self.arrowUpSound, looping=False)
        else:
            self.arrowUpSound.stop()
        if arrowDown:
            if not self.arrowDownSound.status() == self.arrowDownSound.PLAYING:
                base.playSfx(self.arrowDownSound, looping=False)
        else:
            self.arrowDownSound.stop()
        return task.cont

    def normalizeHeadingAndForce(self):
        if self.curForce > self.MaxLocalForce:
            self.curForce = self.MaxLocalForce
        if self.curForce < 0.01:
            self.curForce = 0.01

    def setTireInputs(self, tireInputs):
        if not self.hasLocalToon:
            return
        self.allTireInputs = tireInputs
        self.gameFSM.request('moveTires')

    def enableAllTireBodies(self):
        for avId in self.tireDict.keys():
            self.tireDict[avId]['tireBody'].enable()

    def disableAllTireBodies(self):
        for avId in self.tireDict.keys():
            self.tireDict[avId]['tireBody'].disable()

    def areAllTiresDisabled(self):
        for avId in self.tireDict.keys():
            if self.tireDict[avId]['tireBody'].isEnabled():
                return False

        return True

    def __moveTiresTask(self, task):
        if self.areAllTiresDisabled():
            self.sendTirePositions()
            self.gameFSM.request('synch')
            return task.done
        return task.cont

    def sendTirePositions(self):
        tirePositions = []
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            tire = self.getTireBody(avId)
            pos = Point3(tire.getPosition())
            tirePositions.append([pos[0], pos[1], pos[2]])

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            tire = self.getTireBody(avId)
            pos = Point3(tire.getPosition())
            tirePositions.append([pos[0], pos[1], pos[2]])

        self.sendUpdate('endingPositions', [tirePositions])

    def setFinalPositions(self, finalPos):
        if not self.hasLocalToon:
            return
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            tire = self.getTireBody(avId)
            np = self.getTireNp(avId)
            pos = finalPos[index]
            tire.setPosition(pos[0], pos[1], pos[2])
            np.setPos(pos[0], pos[1], pos[2])

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            tire = self.getTireBody(avId)
            np = self.getTireNp(avId)
            pos = finalPos[index]
            tire.setPosition(pos[0], pos[1], pos[2])
            np.setPos(pos[0], pos[1], pos[2])

    def updateInfoLabel(self):
        self.infoLabel['text'] = TTLocalizer.IceGameInfo % {
            'curMatch': self.curMatch + 1,
            'numMatch': IceGameGlobals.NumMatches,
            'curRound': self.curRound + 1,
            'numRound': IceGameGlobals.NumRounds
        }

    def setMatchAndRound(self, match, round):
        if not self.hasLocalToon:
            return
        self.curMatch = match
        self.curRound = round
        self.updateInfoLabel()

    def setScores(self, match, round, scores):
        if not self.hasLocalToon:
            return
        self.newMatch = match
        self.newRound = round
        self.newScores = scores

    def setNewState(self, state):
        if not self.hasLocalToon:
            return
        self.notify.debug('setNewState gameFSM=%s newState=%s' %
                          (self.gameFSM, state))
        self.gameFSM.request(state)

    def putAllTiresInStartingPositions(self):
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            np = self.tireDict[avId]['tireNodePath']
            np.setPos(IceGameGlobals.StartingPositions[index])
            self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos))
            np.setHpr(0, 0, 0)
            quat = np.getQuat()
            body = self.tireDict[avId]['tireBody']
            body.setPosition(IceGameGlobals.StartingPositions[index])
            body.setQuaternion(quat)

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            np = self.tireDict[avId]['tireNodePath']
            np.setPos(IceGameGlobals.StartingPositions[index])
            self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos))
            np.setHpr(0, 0, 0)
            quat = np.getQuat()
            body = self.tireDict[avId]['tireBody']
            body.setPosition(IceGameGlobals.StartingPositions[index])
            body.setQuaternion(quat)

    def b_setForceArrowInfo(self, avId, force, heading):
        self.setForceArrowInfo(avId, force, heading)
        self.d_setForceArrowInfo(avId, force, heading)

    def d_setForceArrowInfo(self, avId, force, heading):
        sendIt = False
        curTime = self.getCurrentGameTime()
        if self.sendForceArrowUpdateAsap:
            sendIt = True
        elif curTime - self.lastForceArrowUpdateTime > 0.2:
            sendIt = True
        if sendIt:
            self.sendUpdate('setForceArrowInfo', [avId, force, heading])
            self.sendForceArrowUpdateAsap = False
            self.lastForceArrowUpdateTime = self.getCurrentGameTime()

    def setForceArrowInfo(self, avId, force, heading):
        if not self.hasLocalToon:
            return
        self.updateForceArrow(avId, force, heading)

    def setupStartOfMatch(self):
        self.putAllTiresInStartingPositions()
        szId = self.getSafezoneId()
        self.numTreasures = IceGameGlobals.NumTreasures[szId]
        if self.treasures:
            for treasure in self.treasures:
                treasure.destroy()

            self.treasures = []
        index = 0
        treasureMargin = IceGameGlobals.TireRadius + 1.0
        while len(self.treasures) < self.numTreasures:
            xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5,
                                               IceGameGlobals.MaxWall[0] - 5)
            yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5,
                                               IceGameGlobals.MaxWall[1] - 5)
            self.notify.debug('yPos=%s' % yPos)
            pos = Point3(xPos, yPos, IceGameGlobals.TireRadius)
            newTreasure = IceTreasure.IceTreasure(self.treasureModel,
                                                  pos,
                                                  index,
                                                  self.doId,
                                                  penalty=False)
            goodSpot = True
            for obstacle in self.obstacles:
                if newTreasure.nodePath.getDistance(obstacle) < treasureMargin:
                    goodSpot = False
                    break

            if goodSpot:
                for treasure in self.treasures:
                    if newTreasure.nodePath.getDistance(
                            treasure.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                self.treasures.append(newTreasure)
                index += 1
            else:
                newTreasure.destroy()

        self.numPenalties = IceGameGlobals.NumPenalties[szId]
        if self.penalties:
            for penalty in self.penalties:
                penalty.destroy()

            self.penalties = []
        index = 0
        while len(self.penalties) < self.numPenalties:
            xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5,
                                               IceGameGlobals.MaxWall[0] - 5)
            yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5,
                                               IceGameGlobals.MaxWall[1] - 5)
            self.notify.debug('yPos=%s' % yPos)
            pos = Point3(xPos, yPos, IceGameGlobals.TireRadius)
            newPenalty = IceTreasure.IceTreasure(self.penaltyModel,
                                                 pos,
                                                 index,
                                                 self.doId,
                                                 penalty=True)
            goodSpot = True
            for obstacle in self.obstacles:
                if newPenalty.nodePath.getDistance(obstacle) < treasureMargin:
                    goodSpot = False
                    break

            if goodSpot:
                for treasure in self.treasures:
                    if newPenalty.nodePath.getDistance(
                            treasure.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                for penalty in self.penalties:
                    if newPenalty.nodePath.getDistance(
                            penalty.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                self.penalties.append(newPenalty)
                index += 1
            else:
                newPenalty.destroy()

    def toonHitSomething(self, entry):
        self.notify.debug('---- treasure Enter ---- ')
        self.notify.debug('%s' % entry)
        name = entry.getIntoNodePath().getName()
        parts = name.split('-')
        if len(parts) < 3:
            self.notify.debug('collided with %s, but returning' % name)
            return
        if not int(parts[1]) == self.doId:
            self.notify.debug("collided with %s, but doId doesn't match" %
                              name)
            return
        treasureNum = int(parts[2])
        if 'penalty' in parts[0]:
            self.__penaltyGrabbed(treasureNum)
        else:
            self.__treasureGrabbed(treasureNum)

    def __treasureGrabbed(self, treasureNum):
        self.treasures[treasureNum].showGrab()
        self.treasureGrabSound.play()
        self.sendUpdate('claimTreasure', [treasureNum])

    def setTreasureGrabbed(self, avId, treasureNum):
        if not self.hasLocalToon:
            return
        self.notify.debug('treasure %s grabbed by %s' % (treasureNum, avId))
        if avId != self.localAvId:
            self.treasures[treasureNum].showGrab()
        i = self.avIdList.index(avId)
        self.scores[i] += 1
        self.scorePanels[i].setScore(self.scores[i])

    def __penaltyGrabbed(self, penaltyNum):
        self.penalties[penaltyNum].showGrab()
        self.sendUpdate('claimPenalty', [penaltyNum])

    def setPenaltyGrabbed(self, avId, penaltyNum):
        if not self.hasLocalToon:
            return
        self.notify.debug('penalty %s grabbed by %s' % (penaltyNum, avId))
        if avId != self.localAvId:
            self.penalties[penaltyNum].showGrab()
        i = self.avIdList.index(avId)
        self.scores[i] -= 1
        self.scorePanels[i].setScore(self.scores[i])

    def postStep(self):
        DistributedIceWorld.DistributedIceWorld.postStep(self)
        if not self.colCount:
            return
        for count in xrange(self.colCount):
            c0, c1 = self.getOrderedContacts(count)
            if c1 in self.tireCollideIds:
                tireIndex = self.tireCollideIds.index(c1)
                if c0 in self.tireCollideIds:
                    self.tireSounds[tireIndex]['tireHit'].play()
                elif c0 == self.wallCollideId:
                    self.tireSounds[tireIndex]['wallHit'].play()
                elif c0 == self.obstacleCollideId:
                    self.tireSounds[tireIndex]['obstacleHit'].play()

    def forceLocalToonToTire(self):
        toon = localAvatar
        if toon and self.localAvId in self.tireDict:
            tireNp = self.tireDict[self.localAvId]['tireNodePath']
            toon.reparentTo(tireNp)
            toon.setPosHpr(0, 0, 0, 0, 0, 0)
            toon.setY(1.0)
            toon.setZ(-3)
Пример #28
0
class LearnNeuroevolution(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        # Override defaults
        self.disableMouse()
        self.setBackgroundColor(VBase3(160, 200, 150) / 255.0)
        self.setFrameRateMeter(True)

        # Lights
        dlight = DirectionalLight("dlight")
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(180.0, -70.0, 0)
        self.render.setLight(dlnp)

        alight = AmbientLight("alight")
        alnp = self.render.attachNewNode(alight)
        alight.setColor(VBase4(0.4, 0.4, 0.4, 1))
        self.render.setLight(alnp)

        # Collision traverser
        self.cTrav = CollisionTraverser("collisionTraverser")
        # self.cTrav.showCollisions(self.render)

        # Collision handlers
        self.carCollisionHandler = CollisionHandlerEvent()
        self.carCollisionHandler.addInPattern("%fn-into-%in")

        # Camera controls
        self.cameraController = CameraController(self, 600, math.radians(45),
                                                 math.radians(60))

        # Load the track
        self.track = self.loader.loadModel("models/trackMotegi")
        # self.track = self.loader.loadModel("models/trackValencia")
        checkpointsCollision = self.track.find("checkpoints").node()
        checkpointsCollision.setIntoCollideMask(BitMask32(0xF0))
        self.numCheckpoints = checkpointsCollision.getNumSolids()
        self.track.reparentTo(self.render)

        # Enemy cars
        enemyColor = LColor(204 / 255.0, 72 / 255.0, 63 / 255.0, 1.0)
        self.enemyPos = [(-150, -110, 60), (113, -233, 45), (-255, -264, 20),
                         (-364, -237, -90), (-204, -46, 230)]

        self.enemyCars = []
        for pos in self.enemyPos:
            car = NeuralNetworkCar(self)
            car.getNodePath().setColor(enemyColor)
            car.getNodePath().setX(pos[0])
            car.getNodePath().setY(pos[1])
            car.getNodePath().setH(pos[2])
            self.enemyCars.append(car)

        # Neuroevolution
        # self.loggingActive = False
        self.inputLayerSize = 9
        self.hiddenLayer1Size = 5
        self.hiddenLayer2Size = 5
        self.numLabels = 2
        self.thetaSizes = [(self.hiddenLayer1Size, self.inputLayerSize + 1),
                           (self.hiddenLayer2Size, self.hiddenLayer1Size + 1),
                           (self.numLabels, self.hiddenLayer2Size + 1)]

        self.generationSize = 15
        self.weightInit = 0.12
        self.replaceRatio = 0.02
        self.scaleRatio = 0.02
        self.addRatio = 0.02

        self.generationCount = 1
        self.cars = []
        for i in range(self.generationSize):
            car = NeuroevolutionCar(self, i, self.inputLayerSize)
            # Register car collisions with track
            self.cTrav.addCollider(car.carCollider, self.carCollisionHandler)
            self.accept("carCollider{}-into-carCollider".format(i),
                        car.onCrash)
            self.accept("carCollider{}-into-trackCollision".format(i),
                        car.onCrash)
            self.accept("carCollider{}-into-checkpoints".format(i),
                        car.onCheckpoint)
            self.cars.append(car)

        # Initial generation
        np.random.seed(0)
        for i in range(self.generationSize):
            theta1 = self.randWeights(self.thetaSizes[0], self.weightInit)
            theta2 = self.randWeights(self.thetaSizes[1], self.weightInit)
            theta3 = self.randWeights(self.thetaSizes[2], self.weightInit)
            self.cars[i].startSimulation(theta1, theta2, theta3)

        # Run learning task
        self.taskMgr.add(self.neuroevolution, "NeuroevolutionTask")

        # DEBUG
        self.accept("l", self.logGeneration)
        self.txtGen = OnscreenText(text='',
                                   pos=(0.0, -0.04),
                                   scale=0.05,
                                   align=TextNode.ALeft,
                                   fg=(1, 1, 1, 1),
                                   bg=(0, 0, 0, .4))
        self.txtGen.reparentTo(self.a2dTopLeft)

    def logGeneration(self):
        # Write generation to log
        for i in range(self.generationSize):
            car = self.cars[i]
            filename = "data/generations_log/gen_{}_car_{}_theta_1".format(
                self.generationCount, i)
            with open(filename, 'wb') as csvfile:
                wr = csv.writer(csvfile)
                wr.writerows(car.theta1)
            filename = "data/generations_log/gen_{}_car_{}_theta_2".format(
                self.generationCount, i)
            with open(filename, 'wb') as csvfile:
                wr = csv.writer(csvfile)
                wr.writerows(car.theta2)
            filename = "data/generations_log/gen_{}_car_{}_theta_3".format(
                self.generationCount, i)
            with open(filename, 'wb') as csvfile:
                wr = csv.writer(csvfile)
                wr.writerows(car.theta3)
        print "LOG: Generation {} logged.".format(self.generationCount)

    def neuroevolution(self, task):
        generationDone = True
        for car in self.cars:
            if not car.simulationDone:
                generationDone = False

        if generationDone:
            # Compute fitness scores
            fitness = np.zeros(self.generationSize)
            for i in range(self.generationSize):
                fitness[i] = self.fitnessFunction(self.cars[i].checkpointCount,
                                                  self.cars[i].timeAlive)
            prob = fitness / np.sum(fitness)

            # Generate new generation
            nextGenTheta1 = []
            nextGenTheta2 = []
            nextGenTheta3 = []
            for i in range(self.generationSize):
                # Selection
                (p1_i, p2_i) = np.random.choice(self.generationSize,
                                                2,
                                                replace=False,
                                                p=prob)
                if fitness[p1_i] < fitness[p2_i]:
                    p1_i, p2_i = p2_i, p1_i

                r1, c1 = self.cars[p1_i].theta1.shape
                r2, c2 = self.cars[p1_i].theta2.shape
                r3, c3 = self.cars[p1_i].theta3.shape

                # Crossover
                fit1 = fitness[p1_i]
                fit2 = fitness[p2_i]
                crossoverRatio = fit2 / (fit1 + fit2)

                theta1 = np.copy(self.cars[p1_i].theta1)
                mask1 = np.random.rand(r1, c1) < crossoverRatio
                theta1[mask1] = self.cars[p2_i].theta1[mask1]

                theta2 = np.copy(self.cars[p1_i].theta2)
                mask2 = np.random.rand(r2, c2) < crossoverRatio
                theta2[mask2] = self.cars[p2_i].theta2[mask2]

                theta3 = np.copy(self.cars[p1_i].theta3)
                mask3 = np.random.rand(r3, c3) < crossoverRatio
                theta3[mask3] = self.cars[p2_i].theta3[mask3]

                # Mutation
                # replace
                maskReplace = np.random.rand(r1, c1) < self.replaceRatio
                sz = np.sum(maskReplace)
                theta1[maskReplace] = np.random.rand(
                    sz) * 2 * self.weightInit - self.weightInit

                maskReplace = np.random.rand(r2, c2) < self.replaceRatio
                sz = np.sum(maskReplace)
                theta2[maskReplace] = np.random.rand(
                    sz) * 2 * self.weightInit - self.weightInit

                maskReplace = np.random.rand(r3, c3) < self.replaceRatio
                sz = np.sum(maskReplace)
                theta3[maskReplace] = np.random.rand(
                    sz) * 2 * self.weightInit - self.weightInit

                # scale
                maskScale = np.random.rand(r1, c1) < self.scaleRatio
                sz = np.sum(maskScale)
                theta1[maskScale] = theta1[maskScale] * (np.random.rand(sz) +
                                                         0.5)

                maskScale = np.random.rand(r2, c2) < self.scaleRatio
                sz = np.sum(maskScale)
                theta2[maskScale] = theta2[maskScale] * (np.random.rand(sz) +
                                                         0.5)

                maskScale = np.random.rand(r3, c3) < self.scaleRatio
                sz = np.sum(maskScale)
                theta3[maskScale] = theta3[maskScale] * (np.random.rand(sz) +
                                                         0.5)

                # add
                maskAdd = np.random.rand(r1, c1) < self.addRatio
                sz = np.sum(maskAdd)
                theta1[maskAdd] = theta1[maskAdd] + (np.random.rand(sz) -
                                                     0.5) * 2.0

                maskAdd = np.random.rand(r2, c2) < self.addRatio
                sz = np.sum(maskAdd)
                theta2[maskAdd] = theta2[maskAdd] + (np.random.rand(sz) -
                                                     0.5) * 2.0

                maskAdd = np.random.rand(r3, c3) < self.addRatio
                sz = np.sum(maskAdd)
                theta3[maskAdd] = theta3[maskAdd] + (np.random.rand(sz) -
                                                     0.5) * 2.0

                nextGenTheta1.append(theta1)
                nextGenTheta2.append(theta2)
                nextGenTheta3.append(theta3)

            # Run new generation
            for i in range(self.generationSize):
                self.cars[i].startSimulation(nextGenTheta1[i],
                                             nextGenTheta2[i],
                                             nextGenTheta3[i])

            self.generationCount += 1
            self.txtGen.setText('Gen: {}'.format(self.generationCount))

            # Reset enemies
            for i, car in enumerate(self.enemyCars):
                pos = self.enemyPos[i]
                car.getNodePath().setX(pos[0])
                car.getNodePath().setY(pos[1])
                car.getNodePath().setH(pos[2])

        return task.cont

    def fitnessFunction(self, checkpointCount, timeAlive):
        # f = (10 * checkpointCount) ** 2 + timeAlive + 1
        f = (100 * checkpointCount) + timeAlive + 1
        return f

    def randWeights(self, size, weightInit):
        w = np.random.rand(size[0], size[1]) * 2 * weightInit - weightInit
        return w
Пример #29
0
class DKApp(ShowBase):
    def __init__(self):
        super().__init__(self)

        self.scene = self.loader.loadModel("models/DKSet1")
        self.scene.reparentTo(self.render)
        self.scene.setPos(0,0,0)
        self.jumping  = False
        self.jumpTime = 0
        # base.messenger.toggleVerbose()
        self.accept("raw-arrow_left" , self.pressLeft)
        self.accept("raw-arrow_left-up", self.releaseLeft)
        self.accept("raw-arrow_right" , self.pressRight)
        self.accept("raw-arrow_right-up", self.releaseRight)

        self.accept("raw-space" , self.pressSpace)
        self.accept("raw-space-up", self.releaseSpace)
        self.accept("raw-arrow_up" , self.pressUp)
        self.accept("raw-arrow_up-up", self.releaseUp)

        self.taskMgr.add(self.setup,"setup")
        self.taskMgr.add(self.update , "update")


        self.input=  {
            "up":False,
            "left":False,
            "right":False,
            "space":False
        }

    def pressLeft(self):
        self.input["left"] = True
    def releaseLeft(self):
        self.input["left"] = False
    def pressRight(self):
        self.input["right"] = True
    def releaseRight(self):
        self.input["right"] = False

    def pressSpace(self):
        self.input["space"] = True
    def releaseSpace(self):
        self.input["space"] = False
    def pressUp(self):
        self.input["up"] = True
    def releaseUp(self):
        self.input["up"] = False

    def getHorizontalAxis(self):
        if( self.input["left"] and self.input["right"]):
            return 0
        if( self.input["left"] ):
            return -1
        if( self.input["right"]):
            return 1

        return 0
    def setupCollision(self):
        base.cTrav = CollisionTraverser()
        self.collisionHandlerEvent = CollisionHandlerEvent()
        self.collisionHandlerEvent.addInPattern('into-%in')
        self.collisionHandlerEvent.addOutPattern('outof-%in')

        hitBox = CollisionBox(  Point3(7,0,-4.5) , 0.5,5,0.5)
        cnodePath = self.player.attachNewNode( CollisionNode('marioHitBox') )
        cnodePath.node().addSolid(hitBox)
        cnodePath.show()
        base.cTrav.addCollider(cnodePath, self.collisionHandlerEvent)

        stairs1 =  self.scene.find("root/bottomstair")
        hitBox = CollisionBox(  Point3(-6.8,0,-3.0) , 0.5,5,2.5)
        cnodePath = stairs1.attachNewNode( CollisionNode('stairsHitBox') )
        cnodePath.node().addSolid(hitBox)


        cnodePath.show()

        self.accept('into-stairsHitBox', self.enableStair)
        self.accept('outof-stairsHitBox', self.disableStair)
        base.cTrav.showCollisions(self.render)

    def enableStair(self, evt):
        print(f'{evt}')

    def disableStair(self, evt):
        print(f'{evt}')

    def setup(self, task):
        lens = OrthographicLens()
        lens.setFilmSize(25,20)
        base.camNode.setLens(lens)

        node = self.scene.find("root/camera1")
        node.remove()

        self.player = self.scene.find("root/mario")
        self.setupCollision()
        return Task.done

    def update(self,task):
        self.camera.setPos(0,35,0)
        self.camera.lookAt(self.scene)
        # print(f'{globalClock.getDt()}')

        jy = 0  # jump Y/Z
        vi = 4 # initial velocity
        g = -5 # gravity
        if self.jumping:
            self.jumpTime = self.jumpTime + globalClock.getDt()
            jy = vi*self.jumpTime  + 0.5*g*self.jumpTime*self.jumpTime
            vy = vi + g*self.jumpTime
            if vy < 0 and abs(jy) < 0.2: # eventually jy substraction will change for the original y(aka Z) mario had
                self.jumpTime = 0
                self.jumping = False
                jy = 0
        else:
            if self.player.getZ() == 0 and  self.input["space"] :
                self.jumping = True
                self.jumpTime = 0.01

        # stop advancing if jumping!
        adv = self.getHorizontalAxis()*-.2
        if self.jumping :
            adv = 0
        self.player.setPos( self.player.getX()+adv , 0, jy   )
        return Task.cont
Пример #30
0
class LearnNeuroevolution(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        # Override defaults
        self.disableMouse()
        self.setBackgroundColor(VBase3(160, 200, 150) / 255.0)
        self.setFrameRateMeter(True)

        # Lights
        dlight = DirectionalLight("dlight")
        dlnp = self.render.attachNewNode(dlight)
        dlnp.setHpr(180.0, -70.0, 0)
        self.render.setLight(dlnp)

        alight = AmbientLight("alight")
        alnp = self.render.attachNewNode(alight)
        alight.setColor(VBase4(0.4, 0.4, 0.4, 1))
        self.render.setLight(alnp)

        # Collision traverser
        self.cTrav = CollisionTraverser("collisionTraverser")

        # Collision handlers
        self.carCollisionHandler = CollisionHandlerEvent()
        self.carCollisionHandler.addInPattern("%fn-into-%in")

        # Camera controls
        self.cameraController = CameraController(self, 400, math.pi / 4.0,
                                                 math.pi / 4.0)

        # Load the track
        self.track = self.loader.loadModel("models/trackMotegi")
        #self.track = self.loader.loadModel("models/trackValencia")
        checkpointsCollision = self.track.find("checkpoints").node()
        checkpointsCollision.setIntoCollideMask(BitMask32(0xF0))
        self.numCheckpoints = checkpointsCollision.getNumSolids()
        self.track.reparentTo(self.render)

        # Neuroevolution
        self.generationCount = 0
        self.generationSize = 20
        self.cars = []
        for i in range(self.generationSize):
            car = NeuroevolutionCar(self, i)
            # Register car collisions with track
            self.cTrav.addCollider(car.carCollider, self.carCollisionHandler)
            self.accept("carCollider{}-into-trackCollision".format(i),
                        car.onCrash)
            self.accept("carCollider{}-into-checkpoints".format(i),
                        car.onCheckpoint)
            self.cars.append(car)

        # Run learning task
        self.taskMgr.add(self.neuroevolution, "NeuroevolutionTask")

        # DEBUG
        self.txtGen = OnscreenText(text='',
                                   pos=(0.0, -0.04),
                                   scale=0.05,
                                   align=TextNode.ALeft,
                                   fg=(1, 1, 1, 1),
                                   bg=(0, 0, 0, .4))
        self.txtGen.reparentTo(self.a2dTopLeft)

    def neuroevolution(self, task):
        generationDone = True
        for car in self.cars:
            if not car.simulationDone:
                generationDone = False

        if generationDone:
            self.generationCount += 1
            self.txtGen.setText('Gen: {}'.format(self.generationCount))

            # Compute fitness functions

            for i in range(self.generationSize):
                theta1 = self.randWeights(5, 10)
                theta2 = self.randWeights(5, 6)
                theta3 = self.randWeights(2, 6)
                self.cars[i].startSimulation(theta1, theta2, theta3)

        return task.cont

    def randWeights(self, rows, cols):
        epsilonInit = 0.12
        w = np.random.rand(rows, cols) * 2 * epsilonInit - epsilonInit
        return w
Пример #31
0
class MHBProjectile(DirectObject):
    
    #Property stuff
    creaTime = time.clock()
    dur = .5
    vec = 0
    delta = .15
    prevtime = 0
    flag = False

    #defining the thing fired by whatever gun we have
    def __init__(self, camera, look, id, model):
        self.id = id
        #nodepath of the projectile, give it a trajectory
        self.projectileNode = NodePath('projectile'+str(id))
        self.projectileNode.reparentTo(render)
        
        #by passing the camera node form the camMov object, all projectiles are spawned 5 units in front of the camera
        self.projectileNode.setHpr(look, 0, 0, 0)
        self.projectileNode.setPos(camera,0,3, 3)
        
        #fix z position to line up with gun
        self.projectileNode.setScale(.1)
        projectileModel = loader.loadModel("./resources/cubeShot.egg")
        projectileModel.setColor(255, 0, 0)
        projectileModel.reparentTo(self.projectileNode)
    	
        #must calculate unit vector based on direction
        dir = render.getRelativeVector(look, Vec3(0, 1, 0))
    	
        #speed up or slow down projectiles here
        dir = dir*10
        self.vec = dir

        #Balance vectors when magnitude in direction is low
        if self.vec.x < 2:
            self.vec.x += random.randint(-1,1)
        if self.vec.z < 2:
            self.vec.z += random.randint(-1,1)
        if self.vec.y < 2: 
            self.vec.y += random.randint(-1,1)
        
        #Random vector displacements
        self.vec.x *= random.uniform(.5,1)
        self.vec.y *= random.uniform(.5,1)
        self.vec.z *= random.uniform(.5,1)
        
        
        #base.cTrav = CollisionTraverser()
        cs = CollisionSphere(0, 0, 0, 2.5)
        self.cnodepath = self.projectileNode.attachNewNode(CollisionNode('projNode'))
        self.cnodepath.node().addSolid(cs)
        self.collHand = CollisionHandlerEvent()

        self.cnodepath.setTag('tag', str(self.cnodepath))
        self.collHand.addInPattern('%(tag)ix-into'+str(id))
        self.collHand.addOutPattern('outof')
        #cTrav has the distinction of global colider handler
        base.cTrav.addCollider(self.cnodepath, self.collHand) 
        self.acceptOnce(self.cnodepath.getTag('self')+'-into'+str(id), self.hit)
	    #deal with colliding or special effects here.
	    #wanted projectiles to be short lived
	    # so i will make them delete themselves after impact or time expired
        # writing a task that will rek the projectiles at the end of time
        self.damage = 1.1

    def moveTask(self, task):
        
        #curtime = time.clock()
        #self.delta = curtime-self.prevtime
        
        if self.flag:
            self.ignore(self.cnodepath.getTag('self')+'-into'+str(self.id))
            return task.done
        
        velx = self.vec.x*self.delta
        vely = self.vec.y*self.delta
        velz = self.vec.z*self.delta
        x = self.projectileNode.getX()
        y = self.projectileNode.getY()
        z = self.projectileNode.getZ()
        self.projectileNode.setPos(x+velx, y+vely, z+velz)
        #prevtime = time.clock()
            
        
        self.cnodepath.setTag('tag', str(self))
        if task.time < self.dur:
        
            return task.cont
        else:
            
            self.flag = True
            return task.done
      
    def hit(self, collEntry):
        # throw out a custom message for what hit
        if collEntry.getIntoNodePath().getName() != 'projNode':
            
            temp = collEntry.getIntoNodePath().getName()
            messenger.send(temp, [self.damage]) 
            #remove the impacting projectile
            collEntry.getFromNodePath().getParent().getParent().removeNode()
            self.flag =  True
Пример #32
0
class World(DirectObject):
  def __init__(self):
    #--Collision Handler------------------------------------------------------
    self.collHandler = CollisionHandlerEvent()
    self.collHandler.addInPattern('%fn-into-%in')
    base.cTrav = CollisionTraverser('world traverser')

    #--Mouse Control----------------------------------------------------------
    base.disableMouse()
    self.properties = WindowProperties()
    self.properties.setCursorHidden(True)
    base.win.requestProperties(self.properties)

    #--Register Hud Elements--------------------------------------------------
    self.instruction1 = self.addInstruction("[click] to Shoot",2)
    self.instruction2 = self.addInstruction("[a] to accelerate", 1)
    self.instruction3 = self.addInstruction("[esc] to quit", 0)

    self.scoreHud = self.addHudElement("", 0)
    self.accuracy = self.addHudElement("", 1)
    self.speedHud = self.addHudElement("", 2)

    self.bigHud = OnscreenText(text="", style=1, fg=(1,1,1,1), pos=(0,0), align=TextNode.ACenter, scale = .1)

    #--Load Objects and Models------------------------------------------------
    self.ship = Ship(self.collHandler)
    self.loadSkyBox()
    game.camera.reparentTo(self.ship.getModel())

    #--Start Game-------------------------------------------------------------
    self.asteroids = []
    self.resetGame()

    #--Controls --------------------------------------------------------------
    self.keysDown = {'a': 0}

    self.controlTask = taskMgr.add(self.gameLoop, "game-control-task")
    self.controlTask.lastTime = 0

    self.accept("escape", sys.exit, [0])
    self.accept("a", self.keyDown, ['a'])
    self.accept("a-up", self.keyUp, ['a'])
    self.accept("mouse1", self.shoot)
    self.accept("space", self.shoot)
    self.accept("resetgame", self.gameOver)

    if(DEBUG_CONTROLS):
      self.accept("0", self.ship.stop)
      self.accept("9", self.ship.getModel().setHpr, [0,0,0])

    #--Register CollisionEvent Handlers---------------------------------------
    self.accept('asteroid-into-bullet', self.bulletAsteroidCollision)

  ###
  # World.shoot:
  #
  # Dispatch method that overloads the use of the mouse button
  ##
  def shoot(self):
    if(self.ship.isAlive()):
      self.ship.fireBullet()
      self.shots += 1
    else:
      self.resetGame()

  ###
  # World.gameOver()
  #
  #  Displays "Game Over: <SCORE>" then resets game after 5 seconds
  def gameOver(self):
    self.bigHud.setText("GAME OVER: " + str(self.score))
    taskMgr.doMethodLater(GAME_OVER_DELAY,
                          self.resetGame,
                          "reset_game",
                          [])


  ###
  # World.resetGame
  #
  # Resets anything that might change during play essentially reloading
  ##
  def resetGame(self):
    for asteroid in self.asteroids:
      asteroid.remove()
    self.score       = 0
    self.shots       = 0
    self.hits        = 0
    self.lifeLength  = 0
    self.ship.reset()
    self.scoreHud.setText("Score     : " + str(self.score))
    self.accuracy.setText("Hit/Fired : 0/0")
    self.speedHud.setText("Speed     : 0")
    self.bigHud.setText("")
    self.loadAsteroids()

  ###
  # World.bulletAsteroidCollision:
  #
  # Event Handler for collision From Asteroid Into Bullet
  # Triggers the "explosion" of an Asteroid and appends replacments
  ##
  def bulletAsteroidCollision(self, entry):
    bullet = entry.getIntoNodePath().getParent().getPythonTag("owner")
    asteroid = entry.getFromNodePath().getParent().getPythonTag("owner")
    self.ship.removeBullet(bullet)
    self.asteroids.extend(asteroid.registerHit())
    self.asteroids.remove(asteroid)
    self.score += 100
    self.hits += 1
    asteroid.remove()

  ###
  # World.keyDown:
  #
  # Register the given key as being held down
  ##
  def keyDown(self, key):
    self.keysDown[key] = 1

  ###
  # World.keyUp:
  #
  # Register the given key as no longer being held down
  ##
  def keyUp(self, key):
    self.keysDown[key] = 0

  ###
  # World.addHudElement(msg, row)
  #
  # Displays the given string msg in the top left with a row offset of row
  ##
  def addHudElement(self, msg, row):
    return OnscreenText(text=msg, style=1, fg=(1,1,1,1),
        pos=(-1.3,.95 - (.05 * row)), align=TextNode.ALeft, scale = .05)

  ###
  # World.addInstruction(msg, row)
  #
  # Displays the given string msg in the top right with a row offset of row
  ##
  def addInstruction(self, msg, row):
    return OnscreenText(text=msg, style=1, fg=(1,1,1,1),
        pos=(1.3,.95 - (.05 * row)), align=TextNode.ARight, scale = .05)

  ###
  # World.loadSkyBox:
  #
  # Helper method that loads the skybox, sets size and other factors and
  # parents to ship, while keeping a compass effect so it will spin around the 
  # ship
  ##
  def loadSkyBox(self):
    self.skybox = game.loader.loadModel("Models/skybox.egg")
    self.skybox.setScale(100.0,100.0,100.0)
    self.skybox.setPos(0,0,0)
    self.skybox.reparentTo(self.ship.getModel())
    # Roots the skybox with relation to the render node, making it stationary
    # even though its parented to the ship
    self.skybox.setEffect(CompassEffect.make(render, CompassEffect.PRot))

  ###
  # gameLoop
  #
  # Task for managing the input from the mouse and keys. In addition updating
  # the game world.
  ##
  def gameLoop(self, task):
    md = base.win.getPointer(0)
    x = md.getX()
    y = md.getY()

    # Get the delta in time since last frame (allows us to ratelimit rotation
    #   and acceleration
    dt = task.time - task.lastTime
    task.lastTime = task.time
    self.lifeLength += dt

    # Calculate how far the mouse moved, generate a rotation offest and send
    #  to the ship to rotate
    if base.win.movePointer(0, MOUSE_OFFSET, MOUSE_OFFSET):
      self.ship.rotate(Vec3(-((x-MOUSE_OFFSET) * ROTATION_RATE),
                            INVERTED_MOUSE*((y-MOUSE_OFFSET) * ROTATION_RATE),
                            0))

    #--Allows Holding of A key------------------------------------------------

    if(self.keysDown['a'] == 1):
      self.ship.accelerate(dt)
    
    #--Update Asteroid Positions----------------------------------------------
    for asteroid in self.asteroids:
      asteroid.updatePos(dt)

    #--Update HUD-------------------------------------------------------------
    if(self.shots !=0):
      self.accuracy.setText("Hit/Fired : " + str(self.hits) + "/" + str(self.shots))

    self.scoreHud.setText("Score     : " + str(self.score))
    self.speedHud.setText("Speed     : " + str(self.ship.getVel()))

    return Task.cont

  ###
  # World.loadAsteroids
  #
  # Helper method for creating the asteroids
  ##
  def loadAsteroids(self):
    self.asteroids = []
    for i in range(ASTEROID_START_COUNT):
      x = choice([-1,1]) * choice(range(ASTEROID_SPAWN_MIN, ASTEROID_SPAWN_MAX))
      y = choice([-1,1]) * choice(range(ASTEROID_SPAWN_MIN, ASTEROID_SPAWN_MAX))
      z = choice([-1,1]) * choice(range(ASTEROID_SPAWN_MIN, ASTEROID_SPAWN_MAX))
      self.asteroids.append(Asteroid(Vec3(x,y,z), self.collHandler))
class Starfox(ShowBase):
    def __init__(self):
        super().__init__(self)

        self.scene = self.loader.loadModel("models/world.egg")
        playerTexture = self.loader.loadTexture('models/starfoxShip.jpg')
        enemyTexture = self.loader.loadTexture('models/enemyShip.jpg')
        bulletTexture = loader.loadTexture('models/shot.png')

        self.scene.reparentTo(self.render)

        self.player = self.scene.find("player")
        self.player.setTexture(playerTexture)
        self.player.setPythonTag("ObjectController", Player(self.player))
        #self.player.setPos(20,20,20)

        self.dynamic_enemy = self.scene.find("enemy1")
        self.dynamic_enemy.setTexture(enemyTexture)
        #self.dynamic_enemy.setPos(6,6,6)

        self.building_enemy = self.scene.find("building_enemy")
        #self.building_enemy.setPos(20,20,20)

        self.taskMgr.add(self.update, "update")

        InputManager.initWith(self, [
            InputManager.arrowUp, InputManager.arrowDown,
            InputManager.arrowLeft, InputManager.arrowRight,
            InputManager.space, InputManager.keyX, InputManager.keyV
        ])

        base.cTrav = CollisionTraverser()
        self.CollisionHandlerEvent = CollisionHandlerEvent()

        self.CollisionHandlerEvent.addInPattern('into-%in')
        self.CollisionHandlerEvent.addInPattern('out-%in')

        self.accept('into-collision_player', self.crash)
        self.accept('into-collision_plane', self.crash)
        self.accept('into-collision_enemy', self.crash)

        base.cTrav.addCollider(self.scene.find("player/collision**"),
                               self.CollisionHandlerEvent)
        base.cTrav.addCollider(self.scene.find("basePlane/collision**"),
                               self.CollisionHandlerEvent)

        base.cTrav.showCollisions(self.render)

        self.rails = self.scene.attachNewNode("rails")
        #self.scene.find("basePlane").setPos(self.scene,0,0,-10)
        self.scene.find("basePlane").setHpr(70, 0, 0)
        self.scene.setPos(self.scene, 0, 0, 0)
        self.player.reparentTo(self.rails)
        self.player.setPos(self.rails, 0, 0, 0)

        self.createStaticEnemy(self.building_enemy, 0, 50, 0)
        self.createStaticEnemy(self.building_enemy, -50, 40, 0)
        self.createStaticEnemy(self.building_enemy, -100, 50, 0)
        self.createStaticEnemy(self.building_enemy, -70, 130, 0)
        self.createStaticEnemy(self.building_enemy, -120, 80, 0)
        self.createStaticEnemy(self.building_enemy, -220, 130, 0)

        DynamicEnemy(self.scene, self.dynamic_enemy, Vec3(-230, 140, 10),
                     base.cTrav, self.CollisionHandlerEvent)

    def createStaticEnemy(self, original, px, py, pz):
        be = original.copyTo(self.scene)
        be.setPos(px, py, pz)
        base.cTrav.addCollider(be.find("**collision**"),
                               self.CollisionHandlerEvent)

    def crash(self, evt):
        print(evt)

    def update(self, evt):

        rails_pos = self.rails.getPos(self.scene)
        new_y = rails_pos.y + globalClock.getDt() * 10
        self.rails.setPos(Path.getXOfY(new_y), new_y, 12)
        self.rails.setHpr(Path.getHeading(new_y), 0, 0)

        #self.camera.lookAt(self.player)
        self.camera.setHpr(Path.getHeading(new_y), 0, 0)

        relX, relZ = self.player.getPythonTag("ObjectController").update(
            self.rails, globalClock.getDt())
        self.camera.setPos(self.rails, relX, -30, relZ)

        enemies = self.scene.findAllMatches(DynamicEnemy.dynamic_enemy_name)
        for e in enemies:
            e.getPythonTag("ObjectController").update(self.scene,
                                                      globalClock.getDt(),
                                                      self.player)
        return Task.cont
Пример #34
0
class DKGame(ShowBase):
    def __init__(self):
        super().__init__(self)
        self.t = 1
        self.loadScenery()
        self.mario = None
        #base.messenger.toggleVerbose()
        self.taskMgr.add(self.setup, "setup")
        self.taskMgr.add(self.update, "update")

        self.accept("raw-arrow_right" , self.pressRight)
        self.accept("raw-arrow_right-up" , self.stopRight)
        self.accept("raw-arrow_left" , self.pressLeft)
        self.accept("raw-arrow_left-up" , self.stopLeft)

        self.accept("raw-arrow_up" , self.pressUp)
        self.accept("raw-arrow_up-up" , self.stopUp)

        self.accept("raw-space" , self.pressSpace)
        self.accept("raw-space-up" , self.stopSpace)


        self.canClimb = False
        self.isClimbing = False
        #NUEVA!
        self.isGrounded = True
        self.canJump = True
        self.jumpTime = 0
        self.vyi = 0
        self.floorValidPosition = -4.5

        self.barrelTimer = 0
        self.lifes = 3

        self.marioInitialPos = None
        self.posNotInitialized = True
        self.hammer = False
        self.barrels_frames = []
        self.barrels_frames.append(0)
        self.barrels_frames.append( 0.410573 - 0.375774)
        self.barrels_frames.append( 0.444913 - 0.375774)
        self.barrels_frames.append( 0.479941 - 0.375774)

        self.dk_barrel_sequence = self.createDKBarrelSequence()
        self.hammer_sequence = self.createMarioHammerSequence()
        self.input = {
        "left":False,
        "right":False,
        "space":False,
        "up":False
        }


    def showHammerFrame(self, frame):
        if( frame == 1):
            self.marioRealGraphic.find("hammerup").show()
            self.marioRealGraphic.find("hammerdowm").hide()
        if( frame == 2):
            self.marioRealGraphic.find("hammerdowm").show()
            self.marioRealGraphic.find("hammerup").hide()


    def createMarioHammerSequence(self):
        f1 = Func( self.showHammerFrame , 1  )
        f2 = Func( self.showHammerFrame , 2 )
        delay = Wait(0.1)

        mySequence = Sequence(f1, delay,f2, delay)
        return mySequence


    def changeDKFrame(self, frame):
        dk = self.scene.find("hammer1") #remember that the name is wrong here
        if( frame == 1):
            dk.setTexOffset(TextureStage.getDefault() , 0.140867 - 0.0446603 ,0.0 )
        if( frame == 2):
            dk.setTexOffset(TextureStage.getDefault() , 0.0431023 - 0.0446603 ,  0.806672 - 0.703844 )
        if( frame == 3):
            dk.setTexOffset(TextureStage.getDefault() , 0 ,0.0 )

        """
        frames
        2) 0.140867 0.703844

        1) 0.0431023 0.806672 ;

         throw
        0 0.0446603 0.703065
        """

    def createDKBarrelSequence(self):
        func1 = Func(self.changeDKFrame,1)
        func2 = Func(self.changeDKFrame,2)
        func3 = Func(self.changeDKFrame,3)
        func4 = Func(self.createBarrel)
        delay = Wait(0.5)
        mySequence = Sequence(func1, delay,func2, delay, func3, func4, delay, func1)
        mySequence.loop()
        return mySequence

    def loadScenery(self):
        self.scene = self.loader.loadModel("models/DKSetTextured") # only for non animated objects
        myTexture = loader.loadTexture("models/dk-arcade.png")
        self.scene.setTexture(myTexture)
        self.scene.setTransparency(1)
        self.scene.reparentTo(self.render)

    def setup(self,task):
        lens = OrthographicLens()
        lens.setFilmSize(21.8,18)  # Or whatever is appropriate for your scene
        #lens.setFilmSize(142,136)  # Or whatever is appropriate for your scene

        base.camNode.setLens(lens)

        node = self.scene.find("root/camera1")
        node.removeNode()
        self.camera.setPos( 0,30,0 )
        self.camera.lookAt(self.scene)


        self.mario = self.render.attachNewNode("MarioContainer")
        self.mario.setPos(self.scene, 0,0,0)
        self.marioGraphic = self.mario.attachNewNode("MarioGraphic")
        self.marioGraphic.setPos(self.mario, 0,0,0)
        self.scene.find("root/mario").reparentTo(self.marioGraphic)

        myTexture = loader.loadTexture("models/dk-arcade.png")
        self.marioRealGraphic = self.marioGraphic.find("mario")
        self.marioRealGraphic.setPos(self.marioGraphic, -6.7, 1, 4.5 )
        self.marioRealGraphic.setTexture(myTexture)
        self.marioRealGraphic.setTwoSided(True)
        self.marioRealGraphic.setTransparency(1)


        self.scene.find("root/hammerup").reparentTo(self.marioRealGraphic)
        self.scene.find("root/hammerdowm").reparentTo(self.marioRealGraphic)
        self.marioRealGraphic.find("hammerup").hide()
        self.marioRealGraphic.find("hammerdowm").hide()

        self.scene.find("root/bottomstair").reparentTo(self.scene)
        self.scene.find("root/floor0").reparentTo(self.scene)
        self.scene.find("root/floor1").reparentTo(self.scene)


        self.scene.find("root/middlestair").reparentTo(self.scene)
        self.scene.find("root/topstair").reparentTo(self.scene)

        self.scene.find("root/floor2").reparentTo(self.scene)
        self.scene.find("root/pCube4").reparentTo(self.scene)
        self.scene.find("root/floors").reparentTo(self.scene)
        self.scene.find("root/barrel").reparentTo(self.scene)

        self.scene.find("root/walls").reparentTo(self.scene)
        self.scene.find("root/rightWall").reparentTo(self.scene)

        self.scene.find("root/MainGroup").reparentTo(self.scene)
        self.scene.find("root/hammer1").reparentTo(self.scene)

        self.barrel = self.scene.find("barrel")
        self.barrel.setPos(self.scene, 0,0,20)

        myTexture = loader.loadTexture("models/block.png")
        self.scene.find("floor0").setTexture(myTexture)
        self.scene.find("floor1").setTexture(myTexture)
        self.scene.find("floor2").setTexture(myTexture)
        self.scene.find("floors").setTexture(myTexture)
        self.scene.find("pCube4").setTexture(myTexture)

        self.scene.find("floor0").setTransparency(1)
        self.scene.find("floor1").setTransparency(1)
        self.scene.find("floor2").setTransparency(1)
        self.scene.find("floors").setTransparency(1)
        self.scene.find("pCube4").setTransparency(1)

        myTexture = loader.loadTexture("models/stairs.png")
        self.scene.find("bottomstair").setTexture(myTexture)
        self.scene.find("middlestair").setTexture(myTexture)
        self.scene.find("topstair").setTexture(myTexture)

        self.scene.find("bottomstair").setTransparency(1)
        self.scene.find("middlestair").setTransparency(1)
        self.scene.find("topstair").setTransparency(1)

        base.setBackgroundColor(0,0,0)

        self.setupCollision()

        base.enableParticles()
        gravityFN=ForceNode('world-forces')
        gravityFNP=render.attachNewNode(gravityFN)
        gravityForce=LinearVectorForce(0,0,-9.81) #gravity acceleration
        gravityFN.addForce(gravityForce)
        base.physicsMgr.addLinearForce(gravityForce)


        # create dk graphic barrel sequence


        return Task.done


    def barrelGraphicUpdate(self, visual, physics, data):
        def update():
            vel = physics.getPhysicsObject().getVelocity()
            prevFrame = data.node().getPythonTag("subclass").frame
            if( vel.x < 0):
                data.node().getPythonTag("subclass").frame = (prevFrame - 1)%4
            else:
                data.node().getPythonTag("subclass").frame =  (prevFrame + 1)%4

            visual.setTexOffset(TextureStage.getDefault() , self.barrels_frames[prevFrame] ,0.0 )

        return update

    def createBarrelGraphicSequence(self, visual, physics, data):

        funcInterval = FunctionInterval(self.barrelGraphicUpdate(visual, physics, data), name = "BarrelGraphicUpdate")
        delay = Wait(0.1)
        mySequence = Sequence(funcInterval, delay)
        mySequence.loop()
        return mySequence

    def createBarrel(self):

        barrelNode = NodePath("PhysicalBarrel")
        barrelNode.reparentTo(self.scene)
        barrelNode.setPos(self.scene, 0,0,0)
        physicsBarrel = ActorNode("physics_barrel")
        physicsBarrel.getPhysicsObject().setMass(0.01) #in what units? (69 kindda 3 lbs)
        barrel = barrelNode.attachNewNode(physicsBarrel)
        base.physicsMgr.attachPhysicalNode(physicsBarrel)

        barrel.setPos(barrelNode, 0,0,0)

        visual_barrel = self.scene.attachNewNode("BarrelCopy")
        originalBarrel = self.scene.find("barrel")
        originalBarrel.instanceTo(visual_barrel)
        visual_barrel.reparentTo(barrel)
        visual_barrel.setPos(self.scene, -6.5,0,-24.5 )

        dataNode = barrelNode.attachNewNode(AuxData("Sequence",None))
        seq = self.createBarrelGraphicSequence(visual_barrel, physicsBarrel, dataNode)
        dataNode.node().getPythonTag("subclass").sequence = seq

        #sphere =  CollisionSphere(6.6,0,4.78, 0.5)
        sphere =  CollisionSphere(6.6,0,24.7, 0.5)
        cnodePath = visual_barrel.attachNewNode(CollisionNode('barrelCollider'))
        cnodePath.node().addSolid(sphere)
        cnodePath.node().setFromCollideMask(0xD) # crash with default and mario body and walls
        cnodePath.node().setIntoCollideMask(0xD) # crash with default and mario body and walls
        self.showCollision(cnodePath)
        #cnodePath.show()
        self.physicsCollisionPusher.addCollider(cnodePath,barrel)
        base.cTrav.addCollider(cnodePath, self.physicsCollisionPusher)

        barrelForceNode = ForceNode('barrelForce')
        barrel.attachNewNode(barrelForceNode)
        barrelForce = LinearVectorForce(-7,0,0, 1, False)
        # barrelForce.setMassDependent(0)
        barrelForceNode.addForce(barrelForce)
        physicsBarrel.getPhysical(0).addLinearForce(barrelForce)
        # starting barrel point :D
        barrelNode.setPos(self.scene,6.5,0,4.5)

    def setupBoxCollider(self , node, px, py, pz, w,d,h, nm, colliderEventHandler , fromCollisionMask=0, intoCollisionMask=0  ):

        hitBox = CollisionBox(  Point3(px,py,pz) , w,d,h)
        cnodePath = node.attachNewNode( CollisionNode(nm) )
        cnodePath.node().addSolid(hitBox)
        cnodePath.node().setIntoCollideMask(intoCollisionMask)
        cnodePath.node().setFromCollideMask(fromCollisionMask)
        # cnodePath.show()
        self.showCollision(cnodePath)

        base.cTrav.addCollider(cnodePath, colliderEventHandler)


    def setupCollision(self):
        base.cTrav = CollisionTraverser()
        self.collisionHandlerEvent = CollisionHandlerEvent()
        self.physicsCollisionPusher = PhysicsCollisionHandler()

        self.collisionHandlerEvent.addInPattern('into-%in')
        self.collisionHandlerEvent.addOutPattern('outof-%in')

        # create masks
        defaultCollisionMask =      BitMask32(0b0001) #0x1
        segmentCollisionMask =      BitMask32(0b1000) #0x8
        stairsCollisionMask =       BitMask32(0b0010) #0x2
        marioBodyCollisionMask =    BitMask32(0b0011) #0x3
        collisionWallsForBarrels =  BitMask32(0b0100) #0x4


        # mario segment collider
        #ray =  CollisionSegment(7,0,-4.5, 7,0,-5.1)
        ray =  CollisionSegment(0,0,0, 0,0,-.51)
        cnodePath = self.mario.attachNewNode(CollisionNode('marioRay'))
        cnodePath.node().addSolid(ray)
        cnodePath.node().setFromCollideMask(segmentCollisionMask)
        cnodePath.node().setIntoCollideMask(0)
        self.showCollision(cnodePath)
        base.cTrav.addCollider(cnodePath, self.collisionHandlerEvent)

        #self.setupBoxCollider(self.mario, 7,0,-4.5, 0.5,5,0.5, 'marioHitBox', self.collisionHandlerEvent, marioBodyCollisionMask,marioBodyCollisionMask )
        self.setupBoxCollider(self.mario, 0,0,0, 0.5,5,0.5, 'marioHitBox', self.collisionHandlerEvent, marioBodyCollisionMask,marioBodyCollisionMask )


        stairs1 =  self.scene.find("bottomstair")
        self.setupBoxCollider(stairs1, -6.8,0,-3.0, 0.5,5,2.5, 'stairs1HitBox', self.collisionHandlerEvent, stairsCollisionMask,stairsCollisionMask )

        stairs2 =  self.scene.find("middlestair")
        self.setupBoxCollider(stairs2, -0.86,0, .1, 0.5,5,2.1, 'stairs2HitBox', self.collisionHandlerEvent, stairsCollisionMask,stairsCollisionMask  )

        stairs3 =  self.scene.find("topstair")
        self.setupBoxCollider(stairs3, -6.8,0, 3.1, 0.5,5,2.2, 'stairs3HitBox', self.collisionHandlerEvent, stairsCollisionMask,stairsCollisionMask  )

        hammer =  self.scene.find("MainGroup") # hammer
        self.setupBoxCollider(hammer, 5.5,0, -1.5, 0.5,5,0.5, 'hammer1HitBox', self.collisionHandlerEvent, stairsCollisionMask,stairsCollisionMask  )

        dk =  self.scene.find("hammer1")
        self.setupBoxCollider(dk, 8.7,0, 5, 1,5,1, 'dkHitBox', self.collisionHandlerEvent, stairsCollisionMask,stairsCollisionMask  )

        floor0 =  self.scene.find("floor0")
        self.setupBoxCollider(floor0, -2.5,0,-5.5, 10,5,0.5, 'floor0HitBox', self.collisionHandlerEvent , intoCollisionMask=segmentCollisionMask )

        floor1 =  self.scene.find("floor1")
        self.setupBoxCollider(floor1, 2,0, -2.5, 8.4,5,0.5, 'floor1HitBox', self.collisionHandlerEvent , intoCollisionMask=segmentCollisionMask )
        floor2_1 =  self.scene.find("floor2")
        self.setupBoxCollider(floor2_1, 3.6,0, 0.5, 3.8,5,0.5, 'floor21HitBox', self.collisionHandlerEvent, intoCollisionMask=segmentCollisionMask )
        floor2_2 =  self.scene.find("pCube4")
        self.setupBoxCollider(floor2_2, -6.3,0, 0.5, 5.0 ,5,0.5, 'floor22HitBox', self.collisionHandlerEvent, intoCollisionMask=segmentCollisionMask )
        floor3 =  self.scene.find("floors")
        self.setupBoxCollider(floor3, 1.8,0, 3.5, 8,5,0.5, 'floor3HitBox',  self.collisionHandlerEvent , intoCollisionMask=segmentCollisionMask )

        rightWall = self.scene.find("rightWall")
        self.setupBoxCollider(rightWall, -12,0, 0, 1,5,10, 'rightWallHitBox',  self.collisionHandlerEvent , fromCollisionMask=collisionWallsForBarrels, intoCollisionMask=collisionWallsForBarrels )

        leftWall = self.scene.find("walls")
        self.setupBoxCollider(leftWall, 11.5,0, 0, 1,5,10, 'leftWallHitBox',  self.collisionHandlerEvent , fromCollisionMask=collisionWallsForBarrels, intoCollisionMask=collisionWallsForBarrels )


        barrelFixer = self.scene.attachNewNode("barrelFixer")
        self.setupBoxCollider(barrelFixer, -3,0, 0.505, 10,5,0.5, 'barrelFixerHitBox',  self.collisionHandlerEvent , fromCollisionMask=collisionWallsForBarrels, intoCollisionMask=collisionWallsForBarrels )

        barrelDestroyer = self.scene.attachNewNode("barrelDestroyer")
        self.setupBoxCollider(barrelDestroyer, 0,0, -8, 15,5,0.5, 'barrelDestroyerHitBox',  self.collisionHandlerEvent , fromCollisionMask=collisionWallsForBarrels, intoCollisionMask=collisionWallsForBarrels )


        self.accept('into-stairs1HitBox', self.enableStair)
        self.accept('outof-stairs1HitBox', self.disableStair)
        self.accept('into-stairs2HitBox', self.enableStair)
        self.accept('outof-stairs2HitBox', self.disableStair)
        self.accept('into-stairs3HitBox', self.enableStair)
        self.accept('outof-stairs3HitBox', self.disableStair)
        self.accept('into-hammer1HitBox', self.enableHammer)
        self.accept('into-dkHitBox', self.dkArrived)

        self.accept('into-floor0HitBox', self.enableJump)
        self.accept('outof-floor0HitBox', self.disableJump)
        self.accept('into-floor1HitBox', self.enableJump)
        self.accept('outof-floor1HitBox', self.disableJump)
        self.accept('into-floor21HitBox', self.enableJump)
        self.accept('outof-floor21HitBox', self.disableJump)
        self.accept('into-floor22HitBox', self.enableJump)
        self.accept('outof-floor22HitBox', self.disableJump)
        self.accept('into-floor3HitBox', self.enableJump)
        self.accept('outof-floor3HitBox', self.disableJump)

        self.accept("into-barrelCollider", self.barrelCrash)

        #base.cTrav.showCollisions(self.render)

    def showCollision(self, col):
        #col.show()
        print("Not showing collider")

    def dkArrived(self,evt):
        if(self.hammer):
            self.scene.node().removeChild(evt.getIntoNodePath().node().getParent(0))
            text = DirectLabel(text="You won", text_scale=(0.5,0.5))
        else:
            self.floorValidPosition = -4.5
            self.mario.setPos(self.scene, self.marioInitialPos)
            text = DirectLabel(text="Game Over", text_scale=(0.5,0.5))


    def enableHammer(self, evt):
        print(f"{evt.getIntoNodePath()}{evt.getFromNodePath()}")
        self.scene.node().removeChild(evt.getIntoNodePath().node().getParent(0))
        self.hammer_sequence.loop()
        self.hammer = True

    def changeBarrelDirection(self, evt):
        print(f"Changing barrel direction {evt}")


    def barrelCrash(self,evt):
        barrel = evt.getIntoNodePath().node().getParent(0).getParent(0)
        other = evt.getFromNodePath().node().getParent(0)

        parents = barrel.parents
        # print(f"{other}")

        if other.name=="barrelDestroyer":
            p = parents[0]
            childrens = barrel.getParent(0).getChildren()
            childrens[1].getPythonTag("subclass").sequence.finish()
            self.scene.node().removeChild(p)
            return

        if not (other==self.mario.node() or other.name=="barrelFixer" ) :
            forceNode = barrel.getChildren()[1]
            actualForce = forceNode.getForce(0)
            actualForce.setVector( actualForce.getLocalVector().x*-1, 0 , 0 )
            forceNode.clear()
            forceNode.addForce(actualForce)


        if( other == self.mario.node() ):
            if not self.hammer:
                self.lifes = self.lifes - 1
                self.floorValidPosition = -4.5
                self.mario.setPos(self.scene, self.marioInitialPos)

            p = parents[0]
            childrens = barrel.getParent(0).getChildren()
            childrens[1].getPythonTag("subclass").sequence.finish()
            self.scene.node().removeChild(p)

            if(  self.lifes < 0):
                print("game over dude!!")
                text = DirectLabel(text="Game Over", text_scale=(0.5,0.5))

    def enableStair(self, evt):
        print("crashed mario and stair");
        self.canClimb = True

    def disableStair(self, evt):
        print("exit mario and stair");
        self.canClimb = False

    def enableJump(self, evt):
        self.isGrounded = True
        print("enable jump")
        # fromCollider =  evt.getFrom().getCenter().z - evt.getFrom().getDimensions().z/2

        self.floorValidPosition = evt.getInto().getCenter().z + 1
        print(f"{ evt.getInto().getCenter().z } {self.floorValidPosition} ")

    def disableJump(self, evt):
        print("disable jump")
        self.isGrounded = False

    def pressUp(self):
        print("up enabled")
        self.input["up"] = True;

    def stopUp(self):
        print("up disabled")
        self.input["up"] = False;

    def pressRight(self):
        self.input["right"] = True;

    def stopRight(self):
        self.input["right"] = False;

    def pressLeft(self):
        self.input["left"] = True;

    def stopLeft(self):
        self.input["left"] = False;

    def pressSpace(self):
        self.input["space"] = True;
        #self.camera.setPos( 0,30,0 )
        #self.camera.lookAt(self.scene)

    def stopSpace(self):
        self.input["space"] = False;

    def getAdvance(self):
        if self.input["left"] and self.input["right"]:
            return 0
        if self.input["left"]:
            return -1
        if self.input["right"]:
            return 1
        return 0

    def applyJump(self):
        jz = 0  # jump Y/Z
        vi = 4 # initial velocity
        g = -6 # gravity

        if(self.isGrounded):
            if(self.canJump):
                if(self.input["space"]):
                    self.jumpTime = 0.1
                    self.canJump = False
                    self.vyi = vi
                    jz = self.vyi*self.jumpTime  + 0.5*g*self.jumpTime*self.jumpTime
                    vz = self.vyi + g*self.jumpTime
                else:
                    return 0
            else:
                self.jumpTime = self.jumpTime + globalClock.getDt()
                jz = self.vyi*self.jumpTime  + 0.5*g*self.jumpTime*self.jumpTime
                vz = self.vyi + g*self.jumpTime
                if vz < 0: #finished
                    self.jumpTime = 0
                    self.canJump = True
                    self.vyi = 0
                    jz = 0
        else:
            if(not self.isClimbing):
                self.canJump = False
                self.jumpTime = self.jumpTime + globalClock.getDt()
                jz = self.vyi*self.jumpTime  + 0.5*g*self.jumpTime*self.jumpTime
                vz = self.vyi + g*self.jumpTime

        return jz
    def applyStairs(self, pz):
        if( self.canClimb):
            if(self.input["up"]):
                self.isClimbing = True

        if( self.isClimbing ):
            if( self.input["up"]):
                return pz + 0.1
        if( not self.canClimb):
            self.isClimbing = False

        return pz
    def update(self,task):
        self.camera.setPos( 0,30,0 )
        self.camera.lookAt(self.scene)
        pz = self.applyJump()

        if( self.posNotInitialized):
            self.marioInitialPos = self.mario.getPos()
            self.posNotInitialized = False

        self.barrelTimer = self.barrelTimer + globalClock.getDt()
        if self.barrelTimer > (3 + random()*2):  # fix error! when dk has lost! -> exercise :D
            self.dk_barrel_sequence.start()
            self.barrelTimer = 0

        # self.mario.getPos(self.render).z
        advZ = self.applyStairs(self.floorValidPosition )
        self.floorValidPosition = advZ

        if( self.getAdvance() != 0):
            self.marioGraphic.setSx(self.mario, -self.getAdvance())

        self.mario.setPos(self.render, self.mario.getPos().x + -self.getAdvance()*.1 , 0 , advZ+pz ) # advZ+pz

        return Task.cont
Пример #35
0
class DKGame(ShowBase):
    def __init__(self):
        super().__init__(self)
        self.loadScenery()
        self.mario = None
        #base.messenger.toggleVerbose()
        self.taskMgr.add(self.setup, "setup")
        self.taskMgr.add(self.update, "update")

        self.accept("raw-arrow_right", self.pressRight)
        self.accept("raw-arrow_right-up", self.stopRight)
        self.accept("raw-arrow_left", self.pressLeft)
        self.accept("raw-arrow_left-up", self.stopLeft)

        self.accept("raw-arrow_up", self.pressUp)
        self.accept("raw-arrow_up-up", self.stopUp)

        self.accept("raw-space", self.pressSpace)
        self.accept("raw-space-up", self.stopSpace)

        self.canClimb = False
        self.isClimbing = False
        #NUEVA!
        self.isGrounded = True
        self.canJump = True
        self.jumpTime = 0
        self.vyi = 0
        self.floorValidPosition = 0

        self.barrelTimer = 0
        self.lifes = 3

        self.marioInitialPos = None
        self.posNotInitialized = True
        self.hammer = False

        self.input = {
            "left": False,
            "right": False,
            "space": False,
            "up": False
        }

    def loadScenery(self):
        self.scene = self.loader.loadModel(
            "models/DKSet1")  # only for non animated objects
        self.scene.reparentTo(self.render)

    def setup(self, task):
        lens = OrthographicLens()
        lens.setFilmSize(25, 20)  # Or whatever is appropriate for your scene
        base.camNode.setLens(lens)

        node = self.scene.find("root/camera1")
        node.removeNode()
        self.camera.setPos(0, 30, 0)
        self.camera.lookAt(self.scene)

        self.mario = self.scene.find("root/mario")
        self.mario.reparentTo(self.scene)

        self.scene.find("root/bottomstair").reparentTo(self.scene)
        self.scene.find("root/floor0").reparentTo(self.scene)
        self.scene.find("root/floor1").reparentTo(self.scene)

        self.scene.find("root/middlestair").reparentTo(self.scene)
        self.scene.find("root/topstair").reparentTo(self.scene)

        self.scene.find("root/floor2").reparentTo(self.scene)
        self.scene.find("root/pCube4").reparentTo(self.scene)
        self.scene.find("root/floors").reparentTo(self.scene)
        self.scene.find("root/barrel").reparentTo(self.scene)

        self.scene.find("root/walls").reparentTo(self.scene)
        self.scene.find("root/rightWall").reparentTo(self.scene)

        self.scene.find("root/MainGroup").reparentTo(self.scene)
        self.scene.find("root/hammer1").reparentTo(self.scene)

        self.barrel = self.scene.find("barrel")
        self.barrel.setPos(self.scene, 0, 0, 0)

        self.setupCollision()

        base.enableParticles()
        gravityFN = ForceNode('world-forces')
        gravityFNP = render.attachNewNode(gravityFN)
        gravityForce = LinearVectorForce(0, 0, -9.81)  #gravity acceleration
        gravityFN.addForce(gravityForce)
        base.physicsMgr.addLinearForce(gravityForce)

        return Task.done

    def createBarrel(self):

        barrelNode = NodePath("PhysicalBarrel")
        barrelNode.reparentTo(self.scene)

        physicsBarrel = ActorNode("physics_barrel")
        physicsBarrel.getPhysicsObject().setMass(
            0.01)  #in what units? (69 kindda 3 lbs)
        barrel = barrelNode.attachNewNode(physicsBarrel)
        base.physicsMgr.attachPhysicalNode(physicsBarrel)

        barrel.setPos(0, 0, 2)

        visual_barrel = self.scene.attachNewNode("BarrelCopy")
        originalBarrel = self.scene.find("barrel")
        originalBarrel.instanceTo(visual_barrel)
        visual_barrel.reparentTo(barrel)

        sphere = CollisionSphere(6.6, 0, 4.78, 0.5)
        cnodePath = visual_barrel.attachNewNode(
            CollisionNode('barrelCollider'))
        cnodePath.node().addSolid(sphere)
        cnodePath.node().setFromCollideMask(
            0xD)  # crash with default and mario body and walls
        cnodePath.node().setIntoCollideMask(
            0xD)  # crash with default and mario body and walls
        cnodePath.show()
        self.physicsCollisionPusher.addCollider(cnodePath, barrel)
        base.cTrav.addCollider(cnodePath, self.physicsCollisionPusher)

        barrelForceNode = ForceNode('barrelForce')
        barrel.attachNewNode(barrelForceNode)
        barrelForce = LinearVectorForce(-7, 0, 0, 1, False)
        # barrelForce.setMassDependent(0)
        barrelForceNode.addForce(barrelForce)
        physicsBarrel.getPhysical(0).addLinearForce(barrelForce)

    def setupBoxCollider(self,
                         node,
                         px,
                         py,
                         pz,
                         w,
                         d,
                         h,
                         nm,
                         colliderEventHandler,
                         fromCollisionMask=0,
                         intoCollisionMask=0):

        hitBox = CollisionBox(Point3(px, py, pz), w, d, h)
        cnodePath = node.attachNewNode(CollisionNode(nm))
        cnodePath.node().addSolid(hitBox)
        cnodePath.node().setIntoCollideMask(intoCollisionMask)
        cnodePath.node().setFromCollideMask(fromCollisionMask)
        cnodePath.show()
        base.cTrav.addCollider(cnodePath, colliderEventHandler)

    def setupCollision(self):
        base.cTrav = CollisionTraverser()
        self.collisionHandlerEvent = CollisionHandlerEvent()
        self.physicsCollisionPusher = PhysicsCollisionHandler()

        self.collisionHandlerEvent.addInPattern('into-%in')
        self.collisionHandlerEvent.addOutPattern('outof-%in')

        # create masks
        defaultCollisionMask = BitMask32(0b0001)  #0x1
        segmentCollisionMask = BitMask32(0b1000)  #0x8
        stairsCollisionMask = BitMask32(0b0010)  #0x2
        marioBodyCollisionMask = BitMask32(0b0011)  #0x3
        collisionWallsForBarrels = BitMask32(0b0100)  #0x4

        # mario segment collider
        ray = CollisionSegment(7, 0, -4.5, 7, 0, -5.1)
        cnodePath = self.mario.attachNewNode(CollisionNode('marioRay'))
        cnodePath.node().addSolid(ray)
        cnodePath.node().setFromCollideMask(segmentCollisionMask)
        cnodePath.node().setIntoCollideMask(0)
        cnodePath.show()
        base.cTrav.addCollider(cnodePath, self.collisionHandlerEvent)

        self.setupBoxCollider(self.mario, 7, 0, -4.5, 0.5, 5, 0.5,
                              'marioHitBox', self.collisionHandlerEvent,
                              marioBodyCollisionMask, marioBodyCollisionMask)

        stairs1 = self.scene.find("bottomstair")
        self.setupBoxCollider(stairs1, -6.8, 0, -3.0, 0.5, 5, 2.5,
                              'stairs1HitBox', self.collisionHandlerEvent,
                              stairsCollisionMask, stairsCollisionMask)

        stairs2 = self.scene.find("middlestair")
        self.setupBoxCollider(stairs2, -0.86, 0, .1, 0.5, 5, 2.1,
                              'stairs2HitBox', self.collisionHandlerEvent,
                              stairsCollisionMask, stairsCollisionMask)

        stairs3 = self.scene.find("topstair")
        self.setupBoxCollider(stairs3, -6.8, 0, 3.1, 0.5, 5, 2.2,
                              'stairs3HitBox', self.collisionHandlerEvent,
                              stairsCollisionMask, stairsCollisionMask)

        hammer = self.scene.find("MainGroup")  # hammer
        self.setupBoxCollider(hammer, 5.5, 0, -1.5, 0.5, 5, 0.5,
                              'hammer1HitBox', self.collisionHandlerEvent,
                              stairsCollisionMask, stairsCollisionMask)

        dk = self.scene.find("hammer1")
        self.setupBoxCollider(dk, 8.7, 0, 5, 1, 5, 1, 'dkHitBox',
                              self.collisionHandlerEvent, stairsCollisionMask,
                              stairsCollisionMask)

        floor0 = self.scene.find("floor0")
        self.setupBoxCollider(floor0,
                              -2.5,
                              0,
                              -5.5,
                              10,
                              5,
                              0.5,
                              'floor0HitBox',
                              self.collisionHandlerEvent,
                              intoCollisionMask=segmentCollisionMask)

        floor1 = self.scene.find("floor1")
        self.setupBoxCollider(floor1,
                              2,
                              0,
                              -2.5,
                              8.4,
                              5,
                              0.5,
                              'floor1HitBox',
                              self.collisionHandlerEvent,
                              intoCollisionMask=segmentCollisionMask)
        floor2_1 = self.scene.find("floor2")
        self.setupBoxCollider(floor2_1,
                              3.6,
                              0,
                              0.5,
                              3.8,
                              5,
                              0.5,
                              'floor21HitBox',
                              self.collisionHandlerEvent,
                              intoCollisionMask=segmentCollisionMask)
        floor2_2 = self.scene.find("pCube4")
        self.setupBoxCollider(floor2_2,
                              -6.3,
                              0,
                              0.5,
                              5.0,
                              5,
                              0.5,
                              'floor22HitBox',
                              self.collisionHandlerEvent,
                              intoCollisionMask=segmentCollisionMask)
        floor3 = self.scene.find("floors")
        self.setupBoxCollider(floor3,
                              1.8,
                              0,
                              3.5,
                              8,
                              5,
                              0.5,
                              'floor3HitBox',
                              self.collisionHandlerEvent,
                              intoCollisionMask=segmentCollisionMask)

        rightWall = self.scene.find("rightWall")
        self.setupBoxCollider(rightWall,
                              -12,
                              0,
                              0,
                              1,
                              5,
                              10,
                              'rightWallHitBox',
                              self.collisionHandlerEvent,
                              fromCollisionMask=collisionWallsForBarrels,
                              intoCollisionMask=collisionWallsForBarrels)

        leftWall = self.scene.find("walls")
        self.setupBoxCollider(leftWall,
                              11.5,
                              0,
                              0,
                              1,
                              5,
                              10,
                              'leftWallHitBox',
                              self.collisionHandlerEvent,
                              fromCollisionMask=collisionWallsForBarrels,
                              intoCollisionMask=collisionWallsForBarrels)

        barrelFixer = self.scene.attachNewNode("barrelFixer")
        self.setupBoxCollider(barrelFixer,
                              -3,
                              0,
                              0.505,
                              10,
                              5,
                              0.5,
                              'barrelFixerHitBox',
                              self.collisionHandlerEvent,
                              fromCollisionMask=collisionWallsForBarrels,
                              intoCollisionMask=collisionWallsForBarrels)

        barrelDestroyer = self.scene.attachNewNode("barrelDestroyer")
        self.setupBoxCollider(barrelDestroyer,
                              0,
                              0,
                              -8,
                              15,
                              5,
                              0.5,
                              'barrelDestroyerHitBox',
                              self.collisionHandlerEvent,
                              fromCollisionMask=collisionWallsForBarrels,
                              intoCollisionMask=collisionWallsForBarrels)

        self.accept('into-stairs1HitBox', self.enableStair)
        self.accept('outof-stairs1HitBox', self.disableStair)
        self.accept('into-stairs2HitBox', self.enableStair)
        self.accept('outof-stairs2HitBox', self.disableStair)
        self.accept('into-stairs3HitBox', self.enableStair)
        self.accept('outof-stairs3HitBox', self.disableStair)
        self.accept('into-hammer1HitBox', self.enableHammer)
        self.accept('into-dkHitBox', self.dkArrived)

        self.accept('into-floor0HitBox', self.enableJump)
        self.accept('outof-floor0HitBox', self.disableJump)
        self.accept('into-floor1HitBox', self.enableJump)
        self.accept('outof-floor1HitBox', self.disableJump)
        self.accept('into-floor21HitBox', self.enableJump)
        self.accept('outof-floor21HitBox', self.disableJump)
        self.accept('into-floor22HitBox', self.enableJump)
        self.accept('outof-floor22HitBox', self.disableJump)
        self.accept('into-floor3HitBox', self.enableJump)
        self.accept('outof-floor3HitBox', self.disableJump)

        self.accept("into-barrelCollider", self.barrelCrash)

        base.cTrav.showCollisions(self.render)

    def dkArrived(self, evt):
        if (self.hammer):
            self.scene.node().removeChild(
                evt.getIntoNodePath().node().getParent(0))
        else:
            self.floorValidPosition = 0
            self.mario.setPos(self.scene, self.marioInitialPos)
            text = DirectLabel(text="Game Over", text_scale=(0.5, 0.5))

    def enableHammer(self, evt):
        print(f"{evt.getIntoNodePath()}{evt.getFromNodePath()}")
        self.scene.node().removeChild(
            evt.getIntoNodePath().node().getParent(0))
        self.hammer = True

    def changeBarrelDirection(self, evt):
        print(f"Changing barrel direction {evt}")

    def barrelCrash(self, evt):
        barrel = evt.getIntoNodePath().node().getParent(0).getParent(0)
        other = evt.getFromNodePath().node().getParent(0)

        parents = barrel.parents
        print(f"{other}")

        if other.name == "barrelDestroyer":
            p = parents[0]
            self.scene.node().removeChild(p)
            return

        if not (other == self.mario.node() or other.name == "barrelFixer"):
            forceNode = barrel.getChildren()[1]
            actualForce = forceNode.getForce(0)
            actualForce.setVector(actualForce.getLocalVector().x * -1, 0, 0)
            forceNode.clear()
            forceNode.addForce(actualForce)

        if (other == self.mario.node()):
            if not self.hammer:
                self.lifes = self.lifes - 1
                self.floorValidPosition = 0
                self.mario.setPos(self.scene, self.marioInitialPos)

            p = parents[0]
            self.scene.node().removeChild(p)

            if (self.lifes < 0):
                print("game over dude!!")
                text = DirectLabel(text="Game Over", text_scale=(0.5, 0.5))

    def enableStair(self, evt):
        print("crashed mario and stair")
        self.canClimb = True

    def disableStair(self, evt):
        print("exit mario and stair")
        self.canClimb = False

    def enableJump(self, evt):
        self.isGrounded = True
        print("enable jump")
        # fromCollider =  evt.getFrom().getCenter().z - evt.getFrom().getDimensions().z/2
        self.floorValidPosition = evt.getInto().getCenter().z + 5.5
        #print(f"{ evt.getInto().getCenter().z } {self.floorValidPosition} ")

    def disableJump(self, evt):
        print("disable jump")
        self.isGrounded = False

    def pressUp(self):
        print("up enabled")
        self.input["up"] = True

    def stopUp(self):
        print("up disabled")
        self.input["up"] = False

    def pressRight(self):
        self.input["right"] = True

    def stopRight(self):
        self.input["right"] = False

    def pressLeft(self):
        self.input["left"] = True

    def stopLeft(self):
        self.input["left"] = False

    def pressSpace(self):
        self.input["space"] = True
        self.camera.setPos(0, 30, 0)
        self.camera.lookAt(self.scene)

    def stopSpace(self):
        self.input["space"] = False

    def getAdvance(self):
        if self.input["left"] and self.input["right"]:
            return 0
        if self.input["left"]:
            return -1
        if self.input["right"]:
            return 1
        return 0

    def applyJump(self):
        jz = 0  # jump Y/Z
        vi = 4  # initial velocity
        g = -6  # gravity

        if (self.isGrounded):
            if (self.canJump):
                if (self.input["space"]):
                    self.jumpTime = 0.1
                    self.canJump = False
                    self.vyi = vi
                    jz = self.vyi * self.jumpTime + 0.5 * g * self.jumpTime * self.jumpTime
                    vz = self.vyi + g * self.jumpTime
                else:
                    return 0
            else:
                self.jumpTime = self.jumpTime + globalClock.getDt()
                jz = self.vyi * self.jumpTime + 0.5 * g * self.jumpTime * self.jumpTime
                vz = self.vyi + g * self.jumpTime
                if vz < 0:  #finished
                    self.jumpTime = 0
                    self.canJump = True
                    self.vyi = 0
                    jz = 0
        else:
            if (not self.isClimbing):
                self.canJump = False
                self.jumpTime = self.jumpTime + globalClock.getDt()
                jz = self.vyi * self.jumpTime + 0.5 * g * self.jumpTime * self.jumpTime
                vz = self.vyi + g * self.jumpTime

        return jz

    def applyStairs(self, pz):
        if (self.canClimb):
            if (self.input["up"]):
                self.isClimbing = True

        if (self.isClimbing):
            if (self.input["up"]):
                return pz + 0.1
        if (not self.canClimb):
            self.isClimbing = False

        return pz

    def update(self, task):
        self.camera.setPos(0, 30, 0)
        self.camera.lookAt(self.scene)
        pz = self.applyJump()

        if (self.posNotInitialized):
            self.marioInitialPos = self.mario.getPos()
            self.posNotInitialized = False

        self.barrelTimer = self.barrelTimer + globalClock.getDt()
        if self.barrelTimer > (3 + random() * 2):
            self.createBarrel()
            self.barrelTimer = 0

        # self.mario.getPos(self.render).z
        advZ = self.applyStairs(self.floorValidPosition)
        self.floorValidPosition = advZ
        #print(f' {self.mario.getPos(self.render).z} {self.floorValidPosition}  ')
        self.mario.setPos(self.render,
                          self.mario.getPos().x + -self.getAdvance() * .1, 0,
                          advZ + pz)
        return Task.cont
Пример #36
0
class TunnelPinchTask(ShowBase, GripStateMachine):
    DATA_DIR = 'data'
    
    def __init__(self, id, session, hand, block, mode, wrist):
        ShowBase.__init__(self)
        GripStateMachine.__init__(self)
        base.disableMouse()
        wp = WindowProperties()
        wp.setSize(1920,1080)
        wp.setFullscreen(True)
        wp.setUndecorated(True)
        base.win.requestProperties(wp)

        self.sub_id = str(id)
        self.sess_id = str(session)
        self.hand = str(hand)
        self.block = str(block)
        self.mode = str(mode)
        self.wrist = str(wrist)
        
        self.prev_blk = os.path.join(self.DATA_DIR,'exp_2',self.sub_id,self.sess_id,self.wrist,self.hand,"B0")
        self.exp_blk0 = os.path.join(self.DATA_DIR,'exp_1',self.sub_id,self.sess_id,self.wrist,self.hand,"B0")
        self.table = np.loadtxt('src/tunnel_pinch_task/trialtable_flex.csv',dtype='str',delimiter=',',skiprows=1)

        indices = {}
        try:
            self.prev_table = np.loadtxt(os.path.join(self.prev_blk, 'final_targets.csv'),dtype='str',delimiter=',',skiprows=1)
        except:
            try:
                self.prev_table = np.loadtxt(os.path.join(self.exp_blk0, 'final_targets.csv'),dtype='str',delimiter=',',skiprows=1)
            except:
                print('Previous target file not found, results may be suboptimal')
        try:
            for i in range(self.prev_table.shape[0]):
                indices[self.prev_table[i,1]] = int(self.prev_table[i,0])-1
            for i in range(self.table.shape[0]):
                self.table[i,11] = self.prev_table[indices[self.table[i,1].strip()],11]
                self.table[i,12] = self.prev_table[indices[self.table[i,1].strip()],12]
                self.table[i,13] = self.prev_table[indices[self.table[i,1].strip()],13]
        except:
            print('Invalid target file')
        
        self.table = np.array([[item.strip() for item in s] for s in self.table])

        ###################################################
        #only use rows relevant to this block
        #HARDCODED! NOTE IN LOG SHEET
        spec_table = []
        for i in range(self.table.shape[0]):
            if int(self.block)%5 == 0: #block 0 to adjust positions
                if "(p)" in self.table[i,2]:
                    spec_table.append(self.table[i])
            elif int(self.block)%5 == 1:
                if "(L)" in self.table[i,2]:
                    spec_table.append(self.table[i])
            elif int(self.block)%5 == 2:
                if "(L+t)" in self.table[i,2]:
                    spec_table.append(self.table[i])
            elif int(self.block)%5 == 3:
                if "(S)" in self.table[i,2]:
                    spec_table.append(self.table[i])
            elif int(self.block)%5 == 4:
                if "(S+t)" in self.table[i,2]:
                    spec_table.append(self.table[i])
        ###################################################
        self.table = np.array(spec_table)

        self.session_dir = os.path.join(self.DATA_DIR,'exp_2',self.sub_id,self.sess_id,self.wrist,self.hand)
        self.subjinfo = self.sub_id + '_' + self.sess_id + '_' + self.hand + '_log.yml'
        self.p_x,self.p_y,self.p_a = GET_POS(self.session_dir,self.subjinfo,self.hand,self.wrist)

        self.rotmat = ROT_MAT(self.p_a,self.hand)

        self.setup_text()
        self.setup_lights()
        self.setup_camera()
        
        self.trial_counter = 0
        self.load_models()
        self.load_audio()
        self.update_trial_command()
        self.countdown_timer = CountdownTimer()
        self.hold_timer = CountdownTimer()

        self.cTrav = CollisionTraverser()
        self.chandler = CollisionHandlerEvent()
        self.chandler.addInPattern('%fn-into-%in')
        self.chandler.addOutPattern('%fn-outof-%in')
        self.chandler.addAgainPattern('%fn-again-%in')
        self.attachcollnodes()

        taskMgr.add(self.read_data, 'read')
        for i in range(5):
            taskMgr.add(self.move_player, 'move%d' % i, extraArgs = [i], appendTask=True)
        taskMgr.add(self.log_data, 'log_data')
        taskMgr.add(self.update_state, 'update_state', sort=1)

        self.accept('space', self.space_on)
        self.accept('escape', self.clean_up)
        self.space = False
        self.statenum = list()

        self.max_time = 20
        self.med_data = None

        self.grip_dir = os.path.join(self.DATA_DIR,'exp_2',self.sub_id,self.sess_id,self.wrist,self.hand,"B"+self.block)
        if not os.path.exists(self.grip_dir):
           print('Making new folders: ' + self.grip_dir)
           os.makedirs(self.grip_dir)

        self.dev = MpDevice(RightHand(calibration_files=['calibs/cal_mat_70_v2.mat',
                                                'calibs/cal_mat_73_v2.mat',
                                                'calibs/cal_mat_56.mat',
                                                'calibs/cal_mat_58_v2.mat',
                                                'calibs/cal_mat_50.mat'], clock=mono_clock.get_time))

    ############
    #SET UP HUD#
    ############
    def setup_text(self):
        self.bgtext = OnscreenText(text='Not recording.', pos=(-0.8, 0.8),
                                 scale=0.08, fg=(0, 0, 0, 1),
                                 bg=(1, 1, 1, 1), frame=(0.2, 0.2, 0.8, 1),
                                 align=TextNode.ACenter)
        self.bgtext.reparentTo(self.aspect2d)

        self.dirtext = OnscreenText( pos=(-0.6, 0.65),
                                 scale=0.08, fg=(0, 0, 0, 1),
                                 bg=(1, 1, 1, 1), frame=(0.2, 0.2, 0.8, 1),
                                 align=TextNode.ACenter)
        self.dirtext.reparentTo(self.aspect2d)
    
    ##########################
    #SET UP SCENE AND PLAYERS#
    ##########################
    def setup_lights(self):
        pl = PointLight('pl')
        pl.setColor((1, 1, 1, 1))
        plNP = self.render.attachNewNode(pl)
        plNP.setPos(-10, -10, 10)
        self.render.setLight(plNP)
        pos = [[[0, 0, 50], [0, 0, -10]],
               [[0, -50, 0], [0, 10, 0]],
               [[-50, 0, 0], [10, 0, 0]]]
        for i in pos:
            dl = Spotlight('dl')
            dl.setColor((1, 1, 1, 1))
            dlNP = self.render.attachNewNode(dl)
            dlNP.setPos(*i[0])
            dlNP.lookAt(*i[1])
            dlNP.node().setShadowCaster(False)
            self.render.setLight(dlNP)

    def setup_camera(self):
        self.cam.setPos(0, 0, 12)
        self.cam.lookAt(0, 2, 0)
        self.camLens.setFov(90)

    def load_models(self):
        self.back_model = self.loader.loadModel('models/back')
        self.back_model.setScale(10, 10, 10)
        if self.hand == "Left":
            self.back_model.setH(90)
        self.back_model.reparentTo(self.render)

        self.player_offsets = [[self.p_x[0]-5, self.p_y[0]+3, 0], [self.p_x[1]-2.5, self.p_y[1]+4.5, 0], [self.p_x[2], self.p_y[2]+5, 0],
                                [self.p_x[3]+2.5, self.p_y[3]+4.5, 0], [self.p_x[4]+5, self.p_y[4]+3, 0]]
        self.p_col =[[0,0,250],[50,0,200],[125,0,125],[200,0,50],[250,0,0]]
        if self.hand == 'Left':
            self.p_col = self.p_col[::-1]

        self.players = list()
        self.contacts = list()        
        for counter, value in enumerate(self.player_offsets):
            self.players.append(self.loader.loadModel('models/target'))
            self.contacts.append(False)

            self.players[counter].setPos(*value)
            self.players[counter].setScale(0.2, 0.2, 0.2)
            self.players[counter].setColorScale(
                self.p_col[counter][0]/255, self.p_col[counter][1]/255, self.p_col[counter][2]/255, 1)
            self.players[counter].reparentTo(self.render)
            self.players[counter].show()

        self.target_select()

    def load_audio(self):
        self.pop = self.loader.loadSfx('audio/Blop.wav')
        self.buzz = self.loader.loadSfx('audio/Buzzer.wav')


    ############################
    #SET UP COLLISION MECHANICS#
    ############################
    def attachcollnodes(self):
        self.inside = [False]*5
        for i in range(5):
            self.fromObject = self.players[i].attachNewNode(CollisionNode('colfromNode'+str(i)))
            self.fromObject.node().addSolid(CollisionSphere(0,0,0,1))
            self.cTrav.addCollider(self.fromObject, self.chandler)

        for i in range(5):
            self.accept('colfromNode%d-into-colintoNode' % i, self.collide1,[i])
            self.accept('colfromNode%d-again-colintoNode' % i, self.collide2,[i])
            self.accept('colfromNode%d-outof-colintoNode' % i, self.collide3,[i])

    def collide1(self,f,collEntry):
        if f in self.highlighted_indices:
            self.players[f].setColorScale(0,1,0,1)
            self.tar.setColorScale(0.2,0.2,0.2,1)
            self.tar.setAlphaScale(0.7)
            self.contacts[f] = True
            taskMgr.doMethodLater(self.delay,self.too_long,'too_long%d' % f,extraArgs = [f])
                
    def collide2(self,f,collEntry):
        for i in self.highlighted_indices:
            if self.contacts[i] == False:
                return
        taskMgr.remove('too_long%d' % f)

    def collide3(self,f,collEntry):
        taskMgr.remove('too_long%d' % f)
        self.reset_fing(f)
        self.tar.setColorScale(0.1,0.1,0.1,1)
        self.tar.setAlphaScale(0.7)

    def too_long(self,f):
        self.reset_fing(f)
        self.tar.setColorScale(0.5,0.2,0.2,1)
        self.tar.setAlphaScale(0.7)

    def reset_fing(self,f):
        self.players[f].setColorScale(
                self.p_col[f][0]/255, self.p_col[f][1]/255, self.p_col[f][2]/255, 1)
        self.contacts[f] = False

    ###############
    #TARGET THINGS#
    ###############
    def show_target(self):
        self.target_select()
        self.intoObject = self.tar.attachNewNode(CollisionNode('colintoNode'))

        if self.table[self.trial_counter,7] == "sphere":
            self.intoObject.node().addSolid(CollisionSphere(0,0,0,1))
        elif self.table[self.trial_counter,7] == "cylinder":
            self.intoObject.node().addSolid(CollisionTube(0,0,-2,0,0,2,1))
        else:
            raise NameError("No such collision type")

        self.tar.show()
        self.occSolid.show()
        self.occLines.show()

        for i in range(5):
            if i not in self.highlighted_indices:
                self.players[i].hide()

    def target_select(self):
        self.tgtscx=float(self.table[self.trial_counter,14])
        self.tgtscy=float(self.table[self.trial_counter,15])
        self.tgtscz=float(self.table[self.trial_counter,16])
        tgttsx=float(self.table[self.trial_counter,11])
        tgttsy=float(self.table[self.trial_counter,12])
        tgttsz=float(self.table[self.trial_counter,13])
        tgtrx=float(self.table[self.trial_counter,17])
        tgtry=float(self.table[self.trial_counter,18])
        tgtrz=float(self.table[self.trial_counter,19])
        if self.hand == 'Left':
            tgttsx *= -1
            tgtrx *= -1

        self.static_task = (str(self.table[self.trial_counter,5]) == "True")
        self.target_model = str(self.table[self.trial_counter,6])
        self.highlighted_indices=[int(s)-1 for s in self.table[self.trial_counter,4].split(' ')]
        if self.hand == 'Left':
            self.highlighted_indices=[4-i for i in self.highlighted_indices]

        self.tgtposx = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][[-2,-1],0]) + tgttsx
        self.tgtposy = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][[0,1],1]) + tgttsy
        if self.hand == 'Left':
            self.tgtposx = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][[0,1],0]) + tgttsx
            self.tgtposy = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][[-2,-1],1]) + tgttsy
        #self.tgtposx = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][:,0])
        #self.tgtposy = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][:,1])
        self.tgtposz = np.mean(np.asarray(self.player_offsets)[self.highlighted_indices][:,2]) + tgttsz
        
        self.tar = self.loader.loadModel(self.target_model)
        self.tar.setScale(self.tgtscx,self.tgtscy,self.tgtscz)
        self.tar.setPos(self.tgtposx,self.tgtposy,self.tgtposz)
        self.tar.setHpr(tgtrx,tgtry,tgtrz)
        self.tar.setColorScale(0.1, 0.1, 0.1, 1)
        self.tar.setAlphaScale(0.7)
        self.tar.setTransparency(TransparencyAttrib.MAlpha)
        self.tar.reparentTo(self.render)
        self.tar.hide()

        if len(self.highlighted_indices) == 2:
            dx = self.players[self.highlighted_indices[0]].getX() - self.players[self.highlighted_indices[1]].getX()
            dy = self.players[self.highlighted_indices[0]].getY() - self.players[self.highlighted_indices[1]].getY()
            angle = math.degrees(math.atan(dy/dx))
            self.table[self.trial_counter,9] =  str(angle) + ' ' + str(angle-180)
        
        self.angs=self.table[self.trial_counter,9].split(' ')
        self.angs = [float(a) for a in self.angs]
        self.tunn_width=float(self.table[self.trial_counter,10])
        self.r = 1.5
        if int(self.block) == 0:
            self.r = 0
        self.x = [self.r*math.cos(math.radians(a)) for a in self.angs]
        self.y = [self.r*math.sin(math.radians(a)) for a in self.angs]
        self.occ = draw_shape(self.angs,self.tunn_width,self.r)
        self.occSolid = render.attachNewNode(self.occ[0])
        self.occSolid.setPos(self.tgtposx,self.tgtposy,self.tgtposz)
        self.occSolid.setColorScale(0,1,1,0)
        self.occSolid.setTransparency(TransparencyAttrib.MAlpha)
        self.occSolid.setAlphaScale(0.6)
        self.occLines = render.attachNewNode(self.occ[1])
        self.occLines.setPos(self.tgtposx,self.tgtposy,self.tgtposz)
        self.occSolid.hide()
        self.occLines.hide()
        self.delay=float(self.table[self.trial_counter,8])

        self.distances = [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[0,0,0]]

        #change camera to be on top of target
        self.cam.setPos(self.tgtposx, self.tgtposy - 2, 12)
        self.back_model.setPos(self.tgtposx,self.tgtposy - 2,0)
        self.cam.lookAt(self.tgtposx, self.tgtposy, 0)

    ##############
    #MOVE FINGERS#
    ##############
    def read_data(self,task):
        error, data = self.dev.read()
        if data is not None:
            data *= 0.001
            self.ts = data.time
            data = np.dot(data,self.rotmat)
            self.data = data
            if self.med_data is None:
                self.med_data = np.median(data, axis=0)

            if self.space:
                self.statenum.extend(([self.checkstate()])*len(data.time))
                
        return task.cont
        
    def move_player(self,p,task):
        if self.data is not None :
            k = p*3
            new_x = 10*np.mean(self.data[-1,k]) + self.player_offsets[p][0] - 10*self.med_data[k]
            new_y = 10*np.mean(self.data[-1,k + 1]) + self.player_offsets[p][1] - 10*self.med_data[k + 1]
            new_z = 10*np.mean(self.data[-1,k + 2]) + self.player_offsets[p][2] - 10*self.med_data[k + 2]

            #make sure digits do not cross each other
            if ((p in range(1,3) and p+1 in self.highlighted_indices and new_x > self.players[p+1].getX())
                or (p in range(2,4) and p-1 in self.highlighted_indices and new_x < self.players[p-1].getX())):
                    new_x = self.players[p].getX()
            
            #make sure digits do not cross into target
            if self.space == True and p in self.highlighted_indices:
                self.distances[p][0] = new_x - self.tar.getX()
                self.distances[p][1] = new_y - self.tar.getY()
                self.distances[p][2] = new_z - self.tar.getZ()
                self.check_pos(p)
                
            self.players[p].setPos(new_x, new_y, new_z)
            
        return task.cont
    
    def check_pos(self, p):
        x = self.distances[p][0]
        y = self.distances[p][1]
        z = self.distances[p][2]
        hit = True
        for i in range(len(self.angs)):
            p_ang = math.acos((x*self.x[i]+y*self.y[i])/(self.r*(x**2+y**2)**0.5))
            if math.sin(p_ang)*(x**2+y**2)**0.5 < self.tunn_width and p_ang < math.pi/2:
                hit = False
                break
        if (abs(z) <= 1.2 #check z location
            and x**2 + y**2 <= self.r**2 #within radius of circle
            and hit == True):
                if self.inside[p] is False:
                    self.ignore('colfromNode%d-into-colintoNode' % p)
                    self.ignore('colfromNode%d-again-colintoNode' % p)
                    self.players[p].setColorScale(1,1,0,1)
                    self.inside[p] = True
        else:
            if self.inside[p] is True and x**2 + y**2 > self.r**2:
                self.accept('colfromNode%d-into-colintoNode' % p, self.collide1,[p])
                self.accept('colfromNode%d-again-colintoNode' % p, self.collide2,[p])
                self.players[p].setColorScale(
                    self.p_col[p][0]/255, self.p_col[p][1]/255, self.p_col[p][2]/255, 1)
                self.inside[p] = False

    ##################
    #CHECK COMPLETION#
    ##################
    def close_to_target(self):
        for i in self.highlighted_indices:
            if self.contacts[i] == False:
                return False

        self.tar.setColorScale(0,1,1,1)
        return True

    def check_hold(self):
        if not self.close_to_target():
            self.hold_timer.reset(0.5)
            return False
        return self.hold_timer.elapsed() < 0

    def adjust_targets(self):
        #no adjustment if more than 2 fingers or position is prone
        if len(self.highlighted_indices) > 2 or self.wrist == 'pron':
            return

        xadj,yadj,zadj = np.mean(np.asarray(self.distances)[self.highlighted_indices],0)
        #xadj = np.mean(np.asarray(self.distances)[self.highlighted_indices][0])
        #yadj = np.mean(np.asarray(self.distances)[self.highlighted_indices][1])
        #zadj = np.mean(np.asarray(self.distances)[self.highlighted_indices][2])

        #do adjustment on all tasks with same name
        if self.hand == 'Left':
            xadj = -xadj
        for i in range(self.trial_counter+1,self.table.shape[0]):
            if self.table[i,1] == self.table[self.trial_counter,1]:
                self.table[i,11] = float(self.table[i,11]) + xadj
                self.table[i,12] = float(self.table[i,12]) + yadj
                self.table[i,13] = float(self.table[i,13]) + zadj
    
    #########
    #LOGGING#
    #########
    def play_success(self):
        if int(self.block) == 0:
            self.adjust_targets()
        self.pop.play()
        self.tar.hide()
        self.highlighted_indices = [0,1,2,3,4]

    def log_text(self):
        self.bgtext.setText('Now logging...')

    def log_data(self, task):
        if (self.trial_counter + 1) <= self.table.shape[0]:
            if self.space:
                self.log_file_name = os.path.join(self.grip_dir,
                                          self.sub_id+"_"+self.sess_id+"_"+self.hand+"_"+
                                              str(self.table[self.trial_counter,1])+"_"+str(self.table[self.trial_counter,0])+".csv" )
                self.movvars = np.column_stack((self.ts, self.statenum, self.data))
                self.statenum = []
                if self.mode=='task':
                    with open(self.log_file_name, 'ab') as f:
                        np.savetxt(f, self.movvars, fmt='%10.5f', delimiter=',')
            return task.cont
        else:
            pass

    def stoplog_text(self):
        self.dirtext.clearText()
        self.bgtext.setText('Done logging!')
        for i in range(5):
            self.players[i].show()

    #######
    #RESET#
    #######
    def delete_file(self):
        if (self.trial_counter + 1) <= self.table.shape[0]:
            self.log_file_name = os.path.join(self.grip_dir,
                                      self.sub_id+"_"+self.sess_id+"_"+self.hand+"_"+
                                          str(self.table[self.trial_counter,1])+"_"+str(self.table[self.trial_counter,0])+".csv" )
            try:
                os.remove(self.log_file_name)
            except OSError:
                pass
        else:
            pass

    def reset_baseline(self):
       self.med_data = None
                   
    def reset_keyboard_bool(self):
        self.space = False

    def hide_target(self):
        self.tar.hide()
        self.occSolid.hide()
        self.occLines.hide()
        self.intoObject.removeNode()
        self.imageObject.destroy()

    def update_trial_command(self):
        self.dirtext.setText(str(self.table[self.trial_counter,2]))
        if self.hand == 'Left':
            xfac = -0.25
        else:
            xfac = 0.25
        self.imageObject = OnscreenImage(image = str(self.table[self.trial_counter,3]),scale=(xfac,0.25,0.25),pos=(-0.8, 0, 0.3))

    def increment_trial_counter(self):
        self.trial_counter += 1
        self.update_trial_command()

    ########
    #TIMERS#
    ########
    def start_trial_countdown(self):
        self.countdown_timer.reset(self.max_time)

    def start_hold_countdown(self):
        self.hold_timer.reset(0.5)

    def start_post_countdown(self):
        self.countdown_timer.reset(2)

    def time_elapsed(self):
        return self.countdown_timer.elapsed() < 0

    #########
    #MACHINE#
    #########
    def update_state(self, task):
        self.step()
        return task.cont

    def wait_for_space(self):
        return self.space

    def space_on(self):
        self.space = True

    #####
    #END#
    #####
    def trial_counter_exceeded(self):
        return (self.trial_counter+1) > self.table.shape[0]-1

    def clean_up(self):
        #write last known positions to 'final_targets' file
        f = open('src/pinch_task/trialtable_flex.csv')
        header = f.readline().rstrip()
        np.savetxt(self.grip_dir + '/final_targets.csv',self.table,fmt='%s',header = header, delimiter=',')
        f.close()
        sys.exit()
Пример #37
0
class World(DirectObject):
 
    def __init__( self ):
        # Initialize the traverser.
        base.cTrav = CollisionTraverser()
 
        # Initialize the handler.
        self.collHandEvent = CollisionHandlerEvent()
        self.collHandEvent.addInPattern('into-%in')
        self.collHandEvent.addOutPattern('outof-%in')
 
        # Make a variable to store the unique collision string count.
        self.collCount = 0
 
        # Load a model. Reparent it to the camera so we can move it.
        s = loader.loadModel('smiley')	
        s.reparentTo(camera)
        s.setPos(0, 25, 0)
 
        # Setup a collision solid for this model.
        sColl = self.initCollisionSphere(s, True)
 
        # Add this object to the traverser.
        base.cTrav.addCollider(sColl[0], self.collHandEvent)
 
        # Accept the events sent by the collisions.
        self.accept('into-' + sColl[1], self.collide3)
        self.accept('outof-' + sColl[1], self.collide4)
        print(sColl[1])
 
        # Load another model.
        t = loader.loadModel('smiley')
        t.reparentTo(render)
        t.setPos(5, 25, 0)
 
        # Setup a collision solid for this model.
        tColl = self.initCollisionSphere(t, True)
 
        # Add this object to the traverser.
        base.cTrav.addCollider(tColl[0], self.collHandEvent)
 
        # Accept the events sent by the collisions.
        self.accept('into-' + tColl[1], self.collide)
        self.accept('outof-' + tColl[1], self.collide2)
        print(tColl[1])
 
        print("WERT")
 
    def collide(self, collEntry):
        print("WERT: object has collided into another object")
        Sequence(Func(collEntry.getFromNodePath().getParent().setColor,
                      VBase4(1, 0, 0, 1)),
                 Wait(0.2),
                 Func(collEntry.getFromNodePath().getParent().setColor,
                      VBase4(0, 1, 0, 1)),
                 Wait(0.2),
                 Func(collEntry.getFromNodePath().getParent().setColor,
                      VBase4(1, 1, 1, 1))).start()
 
 
    def collide2(self, collEntry):
        print("WERT.: object is no longer colliding with another object")
 
    def collide3(self, collEntry):
        print("WERT2: object has collided into another object")
 
    def collide4(self, collEntry):
        print("WERT2: object is no longer colliding with another object")
 
    def initCollisionSphere(self, obj, show=False):
        # Get the size of the object for the collision sphere.
        bounds = obj.getChild(0).getBounds()
        center = bounds.getCenter()
        radius = bounds.getRadius() * 1.1
 
        # Create a collision sphere and name it something understandable.
        collSphereStr = 'CollisionHull' + str(self.collCount) + "_" + obj.getName()
        self.collCount += 1
        cNode = CollisionNode(collSphereStr)
        cNode.addSolid(CollisionSphere(center, radius))
 
        cNodepath = obj.attachNewNode(cNode)
        if show:
            cNodepath.show()
 
        # Return a tuple with the collision node and its corrsponding string so
        # that the bitmask can be set.
        return (cNodepath, collSphereStr)
Пример #38
0
class DistributedIceGame(DistributedMinigame.DistributedMinigame, DistributedIceWorld.DistributedIceWorld):
    notify = directNotify.newCategory('DistributedIceGame')
    MaxLocalForce = 100
    MaxPhysicsForce = 25000

    def __init__(self, cr):
        DistributedMinigame.DistributedMinigame.__init__(self, cr)
        DistributedIceWorld.DistributedIceWorld.__init__(self, cr)
        self.gameFSM = ClassicFSM.ClassicFSM('DistributedIceGame', [State.State('off', self.enterOff, self.exitOff, ['inputChoice']),
         State.State('inputChoice', self.enterInputChoice, self.exitInputChoice, ['waitServerChoices',
          'moveTires',
          'displayVotes',
          'cleanup']),
         State.State('waitServerChoices', self.enterWaitServerChoices, self.exitWaitServerChoices, ['moveTires', 'cleanup']),
         State.State('moveTires', self.enterMoveTires, self.exitMoveTires, ['synch', 'cleanup']),
         State.State('synch', self.enterSynch, self.exitSynch, ['inputChoice', 'scoring', 'cleanup']),
         State.State('scoring', self.enterScoring, self.exitScoring, ['cleanup', 'finalResults', 'inputChoice']),
         State.State('finalResults', self.enterFinalResults, self.exitFinalResults, ['cleanup']),
         State.State('cleanup', self.enterCleanup, self.exitCleanup, [])], 'off', 'cleanup')
        self.addChildGameFSM(self.gameFSM)
        self.cameraThreeQuarterView = (0, -22, 45, 0, -62.89, 0)
        self.tireDict = {}
        self.forceArrowDict = {}
        self.canDrive = False
        self.timer = None
        self.timerStartTime = None
        self.curForce = 0
        self.curHeading = 0
        self.headingMomentum = 0.0
        self.forceMomentum = 0.0
        self.allTireInputs = None
        self.curRound = 0
        self.curMatch = 0
        self.controlKeyWarningLabel = DirectLabel(text=TTLocalizer.IceGameControlKeyWarning, text_fg=VBase4(1, 0, 0, 1), relief=None, pos=(0.0, 0, 0), scale=0.15)
        self.controlKeyWarningLabel.hide()
        self.waitingMoveLabel = DirectLabel(text=TTLocalizer.IceGameWaitingForPlayersToFinishMove, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075)
        self.waitingMoveLabel.hide()
        self.waitingSyncLabel = DirectLabel(text=TTLocalizer.IceGameWaitingForAISync, text_fg=VBase4(1, 1, 1, 1), relief=None, pos=(-0.6, 0, -0.75), scale=0.075)
        self.waitingSyncLabel.hide()
        self.infoLabel = DirectLabel(text='', text_fg=VBase4(0, 0, 0, 1), relief=None, pos=(0.0, 0, 0.7), scale=0.075)
        self.updateInfoLabel()
        self.lastForceArrowUpdateTime = 0
        self.sendForceArrowUpdateAsap = False
        self.treasures = []
        self.penalties = []
        self.obstacles = []
        self.controlKeyPressed = False
        self.controlKeyWarningIval = None
        return

    def delete(self):
        DistributedIceWorld.DistributedIceWorld.delete(self)
        DistributedMinigame.DistributedMinigame.delete(self)
        if self.controlKeyWarningIval:
            self.controlKeyWarningIval.finish()
            self.controlKeyWarningIval = None
        self.controlKeyWarningLabel.destroy()
        del self.controlKeyWarningLabel
        self.waitingMoveLabel.destroy()
        del self.waitingMoveLabel
        self.waitingSyncLabel.destroy()
        del self.waitingSyncLabel
        self.infoLabel.destroy()
        del self.infoLabel
        for treasure in self.treasures:
            treasure.destroy()

        del self.treasures
        for penalty in self.penalties:
            penalty.destroy()

        del self.penalties
        for obstacle in self.obstacles:
            obstacle.removeNode()

        del self.obstacles
        del self.gameFSM
        return

    def announceGenerate(self):
        DistributedMinigame.DistributedMinigame.announceGenerate(self)
        DistributedIceWorld.DistributedIceWorld.announceGenerate(self)
        self.debugTaskName = self.uniqueName('debugTask')

    def getTitle(self):
        return TTLocalizer.IceGameTitle

    def getInstructions(self):
        szId = self.getSafezoneId()
        numPenalties = IceGameGlobals.NumPenalties[szId]
        result = TTLocalizer.IceGameInstructions
        if numPenalties == 0:
            result = TTLocalizer.IceGameInstructionsNoTnt
        return result

    def getMaxDuration(self):
        return 0

    def load(self):
        self.notify.debug('load')
        DistributedMinigame.DistributedMinigame.load(self)
        self.music = base.loader.loadMusic('phase_4/audio/bgm/MG_IceGame.ogg')
        self.gameBoard = loader.loadModel('phase_4/models/minigames/ice_game_icerink')
        background = loader.loadModel('phase_4/models/minigames/ice_game_2d')
        backgroundWide = loader.loadModel('phase_4/models/minigames/iceslide_ground')
        background.reparentTo(self.gameBoard)
        backgroundWide.reparentTo(self.gameBoard)
        backgroundWide.setPos(0, -0.3, -0.5)
        self.gameBoard.setPosHpr(0, 0, 0, 0, 0, 0)
        self.gameBoard.setScale(1.0)
        self.setupSimulation()
        index = 0
        for avId in self.avIdList:
            self.setupTire(avId, index)
            self.setupForceArrow(avId)
            index += 1

        for index in xrange(len(self.avIdList), 4):
            self.setupTire(-index, index)
            self.setupForceArrow(-index)

        self.showForceArrows(realPlayersOnly=True)
        self.westWallModel = NodePath()
        if not self.westWallModel.isEmpty():
            self.westWallModel.reparentTo(self.gameBoard)
            self.westWallModel.setPos(IceGameGlobals.MinWall[0], IceGameGlobals.MinWall[1], 0)
            self.westWallModel.setScale(4)
        self.eastWallModel = NodePath()
        if not self.eastWallModel.isEmpty():
            self.eastWallModel.reparentTo(self.gameBoard)
            self.eastWallModel.setPos(IceGameGlobals.MaxWall[0], IceGameGlobals.MaxWall[1], 0)
            self.eastWallModel.setScale(4)
            self.eastWallModel.setH(180)
        self.arrowKeys = ArrowKeys.ArrowKeys()
        self.target = loader.loadModel('phase_3/models/misc/sphere')
        self.target.setScale(0.01)
        self.target.reparentTo(self.gameBoard)
        self.target.setPos(0, 0, 0)
        self.scoreCircle = loader.loadModel('phase_4/models/minigames/ice_game_score_circle')
        self.scoreCircle.setScale(0.01)
        self.scoreCircle.reparentTo(self.gameBoard)
        self.scoreCircle.setZ(IceGameGlobals.TireRadius / 2.0)
        self.scoreCircle.setAlphaScale(0.5)
        self.scoreCircle.setTransparency(1)
        self.scoreCircle.hide()
        self.treasureModel = loader.loadModel('phase_4/models/minigames/ice_game_barrel')
        self.penaltyModel = loader.loadModel('phase_4/models/minigames/ice_game_tnt2')
        self.penaltyModel.setScale(0.75, 0.75, 0.7)
        szId = self.getSafezoneId()
        obstacles = IceGameGlobals.Obstacles[szId]
        index = 0
        cubicObstacle = IceGameGlobals.ObstacleShapes[szId]
        for pos in obstacles:
            newPos = Point3(pos[0], pos[1], IceGameGlobals.TireRadius)
            newObstacle = self.createObstacle(newPos, index, cubicObstacle)
            self.obstacles.append(newObstacle)
            index += 1

        self.countSound = loader.loadSfx('phase_3.5/audio/sfx/tick_counter.ogg')
        self.treasureGrabSound = loader.loadSfx('phase_4/audio/sfx/MG_sfx_vine_game_bananas.ogg')
        self.penaltyGrabSound = loader.loadSfx('phase_4/audio/sfx/MG_cannon_fire_alt.ogg')
        self.tireSounds = []
        for tireIndex in xrange(4):
            tireHit = loader.loadSfx('phase_4/audio/sfx/Golf_Hit_Barrier_1.ogg')
            wallHit = loader.loadSfx('phase_4/audio/sfx/MG_maze_pickup.ogg')
            obstacleHit = loader.loadSfx('phase_4/audio/sfx/Golf_Hit_Barrier_2.ogg')
            self.tireSounds.append({'tireHit': tireHit,
             'wallHit': wallHit,
             'obstacleHit': obstacleHit})

        self.arrowRotateSound = loader.loadSfx('phase_4/audio/sfx/MG_sfx_ice_force_rotate.ogg')
        self.arrowUpSound = loader.loadSfx('phase_4/audio/sfx/MG_sfx_ice_force_increase_3sec.ogg')
        self.arrowDownSound = loader.loadSfx('phase_4/audio/sfx/MG_sfx_ice_force_decrease_3sec.ogg')
        self.scoreCircleSound = loader.loadSfx('phase_4/audio/sfx/MG_sfx_ice_scoring_1.ogg')

    def unload(self):
        self.notify.debug('unload')
        DistributedMinigame.DistributedMinigame.unload(self)
        del self.music
        self.gameBoard.removeNode()
        del self.gameBoard
        for forceArrow in self.forceArrowDict.values():
            forceArrow.removeNode()

        del self.forceArrowDict
        self.scoreCircle.removeNode()
        del self.scoreCircle
        del self.countSound

    def onstage(self):
        self.notify.debug('onstage')
        DistributedMinigame.DistributedMinigame.onstage(self)
        self.gameBoard.reparentTo(render)
        self.__placeToon(self.localAvId)
        self.moveCameraToTop()
        self.scorePanels = []
        base.playMusic(self.music, looping=1, volume=0.8)

    def offstage(self):
        self.notify.debug('offstage')
        self.music.stop()
        self.gameBoard.hide()
        self.infoLabel.hide()
        for avId in self.tireDict:
            self.tireDict[avId]['tireNodePath'].hide()

        for panel in self.scorePanels:
            panel.cleanup()

        del self.scorePanels
        for obstacle in self.obstacles:
            obstacle.hide()

        for treasure in self.treasures:
            treasure.nodePath.hide()

        for penalty in self.penalties:
            penalty.nodePath.hide()

        for avId in self.avIdList:
            av = self.getAvatar(avId)
            if av:
                av.dropShadow.show()
                av.resetLOD()

        taskMgr.remove(self.uniqueName('aimtask'))
        self.arrowKeys.destroy()
        del self.arrowKeys
        DistributedMinigame.DistributedMinigame.offstage(self)

    def handleDisabledAvatar(self, avId):
        self.notify.debug('handleDisabledAvatar')
        self.notify.debug('avatar ' + str(avId) + ' disabled')
        DistributedMinigame.DistributedMinigame.handleDisabledAvatar(self, avId)

    def setGameReady(self):
        if not self.hasLocalToon:
            return
        self.notify.debug('setGameReady')
        if DistributedMinigame.DistributedMinigame.setGameReady(self):
            return
        for index in xrange(self.numPlayers):
            avId = self.avIdList[index]
            toon = self.getAvatar(avId)
            if toon:
                toon.reparentTo(render)
                self.__placeToon(avId)
                toon.forwardSpeed = 0
                toon.rotateSpeed = False
                toon.dropShadow.hide()
                toon.setAnimState('Sit')
                if avId in self.tireDict:
                    tireNp = self.tireDict[avId]['tireNodePath']
                    toon.reparentTo(tireNp)
                    toon.setY(1.0)
                    toon.setZ(-3)
                toon.startLookAround()

    def setGameStart(self, timestamp):
        if not self.hasLocalToon:
            return
        self.notify.debug('setGameStart')
        DistributedMinigame.DistributedMinigame.setGameStart(self, timestamp)
        for avId in self.remoteAvIdList:
            toon = self.getAvatar(avId)
            if toon:
                toon.stopLookAround()

        self.scores = [0] * self.numPlayers
        spacing = 0.4
        for i in xrange(self.numPlayers):
            avId = self.avIdList[i]
            avName = self.getAvatarName(avId)
            scorePanel = MinigameAvatarScorePanel.MinigameAvatarScorePanel(avId, avName)
            scorePanel.setScale(0.9)
            scorePanel.setPos(-0.583 - spacing * (self.numPlayers - 1 - i), 0.0, -0.15)
            scorePanel.reparentTo(base.a2dTopRight)
            scorePanel.makeTransparent(0.75)
            self.scorePanels.append(scorePanel)

        self.arrowKeys.setPressHandlers([self.__upArrowPressed,
         self.__downArrowPressed,
         self.__leftArrowPressed,
         self.__rightArrowPressed,
         self.__controlPressed])

    def isInPlayState(self):
        if not self.gameFSM.getCurrentState():
            return False
        if not self.gameFSM.getCurrentState().getName() == 'play':
            return False
        return True

    def enterOff(self):
        self.notify.debug('enterOff')

    def exitOff(self):
        pass

    def enterInputChoice(self):
        self.notify.debug('enterInputChoice')
        self.forceLocalToonToTire()
        self.controlKeyPressed = False
        if self.curRound == 0:
            self.setupStartOfMatch()
        else:
            self.notify.debug('self.curRound = %s' % self.curRound)
        self.timer = ToontownTimer.ToontownTimer()
        self.timer.hide()
        if self.timerStartTime != None:
            self.startTimer()
        self.showForceArrows(realPlayersOnly=True)
        self.localForceArrow().setPosHpr(0, 0, -1.0, 0, 0, 0)
        self.localForceArrow().reparentTo(self.localTireNp())
        self.localForceArrow().setY(IceGameGlobals.TireRadius)
        self.localTireNp().headsUp(self.target)
        self.notify.debug('self.localForceArrow() heading = %s' % self.localForceArrow().getH())
        self.curHeading = self.localTireNp().getH()
        self.curForce = 25
        self.updateLocalForceArrow()
        for avId in self.forceArrowDict:
            forceArrow = self.forceArrowDict[avId]
            forceArrow.setPosHpr(0, 0, -1.0, 0, 0, 0)
            tireNp = self.tireDict[avId]['tireNodePath']
            forceArrow.reparentTo(tireNp)
            forceArrow.setY(IceGameGlobals.TireRadius)
            tireNp.headsUp(self.target)
            self.updateForceArrow(avId, tireNp.getH(), 25)

        taskMgr.add(self.__aimTask, self.uniqueName('aimtask'))
        if base.localAvatar.laffMeter:
            base.localAvatar.laffMeter.stop()
        self.sendForceArrowUpdateAsap = False
        return

    def exitInputChoice(self):
        if not self.controlKeyPressed:
            if self.controlKeyWarningIval:
                self.controlKeyWarningIval.finish()
                self.controlKeyWarningIval = None
            self.controlKeyWarningIval = Sequence(Func(self.controlKeyWarningLabel.show), self.controlKeyWarningLabel.colorScaleInterval(10, VBase4(1, 1, 1, 0), startColorScale=VBase4(1, 1, 1, 1)), Func(self.controlKeyWarningLabel.hide))
            self.controlKeyWarningIval.start()
        if self.timer != None:
            self.timer.destroy()
            self.timer = None
        self.timerStartTime = None
        self.hideForceArrows()
        self.arrowRotateSound.stop()
        self.arrowUpSound.stop()
        self.arrowDownSound.stop()
        taskMgr.remove(self.uniqueName('aimtask'))
        return

    def enterWaitServerChoices(self):
        self.waitingMoveLabel.show()
        self.showForceArrows(True)

    def exitWaitServerChoices(self):
        self.waitingMoveLabel.hide()
        self.hideForceArrows()

    def enterMoveTires(self):
        for key in self.tireDict:
            body = self.tireDict[key]['tireBody']
            body.setAngularVel(0, 0, 0)
            body.setLinearVel(0, 0, 0)

        for index in xrange(len(self.allTireInputs)):
            input = self.allTireInputs[index]
            avId = self.avIdList[index]
            body = self.getTireBody(avId)
            degs = input[1] + 90
            tireNp = self.getTireNp(avId)
            tireH = tireNp.getH()
            self.notify.debug('tireH = %s' % tireH)
            radAngle = deg2Rad(degs)
            foo = NodePath('foo')
            dirVector = Vec3(math.cos(radAngle), math.sin(radAngle), 0)
            self.notify.debug('dirVector is now=%s' % dirVector)
            inputForce = input[0]
            inputForce /= self.MaxLocalForce
            inputForce *= self.MaxPhysicsForce
            force = dirVector * inputForce
            self.notify.debug('adding force %s to %d' % (force, avId))
            body.addForce(force)

        self.enableAllTireBodies()
        self.totalPhysicsSteps = 0
        self.startSim()
        taskMgr.add(self.__moveTiresTask, self.uniqueName('moveTiresTtask'))

    def exitMoveTires(self):
        self.forceLocalToonToTire()
        self.disableAllTireBodies()
        self.stopSim()
        self.notify.debug('total Physics steps = %d' % self.totalPhysicsSteps)
        taskMgr.remove(self.uniqueName('moveTiresTtask'))

    def enterSynch(self):
        self.waitingSyncLabel.show()

    def exitSynch(self):
        self.waitingSyncLabel.hide()

    def enterScoring(self):
        sortedByDistance = []
        for avId in self.avIdList:
            np = self.getTireNp(avId)
            pos = np.getPos()
            pos.setZ(0)
            sortedByDistance.append((avId, pos.length()))

        def compareDistance(x, y):
            if x[1] - y[1] > 0:
                return 1
            elif x[1] - y[1] < 0:
                return -1
            else:
                return 0

        sortedByDistance.sort(cmp=compareDistance)
        self.scoreMovie = Sequence()
        curScale = 0.01
        curTime = 0
        self.scoreCircle.setScale(0.01)
        self.scoreCircle.show()
        self.notify.debug('newScores = %s' % self.newScores)
        circleStartTime = 0
        for index in xrange(len(sortedByDistance)):
            distance = sortedByDistance[index][1]
            avId = sortedByDistance[index][0]
            scorePanelIndex = self.avIdList.index(avId)
            time = (distance - curScale) / IceGameGlobals.ExpandFeetPerSec
            if time < 0:
                time = 0.01
            scaleXY = distance + IceGameGlobals.TireRadius
            self.notify.debug('circleStartTime = %s' % circleStartTime)
            self.scoreMovie.append(Parallel(LerpScaleInterval(self.scoreCircle, time, Point3(scaleXY, scaleXY, 1.0)), SoundInterval(self.scoreCircleSound, duration=time, startTime=circleStartTime)))
            circleStartTime += time
            startScore = self.scorePanels[scorePanelIndex].getScore()
            destScore = self.newScores[scorePanelIndex]
            self.notify.debug('for avId %d, startScore=%d, newScores=%d' % (avId, startScore, destScore))

            def increaseScores(t, scorePanelIndex = scorePanelIndex, startScore = startScore, destScore = destScore):
                oldScore = self.scorePanels[scorePanelIndex].getScore()
                diff = destScore - startScore
                newScore = int(startScore + diff * t)
                if newScore > oldScore:
                    base.playSfx(self.countSound)
                self.scorePanels[scorePanelIndex].setScore(newScore)
                self.scores[scorePanelIndex] = newScore

            duration = (destScore - startScore) * IceGameGlobals.ScoreCountUpRate
            tireNp = self.tireDict[avId]['tireNodePath']
            self.scoreMovie.append(Parallel(LerpFunctionInterval(increaseScores, duration), Sequence(LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 0, 0, 1)), LerpColorScaleInterval(tireNp, duration / 6.0, VBase4(1, 1, 1, 1)))))
            curScale += distance

        self.scoreMovie.append(Func(self.sendUpdate, 'reportScoringMovieDone', []))
        self.scoreMovie.start()

    def exitScoring(self):
        self.scoreMovie.finish()
        self.scoreMovie = None
        self.scoreCircle.hide()
        return

    def enterFinalResults(self):
        lerpTrack = Parallel()
        lerpDur = 0.5
        tY = 0.6
        bY = -.05
        lX = -.5
        cX = 0
        rX = 0.5
        scorePanelLocs = (((cX, bY),),
         ((lX, bY), (rX, bY)),
         ((cX, tY), (lX, bY), (rX, bY)),
         ((lX, tY),
          (rX, tY),
          (lX, bY),
          (rX, bY)))
        scorePanelLocs = scorePanelLocs[self.numPlayers - 1]
        for i in xrange(self.numPlayers):
            panel = self.scorePanels[i]
            pos = scorePanelLocs[i]
            panel.wrtReparentTo(aspect2d)
            lerpTrack.append(Parallel(LerpPosInterval(panel, lerpDur, Point3(pos[0], 0, pos[1]), blendType='easeInOut'), LerpScaleInterval(panel, lerpDur, Vec3(panel.getScale()) * 2.0, blendType='easeInOut')))

        self.showScoreTrack = Parallel(lerpTrack, Sequence(Wait(IceGameGlobals.ShowScoresDuration), Func(self.gameOver)))
        self.showScoreTrack.start()

    def exitFinalResults(self):
        self.showScoreTrack.pause()
        del self.showScoreTrack

    def enterCleanup(self):
        self.notify.debug('enterCleanup')
        if base.localAvatar.laffMeter:
            base.localAvatar.laffMeter.start()

    def exitCleanup(self):
        pass

    def __placeToon(self, avId):
        toon = self.getAvatar(avId)
        if toon:
            toon.setPos(0, 0, 0)
            toon.setHpr(0, 0, 0)

    def moveCameraToTop(self):
        camera.reparentTo(render)
        p = self.cameraThreeQuarterView
        camera.setPosHpr(p[0], p[1], p[2], p[3], p[4], p[5])

    def setupTire(self, avId, index):
        tireNp, tireBody, tireOdeGeom = self.createTire(index)
        self.tireDict[avId] = {'tireNodePath': tireNp,
         'tireBody': tireBody,
         'tireOdeGeom': tireOdeGeom}
        if avId <= 0:
            tireBlocker = tireNp.find('**/tireblockermesh')
            if not tireBlocker.isEmpty():
                tireBlocker.hide()
        if avId == self.localAvId:
            tireNp = self.tireDict[avId]['tireNodePath']
            self.treasureSphereName = 'treasureCollider'
            self.treasureCollSphere = CollisionSphere(0, 0, 0, IceGameGlobals.TireRadius)
            self.treasureCollSphere.setTangible(0)
            self.treasureCollNode = CollisionNode(self.treasureSphereName)
            self.treasureCollNode.setFromCollideMask(ToontownGlobals.PieBitmask)
            self.treasureCollNode.addSolid(self.treasureCollSphere)
            self.treasureCollNodePath = tireNp.attachNewNode(self.treasureCollNode)
            self.treasureHandler = CollisionHandlerEvent()
            self.treasureHandler.addInPattern('%fn-intoTreasure')
            base.cTrav.addCollider(self.treasureCollNodePath, self.treasureHandler)
            eventName = '%s-intoTreasure' % self.treasureCollNodePath.getName()
            self.notify.debug('eventName = %s' % eventName)
            self.accept(eventName, self.toonHitSomething)

    def setupForceArrow(self, avId):
        arrow = loader.loadModel('phase_4/models/minigames/ice_game_arrow')
        priority = 0
        if avId < 0:
            priority = -avId
        else:
            priority = self.avIdList.index(avId)
            if avId == self.localAvId:
                priority = 10
        self.forceArrowDict[avId] = arrow

    def hideForceArrows(self):
        for forceArrow in self.forceArrowDict.values():
            forceArrow.hide()

    def showForceArrows(self, realPlayersOnly = True):
        for avId in self.forceArrowDict:
            if realPlayersOnly:
                if avId > 0:
                    self.forceArrowDict[avId].show()
                else:
                    self.forceArrowDict[avId].hide()
            else:
                self.forceArrowDict[avId].show()

    def localForceArrow(self):
        if self.localAvId in self.forceArrowDict:
            return self.forceArrowDict[self.localAvId]
        else:
            return None
        return None

    def setChoices(self, input0, input1, input2, input3):
        pass

    def startDebugTask(self):
        taskMgr.add(self.debugTask, self.debugTaskName)

    def stopDebugTask(self):
        taskMgr.remove(self.debugTaskName)

    def debugTask(self, task):
        if self.canDrive and localAvatar.doId in self.tireDict:
            dt = globalClock.getDt()
            forceMove = 25000
            forceMoveDt = forceMove
            tireBody = self.tireDict[localAvatar.doId]['tireBody']
            if self.arrowKeys.upPressed() and not tireBody.isEnabled():
                x = 0
                y = 1
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.downPressed() and not tireBody.isEnabled():
                x = 0
                y = -1
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.leftPressed() and not tireBody.isEnabled():
                x = -1
                y = 0
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
            if self.arrowKeys.rightPressed() and not tireBody.isEnabled():
                x = 1
                y = 0
                tireBody.enable()
                tireBody.addForce(Vec3(x * forceMoveDt, y * forceMoveDt, 0))
        return task.cont

    def __upArrowPressed(self):
        pass

    def __downArrowPressed(self):
        pass

    def __leftArrowPressed(self):
        pass

    def __rightArrowPressed(self):
        pass

    def __controlPressed(self):
        if self.gameFSM.getCurrentState().getName() == 'inputChoice':
            self.sendForceArrowUpdateAsap = True
            self.updateLocalForceArrow()
            self.controlKeyPressed = True
            self.sendUpdate('setAvatarChoice', [self.curForce, self.curHeading])
            self.gameFSM.request('waitServerChoices')

    def startTimer(self):
        now = globalClock.getFrameTime()
        elapsed = now - self.timerStartTime
        self.timer.posInTopRightCorner()
        self.timer.setTime(IceGameGlobals.InputTimeout)
        self.timer.countdown(IceGameGlobals.InputTimeout - elapsed, self.handleChoiceTimeout)
        self.timer.show()

    def setTimerStartTime(self, timestamp):
        if not self.hasLocalToon:
            return
        self.timerStartTime = globalClockDelta.networkToLocalTime(timestamp)
        if self.timer != None:
            self.startTimer()
        return

    def handleChoiceTimeout(self):
        self.sendUpdate('setAvatarChoice', [0, 0])
        self.gameFSM.request('waitServerChoices')

    def localTireNp(self):
        ret = None
        if self.localAvId in self.tireDict:
            ret = self.tireDict[self.localAvId]['tireNodePath']
        return ret

    def localTireBody(self):
        ret = None
        if self.localAvId in self.tireDict:
            ret = self.tireDict[self.localAvId]['tireBody']
        return ret

    def getTireBody(self, avId):
        ret = None
        if avId in self.tireDict:
            ret = self.tireDict[avId]['tireBody']
        return ret

    def getTireNp(self, avId):
        ret = None
        if avId in self.tireDict:
            ret = self.tireDict[avId]['tireNodePath']
        return ret

    def updateForceArrow(self, avId, curHeading, curForce):
        forceArrow = self.forceArrowDict[avId]
        tireNp = self.tireDict[avId]['tireNodePath']
        tireNp.setH(curHeading)
        tireBody = self.tireDict[avId]['tireBody']
        tireBody.setQuaternion(tireNp.getQuat())
        self.notify.debug('curHeading = %s' % curHeading)
        yScale = curForce / 100.0
        yScale *= 1
        headY = yScale * 15
        xScale = (yScale - 1) / 2.0 + 1.0
        shaft = forceArrow.find('**/arrow_shaft')
        head = forceArrow.find('**/arrow_head')
        shaft.setScale(xScale, yScale, 1)
        head.setPos(0, headY, 0)
        head.setScale(xScale, xScale, 1)

    def updateLocalForceArrow(self):
        avId = self.localAvId
        self.b_setForceArrowInfo(avId, self.curHeading, self.curForce)

    def __aimTask(self, task):
        if not hasattr(self, 'arrowKeys'):
            return task.done
        dt = globalClock.getDt()
        headingMomentumChange = dt * 60.0
        forceMomentumChange = dt * 160.0
        arrowUpdate = False
        arrowRotating = False
        arrowUp = False
        arrowDown = False
        if self.arrowKeys.upPressed() and not self.arrowKeys.downPressed():
            self.forceMomentum += forceMomentumChange
            if self.forceMomentum < 0:
                self.forceMomentum = 0
            if self.forceMomentum > 50:
                self.forceMomentum = 50
            oldForce = self.curForce
            self.curForce += self.forceMomentum * dt
            arrowUpdate = True
            if oldForce < self.MaxLocalForce:
                arrowUp = True
        elif self.arrowKeys.downPressed() and not self.arrowKeys.upPressed():
            self.forceMomentum += forceMomentumChange
            if self.forceMomentum < 0:
                self.forceMomentum = 0
            if self.forceMomentum > 50:
                self.forceMomentum = 50
            oldForce = self.curForce
            self.curForce -= self.forceMomentum * dt
            arrowUpdate = True
            if oldForce > 0.01:
                arrowDown = True
        else:
            self.forceMomentum = 0
        if self.arrowKeys.leftPressed() and not self.arrowKeys.rightPressed():
            self.headingMomentum += headingMomentumChange
            if self.headingMomentum < 0:
                self.headingMomentum = 0
            if self.headingMomentum > 50:
                self.headingMomentum = 50
            self.curHeading += self.headingMomentum * dt
            arrowUpdate = True
            arrowRotating = True
        elif self.arrowKeys.rightPressed() and not self.arrowKeys.leftPressed():
            self.headingMomentum += headingMomentumChange
            if self.headingMomentum < 0:
                self.headingMomentum = 0
            if self.headingMomentum > 50:
                self.headingMomentum = 50
            self.curHeading -= self.headingMomentum * dt
            arrowUpdate = True
            arrowRotating = True
        else:
            self.headingMomentum = 0
        if arrowUpdate:
            self.normalizeHeadingAndForce()
            self.updateLocalForceArrow()
        if arrowRotating:
            if not self.arrowRotateSound.status() == self.arrowRotateSound.PLAYING:
                base.playSfx(self.arrowRotateSound, looping=True)
        else:
            self.arrowRotateSound.stop()
        if arrowUp:
            if not self.arrowUpSound.status() == self.arrowUpSound.PLAYING:
                base.playSfx(self.arrowUpSound, looping=False)
        else:
            self.arrowUpSound.stop()
        if arrowDown:
            if not self.arrowDownSound.status() == self.arrowDownSound.PLAYING:
                base.playSfx(self.arrowDownSound, looping=False)
        else:
            self.arrowDownSound.stop()
        return task.cont

    def normalizeHeadingAndForce(self):
        if self.curForce > self.MaxLocalForce:
            self.curForce = self.MaxLocalForce
        if self.curForce < 0.01:
            self.curForce = 0.01

    def setTireInputs(self, tireInputs):
        if not self.hasLocalToon:
            return
        self.allTireInputs = tireInputs
        self.gameFSM.request('moveTires')

    def enableAllTireBodies(self):
        for avId in self.tireDict.keys():
            self.tireDict[avId]['tireBody'].enable()

    def disableAllTireBodies(self):
        for avId in self.tireDict.keys():
            self.tireDict[avId]['tireBody'].disable()

    def areAllTiresDisabled(self):
        for avId in self.tireDict.keys():
            if self.tireDict[avId]['tireBody'].isEnabled():
                return False

        return True

    def __moveTiresTask(self, task):
        if self.areAllTiresDisabled():
            self.sendTirePositions()
            self.gameFSM.request('synch')
            return task.done
        return task.cont

    def sendTirePositions(self):
        tirePositions = []
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            tire = self.getTireBody(avId)
            pos = Point3(tire.getPosition())
            tirePositions.append([pos[0], pos[1], pos[2]])

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            tire = self.getTireBody(avId)
            pos = Point3(tire.getPosition())
            tirePositions.append([pos[0], pos[1], pos[2]])

        self.sendUpdate('endingPositions', [tirePositions])

    def setFinalPositions(self, finalPos):
        if not self.hasLocalToon:
            return
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            tire = self.getTireBody(avId)
            np = self.getTireNp(avId)
            pos = finalPos[index]
            tire.setPosition(pos[0], pos[1], pos[2])
            np.setPos(pos[0], pos[1], pos[2])

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            tire = self.getTireBody(avId)
            np = self.getTireNp(avId)
            pos = finalPos[index]
            tire.setPosition(pos[0], pos[1], pos[2])
            np.setPos(pos[0], pos[1], pos[2])

    def updateInfoLabel(self):
        self.infoLabel['text'] = TTLocalizer.IceGameInfo % {'curMatch': self.curMatch + 1,
         'numMatch': IceGameGlobals.NumMatches,
         'curRound': self.curRound + 1,
         'numRound': IceGameGlobals.NumRounds}

    def setMatchAndRound(self, match, round):
        if not self.hasLocalToon:
            return
        self.curMatch = match
        self.curRound = round
        self.updateInfoLabel()

    def setScores(self, match, round, scores):
        if not self.hasLocalToon:
            return
        self.newMatch = match
        self.newRound = round
        self.newScores = scores

    def setNewState(self, state):
        if not self.hasLocalToon:
            return
        self.notify.debug('setNewState gameFSM=%s newState=%s' % (self.gameFSM, state))
        self.gameFSM.request(state)

    def putAllTiresInStartingPositions(self):
        for index in xrange(len(self.avIdList)):
            avId = self.avIdList[index]
            np = self.tireDict[avId]['tireNodePath']
            np.setPos(IceGameGlobals.StartingPositions[index])
            self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos))
            np.setHpr(0, 0, 0)
            quat = np.getQuat()
            body = self.tireDict[avId]['tireBody']
            body.setPosition(IceGameGlobals.StartingPositions[index])
            body.setQuaternion(quat)

        for index in xrange(len(self.avIdList), 4):
            avId = -index
            np = self.tireDict[avId]['tireNodePath']
            np.setPos(IceGameGlobals.StartingPositions[index])
            self.notify.debug('avId=%s newPos=%s' % (avId, np.getPos))
            np.setHpr(0, 0, 0)
            quat = np.getQuat()
            body = self.tireDict[avId]['tireBody']
            body.setPosition(IceGameGlobals.StartingPositions[index])
            body.setQuaternion(quat)

    def b_setForceArrowInfo(self, avId, force, heading):
        self.setForceArrowInfo(avId, force, heading)
        self.d_setForceArrowInfo(avId, force, heading)

    def d_setForceArrowInfo(self, avId, force, heading):
        sendIt = False
        curTime = self.getCurrentGameTime()
        if self.sendForceArrowUpdateAsap:
            sendIt = True
        elif curTime - self.lastForceArrowUpdateTime > 0.2:
            sendIt = True
        if sendIt:
            self.sendUpdate('setForceArrowInfo', [avId, force, heading])
            self.sendForceArrowUpdateAsap = False
            self.lastForceArrowUpdateTime = self.getCurrentGameTime()

    def setForceArrowInfo(self, avId, force, heading):
        if not self.hasLocalToon:
            return
        self.updateForceArrow(avId, force, heading)

    def setupStartOfMatch(self):
        self.putAllTiresInStartingPositions()
        szId = self.getSafezoneId()
        self.numTreasures = IceGameGlobals.NumTreasures[szId]
        if self.treasures:
            for treasure in self.treasures:
                treasure.destroy()

            self.treasures = []
        index = 0
        treasureMargin = IceGameGlobals.TireRadius + 1.0
        while len(self.treasures) < self.numTreasures:
            xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5)
            yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5)
            self.notify.debug('yPos=%s' % yPos)
            pos = Point3(xPos, yPos, IceGameGlobals.TireRadius)
            newTreasure = IceTreasure.IceTreasure(self.treasureModel, pos, index, self.doId, penalty=False)
            goodSpot = True
            for obstacle in self.obstacles:
                if newTreasure.nodePath.getDistance(obstacle) < treasureMargin:
                    goodSpot = False
                    break

            if goodSpot:
                for treasure in self.treasures:
                    if newTreasure.nodePath.getDistance(treasure.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                self.treasures.append(newTreasure)
                index += 1
            else:
                newTreasure.destroy()

        self.numPenalties = IceGameGlobals.NumPenalties[szId]
        if self.penalties:
            for penalty in self.penalties:
                penalty.destroy()

            self.penalties = []
        index = 0
        while len(self.penalties) < self.numPenalties:
            xPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[0] + 5, IceGameGlobals.MaxWall[0] - 5)
            yPos = self.randomNumGen.randrange(IceGameGlobals.MinWall[1] + 5, IceGameGlobals.MaxWall[1] - 5)
            self.notify.debug('yPos=%s' % yPos)
            pos = Point3(xPos, yPos, IceGameGlobals.TireRadius)
            newPenalty = IceTreasure.IceTreasure(self.penaltyModel, pos, index, self.doId, penalty=True)
            goodSpot = True
            for obstacle in self.obstacles:
                if newPenalty.nodePath.getDistance(obstacle) < treasureMargin:
                    goodSpot = False
                    break

            if goodSpot:
                for treasure in self.treasures:
                    if newPenalty.nodePath.getDistance(treasure.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                for penalty in self.penalties:
                    if newPenalty.nodePath.getDistance(penalty.nodePath) < treasureMargin:
                        goodSpot = False
                        break

            if goodSpot:
                self.penalties.append(newPenalty)
                index += 1
            else:
                newPenalty.destroy()

    def toonHitSomething(self, entry):
        self.notify.debug('---- treasure Enter ---- ')
        self.notify.debug('%s' % entry)
        name = entry.getIntoNodePath().getName()
        parts = name.split('-')
        if len(parts) < 3:
            self.notify.debug('collided with %s, but returning' % name)
            return
        if not int(parts[1]) == self.doId:
            self.notify.debug("collided with %s, but doId doesn't match" % name)
            return
        treasureNum = int(parts[2])
        if 'penalty' in parts[0]:
            self.__penaltyGrabbed(treasureNum)
        else:
            self.__treasureGrabbed(treasureNum)

    def __treasureGrabbed(self, treasureNum):
        self.treasures[treasureNum].showGrab()
        self.treasureGrabSound.play()
        self.sendUpdate('claimTreasure', [treasureNum])

    def setTreasureGrabbed(self, avId, treasureNum):
        if not self.hasLocalToon:
            return
        self.notify.debug('treasure %s grabbed by %s' % (treasureNum, avId))
        if avId != self.localAvId:
            self.treasures[treasureNum].showGrab()
        i = self.avIdList.index(avId)
        self.scores[i] += 1
        self.scorePanels[i].setScore(self.scores[i])

    def __penaltyGrabbed(self, penaltyNum):
        self.penalties[penaltyNum].showGrab()
        self.sendUpdate('claimPenalty', [penaltyNum])

    def setPenaltyGrabbed(self, avId, penaltyNum):
        if not self.hasLocalToon:
            return
        self.notify.debug('penalty %s grabbed by %s' % (penaltyNum, avId))
        if avId != self.localAvId:
            self.penalties[penaltyNum].showGrab()
        i = self.avIdList.index(avId)
        self.scores[i] -= 1
        self.scorePanels[i].setScore(self.scores[i])

    def postStep(self):
        DistributedIceWorld.DistributedIceWorld.postStep(self)
        if not self.colCount:
            return
        for count in xrange(self.colCount):
            c0, c1 = self.getOrderedContacts(count)
            if c1 in self.tireCollideIds:
                tireIndex = self.tireCollideIds.index(c1)
                if c0 in self.tireCollideIds:
                    self.tireSounds[tireIndex]['tireHit'].play()
                elif c0 == self.wallCollideId:
                    self.tireSounds[tireIndex]['wallHit'].play()
                elif c0 == self.obstacleCollideId:
                    self.tireSounds[tireIndex]['obstacleHit'].play()

    def forceLocalToonToTire(self):
        toon = localAvatar
        if toon and self.localAvId in self.tireDict:
            tireNp = self.tireDict[self.localAvId]['tireNodePath']
            toon.reparentTo(tireNp)
            toon.setPosHpr(0, 0, 0, 0, 0, 0)
            toon.setY(1.0)
            toon.setZ(-3)
class DistributedGolfSpot(DistributedObject.DistributedObject, FSM.FSM):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGolfSpot')
    positions = ((-45, 100, GolfGlobals.GOLF_BALL_RADIUS),
     (-15, 100, GolfGlobals.GOLF_BALL_RADIUS),
     (15, 100, GolfGlobals.GOLF_BALL_RADIUS),
     (45, 100, GolfGlobals.GOLF_BALL_RADIUS))
    toonGolfOffsetPos = Point3(-2, 0, -GolfGlobals.GOLF_BALL_RADIUS)
    toonGolfOffsetHpr = Point3(-90, 0, 0)
    rotateSpeed = 20
    golfPowerSpeed = base.config.GetDouble('golf-power-speed', 3)
    golfPowerExponent = base.config.GetDouble('golf-power-exponent', 0.75)

    def __init__(self, cr):
        DistributedObject.DistributedObject.__init__(self, cr)
        FSM.FSM.__init__(self, 'DistributedGolfSpot')
        self.boss = None
        self.index = None
        self.avId = 0
        self.toon = None
        self.golfSpotSmoother = SmoothMover()
        self.golfSpotSmoother.setSmoothMode(SmoothMover.SMOn)
        self.smoothStarted = 0
        self.__broadcastPeriod = 0.2
        if self.index > len(self.positions):
            self.notify.error('Invalid index %d' % index)
        self.fadeTrack = None
        self.setupPowerBar()
        self.aimStart = None
        self.golfSpotAdviceLabel = None
        self.changeSeq = 0
        self.lastChangeSeq = 0
        self.controlKeyAllowed = False
        self.flyBallTracks = {}
        self.splatTracks = {}
        self.__flyBallBubble = None
        self.flyBallHandler = None
        self.__flyBallSequenceNum = 0
        self.swingInterval = None
        self.lastHitSequenceNum = -1
        self.goingToReward = False
        self.gotHitByBoss = False
        self.releaseTrack = None
        self.grabTrack = None
        self.restoreScaleTrack = None
        return

    def setBossCogId(self, bossCogId):
        self.bossCogId = bossCogId
        self.boss = base.cr.doId2do[bossCogId]
        self.boss.setGolfSpot(self, self.index)

    def setIndex(self, index):
        self.index = index

    def disable(self):
        DistributedObject.DistributedObject.disable(self)
        self.ignoreAll()

    def delete(self):
        DistributedObject.DistributedObject.delete(self)
        self.ignoreAll()
        self.boss = None
        return

    def announceGenerate(self):
        DistributedObject.DistributedObject.announceGenerate(self)
        self.triggerName = self.uniqueName('trigger')
        self.triggerEvent = 'enter%s' % self.triggerName
        self.smoothName = self.uniqueName('golfSpotSmooth')
        self.golfSpotAdviceName = self.uniqueName('golfSpotAdvice')
        self.posHprBroadcastName = self.uniqueName('golfSpotBroadcast')
        self.ballPowerTaskName = self.uniqueName('updateGolfPower')
        self.adjustClubTaskName = self.uniqueName('adjustClub')
        self.loadAssets()
        self.accept('flyBallHit-%d' % self.index, self.__flyBallHit)

    def loadAssets(self):
        self.root = render.attachNewNode('golfSpot-%d' % self.index)
        self.root.setPos(*self.positions[self.index])
        self.ballModel = loader.loadModel('phase_6/models/golf/golf_ball')
        self.ballColor = VBase4(1, 1, 1, 1)
        if self.index < len(GolfGlobals.PlayerColors):
            self.ballColor = VBase4(*GolfGlobals.PlayerColors[self.index])
            self.ballModel.setColorScale(self.ballColor)
        self.ballModel.reparentTo(self.root)
        self.club = loader.loadModel('phase_6/models/golf/putter')
        self.clubLookatSpot = self.root.attachNewNode('clubLookat')
        self.clubLookatSpot.setY(-(GolfGlobals.GOLF_BALL_RADIUS + 0.1))
        cs = CollisionSphere(0, 0, 0, 1)
        cs.setTangible(0)
        cn = CollisionNode(self.triggerName)
        cn.addSolid(cs)
        cn.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.trigger = self.root.attachNewNode(cn)
        self.trigger.stash()
        self.hitBallSfx = loader.loadSfx('phase_6/audio/sfx/Golf_Hit_Ball.ogg')

    def cleanup(self):
        if self.swingInterval:
            self.swingInterval.finish()
            self.swingInterval = None
        if self.releaseTrack:
            self.releaseTrack.finish()
            self.releaseTrack = None
        flyTracks = self.flyBallTracks.values()
        for track in flyTracks:
            track.finish()

        if self.fadeTrack:
            self.fadeTrack.finish()
            self.fadeTrack = None
        if self.restoreScaleTrack:
            self.restoreScaleTrack.finish()
            self.restoreScaleTrack = None
        self.root.removeNode()
        self.ballModel.removeNode()
        self.club.removeNode()
        if self.powerBar:
            self.powerBar.destroy()
            self.powerBar = None
        taskMgr.remove(self.triggerName)
        self.boss = None
        return

    def setState(self, state, avId, extraInfo):
        if not self.isDisabled():
            self.gotHitByBoss = extraInfo
            if state == 'C':
                self.demand('Controlled', avId)
            elif state == 'F':
                self.demand('Free')
            elif state == 'O':
                self.demand('Off')
            else:
                self.notify.error('Invalid state from AI: %s' % state)

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def enterFree(self):
        if self.fadeTrack:
            self.fadeTrack.finish()
            self.fadeTrack = None
        self.restoreScaleTrack = Sequence(Wait(6), self.getRestoreScaleInterval(), name='restoreScaleTrack')
        self.restoreScaleTrack.start()
        if self.avId == localAvatar.doId:
            if not self.isDisabled():
                self.ballModel.setAlphaScale(0.3)
                self.ballModel.setTransparency(1)
                taskMgr.doMethodLater(5, self.__allowDetect, self.triggerName)
                self.fadeTrack = Sequence(Func(self.ballModel.setTransparency, 1), self.ballModel.colorScaleInterval(0.2, VBase4(1, 1, 1, 0.3)), name='fadeTrack-enterFree')
                self.fadeTrack.start()
        else:
            self.trigger.unstash()
            self.accept(self.triggerEvent, self.__hitTrigger)
        self.avId = 0
        return

    def exitFree(self):
        if self.fadeTrack:
            self.fadeTrack.finish()
            self.fadeTrack = None
        self.restoreScaleTrack.finish()
        self.restoreScaleTrack = None
        taskMgr.remove(self.triggerName)
        self.ballModel.clearTransparency()
        self.trigger.stash()
        self.ignore(self.triggerEvent)
        return

    def enterControlled(self, avId):
        self.avId = avId
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.enableControlKey()
        self.toon = toon
        self.grabTrack = self.makeToonGrabInterval(toon)
        if avId == localAvatar.doId:
            self.boss.toCraneMode()
            camera.reparentTo(self.root)
            camera.setPosHpr(0, -10, 3, 0, 0, 0)
            localAvatar.setPos(self.root, self.toonGolfOffsetPos)
            localAvatar.setHpr(self.root, self.toonGolfOffsetHpr)
            localAvatar.sendCurrentPosition()
            self.__enableControlInterface()
            self.startPosHprBroadcast()
            self.accept('exitCrane', self.gotBossZapped)
        self.grabTrack.start()

    def exitControlled(self):
        self.grabTrack.finish()
        del self.grabTrack
        if self.swingInterval:
            self.swingInterval.finish()
            self.swingInterval = None
        if not self.ballModel.isEmpty():
            if self.ballModel.isHidden():
                self.notify.debug('ball is hidden scale =%s' % self.ballModel.getScale())
            else:
                self.notify.debug('ball is showing scale=%s' % self.ballModel.getScale())
        if self.toon and not self.toon.isDisabled():
            self.toon.startSmooth()
        self.releaseTrack = self.makeToonReleaseInterval(self.toon)
        self.stopPosHprBroadcast()
        self.stopSmooth()
        if self.avId == localAvatar.doId:
            self.__disableControlInterface()
            if not self.goingToReward:
                camera.reparentTo(base.localAvatar)
                camera.setPos(base.localAvatar.cameraPositions[0][0])
                camera.setHpr(0, 0, 0)
        self.stopAdjustClubTask()
        self.releaseTrack.start()
        self.enableControlKey()
        return

    def __allowDetect(self, task):
        if self.fadeTrack:
            self.fadeTrack.finish()
        self.fadeTrack = Sequence(self.ballModel.colorScaleInterval(0.2, self.ballColor), Func(self.ballModel.clearTransparency), name='fadeTrack-allowDetect')
        self.fadeTrack.start()
        self.trigger.unstash()
        self.accept(self.triggerEvent, self.__hitTrigger)

    def __hitTrigger(self, event):
        self.d_requestControl()

    def getRestoreScaleInterval(self):
        return Sequence()

    def d_requestControl(self):
        self.sendUpdate('requestControl')

    def d_requestFree(self, gotHitByBoss):
        self.sendUpdate('requestFree', [gotHitByBoss])

    def makeToonGrabInterval(self, toon):
        origPos = toon.getPos(self.root)
        origHpr = toon.getHpr(self.root)
        a = self.accomodateToon(toon)
        newPos = toon.getPos()
        newHpr = toon.getHpr()
        origHpr.setX(PythonUtil.fitSrcAngle2Dest(origHpr[0], newHpr[0]))
        self.notify.debug('toon.setPosHpr %s %s' % (origPos, origHpr))
        toon.setPosHpr(origPos, origHpr)
        walkTime = 0.2
        reach = Sequence()
        if reach.getDuration() < walkTime:
            reach = Sequence(ActorInterval(toon, 'walk', loop=1, duration=walkTime - reach.getDuration()), reach)
        i = Sequence(Parallel(toon.posInterval(walkTime, newPos, origPos), toon.hprInterval(walkTime, newHpr, origHpr), reach), Func(toon.stopLookAround))
        if toon == base.localAvatar:
            i.append(Func(self.switchToAnimState, 'GolfPuttLoop'))
        i.append(Func(self.startAdjustClubTask))
        i = Parallel(i, a)
        return i

    def accomodateToon(self, toon):
        toon.wrtReparentTo(self.root)
        toon.setPos(self.toonGolfOffsetPos)
        toon.setHpr(self.toonGolfOffsetHpr)
        return Sequence()

    def switchToAnimState(self, animStateName, forced = False):
        curAnimState = base.localAvatar.animFSM.getCurrentState()
        curAnimStateName = ''
        if curAnimState:
            curAnimStateName = curAnimState.getName()
        if curAnimStateName != animStateName or forced:
            base.localAvatar.b_setAnimState(animStateName)

    def __enableControlInterface(self):
        gui = loader.loadModel('phase_3.5/models/gui/avatar_panel_gui')
        self.closeButton = DirectButton(image=(gui.find('**/CloseBtn_UP'),
         gui.find('**/CloseBtn_DN'),
         gui.find('**/CloseBtn_Rllvr'),
         gui.find('**/CloseBtn_UP')), relief=None, scale=2, text=TTLocalizer.BossbotGolfSpotLeave, text_scale=0.04, text_pos=(0, -0.07), text_fg=VBase4(1, 1, 1, 1), pos=(1.05, 0, -0.82), command=self.__exitGolfSpot)
        self.accept('escape', self.__exitGolfSpot)
        self.accept(base.JUMP, self.__controlPressed)
        self.accept(base.JUMP + '-up', self.__controlReleased)
        self.accept('InputState-forward', self.__upArrow)
        self.accept('InputState-reverse', self.__downArrow)
        self.accept('InputState-turnLeft', self.__leftArrow)
        self.accept('InputState-turnRight', self.__rightArrow)
        taskMgr.add(self.__watchControls, 'watchGolfSpotControls')
        taskMgr.doMethodLater(5, self.__displayGolfSpotAdvice, self.golfSpotAdviceName)
        self.arrowVert = 0
        self.arrowHorz = 0
        if self.powerBar:
            self.powerBar.show()
        return

    def __disableControlInterface(self):
        if self.closeButton:
            self.closeButton.destroy()
            self.closeButton = None
        self.__cleanupGolfSpotAdvice()
        self.ignore('escape')
        self.ignore(base.JUMP)
        self.ignore('control-up')
        self.ignore('InputState-forward')
        self.ignore('InputState-reverse')
        self.ignore('InputState-turnLeft')
        self.ignore('InputState-turnRight')
        self.arrowVert = 0
        self.arrowHorz = 0
        taskMgr.remove('watchGolfSpotControls')
        if self.powerBar:
            self.powerBar.hide()
        else:
            self.notify.debug('self.powerBar is none')
        return

    def setupPowerBar(self):
        self.powerBar = DirectWaitBar(pos=(0.0, 0, -0.94), relief=DGG.SUNKEN, frameSize=(-2.0,
         2.0,
         -0.2,
         0.2), borderWidth=(0.02, 0.02), scale=0.25, range=100, sortOrder=50, frameColor=(0.5, 0.5, 0.5, 0.5), barColor=(1.0, 0.0, 0.0, 1.0), text='', text_scale=0.26, text_fg=(1, 1, 1, 1), text_align=TextNode.ACenter, text_pos=(0, -0.05))
        self.power = 0
        self.powerBar['value'] = self.power
        self.powerBar.hide()

    def resetPowerBar(self):
        self.power = 0
        self.powerBar['value'] = self.power
        self.powerBar['text'] = ''

    def __displayGolfSpotAdvice(self, task):
        if self.golfSpotAdviceLabel == None:
            self.golfSpotAdviceLabel = DirectLabel(text=TTLocalizer.BossbotGolfSpotAdvice, text_fg=VBase4(1, 1, 1, 1), text_align=TextNode.ACenter, relief=None, pos=(0, 0, 0.69), scale=0.1)
        return

    def __cleanupGolfSpotAdvice(self):
        if self.golfSpotAdviceLabel:
            self.golfSpotAdviceLabel.destroy()
            self.golfSpotAdviceLabel = None
        taskMgr.remove(self.golfSpotAdviceName)
        return

    def showExiting(self):
        if self.closeButton:
            self.closeButton.destroy()
            self.closeButton = DirectLabel(relief=None, text=TTLocalizer.BossbotGolfSpotLeaving, pos=(1.05, 0, -0.88), text_pos=(0, 0), text_scale=0.06, text_fg=VBase4(1, 1, 1, 1))
        self.__cleanupGolfSpotAdvice()
        return

    def __exitGolfSpot(self):
        self.d_requestFree(False)

    def __controlPressed(self):
        if self.controlKeyAllowed:
            self.__beginFireBall()

    def __controlReleased(self):
        if self.controlKeyAllowed:
            self.__endFireBall()

    def __upArrow(self, pressed):
        self.__incrementChangeSeq()
        self.__cleanupGolfSpotAdvice()
        if pressed:
            self.arrowVert = 1
        elif self.arrowVert > 0:
            self.arrowVert = 0

    def __downArrow(self, pressed):
        self.__incrementChangeSeq()
        self.__cleanupGolfSpotAdvice()
        if pressed:
            self.arrowVert = -1
        elif self.arrowVert < 0:
            self.arrowVert = 0

    def __rightArrow(self, pressed):
        self.__incrementChangeSeq()
        self.__cleanupGolfSpotAdvice()
        if pressed:
            self.arrowHorz = 1
            self.switchToAnimState('GolfRotateLeft')
        elif self.arrowHorz > 0:
            self.arrowHorz = 0
            self.switchToAnimState('GolfPuttLoop')

    def __leftArrow(self, pressed):
        self.__incrementChangeSeq()
        self.__cleanupGolfSpotAdvice()
        if pressed:
            self.arrowHorz = -1
            self.switchToAnimState('GolfRotateRight')
        elif self.arrowHorz < 0:
            self.arrowHorz = 0
            self.switchToAnimState('GolfPuttLoop')

    def __watchControls(self, task):
        if self.arrowHorz:
            self.__moveGolfSpot(self.arrowHorz)
        return Task.cont

    def __moveGolfSpot(self, xd):
        dt = globalClock.getDt()
        h = self.root.getH() - xd * self.rotateSpeed * dt
        h %= 360
        limitH = h
        self.root.setH(limitH)

    def __incrementChangeSeq(self):
        self.changeSeq = self.changeSeq + 1 & 255

    def __beginFireBall(self):
        if self.aimStart != None:
            return
        if not self.state == 'Controlled':
            return
        if not self.avId == localAvatar.doId:
            return
        time = globalClock.getFrameTime()
        self.aimStart = time
        messenger.send('wakeup')
        taskMgr.add(self.__updateBallPower, self.ballPowerTaskName)
        return

    def __endFireBall(self):
        if self.aimStart == None:
            return
        if not self.state == 'Controlled':
            return
        if not self.avId == localAvatar.doId:
            return
        taskMgr.remove(self.ballPowerTaskName)
        self.disableControlKey()
        messenger.send('wakeup')
        self.aimStart = None
        power = self.power
        angle = self.root.getH()
        self.notify.debug('incrementing self.__flyBallSequenceNum')
        self.__flyBallSequenceNum = (self.__flyBallSequenceNum + 1) % 255
        self.sendSwingInfo(power, angle, self.__flyBallSequenceNum)
        self.setSwingInfo(power, angle, self.__flyBallSequenceNum)
        self.resetPowerBar()
        return

    def __updateBallPower(self, task):
        if not self.powerBar:
            print '### no power bar!!!'
            return task.done
        newPower = self.__getBallPower(globalClock.getFrameTime())
        self.power = newPower
        self.powerBar['value'] = newPower
        return task.cont

    def __getBallPower(self, time):
        elapsed = max(time - self.aimStart, 0.0)
        t = elapsed / self.golfPowerSpeed
        t = math.pow(t, self.golfPowerExponent)
        power = int(t * 100) % 200
        if power > 100:
            power = 200 - power
        return power

    def stopPosHprBroadcast(self):
        taskName = self.posHprBroadcastName
        taskMgr.remove(taskName)

    def startPosHprBroadcast(self):
        taskName = self.posHprBroadcastName
        self.b_clearSmoothing()
        self.d_sendGolfSpotPos()
        taskMgr.remove(taskName)
        taskMgr.doMethodLater(self.__broadcastPeriod, self.__posHprBroadcast, taskName)

    def __posHprBroadcast(self, task):
        self.d_sendGolfSpotPos()
        taskName = self.posHprBroadcastName
        taskMgr.doMethodLater(self.__broadcastPeriod, self.__posHprBroadcast, taskName)
        return Task.done

    def d_sendGolfSpotPos(self):
        timestamp = globalClockDelta.getFrameNetworkTime()
        self.sendUpdate('setGolfSpotPos', [self.changeSeq, self.root.getH(), timestamp])

    def setGolfSpotPos(self, changeSeq, h, timestamp):
        self.changeSeq = changeSeq
        if self.smoothStarted:
            now = globalClock.getFrameTime()
            local = globalClockDelta.networkToLocalTime(timestamp, now)
            self.golfSpotSmoother.setH(h)
            self.golfSpotSmoother.setTimestamp(local)
            self.golfSpotSmoother.markPosition()
        else:
            self.root.setH(h)

    def b_clearSmoothing(self):
        self.d_clearSmoothing()
        self.clearSmoothing()

    def d_clearSmoothing(self):
        self.sendUpdate('clearSmoothing', [0])

    def clearSmoothing(self, bogus = None):
        self.golfSpotSmoother.clearPositions(1)

    def doSmoothTask(self, task):
        self.golfSpotSmoother.computeAndApplySmoothHpr(self.root)
        return Task.cont

    def startSmooth(self):
        if not self.smoothStarted:
            taskName = self.smoothName
            taskMgr.remove(taskName)
            self.reloadPosition()
            taskMgr.add(self.doSmoothTask, taskName)
            self.smoothStarted = 1

    def stopSmooth(self):
        if self.smoothStarted:
            taskName = self.smoothName
            taskMgr.remove(taskName)
            self.forceToTruePosition()
            self.smoothStarted = 0

    def makeToonReleaseInterval(self, toon):

        def getSlideToPos(toon = toon):
            return render.getRelativePoint(toon, Point3(0, -5, 0))

        if self.gotHitByBoss:
            grabIval = Sequence(Func(self.detachClub), name='makeToonReleaseInterval-gotHitByBoss')
            if not toon.isEmpty():
                toonIval = Sequence(Func(toon.wrtReparentTo, render), Parallel(ActorInterval(toon, 'slip-backward'), toon.posInterval(0.5, getSlideToPos, fluid=1)), name='makeToonReleaseInterval-toonIval')
                grabIval.append(toonIval)
        else:
            grabIval = Sequence(Func(self.detachClub))
            if not toon.isEmpty():
                toonIval = Sequence(Parallel(ActorInterval(toon, 'walk', duration=1.0, playRate=-1.0), LerpPosInterval(toon, duration=1.0, pos=Point3(-10, 0, 0))), Func(toon.wrtReparentTo, render))
                grabIval.append(toonIval)
        if localAvatar.doId == toon.doId:
            if not self.goingToReward and toon.hp > 0:
                grabIval.append(Func(self.goToFinalBattle))
                grabIval.append(Func(self.notify.debug, 'goingToFinalBattlemode'))
                grabIval.append(Func(self.safeBossToFinalBattleMode))
        return grabIval

    def safeBossToFinalBattleMode(self):
        if self.boss:
            self.boss.toFinalBattleMode()

    def goToFinalBattle(self):
        if self.cr:
            place = self.cr.playGame.getPlace()
            if place and hasattr(place, 'fsm'):
                curState = place.fsm.getCurrentState().getName()
                if place.fsm.getCurrentState().getName() == 'crane':
                    place.setState('finalBattle')
                else:
                    self.notify.debug('NOT going to final battle, state=%s' % curState)

    def attachClub(self, avId, pointToBall = False):
        club = self.club
        if club:
            av = base.cr.doId2do.get(avId)
            if av:
                av.useLOD(1000)
                lHand = av.getLeftHands()[0]
                club.setPos(0, 0, 0)
                club.reparentTo(lHand)
                netScale = club.getNetTransform().getScale()[1]
                counterActToonScale = lHand.find('**/counteractToonScale')
                if counterActToonScale.isEmpty():
                    counterActToonScale = lHand.attachNewNode('counteractToonScale')
                    counterActToonScale.setScale(1 / netScale)
                    self.notify.debug('creating counterActToonScale for %s' % av.getName())
                club.reparentTo(counterActToonScale)
                club.setX(-0.25 * netScale)
                if pointToBall:
                    club.lookAt(self.clubLookatSpot)

    def detachClub(self):
        if not self.club.isEmpty():
            self.club.reparentTo(self.root)
            self.club.setZ(-20)
            self.club.setScale(1)

    def adjustClub(self):
        club = self.club
        if club:
            distance = club.getDistance(self.clubLookatSpot)
            scaleFactor = distance / 2.058
            club.setScale(1, scaleFactor, 1)

    def startAdjustClubTask(self):
        taskMgr.add(self.adjustClubTask, self.adjustClubTaskName)

    def stopAdjustClubTask(self):
        taskMgr.remove(self.adjustClubTaskName)

    def adjustClubTask(self, task):
        self.attachClub(self.avId, True)
        self.adjustClub()
        return task.cont

    def enableControlKey(self):
        self.controlKeyAllowed = True

    def disableControlKey(self):
        self.controlKeyAllowed = False

    def sendSwingInfo(self, power, angle, sequenceNum):
        self.sendUpdate('setSwingInfo', [power, angle, sequenceNum])

    def startBallPlayback(self, power, angle, sequenceNum):
        flyBall = self.ballModel.copyTo(NodePath())
        flyBall.setScale(1.0)
        flyBallBubble = self.getFlyBallBubble().instanceTo(NodePath())
        flyBallBubble.reparentTo(flyBall)
        flyBall.setTag('pieSequence', str(sequenceNum))
        flyBall.setTag('throwerId', str(self.avId))
        t = power / 100.0
        t = 1.0 - t
        dist = 300 - 200 * t
        time = 1.5 + 0.5 * t
        proj = ProjectileInterval(None, startPos=Point3(0, 0, 0), endPos=Point3(0, dist, 0), duration=time)
        relVel = proj.startVel

        def getVelocity(root = self.root, relVel = relVel):
            return render.getRelativeVector(root, relVel)

        fly = Sequence(Func(flyBall.reparentTo, render), Func(flyBall.setPosHpr, self.root, 0, 0, 0, 0, 0, 0), Func(base.cTrav.addCollider, flyBallBubble, self.flyBallHandler), ProjectileInterval(flyBall, startVel=getVelocity, duration=3), Func(flyBall.detachNode), Func(base.cTrav.removeCollider, flyBallBubble), Func(self.notify.debug, 'removed collider'), Func(self.flyBallFinishedFlying, sequenceNum))
        flyWithSound = Parallel(fly, SoundInterval(self.hitBallSfx, node=self.root), name='flyWithSound')
        self.notify.debug('starting flyball track')
        flyWithSound.start()
        self.flyBallTracks[sequenceNum] = flyWithSound
        return

    def setSwingInfo(self, power, angle, sequenceNum):
        av = base.cr.doId2do.get(self.avId)
        self.swingInterval = Sequence()
        if av:
            self.stopAdjustClubTask()
            self.swingInterval = Sequence(ActorInterval(av, 'swing-putt', startFrame=0, endFrame=GolfGlobals.BALL_CONTACT_FRAME), Func(self.startBallPlayback, power, angle, sequenceNum), Func(self.ballModel.hide), ActorInterval(av, 'swing-putt', startFrame=GolfGlobals.BALL_CONTACT_FRAME, endFrame=24), Func(self.ballModel.setScale, 0.1), Func(self.ballModel.show), LerpScaleInterval(self.ballModel, 1.0, Point3(1, 1, 1)), Func(self.enableControlKey))
            if av == localAvatar:
                self.swingInterval.append(Func(self.switchToAnimState, 'GolfPuttLoop', True))
        self.swingInterval.start()

    def getFlyBallBubble(self):
        if self.__flyBallBubble == None:
            bubble = CollisionSphere(0, 0, 0, GolfGlobals.GOLF_BALL_RADIUS)
            node = CollisionNode('flyBallBubble')
            node.addSolid(bubble)
            node.setFromCollideMask(ToontownGlobals.PieBitmask | ToontownGlobals.CameraBitmask | ToontownGlobals.FloorBitmask)
            node.setIntoCollideMask(BitMask32.allOff())
            self.__flyBallBubble = NodePath(node)
            self.flyBallHandler = CollisionHandlerEvent()
            self.flyBallHandler.addInPattern('flyBallHit-%d' % self.index)
        return self.__flyBallBubble

    def __flyBallHit(self, entry):
        print entry

    def flyBallFinishedFlying(self, sequence):
        if sequence in self.flyBallTracks:
            del self.flyBallTracks[sequence]

    def __finishFlyBallTrack(self, sequence):
        if sequence in self.flyBallTracks:
            flyBallTrack = self.flyBallTracks[sequence]
            del self.flyBallTracks[sequence]
            flyBallTrack.finish()

    def flyBallFinishedSplatting(self, sequence):
        if sequence in self.splatTracks:
            del self.splatTracks[sequence]

    def __flyBallHit(self, entry):
        if not entry.hasSurfacePoint() or not entry.hasInto():
            return
        if not entry.getInto().isTangible():
            return
        sequence = int(entry.getFromNodePath().getNetTag('pieSequence'))
        self.__finishFlyBallTrack(sequence)
        if sequence in self.splatTracks:
            splatTrack = self.splatTracks[sequence]
            del self.splatTracks[sequence]
            splatTrack.finish()
        flyBallCode = 0
        flyBallCodeStr = entry.getIntoNodePath().getNetTag('pieCode')
        if flyBallCodeStr:
            flyBallCode = int(flyBallCodeStr)
        pos = entry.getSurfacePoint(render)
        timestamp32 = globalClockDelta.getFrameNetworkTime(bits=32)
        throwerId = int(entry.getFromNodePath().getNetTag('throwerId'))
        splat = self.getFlyBallSplatInterval(pos[0], pos[1], pos[2], flyBallCode, throwerId)
        splat = Sequence(splat, Func(self.flyBallFinishedSplatting, sequence))
        self.splatTracks[sequence] = splat
        splat.start()
        self.notify.debug('doId=%d into=%s flyBallCode=%d, throwerId=%d' % (self.doId,
         entry.getIntoNodePath(),
         flyBallCode,
         throwerId))
        if flyBallCode == ToontownGlobals.PieCodeBossCog and self.avId == localAvatar.doId and self.lastHitSequenceNum != self.__flyBallSequenceNum:
            self.lastHitSequenceNum = self.__flyBallSequenceNum
            self.boss.d_ballHitBoss(1)
        elif flyBallCode == ToontownGlobals.PieCodeToon and self.avId == localAvatar.doId and self.lastHitSequenceNum != self.__flyBallSequenceNum:
            self.lastHitSequenceNum = self.__flyBallSequenceNum
            avatarDoId = entry.getIntoNodePath().getNetTag('avatarDoId')
            if avatarDoId == '':
                self.notify.warning('Toon %s has no avatarDoId tag.' % repr(entry.getIntoNodePath()))
                return
            doId = int(avatarDoId)
            if doId != localAvatar.doId:
                pass

    def getFlyBallSplatInterval(self, x, y, z, flyBallCode, throwerId):
        from toontown.toonbase import ToontownBattleGlobals
        from toontown.battle import BattleProps
        splatName = 'dust'
        splat = BattleProps.globalPropPool.getProp(splatName)
        splat.setBillboardPointWorld(2)
        color = ToontownGlobals.PieCodeColors.get(flyBallCode)
        if color:
            splat.setColor(*color)
        if flyBallCode == ToontownGlobals.PieCodeBossCog:
            self.notify.debug('changing color to %s' % self.ballColor)
            splat.setColor(self.ballColor)
        sound = loader.loadSfx('phase_11/audio/sfx/LB_evidence_miss.ogg')
        vol = 1.0
        if flyBallCode == ToontownGlobals.PieCodeBossCog:
            sound = loader.loadSfx('phase_4/audio/sfx/Golf_Hit_Barrier_1.ogg')
        soundIval = SoundInterval(sound, node=splat, volume=vol)
        if flyBallCode == ToontownGlobals.PieCodeBossCog and localAvatar.doId == throwerId:
            vol = 1.0
            soundIval = SoundInterval(sound, node=localAvatar, volume=vol)
        ival = Parallel(Func(splat.reparentTo, render), Func(splat.setPos, x, y, z), soundIval, Sequence(ActorInterval(splat, splatName), Func(splat.detachNode)))
        return ival

    def setGoingToReward(self):
        self.goingToReward = True

    def gotBossZapped(self):
        self.showExiting()
        self.d_requestFree(True)
Пример #40
0
    mpos=base.mouseWatcherNode.getMouse()
    # this is what set our ray to shoot from the actual camera lenses off the 3d scene, passing by the mouse pointer position, making  magically hit in the 3d space what is pointed by it
    pickerRay.setFromLens(base.camNode, mpos.getX(),mpos.getY())
  return task.cont

#** This function then will be called when we click and release the left mouse button, showing himself changing the ball scale according with the pickingEnabled flag state.
def mousePick(status):
  if pickingEnabled:
    if status == 'down':
      smileyModel.setScale(.9)

  if status == 'up':
    smileyModel.setScale(1.0)

# Here as well we see something already seen in the previous steps related to collision events so I won't go into details.
collisionHandler.addInPattern('%fn-into-%in')
collisionHandler.addOutPattern('%fn-out-%in')

#** Let's manage now the collision events:
DO=DirectObject()
# if you went from step3 and step4, here should not be mysteries for you
DO.accept('mouseraycnode-into-smileycnode', collideEventIn)
DO.accept('mouseraycnode-out-smileycnode', collideEventOut)

#** This little but important variable will be used to know the picking state at any time - note that the picking is enabled ASA the mouse pointer goes above the ball and disabled when it leave.
pickingEnabled=False

#** This is how we interact with mouse clicks - see the mousePick function above for details
DO.accept('mouse1', mousePick, ['down'])
DO.accept('mouse1-up', mousePick, ['up'])
class DonkeyKong(ShowBase):
    def __init__(self):
        super().__init__(self)

        self.playerLost = False
        self.playerWon = False

        self.scene = self.loader.loadModel('models/DKSet')
        self.scene.reparentTo(self.render)

        self.arcadeTexture = self.loader.loadTexture('models/dk-arcade.png')
        self.scene.setTexture(self.arcadeTexture)
        self.scene.setTransparency(1)

        self.blockTexture = self.loader.loadTexture('models/block.png')
        self.stairsTexture = self.loader.loadTexture('models/stairs.png')
        self.taskMgr.add(self.setup, "setup")
        self.taskMgr.add(self.update, "update")
        self.jumpAvailable = False
        self.baseTime = 0
        self.v0 = 0
        self.gravity = -.5
        self.stairsAvailable = False
        self.lastPlayerValidZ = 0
        self.hammerTime = False
        self.dkTimer = 5
        self.lifeCounter = 3

    def pressUp(self):
        print("up")
        self.input["up"] = not self.input["up"]

    def pressDown(self):
        print("down")
        self.input["down"] = not self.input["down"]

    def pressLeft(self):
        print("left")
        self.input["left"] = not self.input["left"]

    def pressRight(self):
        print("right")
        self.input["right"] = not self.input["right"]

    def pressSpace(self):
        print("space")
        self.input["space"] = not self.input["space"]

    def hammerFrame1(self):
        self.hammerDown.show()
        self.hammerUp.hide()

    def hammerFrame2(self):
        self.hammerDown.hide()
        self.hammerUp.show()

    def setup(self, task):
        lens = OrthographicLens()
        lens.setFilmSize(25, 20)
        base.camNode.setLens(lens)

        self.player = self.scene.attachNewNode("Player")

        self.scene.find("root/barrel").setPos(0, 100, 0)

        self.scene.find("root/walls").hide()

        self.scene.find("root/rightWall").hide()

        self.lifes = [
            self.scene.attachNewNode("life1"),
            self.scene.attachNewNode("life2"),
            self.scene.attachNewNode("life3"),
        ]
        # init mario gfx stuff
        self.marioGfx = self.scene.find('root/mario')
        self.marioGfx.instanceTo(self.lifes[0])
        self.marioGfx.instanceTo(self.lifes[1])
        self.marioGfx.instanceTo(self.lifes[2])
        self.lifes[0].setPos(-9, 0, 7.5)
        self.lifes[1].setPos(-10, 0, 7.5)
        self.lifes[2].setPos(-11, 0, 7.5)

        self.marioGfx.reparentTo(self.player)
        self.marioGfx.setTwoSided(True)
        self.hammerDown = self.scene.find('root/hammerdowm')
        self.hammerDown.reparentTo(self.marioGfx)
        self.hammerDown.setPos(1, 0, 0)
        self.hammerUp = self.scene.find('root/hammerup')
        self.hammerUp.reparentTo(self.marioGfx)
        self.hammerUp.setPos(0, 0, 1)
        self.hammerDown.hide()
        self.hammerUp.hide()

        frame1 = Func(self.hammerFrame1)
        frame2 = Func(self.hammerFrame2)
        delay = Wait(0.1)
        self.hammerSequence = Sequence(frame1, delay, frame2, delay)
        #sequence.loop()
        #sequence.start()
        #sequence.finish()

        #input setup
        self.accept("raw-arrow_up", self.pressUp)
        self.accept("raw-arrow_down", self.pressDown)
        self.accept("raw-arrow_left", self.pressLeft)
        self.accept("raw-arrow_right", self.pressRight)
        self.accept("raw-space", self.pressSpace)

        self.accept("raw-arrow_up-up", self.pressUp)
        self.accept("raw-arrow_down-up", self.pressDown)
        self.accept("raw-arrow_left-up", self.pressLeft)
        self.accept("raw-arrow_right-up", self.pressRight)
        self.accept("raw-space-up", self.pressSpace)
        self.input = {
            'left': False,
            'right': False,
            'up': False,
            'down': False,
            'space': False
        }

        # collision handling
        base.cTrav = CollisionTraverser()
        self.collisionHandlerEvent = CollisionHandlerEvent()
        self.collisionHandlerEvent.addInPattern('into-%in')
        self.collisionHandlerEvent.addOutPattern('outof-%in')

        ray = CollisionSegment(0, 0, 0, 0, 0, -.6)
        cNodePath = self.player.attachNewNode(CollisionNode('marioRay'))
        cNodePath.node().addSolid(ray)
        cNodePath.node().setIntoCollideMask(0x3)
        cNodePath.node().setFromCollideMask(0x3)
        cNodePath.show()
        base.cTrav.addCollider(cNodePath, self.collisionHandlerEvent)

        self.donkeykonggfx = self.scene.find(f'root/donkeykong')
        self.donkeykong = self.createSquareCollider(8.7, 5, 1, 1, 'donkeykong',
                                                    'dkHitbox', 'DK',
                                                    self.reachedDk,
                                                    self.exitDk,
                                                    self.arcadeTexture, 0x2)

        self.floor1 = self.createSquareCollider(-1.8, -5.5, 9.3, .5, 'floor0',
                                                'floor1Hitbox', 'Floor1',
                                                self.enableJump,
                                                self.disableJump,
                                                self.blockTexture, 0x01)
        self.floor2 = self.createSquareCollider(2.08, -2.5, 8.0, .5, 'floor1',
                                                'floor2Hitbox', 'Floor2',
                                                self.enableJump,
                                                self.disableJump,
                                                self.blockTexture, 0x01)
        self.floor3_1 = self.createSquareCollider(3.6, 0.5, 3.8, .5, 'floor2',
                                                  'floor3_1Hitbox', 'Floor3_1',
                                                  self.enableJump,
                                                  self.disableJump,
                                                  self.blockTexture, 0x01)
        self.floor3_2 = self.createSquareCollider(-6.3, 0.5, 5, .5, 'pCube4',
                                                  'floor3_2Hitbox', 'Floor3_2',
                                                  self.enableJump,
                                                  self.disableJump,
                                                  self.blockTexture, 0x01)
        self.floor4 = self.createSquareCollider(1.8, 3.5, 8, .5, 'floors',
                                                'floor4Hitbox', 'Floor4',
                                                self.enableJump,
                                                self.disableJump,
                                                self.blockTexture, 0x01)

        self.hammer = self.createSquareCollider(6, 1.5, .5, .5, 'hammer',
                                                'hammerHitbox', 'hammer',
                                                self.enableHammer,
                                                self.disableHammer,
                                                self.arcadeTexture, 0x02)

        self.topstair = self.createSquareCollider(
            -6.8, 3.5, 0.5, 2.5, 'topstair', 'topstairHitbox', 'TopStair',
            self.enableStairs, self.disableStairs, self.stairsTexture, 0x02)
        self.middlestair = self.createSquareCollider(
            -0.86, 0.1, 0.5, 2.5, 'middlestair', 'middlestairHitbox',
            'MiddleStair', self.enableStairs, self.disableStairs,
            self.stairsTexture, 0x02)
        self.bottomstair = self.createSquareCollider(
            -6.8, -2.5, 0.5, 2.5, 'bottomstair', 'bottomstairHitbox',
            'BottomStair', self.enableStairs, self.disableStairs,
            self.stairsTexture, 0x02)

        self.leftWall = self.invisibleSquareCollider(-12.5, 0, 1, 10,
                                                     "leftWallHitbox",
                                                     "leftWall", 0x1)
        self.rightWall = self.invisibleSquareCollider(11.3, 0, 1, 20,
                                                      "rightWallHitbox",
                                                      "rightWall", 0x1)

        self.barrelDestroyer = self.invisibleSquareCollider(
            -0.5, -10, 10.5, 1, "barrelDestroyHitBox", "barrelDestroyer", 0x1)
        self.barrelBridge = self.invisibleSquareCollider(
            -0.4, 0.5, 2, 0.5, "barrelBridgeHitBox", "barrelBridge", 0x4)
        base.enableParticles()
        self.physicsCollisionPusher = PhysicsCollisionHandler()
        gravity = ForceNode("world-forces")
        gravityP = render.attachNewNode(gravity)
        gravityForce = LinearVectorForce(0, 0, -9.81)
        gravity.addForce(gravityForce)
        base.physicsMgr.addLinearForce(gravityForce)
        self.accept("into-barrelCollider", self.barrelCrash)

        #self.accept("raw-a", self.throwBarrel)

        #base.cTrav.showCollisions(self.render)

        self.barrels_frames = []
        self.barrels_frames.append(0)
        self.barrels_frames.append(0.410573 - 0.375774)
        self.barrels_frames.append(0.444913 - 0.375774)
        self.barrels_frames.append(0.479941 - 0.375774)

        self.createDKSequence()
        self.player.setPos(3, 0, -3)
        return Task.done

    def changeDkFrame(self, dk, new_u, new_v):
        dk.setTexOffset(TextureStage.getDefault(), new_u, new_v)

    def createDKSequence(self):
        #self.donkeykonggfx
        f1 = Func(self.changeDkFrame, self.donkeykonggfx, 0.140867 - 0.0446603,
                  0)
        f2 = Func(self.changeDkFrame, self.donkeykonggfx,
                  0.0431023 - 0.0446603, 0.806672 - 0.703844)
        f3 = Func(self.changeDkFrame, self.donkeykonggfx, 0, 0)
        th = Func(self.throwBarrel)
        d = Wait(0.2)

        self.dk_sequence = Sequence(f1, d, f2, d, f3, th, d, f1)

    def reachedDk(self, evt):
        if (self.hammerTime):
            self.playerWon = True
        else:
            self.playerLost = True
        print("dk entered")

    def exitDk(self, evt):
        print("dk exit")

    def enableHammer(self, evt):
        self.hammerTime = True
        self.hammerSequence.loop()
        self.scene.node().removeChild(
            evt.getIntoNodePath().node().getParent(0))

    def disableHammer(self, evt):
        pass

    def barrelCrash(self, evt):
        physicsBarrel = evt.getIntoNodePath().node().getParent(0).getParent(0)
        other = evt.getFromNodePath().node().getParent(0)

        if (other.name == "leftWall" or other.name == "rightWall"):
            forceNode = physicsBarrel.getChildren()[1]
            force = forceNode.getForce(0)
            force.setVector(force.getLocalVector().x * -1, 0, 0)
            forceNode.clear()
            forceNode.addForce(force)

        if other.name == "barrelDestroyer":
            self.scene.node().removeChild(physicsBarrel.getParent(0))

        if other.name == "Player":
            if (self.hammerTime):
                self.scene.node().removeChild(physicsBarrel.getParent(0))
            else:
                self.lifeCounter = self.lifeCounter - 1
                if (self.lifeCounter < 0):
                    self.playerLost = True
                else:
                    self.lifes[self.lifeCounter].hide()

    def throwBarrel(self):
        barrelNode = self.scene.attachNewNode("PhysicalBarrel")
        physicsBarrel = ActorNode("physics_barrel")
        physicsBarrel.getPhysicsObject().setMass(0.01)

        barrel = barrelNode.attachNewNode(physicsBarrel)
        base.physicsMgr.attachPhysicalNode(physicsBarrel)

        visualBarrel = barrel.attachNewNode("BarrelCopy")
        originalBarrel = self.scene.find("root/barrel")
        originalBarrel.instanceTo(visualBarrel)
        visualBarrel.setPos(0, -100, 0)

        sphere = CollisionSphere(0.16, 100, 0, 0.5)
        cNodePath = visualBarrel.attachNewNode(CollisionNode("barrelCollider"))
        cNodePath.node().addSolid(sphere)
        cNodePath.node().setFromCollideMask(0x05)
        cNodePath.node().setIntoCollideMask(0x05)
        #cNodePath.show()

        self.physicsCollisionPusher.addCollider(cNodePath, barrel)
        base.cTrav.addCollider(cNodePath, self.physicsCollisionPusher)

        barrelForceNode = ForceNode("barrelForce")
        barrel.attachNewNode(barrelForceNode)
        barrelForce = LinearVectorForce(-8, 0, 0, 1, False)
        barrelForceNode.addForce(barrelForce)
        physicsBarrel.getPhysical(0).addLinearForce(barrelForce)
        barrelNode.setPos(self.scene, 7, 0, 4.5)

        dataNode = AuxNode("sequenceData")
        seq = self.createBarrelSequence(visualBarrel, physicsBarrel, dataNode)
        dataNode.setSequence(seq)

        barrelNode.attachNewNode(dataNode)

    def createBarrelSequence(self, visual, physics, dataNode):
        def updateBarrel():
            vel = physics.getPhysicsObject().getVelocity()
            frame = dataNode.frame

            if (vel.x > 0):
                frame = (frame + 1) % 4
                #vel.x = 5
            if (vel.x < 0):
                frame = (frame - 1) % 4
                #vel.x = -5
            dataNode.frame = frame

            physics.getPhysicsObject().setVelocity(vel)
            visualFrame = self.barrels_frames[frame]
            visual.setTexOffset(TextureStage.getDefault(), visualFrame, 0.0)

        f1 = Func(updateBarrel)
        d = Wait(0.1)

        seq = Sequence(f1, d)
        seq.loop()
        return seq

    def createSquareCollider(self, px, pz, w, h, modelName, collisionNodeName,
                             nodeName, enableFunction, disableFunction,
                             texture, mask):
        obj = self.scene.attachNewNode(nodeName)
        hitbox = CollisionBox(Point3(0, 0, 0), w, 5, h)
        cNodePath = obj.attachNewNode(CollisionNode(collisionNodeName))
        cNodePath.node().addSolid(hitbox)
        cNodePath.node().setIntoCollideMask(mask)
        cNodePath.node().setFromCollideMask(mask)
        #cNodePath.show()
        base.cTrav.addCollider(cNodePath, self.collisionHandlerEvent)

        self.scene.find(f'root/{modelName}').reparentTo(obj)
        obj.setPos(px, 0, pz)
        obj.setTexture(texture)

        self.accept(f'into-{collisionNodeName}', enableFunction)
        self.accept(f'outof-{collisionNodeName}', disableFunction)
        return obj

    def invisibleSquareCollider(self, px, pz, w, h, collisionNodeName,
                                nodeName, mask):
        obj = self.scene.attachNewNode(nodeName)
        hitbox = CollisionBox(Point3(0, 0, 0), w, 5, h)
        cNodePath = obj.attachNewNode(CollisionNode(collisionNodeName))
        cNodePath.node().addSolid(hitbox)
        cNodePath.node().setIntoCollideMask(mask)
        cNodePath.node().setFromCollideMask(mask)
        #cNodePath.show()
        base.cTrav.addCollider(cNodePath, self.collisionHandlerEvent)
        obj.setPos(px, 0, pz)

    def enableJump(self, evt):
        self.lastPlayerValidZ = evt.getIntoNodePath().node().getParent(
            0).getTransform().getPos().z + 1
        self.jumpAvailable = True
        print("enable jump")

    def disableJump(self, evt):
        print(evt.getIntoNodePath().node().getParent(0))
        self.jumpAvailable = False
        print("disable jump")

    def enableStairs(self, evt):

        self.stairsAvailable = True
        print("enable stairs")

    def disableStairs(self, evt):
        self.stairsAvailable = False
        print("disable stairs")

    def applyMove(self):
        mv = Vec3(0, 0, 0)
        p = self.player.getPos()

        if (self.input["left"]):
            self.marioGfx.setSx(self.player, 1)
            mv.x = 0.1
        if (self.input["right"]):
            self.marioGfx.setSx(self.player, -1)
            mv.x = -0.1

        if (self.jumpAvailable):
            mv.z = self.v0 + self.baseTime * self.gravity
            if (not self.stairsAvailable):
                p.z = self.lastPlayerValidZ
            if (mv.z < 0):
                self.v0 = 0
                self.baseTime = 0
                mv.z = 0

        if (self.input["space"] and self.jumpAvailable):
            self.baseTime = 0
            self.v0 = .2
            mv.z = self.v0 + self.baseTime * self.gravity

        if (not self.jumpAvailable and not self.stairsAvailable):
            self.baseTime = self.baseTime + globalClock.getDt()
            mv.z = self.v0 + self.baseTime * self.gravity

        if (self.stairsAvailable):
            self.baseTime = 0
            self.v0 = 0
            if (self.input["up"]):
                mv.z = mv.z + 0.1
            if (self.input["down"] and not self.jumpAvailable):
                mv.z = mv.z - 0.1
        p.x = p.x + mv.x
        p.z = p.z + mv.z
        self.player.setPos(p)

    def update(self, task):
        self.camera.setPos(0, 35, 0)
        self.camera.lookAt(self.scene)

        self.dkTimer = self.dkTimer + globalClock.getDt()

        if (self.dkTimer > 10):
            self.dk_sequence.start()
            self.dkTimer = 0

        if ((self.playerLost or self.playerWon)):
            if (self.playerLost):
                text = DirectLabel(text="Perdiste!!!!", text_scale=(0.5, 0.5))
            if (self.playerWon):
                text = DirectLabel(text="Ganastesss!", text_scale=(0.5, 0.5))
            return Task.done

        self.applyMove()

        return Task.cont
Пример #42
0
class Load():
    def __init__(self):
        # import leap motion
        self.leap = leapmotion.LeapMotion()
        # disable mouse control
        base.disableMouse()
        render.hide()
        self.inGame = True

        # menu music
        # taken from https://www.youtube.com/watch?v=2iEWbHJDlo4&list=PLzCxunOM5WFIudfMTgJzXkOE-xbVWrpIF&index=7
        self.starterMusic = loader.loadMusic(
            'musics/starterMenuBackground.ogg')
        self.starterMusic.setLoop(True)
        # taken form https://www.youtube.com/watch?v=I0vEzblcnPA&list=PLzCxunOM5WFIudfMTgJzXkOE-xbVWrpIF&index=18
        self.endMusic = loader.loadMusic('musics/endMusic.ogg')
        self.endMusic.setLoop(True)

        # game music from https://www.youtube.com/watch?v=mNFNOEi9QV4&list=PLzCxunOM5WFK7WGa3wGjlONp_9R66a2zz&index=8
        self.gameMusic = loader.loadMusic('musics/gameMusic.ogg')
        self.gameMusic.setLoop(True)

        # import flybot, enemy, door, chests, key, and player
        self.flyBot = FlyBot()
        self.player = player.Player(self.flyBot)
        self.enemies = []
        self.numbEnemies = 0
        keyChest = random.randint(0, 3)
        # self.key = Key(keyChest)
        self.door = Door(225, 190, self.flyBot)
        self.walls = []
        self.chests = []

    def startGame(self):
        # Load the map.
        self.environ = loader.loadModel("models/background_model")
        # Reparent the model to render.
        self.environ.reparentTo(render)
        # Apply scale and position transforms on the model.
        # image taken from http://motorbikes-passion.info/scary-dark-room.html
        myTexture = loader.loadTexture("models/backgroundtexture.jpg")
        self.environ.setTexGen(TextureStage.getDefault(),
                               TexGenAttrib.MWorldCubeMap)
        self.environ.setTexture(myTexture)
        self.environ.setScale(1, 1, 1)
        self.environ.setPos(0, 0, 0)
        self.environ.reparentTo(render)

        # random generate map
        self.numbWalls = 4
        walls = generateRoom([], self.numbWalls)
        # if random generation fails, input default map
        if walls == None:
            walls = [(120, 30, 0), (-100, 80, 90), (-130, -70, 0),
                     (50, -50, 90)]
        # load wall models in respective location
        for wall in walls:
            x, y, angle = wall
            newWall = Wall(x, y, angle)
            self.walls.append(newWall)

        # generate chests in random areas
        chests = generateChestLocation(walls)
        for chest in chests:
            x, y, chestNumb = chest
            newChest = Chest(self.player, self.flyBot, x, y, chestNumb)
            self.chests.append(newChest)

        # display player stats
        self.display = self.player.displayStats()

        # run collision settings
        base.cTrav = CollisionTraverser()
        # Set up collision for environment
        self.backgroundCollide = CollisionRay()
        self.backgroundNode = CollisionNode('backgroundCollider')
        self.backgroundNode.addSolid(self.backgroundCollide)
        self.backgroundNode.setFromCollideMask(CollideMask.bit(0))
        self.backgroundNode.setIntoCollideMask(CollideMask.allOff())
        self.backgroundCollider = self.environ.attachNewNode(
            self.backgroundNode)

        # call all functions that deal with collisions
        taskMgr.add(self.swordHitEnemy, 'killEnemy')
        self.wallCollisions()
        taskMgr.add(self.fireballHitPlayer, 'fireballHits')

        # load sound effects
        # sound taken from https://bigsoundbank.com/detail-0129-sword.html
        self.swordCut = loader.loadSfx('musics/0129.ogg')
        # sound taken from https://bigsoundbank.com/detail-0437-shot-beretta-m12-9-mm.html
        self.fireballHit = loader.loadSfx('musics/0437.ogg')

        # run quitGame
        self.quitGame()

        # Set up initial camera position
        base.camera.setPos(0, 0, 0)
        base.camera.setHpr(0, 0, 0)
        base.camera.reparentTo(self.flyBot.flyBot)
        # import player controls from player file
        self.playerControl = player.KeyboardControl(self.flyBot, self.chests,
                                                    self.door, self.walls,
                                                    self.player)

        # import leap motion control
        self.leapControl = player.swordControl(self.leap, self.player)
        taskMgr.add(self.leapControl.swingsword, 'swingsword')

        # spawn new enemies
        sec = 5 - self.player.atLevel
        taskMgr.doMethodLater(sec, self.spawnEnemies, 'createNewEnemy')

        # test enemy movements
        taskMgr.add(self.enemyMovements, 'enemyMovements')

        # Game AI
        AI = GameAI(self.enemies, self.flyBot)
        taskMgr.add(AI.makeDecision, 'enemyStateDetermination')

    # stop all tasks
    def stopGame(self):
        taskMgr.remove('checkGameState')
        taskMgr.remove('enemyStateDetermination')
        taskMgr.remove('enemyMovements')
        taskMgr.remove('createNewEnemy')
        taskMgr.remove('swingsword')
        taskMgr.remove('fireballHits')
        taskMgr.remove('killEnemy')
        taskMgr.remove("playerMove")
        taskMgr.remove('openChestOrDoor')
        taskMgr.remove('moveFireball')
        taskMgr.remove('fireFireballs')

    # allow keyboard exit
    def quitGame(self):
        textObject = OnscreenText(text='ESC to exit game',
                                  pos=(-0.25, -0.05),
                                  scale=0.05,
                                  parent=base.a2dTopRight)
        # The key esc will exit the game
        base.accept('escape', sys.exit)

    # create new enemies
    def spawnEnemies(self, task):
        if len(self.enemies) < 20:
            # default state is stay
            self.numbEnemies += 1
            newEnemy = enemy.Enemy(1, self.numbEnemies, self.player)
            self.enemies.append(newEnemy)
        task.delayTime += 1
        return task.again

    # moves the enemies towards the player
    def enemyMovements(self, task):
        for enemy in self.enemies:
            enemy.lookAtPlayer(self.flyBot)
            if enemy.state == 0:
                enemy.move(self.flyBot.flyBot)
            if enemy.state == 2:
                randomChest = random.randint(0, 3)
                doorOrChest = random.randint(
                    [self.door.door, self.chests[randomChest].chestModel])
                enemy.move(doorOrChest)
        return task.cont

    # Collision functions, called in init
    def wallCollisions(self):
        # Pusher so that the player cannot move past the walls
        self.playerPusher = CollisionHandlerPusher()
        base.cTrav.addCollider(self.flyBot.playerCollider, self.playerPusher)
        self.playerPusher.addCollider(self.flyBot.playerCollider,
                                      self.flyBot.flyBot)

        self.enemyPusher = CollisionHandlerPusher()
        for enemy in self.enemies:
            base.cTrav.addCollider(enemy.collider, self.enemyPusher)
            self.enemyPusher.addCollider(enemy.collider, enemy.enemyModel)

    def swordHitEnemy(self, task):
        # When the sword collides with enemy, enemy dies
        for enemy in self.enemies:
            self.playerKill = CollisionHandlerEvent()
            base.cTrav.addCollider(enemy.collider, self.playerKill)
            self.playerKill.addInPattern('%fn-into-%in')

            # perform the task
            self.kill = DirectObject()
            self.kill.accept('enemy' + str(enemy.numb) + '-into-swordCollider',
                             enemy.killEnemy)
            self.swordHit = DirectObject()
            self.swordHit.accept(
                'enemy' + str(enemy.numb) + '-into-swordCollider',
                self.swordHitSound)
            if not enemy.isAlive:
                self.enemies.remove(enemy)
        return task.cont

    # play the sound when the sword hits an ememy
    def swordHitSound(self, *args):
        if self.player.damage:
            self.swordCut.play()

    # create collision system for fireballs based on the location of the player
    # and the location of a given enemy
    def fireballHitPlayer(self, task):
        for enemy in self.enemies:
            if enemy.fireballFired.isLive:
                # When fireball collides with player, player health reduces
                playerX = self.flyBot.flyBot.getX()
                playerY = self.flyBot.flyBot.getY()
                margin = 5

                enemyH = math.sin(math.radians(enemy.enemyModel.getH()))
                fireballX = enemy.enemyModel.getX()
                fireballY = enemy.enemyModel.getY(
                ) + enemyH * enemy.fireballFired.fireball.getY()
                enemyY = enemy.enemyModel.getY()
                playerH = self.flyBot.flyBot.getH()

                if abs(fireballY) > 230 or abs(fireballX) > 230:
                    enemy.fireballFired.removeFireball(task)

                if (playerH > -45 and
                        playerH < 45) or (playerH > 135) or (playerH < -135):
                    if playerX - margin <= fireballX and playerX + margin >= fireballX:
                        if (abs(enemy.enemyModel.getH()) <= 45 and fireballY >= playerY) or\
                        (abs(enemy.enemyModel.getH()) >= 135 and fireballY <= playerY):
                            self.fireballHit.play()
                            self.player.changeStats(-5, 0)
                            enemy.fireballFired.removeFireball(task)

                else:
                    if playerY - margin <= fireballY and playerY + margin >= fireballY:
                        if (enemy.enemyModel.getH() <= 0 and fireballX >= playerX) or\
                            (enemy.enemyModel.getH() > 0 and fireballX <= playerX):
                            self.fireballHit.play()
                            self.player.changeStats(-5, 0)
                            enemy.fireballFired.removeFireball(task)

        return task.cont
Пример #43
0
class MyApp(ShowBase):
   def __init__(self):
      ShowBase.__init__(self)

      self.imageObject = OnscreenImage(image = 'earth.jpg', pos = (0, 1, 0))
      self.imageObject.setScale(1.9,1,1)
      tpRed = TextProperties()
      tpRed.setTextColor(1, 1, 1, 1)
      tpSlant = TextProperties()
      tpSlant.setSlant(0.3)
      tpRoman = TextProperties()
      cmr12 = loader.loadFont('cmr12.egg')
      tpRoman.setFont(cmr12)
      tpMgr = TextPropertiesManager.getGlobalPtr()
      tpMgr.setProperties("red", tpRed)
      tpMgr.setProperties("slant", tpSlant)
      tpMgr.setProperties("roman", tpRoman)
      self.textObject = OnscreenText(text = '\1red\1\1roman\1\1slant\1Space Collector', pos = (-0.6, 0.4), scale = 0.2)
      self.textScore=0



      self.b = DirectButton(text = ("Start", "Start", "Start", "disabled"),command=self.beginGame)	
      self.b.setScale(0.1,0.1,0.1)
      self.b.setPos(0.7,0,-0.8)

      myMaterial = Material()
      myMaterial.setShininess(1000)
      myMaterial.setDiffuse(VBase4(0.5,0.5,0.5,1))
      myMaterial.setAmbient(VBase4(5,5,5,1))
      myMaterial.setSpecular(VBase4(10,10,10,1))

      myTexture = loader.loadTexture("maps/grayjumpjetTexture.tif")

      self.ship = loader.loadModel("GrayJumpJet")
      self.ship.setScale(0.15, 0.3, 0.15)
      self.ship.setPos(0,0,0)
      self.ship.setTexture(myTexture,1)
      self.ship.reparentTo(render)

      self.slab = loader.loadModel("box")
      self.slab.find("**/Cube;+h").setCollideMask(BitMask32.bit(0))
      self.slab.setScale(1.5,10,1)
      self.slab.setPos(0,0,-1)
      self.slab.setHpr(0,0,0)
      self.slab.setMaterial(myMaterial)
      self.slab.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
      self.slab.setTexProjector(TextureStage.getDefault(), render, self.slab)
      self.slab.setTexture(loader.loadTexture("maps/crate_Material_#11_CL.tif"),1)
      self.junk = [None]*100
      self.loadJunk()


      self.createTrack()

      base.trackball.node().setPos(0, 20, -4)

      self.acceleration=0
      self.velocity=0
      self.yPos=0

      render.setShaderAuto()

      self.cTrav = CollisionTraverser()

      self.shipGroundRay = CollisionRay()
      self.shipGroundRay.setOrigin(0,0,1000)
      self.shipGroundRay.setDirection(0,0,-1)
      self.shipGroundCol = CollisionNode('shipRay')
      self.shipGroundCol.addSolid(self.shipGroundRay)
      self.shipGroundCol.setFromCollideMask(BitMask32.bit(0))
      self.shipGroundCol.setIntoCollideMask(BitMask32.allOff())
      self.shipGroundColNp = self.ship.attachNewNode(self.shipGroundCol)
      self.shipGroundHandler = CollisionHandlerQueue()
      self.cTrav.addCollider(self.shipGroundColNp, self.shipGroundHandler)
      self.collHandEvent = CollisionHandlerEvent()        
      # add the into pattern with fromObject-into-thisObject        
      self.collHandEvent.addInPattern( 'into-%in' )
      self.accept("into-Junk",self.cHandler)
      bkground = loader.loadModel("square")
      bkground.reparentTo(camera)
      bkground.setScale(300,170,50)
      tex = loader.loadTexture("earth2.jpg")
      bkground.setTexture(tex,1)
      bkground.setPos(0,299,0)
      bkground.setHpr(0,90,0)
      base.camLens.setFar(300)

      self.mySound = loader.loadMusic("coinslot1.wav")
      self.timer=60
      self.textTimer=0
      self.prevY=0
      self.prevX=0
      self.shipGroundColNp.show()
      #self.camGroundColNp.show()
      self.collided=1
      self.jumpTime=0
      self.jumpOn=0
      self.curZ=0
      self.interval=0
      self.zPosition=0
      self.isGameOver=0
      self.score=0
      # Uncomment this line to show a visual representation of the 
      # collisions occuring
      #self.cTrav.showCollisions(render)
      if base.mouseWatcherNode.hasMouse():
             self.prevX=base.mouseWatcherNode.getMouseX()
             self.prevY=base.mouseWatcherNode.getMouseY()

   def beginGame(self):
      self.textObject.destroy()
      self.imageObject.destroy()
      self.b.destroy()
      props = WindowProperties()
      props.setCursorHidden(True)
      base.win.requestProperties(props)
      self.taskMgr.add(self.moveForward, "MoveForward")
      self.accept("mouse1",self.jump)
      self.textScore = OnscreenText(text = '\1red\1\1slant\1Score : 0', pos = (-0.8, 0.8), scale = 0.1)
      self.textTimer = OnscreenText(text = '\1red\1\1slant\1Time Left : 2:00', pos = (-0.8, 0.7), scale = 0.1)
      print 'GameBegin'


   def cHandler(self,collEntry):
      print "collision"

   def loadJunk(self):
      f = open('junk1.txt','r')
      x=f.readline()
      y=f.readline()
      z=f.readline()
      i=0
      while x!="":
             self.junk[i] = loader.loadModel("rubbishset/rubbish-set.lwo")
             self.junk[i].setScale(0.5,1,0.5)
             self.junk[i].reparentTo(render)
             colSphere=self.initCollisionSphere(self.junk[i],"Junk")
             self.junk[i].setPos(int(x),int(y),int(z))
             x=f.readline()
             y=f.readline()
             z=f.readline()
             i=i+1
                 
                
   def initCollisionSphere(self,node,name):
      bounds = node.getBounds()
      center = bounds.getCenter()
      radius = bounds.getRadius()*0.6
      cNode = CollisionNode(name)
      cNode.addSolid(CollisionSphere(center,radius))
      cNP=node.attachNewNode(cNode)
      cNP.show()
      return cNP

   def createTrack(self):
      f = open('track.txt','r')
      a = f.read(1)
      i=0
      j=0
      while(a!=""):
         if a=="\n":
            a=f.read(1)
         if(a==""):
            break
         nSlab = int(a)
         #print nSlab
         while nSlab!=0:
            placeholder = render.attachNewNode("Slab")
            placeholder.setColor(j*0.92*0.4,nSlab*nSlab*0.51,0.23,1)
            placeholder.setPos(j*3-7,i*15,nSlab-3)
            self.slab.instanceTo(placeholder)
            nSlab=nSlab-1
         j=j+1
         if(j==5):
            i=i+1
            j=0
            print i
         a=f.read(1)
                             

   def moveForward(self, task):
      curX=0
      curY=0
      shipCollided=0
      c=self.timer-int(task.time)
      self.textTimer.setText('\1red\1\1slant\1Time Left : '+str(int(c/60))+':'+str(c%60))
      if base.mouseWatcherNode.hasMouse():
          curX=base.mouseWatcherNode.getMouseX()
          curY=base.mouseWatcherNode.getMouseY()
      #if(curY>self.prevY+0.01):
      self.acceleration = self.acceleration+1
      #if(curY<self.prevY-0.01):
      #	self.acceleration = self.acceleration-1

      if(self.acceleration<45 and self.acceleration>=0):
          self.velocity=self.acceleration*task.time

      self.yPos=self.velocity * task.time
      self.ship.setY(self.yPos)

      if self.prevX<curX-0.001:
          self.ship.setHpr(0,0,5)
          #Sequence(self.ship.hprInterval(0.1,Point3(0,0,10),self.ship.getHpr())).start()
          self.ship.setX(curX*8)
          self.prevX=curX
      elif self.prevX>curX+0.001:
          self.ship.setHpr(0,0,-5)
          #Sequence(self.ship.hprInterval(0.1,Point3(0,0,-10),self.ship.getHpr())).start()
          self.ship.setX(curX*8)
          self.prevX=curX
      else:
          #self.ship.setHpr(0,0,0)
          Sequence(self.ship.hprInterval(0.1,Point3(0,0,0),self.ship.getHpr())).start()

      #print yPos
      self.camera.setPos(0,self.yPos-25,4)
      #self.slnp.setPos(0,self.yPos+20,4)
      self.cTrav.traverse(render)

      entries = []
      for i in range(self.shipGroundHandler.getNumEntries()):
         entry = self.shipGroundHandler.getEntry(i)
         entries.append(entry)
      entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                  x.getSurfacePoint(render).getZ()))
      if (len(entries)>0) and (entries[0].getIntoNode().getName() == "Cube"):
         self.zPosition=entries[0].getSurfacePoint(render).getZ()
         #self.ship.setZ(entries[0].getSurfacePoint(render).getZ()+1)
         print str(self.zPosition) + " "+str(self.ship.getZ())
         if self.zPosition>=self.ship.getZ():
            shipCollided=1
            self.isGameOver=1
         else:
            shipCollided=0
         self.collided=1
         print entries[0].getIntoNode().getName() + "collided"
      elif (len(entries)>0) and (entries[0].getIntoNode().getName() == "Junk"):
         pZ=entries[0].getSurfacePoint(render).getZ()
         if(self.ship.getZ()<=pZ and self.ship.getZ()>=pZ-2):
            entries[0].getIntoNode().getParent(0).removeAllChildren()
            self.score=self.score+1000
            self.timer=self.timer+20
            self.textScore.setText('\1red\1\1slant\1Score : '+str(self.score))
            self.mySound.play()
            print self.score 
      else:
         self.collided=0
      if shipCollided!=1:
         val=0
         if(self.jumpOn==1):
            val=10
         if(self.interval==0):
            self.interval=task.time
            self.curZ=self.ship.getZ()
            self.jumpTime=0
         else:
            self.jumpTime=self.jumpTime+task.time-self.interval
            self.interval=task.time
            zPos = self.curZ + val*self.jumpTime - 12*self.jumpTime*self.jumpTime
            if(zPos<self.zPosition+1 and self.collided==1):
               zPos=self.zPosition+1
               self.ship.setZ(zPos)
               self.accept("mouse1",self.jump)
               self.jumpOn=0
               self.interval=0
            else:
               self.ship.setZ(zPos)
               if zPos<-40:
                  self.isGameOver=1
                             
      self.prevX=curX
      self.prevY=curY
      self.score=self.score+1
      self.textScore.setText('\1red\1\1slant\1Score : '+str(self.score))
      if(self.isGameOver==1):
         props = WindowProperties()
         props.setCursorHidden(False)
         base.win.requestProperties(props)
         self.imageObject = OnscreenImage(image = 'earth.jpg', pos = (0, 1, 0))
         self.imageObject.setScale(1.9,1,1)
         self.textObject = OnscreenText(text = '\1red\1\1roman\1\1slant\1Space Collector', pos = (-0.6, 0.4), scale = 0.2)
         self.b = DirectButton(text = ("Start", "Start", "Start", "disabled"),command=self.beginGame)
         self.b.setScale(0.1,0.1,0.1)
         self.b.setPos(0.7,0,-0.8)
         self.ship.setPos(0,0,0)
         self.zPosition=0
         self.prevY=0
         self.prevX=0
         self.collided=1
         self.jumpTime=0
         self.jumpOn=0
         self.curZ=0
         self.interval=0
         self.zPosition=0
         self.isGameOver=0
         self.score=0
         self.acceleration=0
         self.velocity=0
         self.yPos=0
         self.score=0
         self.timer=120
         self.textTimer.destroy()
         self.textScore.destroy()
         for x in self.junk:
               if(x!=None):
                       x.detachNode()
                       x=None
                       print 'destroyed'
         self.loadJunk()
      else:
         return Task.cont

   def jump(self):
      self.jumpOn=1
      self.ignore("mouse1")
Пример #44
0
class ChargeProjectile(DirectObject):
    
    dur = 2
    delta = .15
    flag = False
    
    def __init__(self, spawn, taregt, id):
        
        self.projectileNode = NodePath('projectile'+str(id))
        self.projectileNode.reparentTo(render)

        self.projectileNode.setPos(spawn,0,-10, 0)
        self.projectileNode.setScale(1.5)
        self.projectileModel = Actor("./resources/sphereShot",{"grow":"./resources/sphereShot-grow"})
        self.projectileModel.setColorScale(200, 0, 255, 100)
        self.projectileModel.reparentTo(self.projectileNode)
        self.projectileNode.setHpr(spawn, 0, 0, 0)


        dir = render.getRelativeVector(spawn, Vec3(0, 1, 0))
        self.vec = dir*-100
        cs = CollisionSphere(0, 0, 0, 2.5)
        cnodepath = self.projectileNode.attachNewNode(CollisionNode('projNode'))
        cnodepath.node().addSolid(cs)
        self.collHand = CollisionHandlerEvent()
        self.collHand.addInPattern('bossProjectileinto'+str(id))
        self.collHand.addOutPattern('outof')
        base.cTrav.addCollider(cnodepath, self.collHand)
        self.acceptOnce('bossProjectileinto'+str(id), self.hit)
        self.damage = 15


    def moveTask(self, task):    
        
        if self.flag:
            return task.done
        
        velx = self.vec.x*self.delta
        vely = self.vec.y*self.delta
        velz = self.vec.z*self.delta
        x = self.projectileNode.getX()
        y = self.projectileNode.getY()
        z = self.projectileNode.getZ()
        self.projectileNode.setPos(x+velx, y+vely, z+velz)

        if task.time < self.dur:
        
            return task.cont
        else:
            
            self.flag = True
            return task.done

    def hit(self, collEntry):
        
        #throw out a custom message for what hit
        if collEntry.getIntoNodePath().getName() != 'projNode':
           
            temp = collEntry.getIntoNodePath().getName()
            print temp
            messenger.send(temp, [self.damage]) 
            
            #remove the impacting projectile
            collEntry.getFromNodePath().getParent().getParent().removeNode()
            self.flag =  True
            del self

    def wait(self, task):

        if task.time > 2.24:
            return task.done
	    
        return task.cont
Пример #45
0
class CogdoFlyingCollisions(GravityWalker):
    wantFloorSphere = 0

    def __init__(self):
        GravityWalker.__init__(self, gravity=0.0)

    def initializeCollisions(self,
                             collisionTraverser,
                             avatarNodePath,
                             avatarRadius=1.4,
                             floorOffset=1.0,
                             reach=1.0):
        self.cHeadSphereNodePath = None
        self.cFloorEventSphereNodePath = None
        self.setupHeadSphere(avatarNodePath)
        self.setupFloorEventSphere(avatarNodePath,
                                   ToontownGlobals.FloorEventBitmask,
                                   avatarRadius)
        GravityWalker.initializeCollisions(self, collisionTraverser,
                                           avatarNodePath, avatarRadius,
                                           floorOffset, reach)
        return

    def setupWallSphere(self, bitmask, avatarRadius):
        self.avatarRadius = avatarRadius
        cSphere = CollisionSphere(0.0, 0.0, self.avatarRadius + 0.75,
                                  self.avatarRadius)
        cSphereNode = CollisionNode('Flyer.cWallSphereNode')
        cSphereNode.addSolid(cSphere)
        cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
        cSphereNode.setFromCollideMask(bitmask)
        cSphereNode.setIntoCollideMask(BitMask32.allOff())
        if config.GetBool('want-fluid-pusher', 0):
            self.pusher = CollisionHandlerFluidPusher()
        else:
            self.pusher = CollisionHandlerPusher()
        self.pusher.addCollider(cSphereNodePath, self.avatarNodePath)
        self.cWallSphereNodePath = cSphereNodePath

    def setupEventSphere(self, bitmask, avatarRadius):
        self.avatarRadius = avatarRadius
        cSphere = CollisionSphere(0.0, 0.0, self.avatarRadius + 0.75,
                                  self.avatarRadius * 1.04)
        cSphere.setTangible(0)
        cSphereNode = CollisionNode('Flyer.cEventSphereNode')
        cSphereNode.addSolid(cSphere)
        cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
        cSphereNode.setFromCollideMask(bitmask)
        cSphereNode.setIntoCollideMask(BitMask32.allOff())
        self.event = CollisionHandlerEvent()
        self.event.addInPattern('enter%in')
        self.event.addOutPattern('exit%in')
        self.cEventSphereNodePath = cSphereNodePath

    def setupRay(self, bitmask, floorOffset, reach):
        cRay = CollisionRay(0.0, 0.0, 3.0, 0.0, 0.0, -1.0)
        cRayNode = CollisionNode('Flyer.cRayNode')
        cRayNode.addSolid(cRay)
        self.cRayNodePath = self.avatarNodePath.attachNewNode(cRayNode)
        cRayNode.setFromCollideMask(bitmask)
        cRayNode.setIntoCollideMask(BitMask32.allOff())
        self.lifter = CollisionHandlerGravity()
        self.lifter.setLegacyMode(self._legacyLifter)
        self.lifter.setGravity(self.getGravity(0))
        self.lifter.addInPattern('%fn-enter-%in')
        self.lifter.addAgainPattern('%fn-again-%in')
        self.lifter.addOutPattern('%fn-exit-%in')
        self.lifter.setOffset(floorOffset)
        self.lifter.setReach(reach)
        self.lifter.addCollider(self.cRayNodePath, self.avatarNodePath)

    def setupHeadSphere(self, avatarNodePath):
        collSphere = CollisionSphere(0, 0, 0, 1)
        collSphere.setTangible(1)
        collNode = CollisionNode('Flyer.cHeadCollSphere')
        collNode.setFromCollideMask(ToontownGlobals.CeilingBitmask)
        collNode.setIntoCollideMask(BitMask32.allOff())
        collNode.addSolid(collSphere)
        self.cHeadSphereNodePath = avatarNodePath.attachNewNode(collNode)
        self.cHeadSphereNodePath.setZ(base.localAvatar.getHeight() + 1.0)
        self.headCollisionEvent = CollisionHandlerEvent()
        self.headCollisionEvent.addInPattern('%fn-enter-%in')
        self.headCollisionEvent.addOutPattern('%fn-exit-%in')
        base.cTrav.addCollider(self.cHeadSphereNodePath,
                               self.headCollisionEvent)

    def setupFloorEventSphere(self, avatarNodePath, bitmask, avatarRadius):
        cSphere = CollisionSphere(0.0, 0.0, 0.0, 0.75)
        cSphereNode = CollisionNode('Flyer.cFloorEventSphere')
        cSphereNode.addSolid(cSphere)
        cSphereNodePath = avatarNodePath.attachNewNode(cSphereNode)
        cSphereNode.setFromCollideMask(bitmask)
        cSphereNode.setIntoCollideMask(BitMask32.allOff())
        self.floorCollisionEvent = CollisionHandlerEvent()
        self.floorCollisionEvent.addInPattern('%fn-enter-%in')
        self.floorCollisionEvent.addAgainPattern('%fn-again-%in')
        self.floorCollisionEvent.addOutPattern('%fn-exit-%in')
        base.cTrav.addCollider(cSphereNodePath, self.floorCollisionEvent)
        self.cFloorEventSphereNodePath = cSphereNodePath

    def deleteCollisions(self):
        GravityWalker.deleteCollisions(self)
        if self.cHeadSphereNodePath != None:
            base.cTrav.removeCollider(self.cHeadSphereNodePath)
            self.cHeadSphereNodePath.detachNode()
            self.cHeadSphereNodePath = None
            self.headCollisionsEvent = None
        if self.cFloorEventSphereNodePath != None:
            base.cTrav.removeCollider(self.cFloorEventSphereNodePath)
            self.cFloorEventSphereNodePath.detachNode()
            self.cFloorEventSphereNodePath = None
            self.floorCollisionEvent = None
        self.cRayNodePath.detachNode()
        del self.cRayNodePath
        self.cEventSphereNodePath.detachNode()
        del self.cEventSphereNodePath
        return

    def setCollisionsActive(self, active=1):
        if self.collisionsActive != active:
            if self.cHeadSphereNodePath != None:
                base.cTrav.removeCollider(self.cHeadSphereNodePath)
                if active:
                    base.cTrav.addCollider(self.cHeadSphereNodePath,
                                           self.headCollisionEvent)
            if self.cFloorEventSphereNodePath != None:
                base.cTrav.removeCollider(self.cFloorEventSphereNodePath)
                if active:
                    base.cTrav.addCollider(self.cFloorEventSphereNodePath,
                                           self.floorCollisionEvent)
        GravityWalker.setCollisionsActive(self, active)
        return

    def enableAvatarControls(self):
        pass

    def disableAvatarControls(self):
        pass

    def handleAvatarControls(self, task):
        pass
Пример #46
0
class DistributedGolfSpot(DistributedObject.DistributedObject, FSM.FSM):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGolfSpot')
    positions = ((-45, 100, GolfGlobals.GOLF_BALL_RADIUS),
     (-15, 100, GolfGlobals.GOLF_BALL_RADIUS),
     (15, 100, GolfGlobals.GOLF_BALL_RADIUS),
     (45, 100, GolfGlobals.GOLF_BALL_RADIUS))
    toonGolfOffsetPos = Point3(-2, 0, -GolfGlobals.GOLF_BALL_RADIUS)
    toonGolfOffsetHpr = Point3(-90, 0, 0)
    rotateSpeed = 20
    golfPowerSpeed = base.config.GetDouble('golf-power-speed', 3)
    golfPowerExponent = base.config.GetDouble('golf-power-exponent', 0.75)

    def __init__(self, cr):
        DistributedObject.DistributedObject.__init__(self, cr)
        FSM.FSM.__init__(self, 'DistributedGolfSpot')
        self.boss = None
        self.index = None
        self.avId = 0
        self.toon = None
        self.golfSpotSmoother = SmoothMover()
        self.golfSpotSmoother.setSmoothMode(SmoothMover.SMOn)
        self.smoothStarted = 0
        self.__broadcastPeriod = 0.2
        if self.index > len(self.positions):
            self.notify.error('Invalid index %d' % index)
        self.fadeTrack = None
        self.setupPowerBar()
        self.aimStart = None
        self.golfSpotAdviceLabel = None
        self.changeSeq = 0
        self.lastChangeSeq = 0
        self.controlKeyAllowed = False
        self.flyBallTracks = {}
        self.splatTracks = {}
        self.__flyBallBubble = None
        self.flyBallHandler = None
        self.__flyBallSequenceNum = 0
        self.swingInterval = None
        self.lastHitSequenceNum = -1
        self.goingToReward = False
        self.gotHitByBoss = False
        self.releaseTrack = None
        self.grabTrack = None
        self.restoreScaleTrack = None
        return

    def setBossCogId(self, bossCogId):
        self.bossCogId = bossCogId
        self.boss = base.cr.doId2do[bossCogId]
        self.boss.setGolfSpot(self, self.index)

    def setIndex(self, index):
        self.index = index

    def disable(self):
        DistributedObject.DistributedObject.disable(self)
        self.ignoreAll()

    def delete(self):
        DistributedObject.DistributedObject.delete(self)
        self.ignoreAll()
        self.boss = None
        return

    def announceGenerate(self):
        DistributedObject.DistributedObject.announceGenerate(self)
        self.triggerName = self.uniqueName('trigger')
        self.triggerEvent = 'enter%s' % self.triggerName
        self.smoothName = self.uniqueName('golfSpotSmooth')
        self.golfSpotAdviceName = self.uniqueName('golfSpotAdvice')
        self.posHprBroadcastName = self.uniqueName('golfSpotBroadcast')
        self.ballPowerTaskName = self.uniqueName('updateGolfPower')
        self.adjustClubTaskName = self.uniqueName('adjustClub')
        self.loadAssets()
        self.accept('flyBallHit-%d' % self.index, self.__flyBallHit)

    def loadAssets(self):
        self.root = render.attachNewNode('golfSpot-%d' % self.index)
        self.root.setPos(*self.positions[self.index])
        self.ballModel = loader.loadModel('phase_6/models/golf/golf_ball')
        self.ballColor = VBase4(1, 1, 1, 1)
        if self.index < len(GolfGlobals.PlayerColors):
            self.ballColor = VBase4(*GolfGlobals.PlayerColors[self.index])
            self.ballModel.setColorScale(self.ballColor)
        self.ballModel.reparentTo(self.root)
        self.club = loader.loadModel('phase_6/models/golf/putter')
        self.clubLookatSpot = self.root.attachNewNode('clubLookat')
        self.clubLookatSpot.setY(-(GolfGlobals.GOLF_BALL_RADIUS + 0.1))
        cs = CollisionSphere(0, 0, 0, 1)
        cs.setTangible(0)
        cn = CollisionNode(self.triggerName)
        cn.addSolid(cs)
        cn.setIntoCollideMask(ToontownGlobals.WallBitmask)
        self.trigger = self.root.attachNewNode(cn)
        self.trigger.stash()
        self.hitBallSfx = loader.loadSfx('phase_6/audio/sfx/Golf_Hit_Ball.ogg')

    def cleanup(self):
        if self.swingInterval:
            self.swingInterval.finish()
            self.swingInterval = None
        if self.releaseTrack:
            self.releaseTrack.finish()
            self.releaseTrack = None
        flyTracks = self.flyBallTracks.values()
        for track in flyTracks:
            track.finish()

        if self.fadeTrack:
            self.fadeTrack.finish()
            self.fadeTrack = None
        if self.restoreScaleTrack:
            self.restoreScaleTrack.finish()
            self.restoreScaleTrack = None
        self.root.removeNode()
        self.ballModel.removeNode()
        self.club.removeNode()
        if self.powerBar:
            self.powerBar.destroy()
            self.powerBar = None
        taskMgr.remove(self.triggerName)
        self.boss = None
        return

    def setState(self, state, avId, extraInfo):
        if not self.isDisabled():
            self.gotHitByBoss = extraInfo
            if state == 'C':
                self.demand('Controlled', avId)
            elif state == 'F':
                self.demand('Free')
            elif state == 'O':
                self.demand('Off')
            else:
                self.notify.error('Invalid state from AI: %s' % state)

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def enterFree(self):
        if self.fadeTrack:
            self.fadeTrack.finish()
            self.fadeTrack = None
        self.restoreScaleTrack = Sequence(Wait(6), self.getRestoreScaleInterval(), name='restoreScaleTrack')
        self.restoreScaleTrack.start()
        if self.avId == localAvatar.doId:
            if not self.isDisabled():
                self.ballModel.setAlphaScale(0.3)
                self.ballModel.setTransparency(1)
                taskMgr.doMethodLater(5, self.__allowDetect, self.triggerName)
                self.fadeTrack = Sequence(Func(self.ballModel.setTransparency, 1), self.ballModel.colorScaleInterval(0.2, VBase4(1, 1, 1, 0.3)), name='fadeTrack-enterFree')
                self.fadeTrack.start()
        else:
            self.trigger.unstash()
            self.accept(self.triggerEvent, self.__hitTrigger)
        self.avId = 0
        return

    def exitFree(self):
        if self.fadeTrack:
            self.fadeTrack.finish()
            self.fadeTrack = None
        self.restoreScaleTrack.finish()
        self.restoreScaleTrack = None
        taskMgr.remove(self.triggerName)
        self.ballModel.clearTransparency()
        self.trigger.stash()
        self.ignore(self.triggerEvent)
        return

    def enterControlled(self, avId):
        self.avId = avId
        toon = base.cr.doId2do.get(avId)
        if not toon:
            return
        self.enableControlKey()
        self.toon = toon
        self.grabTrack = self.makeToonGrabInterval(toon)
        if avId == localAvatar.doId:
            self.boss.toCraneMode()
            camera.reparentTo(self.root)
            camera.setPosHpr(0, -10, 3, 0, 0, 0)
            localAvatar.setPos(self.root, self.toonGolfOffsetPos)
            localAvatar.setHpr(self.root, self.toonGolfOffsetHpr)
            localAvatar.sendCurrentPosition()
            self.__enableControlInterface()
            self.startPosHprBroadcast()
            self.accept('exitCrane', self.gotBossZapped)
        self.grabTrack.start()

    def exitControlled(self):
        self.grabTrack.finish()
        del self.grabTrack
        if self.swingInterval:
            self.swingInterval.finish()
            self.swingInterval = None
        if not self.ballModel.isEmpty():
            if self.ballModel.isHidden():
                self.notify.debug('ball is hidden scale =%s' % self.ballModel.getScale())
            else:
                self.notify.debug('ball is showing scale=%s' % self.ballModel.getScale())
        if self.toon and not self.toon.isDisabled():
            self.toon.startSmooth()
        self.releaseTrack = self.makeToonReleaseInterval(self.toon)
        self.stopPosHprBroadcast()
        self.stopSmooth()
        if self.avId == localAvatar.doId:
            self.__disableControlInterface()
            if not self.goingToReward:
                camera.reparentTo(base.localAvatar)
                camera.setPos(base.localAvatar.cameraPositions[0][0])
                camera.setHpr(0, 0, 0)
        self.stopAdjustClubTask()
        self.releaseTrack.start()
        self.enableControlKey()
        return

    def __allowDetect(self, task):
        if self.fadeTrack:
            self.fadeTrack.finish()
        self.fadeTrack = Sequence(self.ballModel.colorScaleInterval(0.2, self.ballColor), Func(self.ballModel.clearTransparency), name='fadeTrack-allowDetect')
        self.fadeTrack.start()
        self.trigger.unstash()
        self.accept(self.triggerEvent, self.__hitTrigger)

    def __hitTrigger(self, event):
        self.d_requestControl()

    def getRestoreScaleInterval(self):
        return Sequence()

    def d_requestControl(self):
        self.sendUpdate('requestControl')

    def d_requestFree(self, gotHitByBoss):
        self.sendUpdate('requestFree', [gotHitByBoss])

    def makeToonGrabInterval(self, toon):
        origPos = toon.getPos(self.root)
        origHpr = toon.getHpr(self.root)
        a = self.accomodateToon(toon)
        newPos = toon.getPos()
        newHpr = toon.getHpr()
        origHpr.setX(PythonUtil.fitSrcAngle2Dest(origHpr[0], newHpr[0]))
        self.notify.debug('toon.setPosHpr %s %s' % (origPos, origHpr))
        toon.setPosHpr(origPos, origHpr)
        walkTime = 0.2
        reach = Sequence()
        if reach.getDuration() < walkTime:
            reach = Sequence(ActorInterval(toon, 'walk', loop=1, duration=walkTime - reach.getDuration()), reach)
        i = Sequence(Parallel(toon.posInterval(walkTime, newPos, origPos), toon.hprInterval(walkTime, newHpr, origHpr), reach), Func(toon.stopLookAround))
        if toon == base.localAvatar:
            i.append(Func(self.switchToAnimState, 'GolfPuttLoop'))
        i.append(Func(self.startAdjustClubTask))
        i = Parallel(i, a)
        return i

    def accomodateToon(self, toon):
        toon.wrtReparentTo(self.root)
        toon.setPos(self.toonGolfOffsetPos)
        toon.setHpr(self.toonGolfOffsetHpr)
        return Sequence()

    def switchToAnimState(self, animStateName, forced = False):
        curAnimState = base.localAvatar.animFSM.getCurrentState()
        curAnimStateName = ''
        if curAnimState:
            curAnimStateName = curAnimState.getName()
        if curAnimStateName != animStateName or forced:
            base.localAvatar.b_setAnimState(animStateName)

    def __enableControlInterface(self):
        gui = loader.loadModel('phase_3.5/models/gui/avatar_panel_gui')
        self.closeButton = DirectButton(image=(gui.find('**/CloseBtn_UP'),
         gui.find('**/CloseBtn_DN'),
         gui.find('**/CloseBtn_Rllvr'),
         gui.find('**/CloseBtn_UP')), relief=None, scale=2, text=TTLocalizer.BossbotGolfSpotLeave, text_scale=0.04, text_pos=(0, -0.07), text_fg=VBase4(1, 1, 1, 1), pos=(1.05, 0, -0.82), command=self.__exitGolfSpot)
        self.accept('escape', self.__exitGolfSpot)
        self.accept('control', self.__controlPressed)
        self.accept('control-up', self.__controlReleased)
        self.accept('InputState-forward', self.__upArrow)
        self.accept('InputState-reverse', self.__downArrow)
        self.accept('InputState-turnLeft', self.__leftArrow)
        self.accept('InputState-turnRight', self.__rightArrow)
        taskMgr.add(self.__watchControls, 'watchGolfSpotControls')
        taskMgr.doMethodLater(5, self.__displayGolfSpotAdvice, self.golfSpotAdviceName)
        self.arrowVert = 0
        self.arrowHorz = 0
        if self.powerBar:
            self.powerBar.show()
        return

    def __disableControlInterface(self):
        if self.closeButton:
            self.closeButton.destroy()
            self.closeButton = None
        self.__cleanupGolfSpotAdvice()
        self.ignore('escape')
        self.ignore('control')
        self.ignore('control-up')
        self.ignore('InputState-forward')
        self.ignore('InputState-reverse')
        self.ignore('InputState-turnLeft')
        self.ignore('InputState-turnRight')
        self.arrowVert = 0
        self.arrowHorz = 0
        taskMgr.remove('watchGolfSpotControls')
        if self.powerBar:
            self.powerBar.hide()
        else:
            self.notify.debug('self.powerBar is none')
        return

    def setupPowerBar(self):
        self.powerBar = DirectWaitBar(pos=(0.0, 0, -0.94), relief=DGG.SUNKEN, frameSize=(-2.0,
         2.0,
         -0.2,
         0.2), borderWidth=(0.02, 0.02), scale=0.25, range=100, sortOrder=50, frameColor=(0.5, 0.5, 0.5, 0.5), barColor=(1.0, 0.0, 0.0, 1.0), text='', text_scale=0.26, text_fg=(1, 1, 1, 1), text_align=TextNode.ACenter, text_pos=(0, -0.05))
        self.power = 0
        self.powerBar['value'] = self.power
        self.powerBar.hide()

    def resetPowerBar(self):
        self.power = 0
        self.powerBar['value'] = self.power
        self.powerBar['text'] = ''

    def __displayGolfSpotAdvice(self, task):
        if self.golfSpotAdviceLabel == None:
            self.golfSpotAdviceLabel = DirectLabel(text=TTLocalizer.BossbotGolfSpotAdvice, text_fg=VBase4(1, 1, 1, 1), text_align=TextNode.ACenter, relief=None, pos=(0, 0, 0.69), scale=0.1)
        return

    def __cleanupGolfSpotAdvice(self):
        if self.golfSpotAdviceLabel:
            self.golfSpotAdviceLabel.destroy()
            self.golfSpotAdviceLabel = None
        taskMgr.remove(self.golfSpotAdviceName)
        return

    def showExiting(self):
        if self.closeButton:
            self.closeButton.destroy()
            self.closeButton = DirectLabel(relief=None, text=TTLocalizer.BossbotGolfSpotLeaving, pos=(1.05, 0, -0.88), text_pos=(0, 0), text_scale=0.06, text_fg=VBase4(1, 1, 1, 1))
        self.__cleanupGolfSpotAdvice()
        return

    def __exitGolfSpot(self):
        self.d_requestFree(False)

    def __controlPressed(self):
        if self.controlKeyAllowed:
            self.__beginFireBall()

    def __controlReleased(self):
        if self.controlKeyAllowed:
            self.__endFireBall()

    def __upArrow(self, pressed):
        self.__incrementChangeSeq()
        self.__cleanupGolfSpotAdvice()
        if pressed:
            self.arrowVert = 1
        elif self.arrowVert > 0:
            self.arrowVert = 0

    def __downArrow(self, pressed):
        self.__incrementChangeSeq()
        self.__cleanupGolfSpotAdvice()
        if pressed:
            self.arrowVert = -1
        elif self.arrowVert < 0:
            self.arrowVert = 0

    def __rightArrow(self, pressed):
        self.__incrementChangeSeq()
        self.__cleanupGolfSpotAdvice()
        if pressed:
            self.arrowHorz = 1
            self.switchToAnimState('GolfRotateLeft')
        elif self.arrowHorz > 0:
            self.arrowHorz = 0
            self.switchToAnimState('GolfPuttLoop')

    def __leftArrow(self, pressed):
        self.__incrementChangeSeq()
        self.__cleanupGolfSpotAdvice()
        if pressed:
            self.arrowHorz = -1
            self.switchToAnimState('GolfRotateRight')
        elif self.arrowHorz < 0:
            self.arrowHorz = 0
            self.switchToAnimState('GolfPuttLoop')

    def __watchControls(self, task):
        if self.arrowHorz:
            self.__moveGolfSpot(self.arrowHorz)
        return Task.cont

    def __moveGolfSpot(self, xd):
        dt = globalClock.getDt()
        h = self.root.getH() - xd * self.rotateSpeed * dt
        h %= 360
        limitH = h
        self.root.setH(limitH)

    def __incrementChangeSeq(self):
        self.changeSeq = self.changeSeq + 1 & 255

    def __beginFireBall(self):
        if self.aimStart != None:
            return
        if not self.state_ == 'Controlled':
            return
        if not self.avId == localAvatar.doId:
            return
        time = globalClock.getFrameTime()
        self.aimStart = time
        messenger.send('wakeup')
        taskMgr.add(self.__updateBallPower, self.ballPowerTaskName)
        return

    def __endFireBall(self):
        if self.aimStart == None:
            return
        if not self.state_ == 'Controlled':
            return
        if not self.avId == localAvatar.doId:
            return
        taskMgr.remove(self.ballPowerTaskName)
        self.disableControlKey()
        messenger.send('wakeup')
        self.aimStart = None
        power = self.power
        angle = self.root.getH()
        self.notify.debug('incrementing self.__flyBallSequenceNum')
        self.__flyBallSequenceNum = (self.__flyBallSequenceNum + 1) % 255
        self.sendSwingInfo(power, angle, self.__flyBallSequenceNum)
        self.setSwingInfo(power, angle, self.__flyBallSequenceNum)
        self.resetPowerBar()
        return

    def __updateBallPower(self, task):
        if not self.powerBar:
            print '### no power bar!!!'
            return task.done
        newPower = self.__getBallPower(globalClock.getFrameTime())
        self.power = newPower
        self.powerBar['value'] = newPower
        return task.cont

    def __getBallPower(self, time):
        elapsed = max(time - self.aimStart, 0.0)
        t = elapsed / self.golfPowerSpeed
        t = math.pow(t, self.golfPowerExponent)
        power = int(t * 100) % 200
        if power > 100:
            power = 200 - power
        return power

    def stopPosHprBroadcast(self):
        taskName = self.posHprBroadcastName
        taskMgr.remove(taskName)

    def startPosHprBroadcast(self):
        taskName = self.posHprBroadcastName
        self.b_clearSmoothing()
        self.d_sendGolfSpotPos()
        taskMgr.remove(taskName)
        taskMgr.doMethodLater(self.__broadcastPeriod, self.__posHprBroadcast, taskName)

    def __posHprBroadcast(self, task):
        self.d_sendGolfSpotPos()
        taskName = self.posHprBroadcastName
        taskMgr.doMethodLater(self.__broadcastPeriod, self.__posHprBroadcast, taskName)
        return Task.done

    def d_sendGolfSpotPos(self):
        timestamp = globalClockDelta.getFrameNetworkTime()
        self.sendUpdate('setGolfSpotPos', [self.changeSeq, self.root.getH(), timestamp])

    def setGolfSpotPos(self, changeSeq, h, timestamp):
        self.changeSeq = changeSeq
        if self.smoothStarted:
            now = globalClock.getFrameTime()
            local = globalClockDelta.networkToLocalTime(timestamp, now)
            self.golfSpotSmoother.setH(h)
            self.golfSpotSmoother.setTimestamp(local)
            self.golfSpotSmoother.markPosition()
        else:
            self.root.setH(h)

    def b_clearSmoothing(self):
        self.d_clearSmoothing()
        self.clearSmoothing()

    def d_clearSmoothing(self):
        self.sendUpdate('clearSmoothing', [0])

    def clearSmoothing(self, bogus = None):
        self.golfSpotSmoother.clearPositions(1)

    def doSmoothTask(self, task):
        self.golfSpotSmoother.computeAndApplySmoothHpr(self.root)
        return Task.cont

    def startSmooth(self):
        if not self.smoothStarted:
            taskName = self.smoothName
            taskMgr.remove(taskName)
            self.reloadPosition()
            taskMgr.add(self.doSmoothTask, taskName)
            self.smoothStarted = 1

    def stopSmooth(self):
        if self.smoothStarted:
            taskName = self.smoothName
            taskMgr.remove(taskName)
            self.forceToTruePosition()
            self.smoothStarted = 0

    def makeToonReleaseInterval(self, toon):

        def getSlideToPos(toon = toon):
            return render.getRelativePoint(toon, Point3(0, -5, 0))

        if self.gotHitByBoss:
            grabIval = Sequence(Func(self.detachClub), name='makeToonReleaseInterval-gotHitByBoss')
            if not toon.isEmpty():
                toonIval = Sequence(Func(toon.wrtReparentTo, render), Parallel(ActorInterval(toon, 'slip-backward'), toon.posInterval(0.5, getSlideToPos, fluid=1)), name='makeToonReleaseInterval-toonIval')
                grabIval.append(toonIval)
        else:
            grabIval = Sequence(Func(self.detachClub))
            if not toon.isEmpty():
                toonIval = Sequence(Parallel(ActorInterval(toon, 'walk', duration=1.0, playRate=-1.0), LerpPosInterval(toon, duration=1.0, pos=Point3(-10, 0, 0))), Func(toon.wrtReparentTo, render))
                grabIval.append(toonIval)
        if localAvatar.doId == toon.doId:
            if not self.goingToReward and toon.hp > 0:
                grabIval.append(Func(self.goToFinalBattle))
                grabIval.append(Func(self.notify.debug, 'goingToFinalBattlemode'))
                grabIval.append(Func(self.safeBossToFinalBattleMode))
        return grabIval

    def safeBossToFinalBattleMode(self):
        if self.boss:
            self.boss.toFinalBattleMode()

    def goToFinalBattle(self):
        if self.cr:
            place = self.cr.playGame.getPlace()
            if place and hasattr(place, 'fsm'):
                curState = place.fsm.getCurrentState().getName()
                if place.fsm.getCurrentState().getName() == 'crane':
                    place.setState('finalBattle')
                else:
                    self.notify.debug('NOT going to final battle, state=%s' % curState)

    def attachClub(self, avId, pointToBall = False):
        club = self.club
        if club:
            av = base.cr.doId2do.get(avId)
            if av:
                av.useLOD(1000)
                lHand = av.getLeftHands()[0]
                club.setPos(0, 0, 0)
                club.reparentTo(lHand)
                netScale = club.getNetTransform().getScale()[1]
                counterActToonScale = lHand.find('**/counteractToonScale')
                if counterActToonScale.isEmpty():
                    counterActToonScale = lHand.attachNewNode('counteractToonScale')
                    counterActToonScale.setScale(1 / netScale)
                    self.notify.debug('creating counterActToonScale for %s' % av.getName())
                club.reparentTo(counterActToonScale)
                club.setX(-0.25 * netScale)
                if pointToBall:
                    club.lookAt(self.clubLookatSpot)

    def detachClub(self):
        if not self.club.isEmpty():
            self.club.reparentTo(self.root)
            self.club.setZ(-20)
            self.club.setScale(1)

    def adjustClub(self):
        club = self.club
        if club:
            distance = club.getDistance(self.clubLookatSpot)
            scaleFactor = distance / 2.058
            club.setScale(1, scaleFactor, 1)

    def startAdjustClubTask(self):
        taskMgr.add(self.adjustClubTask, self.adjustClubTaskName)

    def stopAdjustClubTask(self):
        taskMgr.remove(self.adjustClubTaskName)

    def adjustClubTask(self, task):
        self.attachClub(self.avId, True)
        self.adjustClub()
        return task.cont

    def enableControlKey(self):
        self.controlKeyAllowed = True

    def disableControlKey(self):
        self.controlKeyAllowed = False

    def sendSwingInfo(self, power, angle, sequenceNum):
        self.sendUpdate('setSwingInfo', [power, angle, sequenceNum])

    def startBallPlayback(self, power, angle, sequenceNum):
        flyBall = self.ballModel.copyTo(NodePath())
        flyBall.setScale(1.0)
        flyBallBubble = self.getFlyBallBubble().instanceTo(NodePath())
        flyBallBubble.reparentTo(flyBall)
        flyBall.setTag('pieSequence', str(sequenceNum))
        flyBall.setTag('throwerId', str(self.avId))
        t = power / 100.0
        t = 1.0 - t
        dist = 300 - 200 * t
        time = 1.5 + 0.5 * t
        proj = ProjectileInterval(None, startPos=Point3(0, 0, 0), endPos=Point3(0, dist, 0), duration=time)
        relVel = proj.startVel

        def getVelocity(root = self.root, relVel = relVel):
            return render.getRelativeVector(root, relVel)

        fly = Sequence(Func(flyBall.reparentTo, render), Func(flyBall.setPosHpr, self.root, 0, 0, 0, 0, 0, 0), Func(base.cTrav.addCollider, flyBallBubble, self.flyBallHandler), ProjectileInterval(flyBall, startVel=getVelocity, duration=3), Func(flyBall.detachNode), Func(base.cTrav.removeCollider, flyBallBubble), Func(self.notify.debug, 'removed collider'), Func(self.flyBallFinishedFlying, sequenceNum))
        flyWithSound = Parallel(fly, SoundInterval(self.hitBallSfx, node=self.root), name='flyWithSound')
        self.notify.debug('starting flyball track')
        flyWithSound.start()
        self.flyBallTracks[sequenceNum] = flyWithSound
        return

    def setSwingInfo(self, power, angle, sequenceNum):
        av = base.cr.doId2do.get(self.avId)
        self.swingInterval = Sequence()
        if av:
            self.stopAdjustClubTask()
            self.swingInterval = Sequence(ActorInterval(av, 'swing-putt', startFrame=0, endFrame=GolfGlobals.BALL_CONTACT_FRAME), Func(self.startBallPlayback, power, angle, sequenceNum), Func(self.ballModel.hide), ActorInterval(av, 'swing-putt', startFrame=GolfGlobals.BALL_CONTACT_FRAME, endFrame=24), Func(self.ballModel.setScale, 0.1), Func(self.ballModel.show), LerpScaleInterval(self.ballModel, 1.0, Point3(1, 1, 1)), Func(self.enableControlKey))
            if av == localAvatar:
                self.swingInterval.append(Func(self.switchToAnimState, 'GolfPuttLoop', True))
        self.swingInterval.start()

    def getFlyBallBubble(self):
        if self.__flyBallBubble == None:
            bubble = CollisionSphere(0, 0, 0, GolfGlobals.GOLF_BALL_RADIUS)
            node = CollisionNode('flyBallBubble')
            node.addSolid(bubble)
            node.setFromCollideMask(ToontownGlobals.PieBitmask | ToontownGlobals.CameraBitmask | ToontownGlobals.FloorBitmask)
            node.setIntoCollideMask(BitMask32.allOff())
            self.__flyBallBubble = NodePath(node)
            self.flyBallHandler = CollisionHandlerEvent()
            self.flyBallHandler.addInPattern('flyBallHit-%d' % self.index)
        return self.__flyBallBubble

    def __flyBallHit(self, entry):
        print entry

    def flyBallFinishedFlying(self, sequence):
        if sequence in self.flyBallTracks:
            del self.flyBallTracks[sequence]

    def __finishFlyBallTrack(self, sequence):
        if sequence in self.flyBallTracks:
            flyBallTrack = self.flyBallTracks[sequence]
            del self.flyBallTracks[sequence]
            flyBallTrack.finish()

    def flyBallFinishedSplatting(self, sequence):
        if sequence in self.splatTracks:
            del self.splatTracks[sequence]

    def __flyBallHit(self, entry):
        if not entry.hasSurfacePoint() or not entry.hasInto():
            return
        if not entry.getInto().isTangible():
            return
        sequence = int(entry.getFromNodePath().getNetTag('pieSequence'))
        self.__finishFlyBallTrack(sequence)
        if sequence in self.splatTracks:
            splatTrack = self.splatTracks[sequence]
            del self.splatTracks[sequence]
            splatTrack.finish()
        flyBallCode = 0
        flyBallCodeStr = entry.getIntoNodePath().getNetTag('pieCode')
        if flyBallCodeStr:
            flyBallCode = int(flyBallCodeStr)
        pos = entry.getSurfacePoint(render)
        timestamp32 = globalClockDelta.getFrameNetworkTime(bits=32)
        throwerId = int(entry.getFromNodePath().getNetTag('throwerId'))
        splat = self.getFlyBallSplatInterval(pos[0], pos[1], pos[2], flyBallCode, throwerId)
        splat = Sequence(splat, Func(self.flyBallFinishedSplatting, sequence))
        self.splatTracks[sequence] = splat
        splat.start()
        self.notify.debug('doId=%d into=%s flyBallCode=%d, throwerId=%d' % (self.doId,
         entry.getIntoNodePath(),
         flyBallCode,
         throwerId))
        if flyBallCode == ToontownGlobals.PieCodeBossCog and self.avId == localAvatar.doId and self.lastHitSequenceNum != self.__flyBallSequenceNum:
            self.lastHitSequenceNum = self.__flyBallSequenceNum
            self.boss.d_ballHitBoss(2)
        elif flyBallCode == ToontownGlobals.PieCodeToon and self.avId == localAvatar.doId and self.lastHitSequenceNum != self.__flyBallSequenceNum:
            self.lastHitSequenceNum = self.__flyBallSequenceNum
            avatarDoId = entry.getIntoNodePath().getNetTag('avatarDoId')
            if avatarDoId == '':
                self.notify.warning('Toon %s has no avatarDoId tag.' % repr(entry.getIntoNodePath()))
                return
            doId = int(avatarDoId)
            if doId != localAvatar.doId:
                pass

    def getFlyBallSplatInterval(self, x, y, z, flyBallCode, throwerId):
        from toontown.toonbase import ToontownBattleGlobals
        from toontown.battle import BattleProps
        splatName = 'dust'
        splat = BattleProps.globalPropPool.getProp(splatName)
        splat.setBillboardPointWorld(2)
        color = ToontownGlobals.PieCodeColors.get(flyBallCode)
        if color:
            splat.setColor(*color)
        if flyBallCode == ToontownGlobals.PieCodeBossCog:
            self.notify.debug('changing color to %s' % self.ballColor)
            splat.setColor(self.ballColor)
        sound = loader.loadSfx('phase_11/audio/sfx/LB_evidence_miss.ogg')
        vol = 1.0
        if flyBallCode == ToontownGlobals.PieCodeBossCog:
            sound = loader.loadSfx('phase_4/audio/sfx/Golf_Hit_Barrier_1.ogg')
        soundIval = SoundInterval(sound, node=splat, volume=vol)
        if flyBallCode == ToontownGlobals.PieCodeBossCog and localAvatar.doId == throwerId:
            vol = 1.0
            soundIval = SoundInterval(sound, node=localAvatar, volume=vol)
        ival = Parallel(Func(splat.reparentTo, render), Func(splat.setPos, x, y, z), soundIval, Sequence(ActorInterval(splat, splatName), Func(splat.detachNode)))
        return ival

    def setGoingToReward(self):
        self.goingToReward = True

    def gotBossZapped(self):
        self.showExiting()
        self.d_requestFree(True)