Ejemplo n.º 1
0
    def _add_side_walk2bullet(self, lane_start, lane_end, middle, radius=0.0, direction=0):
        length = norm(lane_end[0] - lane_start[0], lane_end[1] - lane_start[1])
        body_node = BulletRigidBodyNode(BodyName.Side_walk)
        body_node.setActive(False)
        body_node.setKinematic(False)
        body_node.setStatic(True)
        side_np = self.side_walk_node_path.attachNewNode(body_node)
        shape = BulletBoxShape(Vec3(1 / 2, 1 / 2, 1 / 2))
        body_node.addShape(shape)
        body_node.setIntoCollideMask(BitMask32.bit(Block.LANE_LINE_COLLISION_MASK))
        self.dynamic_nodes.append(body_node)

        if radius == 0:
            factor = 1
        else:
            if direction == 1:
                factor = (1 - self.SIDE_WALK_LINE_DIST / radius)
            else:
                factor = (1 + self.SIDE_WALK_WIDTH / radius) * (1 + self.SIDE_WALK_LINE_DIST / radius)
        direction_v = lane_end - lane_start
        vertical_v = (-direction_v[1], direction_v[0]) / numpy.linalg.norm(direction_v)
        middle += vertical_v * (self.SIDE_WALK_WIDTH / 2 + self.SIDE_WALK_LINE_DIST)
        side_np.setPos(panda_position(middle, 0))
        theta = -numpy.arctan2(direction_v[1], direction_v[0])
        side_np.setQuat(LQuaternionf(numpy.cos(theta / 2), 0, 0, numpy.sin(theta / 2)))
        side_np.setScale(
            length * factor, self.SIDE_WALK_WIDTH, self.SIDE_WALK_THICKNESS * (1 + 0.1 * numpy.random.rand())
        )
        if self.render:
            side_np.setTexture(self.ts_color, self.side_texture)
            self.side_walk.instanceTo(side_np)
Ejemplo n.º 2
0
    def _add_lane_line2bullet(
        self,
        lane_start,
        lane_end,
        middle,
        parent_np: NodePath,
        color: Vec4,
        line_type: LineType,
        straight_stripe=False
    ):
        length = norm(lane_end[0] - lane_start[0], lane_end[1] - lane_start[1])
        if length <= 0:
            return
        if LineType.prohibit(line_type):
            node_name = BodyName.Continuous_line
        else:
            node_name = BodyName.Stripped_line

        # add bullet body for it
        if straight_stripe:
            body_np = parent_np.attachNewNode(node_name)
        else:
            scale = 2 if line_type == LineType.STRIPED else 1
            body_node = BulletRigidBodyNode(node_name)
            body_node.setActive(False)
            body_node.setKinematic(False)
            body_node.setStatic(True)
            body_np = parent_np.attachNewNode(body_node)
            shape = BulletBoxShape(Vec3(scale / 2, Block.LANE_LINE_WIDTH / 2, Block.LANE_LINE_THICKNESS))
            body_np.node().addShape(shape)
            body_np.node().setIntoCollideMask(BitMask32.bit(Block.LANE_LINE_COLLISION_MASK))
            self.dynamic_nodes.append(body_np.node())

        # position and heading
        body_np.setPos(panda_position(middle, 0))
        direction_v = lane_end - lane_start
        theta = -numpy.arctan2(direction_v[1], direction_v[0])
        body_np.setQuat(LQuaternionf(numpy.cos(theta / 2), 0, 0, numpy.sin(theta / 2)))

        if self.render:
            # For visualization
            lane_line = self.loader.loadModel(AssetLoader.file_path("models", "box.bam"))
            lane_line.getChildren().reparentTo(body_np)
        body_np.setScale(length, Block.LANE_LINE_WIDTH, Block.LANE_LINE_THICKNESS)
        body_np.set_color(color)
Ejemplo n.º 3
0
    def _add_box_body(self, lane_start, lane_end, middle, parent_np: NodePath, line_type):
        length = norm(lane_end[0] - lane_start[0], lane_end[1] - lane_start[1])
        if LineType.prohibit(line_type):
            node_name = BodyName.Continuous_line
        else:
            node_name = BodyName.Stripped_line
        body_node = BulletRigidBodyNode(node_name)
        body_node.setActive(False)
        body_node.setKinematic(False)
        body_node.setStatic(True)
        body_np = parent_np.attachNewNode(body_node)
        shape = BulletBoxShape(Vec3(length / 2, Block.LANE_LINE_WIDTH / 2, Block.LANE_LINE_THICKNESS))
        body_np.node().addShape(shape)
        body_np.node().setIntoCollideMask(BitMask32.bit(Block.LANE_LINE_COLLISION_MASK))
        self.dynamic_nodes.append(body_np.node())

        body_np.setPos(panda_position(middle, 0))
        direction_v = lane_end - lane_start
        theta = -numpy.arctan2(direction_v[1], direction_v[0])
        body_np.setQuat(LQuaternionf(numpy.cos(theta / 2), 0, 0, numpy.sin(theta / 2)))
Ejemplo n.º 4
0
class CharacterController(DynamicObject, FSM):
    def __init__(self, game):
        self.game = game
        FSM.__init__(self, "Player")

        # key states
        # dx direction left or right, dy direction forward or backward
        self.kh = self.game.kh
        self.dx = 0
        self.dy = 0
        self.jumping = 0
        self.crouching = 0

        # maximum speed when only walking
        self.groundSpeed = 5.0

        # acceleration used when walking to rise to self.groundSpeed
        self.groundAccel = 100.0

        # maximum speed in the air (air friction)
        self.airSpeed = 30.0

        # player movement control when in the air
        self.airAccel = 10.0

        # horizontal speed on jump start
        self.jumpSpeed = 5.5

        self.turnSpeed = 5

        self.moveSpeedVec = Vec3(0, 0, 0)
        self.platformSpeedVec = Vec3(0, 0, 0)

        h = 1.75
        w = 0.4

        self.shape = BulletCapsuleShape(w, h - 2 * w, ZUp)
        self.node = BulletRigidBodyNode('Player')
        self.node.setMass(2)
        self.node.addShape(self.shape)
        self.node.setActive(True, True)
        self.node.setDeactivationEnabled(False, True)
        self.node.setFriction(200)
        #self.node.setGravity(10)
        #self.node.setFallSpeed(200)
        self.node.setCcdMotionThreshold(1e-7)
        self.node.setCcdSweptSphereRadius(0.5)
        self.node.setAngularFactor(Vec3(0, 0, 1))

        self.np = self.game.render.attachNewNode(self.node)
        self.np.setPos(0, 0, 0)
        self.np.setH(0)
        #self.np.setCollideMask(BitMask32.allOn())

        self.game.world.attachRigidBody(self.node)
        self.playerModel = None
        self.slice_able = False

    def setActor(self,
                 modelPath,
                 animDic={},
                 flip=False,
                 pos=(0, 0, 0),
                 scale=1.0):
        self.playerModel = Actor(modelPath, animDic)
        self.playerModel.reparentTo(self.np)
        self.playerModel.setScale(scale)  # 1ft = 0.3048m
        if flip:
            self.playerModel.setH(180)
        self.playerModel.setPos(pos)
        self.playerModel.setScale(scale)

    #-------------------------------------------------------------------
    # Speed
    def getSpeedVec(self):
        return self.node.getLinearVelocity()

    def setSpeedVec(self, speedVec):
        #print "setting speed to %s" % (speedVec)
        self.node.setLinearVelocity(speedVec)
        return speedVec

    def setPlatformSpeed(self, speedVec):
        self.platformSpeedVec = speedVec

    def getSpeed(self):
        return self.getSpeedVec().length()

    def setSpeed(self, speed):
        speedVec = self.getSpeedVec()
        speedVec.normalize()
        self.setSpeedVec(speedVec * speed)

    def getLocalSpeedVec(self):
        return self.np.getRelativeVector(self.getSpeed())

    def getSpeedXY(self):
        vec = self.getSpeedVec()
        return Vec3(vec[0], vec[1], 0)

    def setSpeedXY(self, speedX, speedY):
        vec = self.getSpeedVec()
        z = self.getSpeedZ()
        self.setSpeedVec(Vec3(speedX, speedY, z))

    def getSpeedH(self):
        return self.getSpeedXY().length()

    def getSpeedZ(self):
        return self.getSpeedVec()[2]

    def setSpeedZ(self, zSpeed):
        vec = self.getSpeedVec()
        speedVec = Vec3(vec[0], vec[1], zSpeed)
        return self.setSpeedVec(speedVec)

    def setLinearVelocity(self, speedVec):
        return self.setSpeedVec(speedVec)

    def setAngularVelocity(self, speed):
        self.node.setAngularVelocity(Vec3(0, 0, speed))

    def getFriction(self):
        return self.node.getFriction()

    def setFriction(self, friction):
        return self.node.setFriction(friction)

    #-------------------------------------------------------------------
    # Acceleration
    def doJump(self):
        #self.setSpeedZ(self.getSpeedZ()+self.jumpSpeed)
        self.setSpeedZ(self.jumpSpeed)

    def setForce(self, force):
        self.node.applyCentralForce(force)

    #-------------------------------------------------------------------
    # contacts

    #-------------------------------------------------------------------
    # update

    def update(self, dt, dx=0, dy=0, jumping=0, crouching=0, dRot=0):
        #self.setR(0)
        #self.setP(0)

        self.jumping = jumping
        self.crouching = crouching
        self.dx = dx
        self.dy = dy

        #self.setAngularVelocity(dRot*self.turnSpeed)
        #self.setAngularVelocity(0)
        self.setH(self.game.camHandler.gameNp.getH())
        speedVec = self.getSpeedVec() - self.platformSpeedVec
        speed = speedVec.length()
        localSpeedVec = self.np.getRelativeVector(self.game.render, speedVec)
        pushVec = self.game.render.getRelativeVector(self.np,
                                                     Vec3(self.dx, self.dy, 0))
        if self.dx != 0 or self.dy != 0:
            pushVec.normalize()
        else:
            pushVec = Vec3(0, 0, 0)

        contacts = self.getContacts()
        contact = self.checkFeet()

        if self.jumping and contact in contacts:
            self.setFriction(0)
            self.doJump()

        if self.jumping:
            self.setForce(pushVec * self.airAccel)

            if speed > self.airSpeed:
                self.setSpeed(self.airSpeed)

        else:
            if contacts:
                self.setForce(pushVec * self.groundAccel)
            else:
                self.setForce(pushVec * self.airAccel)

            if self.dx == 0 and self.dy == 0:
                self.setFriction(100)
            else:
                self.setFriction(0)

            if speed > self.groundSpeed:
                if contacts:
                    self.setSpeed(self.groundSpeed)
        '''
Ejemplo n.º 5
0
class CharacterController(DynamicObject, FSM):
	def __init__(self, game):
		self.game = game
		FSM.__init__(self, "Player")
		
		# key states
		# dx direction left or right, dy direction forward or backward
		self.kh = self.game.kh
		self.dx = 0
		self.dy = 0
		self.jumping = 0
		self.crouching = 0
		
		# maximum speed when only walking
		self.groundSpeed = 5.0
		
		# acceleration used when walking to rise to self.groundSpeed
		self.groundAccel = 100.0
		
		# maximum speed in the air (air friction)
		self.airSpeed = 30.0
		
		# player movement control when in the air
		self.airAccel = 10.0
		
		# horizontal speed on jump start
		self.jumpSpeed = 5.5
		
		self.turnSpeed = 5
		
		self.moveSpeedVec = Vec3(0,0,0)
		self.platformSpeedVec = Vec3(0,0,0)
		
		h = 1.75
		w = 0.4
		
		self.shape = BulletCapsuleShape(w, h - 2 * w, ZUp)
		self.node = BulletRigidBodyNode('Player')
		self.node.setMass(2)
		self.node.addShape(self.shape)
		self.node.setActive(True, True)
		self.node.setDeactivationEnabled(False, True)
		self.node.setFriction(200)
		#self.node.setGravity(10)
		#self.node.setFallSpeed(200)
		self.node.setCcdMotionThreshold(1e-7)
		self.node.setCcdSweptSphereRadius(0.5)
		self.node.setAngularFactor(Vec3(0,0,1))
		
		self.np = self.game.render.attachNewNode(self.node)
		self.np.setPos(0, 0, 0)
		self.np.setH(0)
		#self.np.setCollideMask(BitMask32.allOn())
		
		self.game.world.attachRigidBody(self.node)
		self.playerModel = None
		self.slice_able = False
		
	def setActor(self, modelPath, animDic={}, flip = False, pos = (0,0,0), scale = 1.0):
		self.playerModel = Actor(modelPath, animDic)
		self.playerModel.reparentTo(self.np)
		self.playerModel.setScale(scale) # 1ft = 0.3048m
		if flip:
			self.playerModel.setH(180)
		self.playerModel.setPos(pos)
		self.playerModel.setScale(scale)
	
	
	#-------------------------------------------------------------------
	# Speed	
	def getSpeedVec(self):
		return self.node.getLinearVelocity()
	def setSpeedVec(self, speedVec):
		#print "setting speed to %s" % (speedVec)
		self.node.setLinearVelocity(speedVec)
		return speedVec
		
	def setPlatformSpeed(self, speedVec):
		self.platformSpeedVec = speedVec
		
	def getSpeed(self):
		return self.getSpeedVec().length()
	def setSpeed(self, speed):
		speedVec = self.getSpeedVec()
		speedVec.normalize()
		self.setSpeedVec(speedVec*speed)
	
	def getLocalSpeedVec(self):
		return self.np.getRelativeVector(self.getSpeed())
	
	def getSpeedXY(self):
		vec = self.getSpeedVec()
		return Vec3(vec[0], vec[1], 0)
	def setSpeedXY(self, speedX, speedY):
		vec = self.getSpeedVec()
		z = self.getSpeedZ()
		self.setSpeedVec(Vec3(speedX, speedY, z))
	
	def getSpeedH(self):
		return self.getSpeedXY().length()
		
	def getSpeedZ(self):
		return self.getSpeedVec()[2]
	def setSpeedZ(self, zSpeed):
		vec = self.getSpeedVec()
		speedVec = Vec3(vec[0], vec[1], zSpeed)
		return self.setSpeedVec(speedVec)
		
		
	def setLinearVelocity(self, speedVec):
		return self.setSpeedVec(speedVec)
	
	def setAngularVelocity(self, speed):
		self.node.setAngularVelocity(Vec3(0, 0, speed))
	
	def getFriction(self):
		return self.node.getFriction()
	def setFriction(self, friction):
		return self.node.setFriction(friction)
	
	#-------------------------------------------------------------------
	# Acceleration	
	def doJump(self):
		#self.setSpeedZ(self.getSpeedZ()+self.jumpSpeed)
		self.setSpeedZ(self.jumpSpeed)
	
	def setForce(self, force):
		self.node.applyCentralForce(force)
		
	#-------------------------------------------------------------------
	# contacts
	
	#-------------------------------------------------------------------
	# update

	
		
	def update(self, dt, dx=0, dy=0, jumping=0, crouching=0, dRot=0):
		#self.setR(0)
		#self.setP(0)
		
		self.jumping = jumping
		self.crouching = crouching
		self.dx = dx
		self.dy = dy
		
		#self.setAngularVelocity(dRot*self.turnSpeed)
		#self.setAngularVelocity(0)
		self.setH(self.game.camHandler.gameNp.getH())
		speedVec = self.getSpeedVec() - self.platformSpeedVec
		speed = speedVec.length()
		localSpeedVec = self.np.getRelativeVector(self.game.render, speedVec)
		pushVec = self.game.render.getRelativeVector(self.np, Vec3(self.dx,self.dy,0))
		if self.dx != 0 or self.dy != 0:
			pushVec.normalize()
		else:
			pushVec = Vec3(0,0,0)
		
		contacts = self.getContacts()
		contact = self.checkFeet()
		
		if self.jumping and contact in contacts:
			self.setFriction(0)
			self.doJump()
		
		if self.jumping:	
			self.setForce(pushVec * self.airAccel)
			
			if speed > self.airSpeed:
				self.setSpeed(self.airSpeed)
		
		else:
			if contacts:
				self.setForce(pushVec * self.groundAccel)
			else:
				self.setForce(pushVec * self.airAccel)
			
			if self.dx == 0 and self.dy == 0:
				self.setFriction(100)
			else:
				self.setFriction(0)
			
			if speed > self.groundSpeed:
				if contacts:
					self.setSpeed(self.groundSpeed)
		
		'''
Ejemplo n.º 6
0
class BulletNPC(DynamicObject):
    def __init__(self, name, game, pos):
        self.game = game
        self.name = name

        self.jumping = 0
        self.crouching = 0

        # maximum speed when only walking
        self.groundSpeed = 4.0

        # acceleration used when walking to rise to self.groundSpeed
        self.groundAccel = 150.0

        self.groundFriction = 0.0

        # maximum speed in the air (air friction)
        self.airSpeed = 30.0

        # player movement control when in the air
        self.airAccel = 10.0

        # horizontal speed on jump start
        self.jumpSpeed = 5.5

        self.turnSpeed = 5

        self.moveSpeedVec = Vec3(0, 0, 0)
        self.platformSpeedVec = Vec3(0, 0, 0)

        h = 1.75
        w = 0.4

        self.shape = BulletCapsuleShape(w, h - 2 * w, ZUp)
        self.node = BulletRigidBodyNode(self.name)
        self.node.setMass(1.0)
        self.node.addShape(self.shape)
        self.node.setActive(True, True)
        self.node.setDeactivationEnabled(False, True)
        self.node.setFriction(self.groundFriction)
        # self.node.setGravity(10)
        # self.node.setFallSpeed(200)
        self.node.setCcdMotionThreshold(1e-7)

        # do not use setCcdSweptSphereRadius
        # it messes up the bite contact test
        # self.node.setCcdSweptSphereRadius(0.5)

        self.node.setAngularFactor(Vec3(0, 0, 1))

        self.np = self.game.render.attachNewNode(self.node)
        self.setPos(pos)
        self.setH(0)
        # self.np.setCollideMask(BitMask32.allOn())

        self.game.world.attachRigidBody(self.node)
        self.playerModel = Actor(
            "models/monsters/ghoul2.egg",
            {"idle": "models/monsters/ghoul2-idle.egg", "walk": "models/monsters/ghoul2-walk.egg"},
        )
        self.playerModel.setScale(0.15)
        self.playerModel.setZ(0.15)
        self.playerModel.reparentTo(self.np)

        interval = Wait(random.uniform(0, 1))
        i2 = Func(self.startWalkAnim)
        seq = Sequence()
        seq.append(interval)
        seq.append(i2)
        seq.start()

        self.growlTimer = 5.0
        self.sound = None
        self.alive = True

        self.targetNp = NodePath(self.name)

        self.brainTimer = 0.0
        self.brainDelay = 1.2

        self.currentForce = Vec3(0, 0, 0)

    def startWalkAnim(self):
        self.playerModel.loop("walk")

    def stopWalkAnim(self):
        self.playerModel.loop("idle")

    def checkFront(self):
        p1 = Point3(self.getPos())
        direction = self.game.playerNp.getPos() - self.getPos()
        direction.normalize()
        direction = direction * 2.0
        p2 = Point3(self.getPos() + direction)

        result = self.game.world.rayTestClosest(p1, p2)

        # ts1 = TransformState.makePos(p1)
        # ts2 = TransformState.makePos(p2)
        # result = self.game.world.sweepTestClosest(self.shape, ts1, ts2, 0)

        if result.hasHit():
            pos = result.getHitPos()
            n = result.getHitNormal()
            frac = result.getHitFraction()
            node = result.getNode()
            return node.getName()
        return None

    def checkRight(self):
        p1 = Point3(self.getPos())
        direction = self.game.playerNp.getPos() - self.getPos()
        direction.normalize()
        right = direction.cross(Vec3(0, 0, 1))
        right = right * 2.0
        p2 = Point3(self.getPos() + right)
        result = self.game.world.rayTestClosest(p1, p2)

        if result.hasHit():
            pos = result.getHitPos()
            n = result.getHitNormal()
            frac = result.getHitFraction()
            node = result.getNode()
            return node.getName()
        return None

    def checkLeft(self):
        p1 = Point3(self.getPos())
        direction = self.game.playerNp.getPos() - self.getPos()
        direction.normalize()
        left = -direction.cross(Vec3(0, 0, 1))
        left = left * 2.0
        p2 = Point3(self.getPos() + left)
        result = self.game.world.rayTestClosest(p1, p2)

        if result.hasHit():
            pos = result.getHitPos()
            n = result.getHitNormal()
            frac = result.getHitFraction()
            node = result.getNode()
            return node.getName()
        return None

    def updateDirection(self):
        direction = self.game.playerNp.getPos() - self.getPos()
        direction.setZ(0)
        direction.normalize()
        direction = direction * self.groundAccel
        right = direction.cross(Vec3(0, 0, 1))
        left = -right

        inFront = self.checkFront()
        inRight = self.checkRight()
        inLeft = self.checkLeft()

        if inFront == "boxpack":
            if inRight == "boxpack":
                if inLeft == "boxPack":
                    self.currentForce = -direction

                else:
                    self.currentForce = left

            else:
                self.currentForce = right
        else:
            self.currentForce = direction

    def update(self, dt=0.0):
        if not self.alive:
            return

        self.brainTimer -= dt
        if self.brainTimer <= 0.0:
            self.updateDirection()
            self.brainTimer = self.brainDelay

        self.setForce(self.currentForce)
        self.capSpeedXY()

        speedVec = self.getSpeedVec()

        self.targetNp.setPos(self.getPos() + speedVec)
        self.lookAt(self.targetNp)

        # growl!
        self.growlTimer -= dt
        if self.growlTimer <= 0.0:
            if self.sound:
                self.game.soundDic3D[self.sound].stop()
                self.game.detachSound(self.sound)

            growlIndex = random.randint(1, len(self.game.zombieGrowlSounds))
            soundName = "monster-" + str(growlIndex)
            self.sound = soundName
            self.game.attachSound(soundName, self.np)
            self.game.playSound3D(soundName)
            self.growlTimer = 1.0 + random.uniform(0.0, 1.0)

            # print "Growl from %s" % (self.name)

            # bite! # player is the only one checking for that now
            # res = self.getContacts()
            # if "player" in res:
            # print "%s took a bite on player at %s!" % (self.name, self.game.globalClock.getFrameTime())
            # self.game.onDie()

    def destroy(self):
        self.alive = False
        self.game.world.removeRigidBody(self.node)
        self.stopWalkAnim()
        self.np.setTransparency(True)
        self.np.setColor(1, 1, 1, 1)
        self.setGlowOff()

        i1 = Wait(random.uniform(0, 1))
        i2 = LerpColorInterval(self.np, 1.0, (1, 1, 1, 0))
        i3 = Func(self.np.remove)
        seq = Sequence()
        seq.append(i1)
        seq.append(i2)
        seq.append(i3)
        seq.start()
Ejemplo n.º 7
0
class BulletNPC(DynamicObject):
    def __init__(self, name, game, pos):
        self.game = game
        self.name = name

        self.jumping = 0
        self.crouching = 0

        # maximum speed when only walking
        self.groundSpeed = 4.0

        # acceleration used when walking to rise to self.groundSpeed
        self.groundAccel = 150.0

        self.groundFriction = 0.0

        # maximum speed in the air (air friction)
        self.airSpeed = 30.0

        # player movement control when in the air
        self.airAccel = 10.0

        # horizontal speed on jump start
        self.jumpSpeed = 5.5

        self.turnSpeed = 5

        self.moveSpeedVec = Vec3(0, 0, 0)
        self.platformSpeedVec = Vec3(0, 0, 0)

        h = 1.75
        w = 0.4

        self.shape = BulletCapsuleShape(w, h - 2 * w, ZUp)
        self.node = BulletRigidBodyNode(self.name)
        self.node.setMass(1.0)
        self.node.addShape(self.shape)
        self.node.setActive(True, True)
        self.node.setDeactivationEnabled(False, True)
        self.node.setFriction(self.groundFriction)
        #self.node.setGravity(10)
        #self.node.setFallSpeed(200)
        self.node.setCcdMotionThreshold(1e-7)

        # do not use setCcdSweptSphereRadius
        # it messes up the bite contact test
        #self.node.setCcdSweptSphereRadius(0.5)

        self.node.setAngularFactor(Vec3(0, 0, 1))

        self.np = self.game.render.attachNewNode(self.node)
        self.setPos(pos)
        self.setH(0)
        #self.np.setCollideMask(BitMask32.allOn())

        self.game.world.attachRigidBody(self.node)
        self.playerModel = Actor(
            "models/monsters/ghoul2.egg", {
                "idle": "models/monsters/ghoul2-idle.egg",
                "walk": "models/monsters/ghoul2-walk.egg"
            })
        self.playerModel.setScale(0.15)
        self.playerModel.setZ(0.15)
        self.playerModel.reparentTo(self.np)

        interval = Wait(random.uniform(0, 1))
        i2 = Func(self.startWalkAnim)
        seq = Sequence()
        seq.append(interval)
        seq.append(i2)
        seq.start()

        self.growlTimer = 5.0
        self.sound = None
        self.alive = True

        self.targetNp = NodePath(self.name)

        self.brainTimer = 0.0
        self.brainDelay = 1.2

        self.currentForce = Vec3(0, 0, 0)

    def startWalkAnim(self):
        self.playerModel.loop("walk")

    def stopWalkAnim(self):
        self.playerModel.loop("idle")

    def checkFront(self):
        p1 = Point3(self.getPos())
        direction = self.game.playerNp.getPos() - self.getPos()
        direction.normalize()
        direction = direction * 2.0
        p2 = Point3(self.getPos() + direction)

        result = self.game.world.rayTestClosest(p1, p2)

        #ts1 = TransformState.makePos(p1)
        #ts2 = TransformState.makePos(p2)
        #result = self.game.world.sweepTestClosest(self.shape, ts1, ts2, 0)

        if result.hasHit():
            pos = result.getHitPos()
            n = result.getHitNormal()
            frac = result.getHitFraction()
            node = result.getNode()
            return node.getName()
        return None

    def checkRight(self):
        p1 = Point3(self.getPos())
        direction = self.game.playerNp.getPos() - self.getPos()
        direction.normalize()
        right = direction.cross(Vec3(0, 0, 1))
        right = right * 2.0
        p2 = Point3(self.getPos() + right)
        result = self.game.world.rayTestClosest(p1, p2)

        if result.hasHit():
            pos = result.getHitPos()
            n = result.getHitNormal()
            frac = result.getHitFraction()
            node = result.getNode()
            return node.getName()
        return None

    def checkLeft(self):
        p1 = Point3(self.getPos())
        direction = self.game.playerNp.getPos() - self.getPos()
        direction.normalize()
        left = -direction.cross(Vec3(0, 0, 1))
        left = left * 2.0
        p2 = Point3(self.getPos() + left)
        result = self.game.world.rayTestClosest(p1, p2)

        if result.hasHit():
            pos = result.getHitPos()
            n = result.getHitNormal()
            frac = result.getHitFraction()
            node = result.getNode()
            return node.getName()
        return None

    def updateDirection(self):
        direction = self.game.playerNp.getPos() - self.getPos()
        direction.setZ(0)
        direction.normalize()
        direction = direction * self.groundAccel
        right = direction.cross(Vec3(0, 0, 1))
        left = -right

        inFront = self.checkFront()
        inRight = self.checkRight()
        inLeft = self.checkLeft()

        if inFront == "boxpack":
            if inRight == "boxpack":
                if inLeft == "boxPack":
                    self.currentForce = -direction

                else:
                    self.currentForce = left

            else:
                self.currentForce = right
        else:
            self.currentForce = direction

    def update(self, dt=0.0):
        if not self.alive:
            return

        self.brainTimer -= dt
        if self.brainTimer <= 0.0:
            self.updateDirection()
            self.brainTimer = self.brainDelay

        self.setForce(self.currentForce)
        self.capSpeedXY()

        speedVec = self.getSpeedVec()

        self.targetNp.setPos(self.getPos() + speedVec)
        self.lookAt(self.targetNp)

        # growl!
        self.growlTimer -= dt
        if self.growlTimer <= 0.0:
            if self.sound:
                self.game.soundDic3D[self.sound].stop()
                self.game.detachSound(self.sound)

            growlIndex = random.randint(1, len(self.game.zombieGrowlSounds))
            soundName = "monster-" + str(growlIndex)
            self.sound = soundName
            self.game.attachSound(soundName, self.np)
            self.game.playSound3D(soundName)
            self.growlTimer = 1.0 + random.uniform(0.0, 1.0)

            #print "Growl from %s" % (self.name)

        # bite! # player is the only one checking for that now
        #res = self.getContacts()
        #if "player" in res:
        #print "%s took a bite on player at %s!" % (self.name, self.game.globalClock.getFrameTime())
        #self.game.onDie()

    def destroy(self):
        self.alive = False
        self.game.world.removeRigidBody(self.node)
        self.stopWalkAnim()
        self.np.setTransparency(True)
        self.np.setColor(1, 1, 1, 1)
        self.setGlowOff()

        i1 = Wait(random.uniform(0, 1))
        i2 = LerpColorInterval(self.np, 1.0, (1, 1, 1, 0))
        i3 = Func(self.np.remove)
        seq = Sequence()
        seq.append(i1)
        seq.append(i2)
        seq.append(i3)
        seq.start()