Beispiel #1
0
 def ship(self):
     an = ActorNode()
     an.getPhysicsObject().setMass(100)
     self.fighter = self.render.attachNewNode(an)
     self.physicsMgr.attachPhysicalNode(an)
     self.anpo = an.getPhysicsObject()
     fn = ForceNode("force-node-fighter")
     self.fighter.attachNewNode(fn)
     self.pft = LinearVectorForce(Vec3(0, +1, 0) * 500)  # forward thrust
     self.prt = LinearVectorForce(Vec3(0, -1, 0) * 500)  # reverse thrust
     self.pft.setMassDependent(1)
     self.prt.setMassDependent(1)
     self.pft.setActive(False)
     self.prt.setActive(False)
     fn.addForce(self.pft)
     fn.addForce(self.prt)
     an.getPhysical(0).addLinearForce(self.pft)
     an.getPhysical(0).addLinearForce(self.prt)
     self.camera.reparentTo(self.fighter)
     from_obj = self.fighter.attachNewNode(CollisionNode('fighter'))
     from_obj.node().setFromCollideMask(BitMask32(0x1))
     from_obj.setCollideMask(BitMask32(0x1))
     from_obj.node().addSolid(CollisionSphere(0, 0, 0, 1))
     # from_obj.show()
     self.pusher.addCollider(from_obj, self.fighter)
     self.cTrav.addCollider(from_obj, self.pusher)
Beispiel #2
0
 def __init__(self, base, name, speed, scale, color, mask, relA, xyz, relB, lookat, life):
     an = ActorNode()
     self.anp = base.render.attachNewNode(an)
     base.physicsMgr.attachPhysicalNode(an)
     self.anpo = an.getPhysicsObject()
     fn = ForceNode("force-missile")
     self.anp.attachNewNode(fn)
     bft = LinearVectorForce(Vec3(0, 1, 0)*speed)
     fn.addForce(bft)
     an.getPhysical(0).addLinearForce(bft)
     missile = base.loader.loadModel("./mdl/missile.egg")
     missile.setColor(color)
     missile.setScale(scale)
     missile.reparentTo(self.anp)
     missile.setTag(name, '1')
     missile_from_obj = missile.attachNewNode(CollisionNode(name))
     missile_from_obj.node().addSolid(CollisionSphere(0, 0, 0, 1))
     missile_from_obj.node().setFromCollideMask(mask)
     missile_from_obj.setCollideMask(mask)
     base.pusher.addCollider(missile_from_obj, self.anp)
     base.cTrav.addCollider(missile_from_obj, base.pusher)
     self.anp.setPos(relA, xyz)
     self.anp.lookAt(relB, lookat)
     # light the missile
     mlight = DirectionalLight('mlight')
     mlight.setColor(VBase4(1., 1., 1., 1))
     mlnp = base.render.attachNewNode(mlight)
     mlnp.setHpr(self.anp.getHpr())
     self.anp.setLightOff()
     self.anp.setLight(mlnp)
     # remove the missile
     base.taskMgr.doMethodLater(life, self.remove_missile, 'task-remove-missile', extraArgs=[self.anp], appendTask=True)
	def __init__(self, name):
		self.name = name
		self.cell_x = 0
		self.cell_y = 0
		self.vel = LPoint3(0, 0, 0)

		self.c_node = base.render.attachNewNode(
			self.name+"_camera_node")


		self.panda_actor = Actor("models/panda-model", {"walk": "models/panda-walk4"})
		self.panda_actor.setScale(0.05, 0.05, 0.05)

		self.p_node = NodePath(self.name+"_phys_node")
		self.p_node.reparentTo(render)

		self.an = ActorNode("panda-phys")
		self.anp = self.p_node.attachNewNode(self.an)
		base.enableParticles()
		base.physicsMgr.attachPhysicalNode(self.an)
		self.panda_actor.reparentTo(self.anp)

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

		base.physicsMgr.addLinearForce(self.gravityForce)


		self.c_node.reparentTo(self.panda_actor)
		self.c_node.setCompass()
		#self.panda_actor.reparentTo(base.render)
		base.camera.reparentTo(self.c_node)

		self.box = loader.loadModel("box.egg")
		self.box.setScale(100, 100, 100)
		self.box.setPos(-180, 0, 0)
		self.boxc = self.box.find("**/Cube")
		self.boxc.node().setIntoCollideMask(BitMask32.bit(0))
		self.boxc.node().setFromCollideMask(BitMask32.allOff())

		self.ban = ActorNode("box-phys")
		base.physicsMgr.attachPhysicalNode(self.ban)

		self.bp_node = NodePath(self.name+"_phys_node2")
		self.bp_node.reparentTo(render)

		self.banp = self.bp_node.attachNewNode(self.ban)
		self.box.reparentTo(self.banp)

		self.boxc.show()
Beispiel #4
0
    def shoot(self, pos, shootVec=None):
        if shootVec != None:
            v = shootVec
            v *= 214.0
        else:
            # Get from/to points from mouse click
            pMouse = base.mouseWatcherNode.getMouse()
            pFrom = Point3()
            pTo = Point3()
            base.camLens.extrude(pMouse, pFrom, pTo)

            pFrom = render.getRelativePoint(base.cam, pFrom)
            pTo = render.getRelativePoint(base.cam, pTo)

            # Calculate initial velocity
            v = pTo - pFrom
            v.normalize()
            v *= 214.0

        self.bulletNP.setPos(pos)
        self.bulletNP.reparentTo(render)
        self.bulletFN = ForceNode("Bullet-force-%d" % id(self))
        self.bulletFNP = self.bulletNP.attachNewNode(self.bulletFN)
        # speed of a paintball when he leafes the muzzle: 214 fps
        self.lvf = LinearVectorForce(v)
        self.lvf.setMassDependent(1)
        self.bulletFN.addForce(self.lvf)
        self.bulletAN.getPhysical(0).addLinearForce(self.lvf)

        self.accept("bulletCollision-%d-hit" % id(self), self.bulletHit)
        taskMgr.doMethodLater(
            2,
            self.doRemove,
            'doRemove-%d' % id(self),
            appendTask=True)
    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
Beispiel #6
0
    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)
Beispiel #7
0
 def __init__(self, base, name, speed, scale, color, mask, relA, xyz, relB,
              lookat, life):
     an = ActorNode()
     self.anp = base.render.attachNewNode(an)
     base.physicsMgr.attachPhysicalNode(an)
     self.anpo = an.getPhysicsObject()
     fn = ForceNode("force-missile")
     self.anp.attachNewNode(fn)
     bft = LinearVectorForce(Vec3(0, 1, 0) * speed)
     fn.addForce(bft)
     an.getPhysical(0).addLinearForce(bft)
     missile = base.loader.loadModel("./mdl/missile.egg")
     missile.setColor(color)
     missile.setScale(scale)
     missile.reparentTo(self.anp)
     missile.setTag(name, '1')
     missile_from_obj = missile.attachNewNode(CollisionNode(name))
     missile_from_obj.node().addSolid(CollisionSphere(0, 0, 0, 1))
     missile_from_obj.node().setFromCollideMask(mask)
     missile_from_obj.setCollideMask(mask)
     base.pusher.addCollider(missile_from_obj, self.anp)
     base.cTrav.addCollider(missile_from_obj, base.pusher)
     self.anp.setPos(relA, xyz)
     self.anp.lookAt(relB, lookat)
     # light the missile
     mlight = DirectionalLight('mlight')
     mlight.setColor(VBase4(1., 1., 1., 1))
     mlnp = base.render.attachNewNode(mlight)
     mlnp.setHpr(self.anp.getHpr())
     self.anp.setLightOff()
     self.anp.setLight(mlnp)
     # remove the missile
     base.taskMgr.doMethodLater(life,
                                self.remove_missile,
                                'task-remove-missile',
                                extraArgs=[self.anp],
                                appendTask=True)
    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)
Beispiel #9
0
    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
Beispiel #10
0
 def __init__(self):
     self.forces = render.attachNewNode(ForceNode("global_forces"))
     self.gravity = None
     self._physicalnodes = []
Beispiel #11
0
base.enableParticles()
# here there is the handler to use this time to manage collisions.
collisionHandler = PhysicsCollisionHandler()

#** This is the first time we see this collider: it is used mainly to define a flat infinite plane surface -
# it is very reliable and stable and gives high fame rate performances so use it as much as you can.
# Note that we specify 2 corners of the plane of just 1 unit per side but this collider will collide
#  with everithing as it was an infinite plane anyhow. Note that there is no need to set anything further for it.

cp = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
planeNP = base.render.attachNewNode(CollisionNode('planecnode'))
planeNP.node().addSolid(cp)
planeNP.show()

#** This is how to define the gravity force to make our stuff fall down: first off we define a ForceNode and attach to the render, so that everything below will be affected by this force
globalforcesFN = ForceNode('world-forces')
globalforcesFNP = base.render.attachNewNode(globalforcesFN)
# then we set a linear force that will act in Z axis-drag-down-force of 9.81 units per second.
globalforcesGravity = LinearVectorForce(0, 0, -5.81)
globalforcesFN.addForce(globalforcesGravity)
# and then we assign this force to the physics manager. By the way, we never defined that manager, but it was made automatically when we called base.enableParticles()
base.physicsMgr.addLinearForce(globalforcesGravity)


#** Inside this function we'll load a model and assign a collide ball to it, suitable to collide with everything interacting in the physics environment.
#  I put it in a function because I'll going to call it several times. It will return at last the topmost nodepath of its structure so that we may drive each ball around.
def phyball_dispenser(modelname, scale=1.):
    # first off we gotta define the topmost node that should be a PandaNode wrapped into a nodepath - this is mandatory cos if we try to directly use the  Actornode defined below, we'll face inexpected behavior manipulating the object.
    ballNP = NodePath(PandaNode("phisicsball"))
    # we then need an ActorNode - this is required when playing with physics cos it got an interface suitable for this
    #  task while the usual nodepath ain't. Then we'll stick it to the main nodepath we'll put into the scene render node, wrapped into a nodepath of course.
Beispiel #12
0
    def __init__(self, parent=None):
        '''
        Create a new Vehicle node. Physics should be initialized before any
        instances of Vehicle are created.

        arguments:
          parent -- A PandaNode for the vehicle to attach to. Default is None,
                    in which case the Vehicle should be added to the scene
                    graph via NodePath.attachNewNode().

        '''
        ActorNode.__init__(self, 'VehiclePhysics')
        base.physicsMgr.attachPhysicalNode(self)

        self.getPhysicsObject().setMass(MASS)
        if parent:
            self.myPath = parent.attachNewNode(self)
        else:
            self.myPath = NodePath(self)

        # Load vehicle model and place in the transparent bin.
        vehicleModel = loader.loadModel(MODEL_PATH)
        hull = vehicleModel.find('**/Hull')
        hull.setBin('transparent', 30)
        pwnsEnclosure = vehicleModel.find('**/Pwns_Enclosure')
        pwnsEnclosure.setBin('transparent', 30)
        self.myPath.setPos(0, 0, -0.0)
        selectable = self.myPath.attachNewNode(SelectableNode('vehicle sel'))
        vehicleModel.reparentTo(selectable)

        # ==== Initialize Physics ==== #
        thrusterForceNode = ForceNode('ThrusterForce')
        self.myPath.attachNewNode(thrusterForceNode)

        self.linearForce = LinearVectorForce(0, 0, 0)
        self.linearForce.setMassDependent(1)
        self.angularForce = AngularVectorForce(0, 0, 0)

        thrusterForceNode.addForce(self.linearForce)
        thrusterForceNode.addForce(self.angularForce)

        self.getPhysical(0).addLinearForce(self.linearForce)
        self.getPhysical(0).addAngularForce(self.angularForce)

        self.previousXY = (self.myPath.getX(), self.myPath.getY())

        self.tm = ThrusterManager()

        # Add self.updatePhysics to the task manager and run this task as
        # frequently as possible.
        self.updatePhysicsTask = taskMgr.add(self.updatePhysics,
                                             'UpdatePhysics')

        # ==== Initialize Cameras ==== #
        lens = PerspectiveLens()
        lens.setNearFar(0.05, 100.0)
        #Use either FocalLength or Fov. Fov ~40 is about what actual forward cameras are
        #lens.setFocalLength(0.8)
        lens.setFov(70, 70)
        camera = Camera("Forward_left", lens).getPath()
        camera.reparentTo(vehicleModel.find('**/Forward_Camera'))
        camera.setX(camera.getX() - 0.1)  # Forward cameras 20cm apart
        camera.setY(
            camera.getY() +
            0.05)  # Move in front of torpedo tubes to avoid abstruction
        camera.setHpr(0, 0, 0)

        camera = Camera("Forward_right", lens).getPath()
        camera.reparentTo(vehicleModel.find('**/Forward_Camera'))
        camera.setX(camera.getX() + 0.1)  # Forward cameras 20cm apart
        camera.setY(
            camera.getY() +
            0.05)  # Move in front of torpedo tubes to avoid abstruction
        camera.setHpr(0, 0, 0)

        lens = PerspectiveLens()
        lens.setNearFar(0.05, 100.0)
        lens.setFocalLength(0.8)
        camera = Camera("Downward", lens).getPath()
        camera.reparentTo(vehicleModel.find('**/Downward_Camera'))
        camera.setHpr(0, -90, 0)

        #Layout link (to access hydrophone information)
        self.layout = None

        #Hydrophone variables
        self.start_time = time()
        self.last_hydro_update = time()
Beispiel #13
0
    def __init__(self):
        self.base = ShowBase()
        self.thrust = 0.5
        self.wind = 0.2

        self.UP = Vec3(0, 0, 1)  # might as well just make this a variable
        # set up camera
        self.base.disableMouse()
        self.base.camera.setPos(20, -20, 5)
        self.base.camera.lookAt(0, 0, 5)

        # Set up the collision traverser.  If we bind it to base.cTrav, then Panda will handle
        # management of this traverser (for example, by calling traverse() automatically for us once per frame)
        self.base.cTrav = CollisionTraverser()

        # Now let's set up some collision bits for our masks
        self.ground_bit = 1
        self.ball_bit = 2

        self.base.setBackgroundColor(0.64, 0, 0)
        # First, we build a card to represent the ground
        cm = CardMaker('ground-card')
        cm.setFrame(-60, 60, -60, 60)
        card = self.base.render.attachNewNode(cm.generate())
        card.lookAt(0, 0, -1)  # align upright
        #tex = loader.loadTexture('maps/envir-ground.jpg')
        tex = loader.loadTexture('models/textures/rock12.bmp')
        card.setTexture(tex)

        # Then we build a collisionNode which has a plane solid which will be the ground's collision
        # representation
        groundColNode = card.attachNewNode(CollisionNode('ground-cnode'))
        groundColPlane = CollisionPlane(Plane(Vec3(0, -1, 0), Point3(0, 0, 0)))
        groundColNode.node().addSolid(groundColPlane)

        # Now, set the ground to the ground mask
        groundColNode.setCollideMask(BitMask32().bit(self.ground_bit))

        # Why aren't we adding a collider?  There is no need to tell the collision traverser about this
        # collisionNode, as it will automatically be an Into object during traversal.

        # enable forces
        self.base.enableParticles()
        node = NodePath("PhysicsNode")
        node.reparentTo(self.base.render)

        # may want to have force dependent on mass eventually,
        # but at the moment assume all balls same weight
        self.force_mag = 200

        # gravity
        gravity_fn = ForceNode('world-forces')
        gravity_fnp = self.base.render.attachNewNode(gravity_fn)
        gravity_force = LinearVectorForce(0.0, 0.0, -9.81)
        gravity_fn.addForce(gravity_force)
        self.base.physicsMgr.addLinearForce(gravity_force)

        # wind
        wind_fn = ForceNode('world-forces')
        wind_fnp = self.base.render.attachNewNode(wind_fn)
        wind_force = LinearVectorForce(1.0, 0.5, 0.0)
        wind_fn.addForce(wind_force)
        self.base.physicsMgr.addLinearForce(wind_force)

        # spurt out of fountain, bounce
        self.spurt = ForceNode("spurt")
        spurt_np = self.base.render.attachNewNode(self.spurt)

        # create a list for our ball actors, not sure if I need this, but seems likely
        self.ball_actors = []

        # make a teapot
        teapot = loader.loadModel('teapot.egg')
        tex = loader.loadTexture('maps/color-grid.rgb')
        #teapot.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
        teapot.setTexture(tex)
        teapot.reparentTo(self.base.render)
        teapot.setPos(-5, 10, 10)
        # create the first ball:
        #ball = self.create_a_ball()
        #self.enliven_ball(ball)

        smiley = loader.loadModel('smiley.egg')
        lerper = NodePath('lerper')
        smiley.setTexProjector(TextureStage.getDefault(), NodePath(), lerper)
        smiley.reparentTo(self.base.render)
        smiley.setPos(5, 10, 10)
        i = lerper.posInterval(5, VBase3(0, 1, 0))
        i.loop()

        # Tell the messenger system we're listening for smiley-into-ground messages and invoke our callback
        self.base.accept('ball_cnode-into-ground-cnode', self.ground_callback)

        ball_fountain = taskMgr.doMethodLater(.5, self.spurt_balls, 'tickTask')
Beispiel #14
0
class Bullet(DirectObject):
    def __init__(self, playerID, color=LPoint3f(0,0,0)):
        self.color = color
        self.playerID = playerID

        self.bulletNP = NodePath("Bullet-%d" % id(self))
        self.bulletAN = ActorNode("bullet-physics-%d" % id(self))
        # set the mass of the ball to 3.3g = average weight of a paintball
        self.bulletAN.getPhysicsObject().setMass(0.033)
        self.bulletANP = self.bulletNP.attachNewNode(self.bulletAN)
        base.physicsMgr.attachPhysicalNode(self.bulletAN)
        self.bullet = loader.loadModel("Bullet")
        self.bullet.setScale(2)
        self.bullet.setColorScale(
            self.color.getX(),
            self.color.getY(),
            self.color.getZ(),
            1.0)
        self.bullet.reparentTo(self.bulletANP)

        # setup the collision detection
        # 17.3 mm (0.0173) = size of a .68cal paintball
        self.bulletColName = "bulletCollision-%02d" % id(self)
        self.bulletSphere = CollisionSphere(0, 0, 0, 0.0173*2)
        self.bulletCollision = self.bulletANP.attachNewNode(CollisionNode(self.bulletColName))
        self.bulletCollision.node().addSolid(self.bulletSphere)
        #self.bulletCollision.show()
        base.physicpusher.addCollider(self.bulletCollision, self.bulletANP)
        base.cTrav.addCollider(self.bulletCollision, base.physicpusher)

    def shoot(self, pos, shootVec=None):
        if shootVec != None:
            v = shootVec
            v *= 214.0
        else:
            # Get from/to points from mouse click
            pMouse = base.mouseWatcherNode.getMouse()
            pFrom = Point3()
            pTo = Point3()
            base.camLens.extrude(pMouse, pFrom, pTo)

            pFrom = render.getRelativePoint(base.cam, pFrom)
            pTo = render.getRelativePoint(base.cam, pTo)

            # Calculate initial velocity
            v = pTo - pFrom
            v.normalize()
            v *= 214.0

        self.bulletNP.setPos(pos)
        self.bulletNP.reparentTo(render)
        self.bulletFN = ForceNode("Bullet-force-%d" % id(self))
        self.bulletFNP = self.bulletNP.attachNewNode(self.bulletFN)
        # speed of a paintball when he leafes the muzzle: 214 fps
        self.lvf = LinearVectorForce(v)
        self.lvf.setMassDependent(1)
        self.bulletFN.addForce(self.lvf)
        self.bulletAN.getPhysical(0).addLinearForce(self.lvf)

        self.accept("bulletCollision-%d-hit" % id(self), self.bulletHit)
        taskMgr.doMethodLater(
            2,
            self.doRemove,
            'doRemove-%d' % id(self),
            appendTask=True)

    def doRemove(self, task):
        if self is None: return task.done
        self.ignoreAll()
        self.bulletNP.removeNode()
        self.bulletAN.getPhysical(0).removeLinearForce(self.lvf)
        return task.done

    def bulletHit(self, entry):
        hitName = entry.getIntoNode().getName()
        if str(self.playerID) not in hitName and \
            self.bulletColName not in hitName:
            base.messenger.send("Bulet-hit-%s" % hitName, [entry, self.color])
            self.bulletNP.removeNode()
            self.bulletAN.getPhysical(0).removeLinearForce(self.lvf)
Beispiel #15
0
class Fountain(object):

    def __init__(self):
        self.base = ShowBase()
        self.thrust = 0.5
        self.wind = 0.2

        self.UP = Vec3(0, 0, 1)  # might as well just make this a variable
        # set up camera
        self.base.disableMouse()
        self.base.camera.setPos(20, -20, 5)
        self.base.camera.lookAt(0, 0, 5)

        # Set up the collision traverser.  If we bind it to base.cTrav, then Panda will handle
        # management of this traverser (for example, by calling traverse() automatically for us once per frame)
        self.base.cTrav = CollisionTraverser()

        # Now let's set up some collision bits for our masks
        self.ground_bit = 1
        self.ball_bit = 2

        self.base.setBackgroundColor(0.64, 0, 0)
        # First, we build a card to represent the ground
        cm = CardMaker('ground-card')
        cm.setFrame(-60, 60, -60, 60)
        card = self.base.render.attachNewNode(cm.generate())
        card.lookAt(0, 0, -1)  # align upright
        #tex = loader.loadTexture('maps/envir-ground.jpg')
        tex = loader.loadTexture('models/textures/rock12.bmp')
        card.setTexture(tex)

        # Then we build a collisionNode which has a plane solid which will be the ground's collision
        # representation
        groundColNode = card.attachNewNode(CollisionNode('ground-cnode'))
        groundColPlane = CollisionPlane(Plane(Vec3(0, -1, 0), Point3(0, 0, 0)))
        groundColNode.node().addSolid(groundColPlane)

        # Now, set the ground to the ground mask
        groundColNode.setCollideMask(BitMask32().bit(self.ground_bit))

        # Why aren't we adding a collider?  There is no need to tell the collision traverser about this
        # collisionNode, as it will automatically be an Into object during traversal.

        # enable forces
        self.base.enableParticles()
        node = NodePath("PhysicsNode")
        node.reparentTo(self.base.render)

        # may want to have force dependent on mass eventually,
        # but at the moment assume all balls same weight
        self.force_mag = 200

        # gravity
        gravity_fn = ForceNode('world-forces')
        gravity_fnp = self.base.render.attachNewNode(gravity_fn)
        gravity_force = LinearVectorForce(0.0, 0.0, -9.81)
        gravity_fn.addForce(gravity_force)
        self.base.physicsMgr.addLinearForce(gravity_force)

        # wind
        wind_fn = ForceNode('world-forces')
        wind_fnp = self.base.render.attachNewNode(wind_fn)
        wind_force = LinearVectorForce(1.0, 0.5, 0.0)
        wind_fn.addForce(wind_force)
        self.base.physicsMgr.addLinearForce(wind_force)

        # spurt out of fountain, bounce
        self.spurt = ForceNode("spurt")
        spurt_np = self.base.render.attachNewNode(self.spurt)

        # create a list for our ball actors, not sure if I need this, but seems likely
        self.ball_actors = []

        # make a teapot
        teapot = loader.loadModel('teapot.egg')
        tex = loader.loadTexture('maps/color-grid.rgb')
        #teapot.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
        teapot.setTexture(tex)
        teapot.reparentTo(self.base.render)
        teapot.setPos(-5, 10, 10)
        # create the first ball:
        #ball = self.create_a_ball()
        #self.enliven_ball(ball)

        smiley = loader.loadModel('smiley.egg')
        lerper = NodePath('lerper')
        smiley.setTexProjector(TextureStage.getDefault(), NodePath(), lerper)
        smiley.reparentTo(self.base.render)
        smiley.setPos(5, 10, 10)
        i = lerper.posInterval(5, VBase3(0, 1, 0))
        i.loop()

        # Tell the messenger system we're listening for smiley-into-ground messages and invoke our callback
        self.base.accept('ball_cnode-into-ground-cnode', self.ground_callback)

        ball_fountain = taskMgr.doMethodLater(.5, self.spurt_balls, 'tickTask')

        # tasks
        #self.frameTask = self.base.taskMgr.add(self.frame_loop, "frame_loop")
        #self.frameTask.last = 0

    def frame_loop(self, task):
        # Make more balls!
        dt = task.time - task.last
        task.last = task.time
        # self.move_ball(dt)
        return task.cont

    # This task increments itself so that the delay between task executions
    # gradually increases over time. If you do not change task.delayTime
    # the task will simply repeat itself every 2 seconds
    def spurt_balls(self, task):
        print "Delay:", task.delayTime
        print "Frame:", task.frame
        # task.delayTime += 1
        # for i in range(5):
        ball = self.create_a_ball()
        self.enliven_ball(ball)
        return task.again

    def move_ball(self, dt):
        pass
        #x, y, z = self.ball.getPos()
        #print x, y, z
        #print self.actor_node.getPhysicsObject().getPosition()
        # rotate ball
        #prevRot = LRotationf(self.ball.getQuat())
        #axis = self.UP.cross(self.ballV)
        #newRot = LRotationf(axis, 45, 5 * dt)
        #self.ball.setQuat(prevRot + newRot)
        #print x, y, z
        #z += dt * self.thrust
        #x += dt * self.wind
        #y += dt * self.wind
        #self.ball.setPos(x, y, z)

    def remove_force(self, actor, force, task):
        print('remove force', force)
        actor.getPhysical(0).removeLinearForce(force)
        self.spurt.removeForce(force)
        return task.done

    def apply_spurt(self, actor_node, force=None):
        print 'spurt'
        print('force', force)
        #print actor_node
        # really want this to remember its previous state with that
        # particular ball, and reduce the force from then by some amount.
        if force is None:
            # force = LinearVectorForce(0.0, 0.0, self.force_mag)
            force = LinearVectorForce(0.0, 0.0, self.force_mag)
            self.spurt.addForce(force)
            print('new', force)
            #self.force_mag -= 15
        else:
            force.getAmplitude()
        # apply the spurt
        actor_node.getPhysical(0).addLinearForce(force)
        print('added force', self.spurt.getForce(0).getVector(actor_node.getPhysicsObject())[2])
        #print force, actor_node
        #for child in self.base.render.getChildren():
        #    print child
        # set a task that will clear this force a short moment later
        self.base.taskMgr.doMethodLater(0.01, self.remove_force, 'removeForceTask',
                                        extraArgs=[actor_node, force],
                                        appendTask=True)
        print 'set do method later'

    def ground_callback(self, entry):
        '''This is our ground collision message handler.  It is called whenever a collision message is
        triggered'''
        print 'callback'
        # Get our parent actor_node
        ball_actor_node = entry.getFromNodePath().getParent().node()
        # Why do we call getParent?  Because we are passed the CollisionNode during the event and the
        # ActorNode is one level up from there.  Our node graph looks like so:
        # - ActorNode
        #   + ModelNode
        #   + CollisionNode
        # add bounce!
        self.apply_spurt(ball_actor_node)

    def create_a_ball(self):
        print 'new ball'
        ball = self.base.loader.loadModel('smiley')
        texture = self.base.loader.loadTexture('models/textures/rock12.bmp')
        #ball.setTexture(texture)
        #tex = loader.loadTexture('maps/noise.rgb')
        ball.setPos(0, 0, 0)
        ball.reparentTo(self.base.render)
        ball.setTexture(texture, 1)
        return ball

    def enliven_ball(self, ball):
        # create an actor node for the balls
        ball_actor = self.base.render.attachNewNode(ActorNode("ball_actor_node"))
        # choose a random color
        #ball_actor.setColor(random.random(), random.random(), random.random(), random.random())
        self.create_ball_coll(ball_actor)
        # apply forces to it
        self.base.physicsMgr.attachPhysicalNode(ball_actor.node())
        #spurt_force = LinearVectorForce(0.0, 0.0, self.force_mag)
        #spurt_force.setMassDependent(True)
        #self.spurt.addForce(spurt_force)
        #self.spurt.addForce()
        self.apply_spurt(ball_actor.node())
        ball.reparentTo(ball_actor)
        self.ball_actors.append(ball_actor)

    def create_ball_coll(self, ball_actor):
        # Build a collisionNode for this smiley which is a sphere of the same diameter as the model
        ball_coll_node = ball_actor.attachNewNode(CollisionNode('ball_cnode'))
        ball_coll_sphere = CollisionSphere(0, 0, 0, 1)
        ball_coll_node.node().addSolid(ball_coll_sphere)
        # Watch for collisions with our brothers, so we'll push out of each other
        ball_coll_node.node().setIntoCollideMask(BitMask32().bit(self.ball_bit))
        # we're only interested in colliding with the ground and other smileys
        cMask = BitMask32()
        cMask.setBit(self.ground_bit)
        cMask.setBit(self.ball_bit)
        ball_coll_node.node().setFromCollideMask(cMask)

        # Now, to keep the spheres out of the ground plane and each other, let's attach a physics handler to them
        ball_handler = PhysicsCollisionHandler()

        # Set the physics handler to manipulate the smiley actor's transform.
        ball_handler.addCollider(ball_coll_node, ball_actor)

        # This call adds the physics handler to the traverser list
        # (not related to last call to addCollider!)
        self.base.cTrav.addCollider(ball_coll_node, ball_handler)

        # Now, let's set the collision handler so that it will also do a CollisionHandlerEvent callback
        # But...wait?  Aren't we using a PhysicsCollisionHandler?
        # The reason why we can get away with this is that all CollisionHandlerXs are inherited from
        # CollisionHandlerEvent,
        # so all the pattern-matching event handling works, too
        ball_handler.addInPattern('%fn-into-%in')

        return ball_coll_node
Beispiel #16
0
    def __init__(self):
        self.base = ShowBase()
        self.thrust = 0.5
        self.wind = 0.2

        self.UP = Vec3(0, 0, 1)  # might as well just make this a variable
        # set up camera
        self.base.disableMouse()
        self.base.camera.setPos(20, -20, 5)
        self.base.camera.lookAt(0, 0, 5)

        # Set up the collision traverser.  If we bind it to base.cTrav, then Panda will handle
        # management of this traverser (for example, by calling traverse() automatically for us once per frame)
        self.base.cTrav = CollisionTraverser()

        # Now let's set up some collision bits for our masks
        self.ground_bit = 1
        self.ball_bit = 2

        self.base.setBackgroundColor(0.64, 0, 0)
        # First, we build a card to represent the ground
        cm = CardMaker('ground-card')
        cm.setFrame(-60, 60, -60, 60)
        card = self.base.render.attachNewNode(cm.generate())
        card.lookAt(0, 0, -1)  # align upright
        #tex = loader.loadTexture('maps/envir-ground.jpg')
        tex = loader.loadTexture('models/textures/rock12.bmp')
        card.setTexture(tex)

        # Then we build a collisionNode which has a plane solid which will be the ground's collision
        # representation
        groundColNode = card.attachNewNode(CollisionNode('ground-cnode'))
        groundColPlane = CollisionPlane(Plane(Vec3(0, -1, 0), Point3(0, 0, 0)))
        groundColNode.node().addSolid(groundColPlane)

        # Now, set the ground to the ground mask
        groundColNode.setCollideMask(BitMask32().bit(self.ground_bit))

        # Why aren't we adding a collider?  There is no need to tell the collision traverser about this
        # collisionNode, as it will automatically be an Into object during traversal.

        # enable forces
        self.base.enableParticles()
        node = NodePath("PhysicsNode")
        node.reparentTo(self.base.render)

        # may want to have force dependent on mass eventually,
        # but at the moment assume all balls same weight
        self.force_mag = 200

        # gravity
        gravity_fn = ForceNode('world-forces')
        gravity_fnp = self.base.render.attachNewNode(gravity_fn)
        gravity_force = LinearVectorForce(0.0, 0.0, -9.81)
        gravity_fn.addForce(gravity_force)
        self.base.physicsMgr.addLinearForce(gravity_force)

        # wind
        wind_fn = ForceNode('world-forces')
        wind_fnp = self.base.render.attachNewNode(wind_fn)
        wind_force = LinearVectorForce(1.0, 0.5, 0.0)
        wind_fn.addForce(wind_force)
        self.base.physicsMgr.addLinearForce(wind_force)

        # spurt out of fountain, bounce
        self.spurt = ForceNode("spurt")
        spurt_np = self.base.render.attachNewNode(self.spurt)

        # create a list for our ball actors, not sure if I need this, but seems likely
        self.ball_actors = []

        # make a teapot
        teapot = loader.loadModel('teapot.egg')
        tex = loader.loadTexture('maps/color-grid.rgb')
        #teapot.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
        teapot.setTexture(tex)
        teapot.reparentTo(self.base.render)
        teapot.setPos(-5, 10, 10)
        # create the first ball:
        #ball = self.create_a_ball()
        #self.enliven_ball(ball)

        smiley = loader.loadModel('smiley.egg')
        lerper = NodePath('lerper')
        smiley.setTexProjector(TextureStage.getDefault(), NodePath(), lerper)
        smiley.reparentTo(self.base.render)
        smiley.setPos(5, 10, 10)
        i = lerper.posInterval(5, VBase3(0, 1, 0))
        i.loop()

        # Tell the messenger system we're listening for smiley-into-ground messages and invoke our callback
        self.base.accept('ball_cnode-into-ground-cnode', self.ground_callback)

        ball_fountain = taskMgr.doMethodLater(.5, self.spurt_balls, 'tickTask')
Beispiel #17
0
 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()
Beispiel #18
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
    def quad_move(self, task):
        position_proportionality_constant = 0.0007
        angle_proportionality_constant = 0.2
        angle_max = 10
        angle_directions = {i: k, j: -j}

        keys_vs_moves = {'w': i,
                         's': -i,
                         'a': j,
                         'd': -j,
                         'e': k,
                         'q': -k}

        move_total = LPoint3f(0, 0, 0)
        angle_total = LPoint3f(0, 0, 0)

        for key, move in keys_vs_moves.items():
            pressed_key = self.mouseWatcherNode.is_button_down(KeyboardButton.asciiKey(key))
            if pressed_key:
                move_total += move

                if key not in ['e', 'q', 'm']:
                    angle_total += LPoint3f(*tuple(sign(move) *
                                                   np.array(
                                                       angle_directions[LPoint3f(*tuple(int(abs(c)) for c in move))])
                                                   * angle_proportionality_constant))
                else:
                    prop_sign = 1 if key == 'e' else -1

                    for prop in self.prop_models:
                        prop.setHpr(prop.get_hpr() + LPoint3f(10 * prop_sign, 0, 0))

                self.movements += key

                with open(ROOT_DIR + self.simulation_folder + 'movements.txt', 'w') as file:
                    file.write(self.movements)

                    # self.movie(namePrefix=self.simulation_folder, duration=1.0, fps=30,
                    #       format='png', sd=4, source=None)

        if any([abs(coordinate) > 0 for coordinate in angle_total]):
            # tilt_force_node = ForceNode('tilt-force')
            # tilt_force = AngularVectorForce(*angle_total)
            # tilt_force_node.addForce(tilt_force)
            #
            # self.actor_node.getPhysical(0).addAngularForce(tilt_force)

            desired_quad_hpr = list(self.quad_model.getHpr() + angle_total)

            for index, coordinate in enumerate(desired_quad_hpr):
                if coordinate:
                    desired_quad_hpr[index] = sign(coordinate) * min(abs(coordinate), 90 + angle_max
                    if index == 0 else angle_max)

            desired_quad_hpr = LPoint3f(*desired_quad_hpr)
            self.quad_model.setHpr(desired_quad_hpr)

        if any([abs(coordinate) > 0 for coordinate in move_total]):

            movement_force_node = ForceNode('movement-force')
            movement_force = LinearVectorForce(*(- move_total * position_proportionality_constant))
            # movement_force.setMassDependent(1)
            movement_force_node.addForce(movement_force)

            self.actor_node.getPhysical(0).addLinearForce(movement_force)

            # time.sleep(0.1)

            # thruster.setP(-45)  # bend the thruster nozzle out at 45 degrees

            # desired_quad_pos = self.quad_model.getPos() + move_total * position_proportionality_constant
            # self.quad_model.setPos(desired_quad_pos)

        return task.cont
Beispiel #20
0
class Fountain(object):
    def __init__(self):
        self.base = ShowBase()
        self.thrust = 0.5
        self.wind = 0.2

        self.UP = Vec3(0, 0, 1)  # might as well just make this a variable
        # set up camera
        self.base.disableMouse()
        self.base.camera.setPos(20, -20, 5)
        self.base.camera.lookAt(0, 0, 5)

        # Set up the collision traverser.  If we bind it to base.cTrav, then Panda will handle
        # management of this traverser (for example, by calling traverse() automatically for us once per frame)
        self.base.cTrav = CollisionTraverser()

        # Now let's set up some collision bits for our masks
        self.ground_bit = 1
        self.ball_bit = 2

        self.base.setBackgroundColor(0.64, 0, 0)
        # First, we build a card to represent the ground
        cm = CardMaker('ground-card')
        cm.setFrame(-60, 60, -60, 60)
        card = self.base.render.attachNewNode(cm.generate())
        card.lookAt(0, 0, -1)  # align upright
        #tex = loader.loadTexture('maps/envir-ground.jpg')
        tex = loader.loadTexture('models/textures/rock12.bmp')
        card.setTexture(tex)

        # Then we build a collisionNode which has a plane solid which will be the ground's collision
        # representation
        groundColNode = card.attachNewNode(CollisionNode('ground-cnode'))
        groundColPlane = CollisionPlane(Plane(Vec3(0, -1, 0), Point3(0, 0, 0)))
        groundColNode.node().addSolid(groundColPlane)

        # Now, set the ground to the ground mask
        groundColNode.setCollideMask(BitMask32().bit(self.ground_bit))

        # Why aren't we adding a collider?  There is no need to tell the collision traverser about this
        # collisionNode, as it will automatically be an Into object during traversal.

        # enable forces
        self.base.enableParticles()
        node = NodePath("PhysicsNode")
        node.reparentTo(self.base.render)

        # may want to have force dependent on mass eventually,
        # but at the moment assume all balls same weight
        self.force_mag = 200

        # gravity
        gravity_fn = ForceNode('world-forces')
        gravity_fnp = self.base.render.attachNewNode(gravity_fn)
        gravity_force = LinearVectorForce(0.0, 0.0, -9.81)
        gravity_fn.addForce(gravity_force)
        self.base.physicsMgr.addLinearForce(gravity_force)

        # wind
        wind_fn = ForceNode('world-forces')
        wind_fnp = self.base.render.attachNewNode(wind_fn)
        wind_force = LinearVectorForce(1.0, 0.5, 0.0)
        wind_fn.addForce(wind_force)
        self.base.physicsMgr.addLinearForce(wind_force)

        # spurt out of fountain, bounce
        self.spurt = ForceNode("spurt")
        spurt_np = self.base.render.attachNewNode(self.spurt)

        # create a list for our ball actors, not sure if I need this, but seems likely
        self.ball_actors = []

        # make a teapot
        teapot = loader.loadModel('teapot.egg')
        tex = loader.loadTexture('maps/color-grid.rgb')
        #teapot.setTexGen(TextureStage.getDefault(), TexGenAttrib.MWorldPosition)
        teapot.setTexture(tex)
        teapot.reparentTo(self.base.render)
        teapot.setPos(-5, 10, 10)
        # create the first ball:
        #ball = self.create_a_ball()
        #self.enliven_ball(ball)

        smiley = loader.loadModel('smiley.egg')
        lerper = NodePath('lerper')
        smiley.setTexProjector(TextureStage.getDefault(), NodePath(), lerper)
        smiley.reparentTo(self.base.render)
        smiley.setPos(5, 10, 10)
        i = lerper.posInterval(5, VBase3(0, 1, 0))
        i.loop()

        # Tell the messenger system we're listening for smiley-into-ground messages and invoke our callback
        self.base.accept('ball_cnode-into-ground-cnode', self.ground_callback)

        ball_fountain = taskMgr.doMethodLater(.5, self.spurt_balls, 'tickTask')

        # tasks
        #self.frameTask = self.base.taskMgr.add(self.frame_loop, "frame_loop")
        #self.frameTask.last = 0

    def frame_loop(self, task):
        # Make more balls!
        dt = task.time - task.last
        task.last = task.time
        # self.move_ball(dt)
        return task.cont

    # This task increments itself so that the delay between task executions
    # gradually increases over time. If you do not change task.delayTime
    # the task will simply repeat itself every 2 seconds
    def spurt_balls(self, task):
        print "Delay:", task.delayTime
        print "Frame:", task.frame
        # task.delayTime += 1
        # for i in range(5):
        ball = self.create_a_ball()
        self.enliven_ball(ball)
        return task.again

    def move_ball(self, dt):
        pass
        #x, y, z = self.ball.getPos()
        #print x, y, z
        #print self.actor_node.getPhysicsObject().getPosition()
        # rotate ball
        #prevRot = LRotationf(self.ball.getQuat())
        #axis = self.UP.cross(self.ballV)
        #newRot = LRotationf(axis, 45, 5 * dt)
        #self.ball.setQuat(prevRot + newRot)
        #print x, y, z
        #z += dt * self.thrust
        #x += dt * self.wind
        #y += dt * self.wind
        #self.ball.setPos(x, y, z)

    def remove_force(self, actor, force, task):
        print('remove force', force)
        actor.getPhysical(0).removeLinearForce(force)
        self.spurt.removeForce(force)
        return task.done

    def apply_spurt(self, actor_node, force=None):
        print 'spurt'
        print('force', force)
        #print actor_node
        # really want this to remember its previous state with that
        # particular ball, and reduce the force from then by some amount.
        if force is None:
            # force = LinearVectorForce(0.0, 0.0, self.force_mag)
            force = LinearVectorForce(0.0, 0.0, self.force_mag)
            self.spurt.addForce(force)
            print('new', force)
            #self.force_mag -= 15
        else:
            force.getAmplitude()
        # apply the spurt
        actor_node.getPhysical(0).addLinearForce(force)
        print(
            'added force',
            self.spurt.getForce(0).getVector(actor_node.getPhysicsObject())[2])
        #print force, actor_node
        #for child in self.base.render.getChildren():
        #    print child
        # set a task that will clear this force a short moment later
        self.base.taskMgr.doMethodLater(0.01,
                                        self.remove_force,
                                        'removeForceTask',
                                        extraArgs=[actor_node, force],
                                        appendTask=True)
        print 'set do method later'

    def ground_callback(self, entry):
        '''This is our ground collision message handler.  It is called whenever a collision message is
        triggered'''
        print 'callback'
        # Get our parent actor_node
        ball_actor_node = entry.getFromNodePath().getParent().node()
        # Why do we call getParent?  Because we are passed the CollisionNode during the event and the
        # ActorNode is one level up from there.  Our node graph looks like so:
        # - ActorNode
        #   + ModelNode
        #   + CollisionNode
        # add bounce!
        self.apply_spurt(ball_actor_node)

    def create_a_ball(self):
        print 'new ball'
        ball = self.base.loader.loadModel('smiley')
        texture = self.base.loader.loadTexture('models/textures/rock12.bmp')
        #ball.setTexture(texture)
        #tex = loader.loadTexture('maps/noise.rgb')
        ball.setPos(0, 0, 0)
        ball.reparentTo(self.base.render)
        ball.setTexture(texture, 1)
        return ball

    def enliven_ball(self, ball):
        # create an actor node for the balls
        ball_actor = self.base.render.attachNewNode(
            ActorNode("ball_actor_node"))
        # choose a random color
        #ball_actor.setColor(random.random(), random.random(), random.random(), random.random())
        self.create_ball_coll(ball_actor)
        # apply forces to it
        self.base.physicsMgr.attachPhysicalNode(ball_actor.node())
        #spurt_force = LinearVectorForce(0.0, 0.0, self.force_mag)
        #spurt_force.setMassDependent(True)
        #self.spurt.addForce(spurt_force)
        #self.spurt.addForce()
        self.apply_spurt(ball_actor.node())
        ball.reparentTo(ball_actor)
        self.ball_actors.append(ball_actor)

    def create_ball_coll(self, ball_actor):
        # Build a collisionNode for this smiley which is a sphere of the same diameter as the model
        ball_coll_node = ball_actor.attachNewNode(CollisionNode('ball_cnode'))
        ball_coll_sphere = CollisionSphere(0, 0, 0, 1)
        ball_coll_node.node().addSolid(ball_coll_sphere)
        # Watch for collisions with our brothers, so we'll push out of each other
        ball_coll_node.node().setIntoCollideMask(BitMask32().bit(
            self.ball_bit))
        # we're only interested in colliding with the ground and other smileys
        cMask = BitMask32()
        cMask.setBit(self.ground_bit)
        cMask.setBit(self.ball_bit)
        ball_coll_node.node().setFromCollideMask(cMask)

        # Now, to keep the spheres out of the ground plane and each other, let's attach a physics handler to them
        ball_handler = PhysicsCollisionHandler()

        # Set the physics handler to manipulate the smiley actor's transform.
        ball_handler.addCollider(ball_coll_node, ball_actor)

        # This call adds the physics handler to the traverser list
        # (not related to last call to addCollider!)
        self.base.cTrav.addCollider(ball_coll_node, ball_handler)

        # Now, let's set the collision handler so that it will also do a CollisionHandlerEvent callback
        # But...wait?  Aren't we using a PhysicsCollisionHandler?
        # The reason why we can get away with this is that all CollisionHandlerXs are inherited from
        # CollisionHandlerEvent,
        # so all the pattern-matching event handling works, too
        ball_handler.addInPattern('%fn-into-%in')

        return ball_coll_node