Ejemplo n.º 1
0
class SMAI():
    #This constructs the nods tree needed for an AIChar object.
    #Takes in a model as a string, a speed double, a world object, a bullet physics world and n x, y and z positions
    def __init__(self, model, speed, world, worldNP, x, y, z):
        self.AISpeed = 80000
        self.maxSpeed = speed
        self.AIX = x
        self.AIY = y
        self.AIZ = z
        self.worldNP = worldNP
        bulletWorld = world
        self.type = ""
        self.AIModel = loader.loadModel(model)
        self.AIModel.setScale(0.5)
        self.AIModel.reparentTo(render)

        AIShape = BulletBoxShape(Vec3(3, 3, 1))
        self.AINode = BulletRigidBodyNode('AIChar')
        self.AINode.setMass(100)
        self.AINode.addShape(AIShape)

        self.AINode.setDeactivationEnabled(False)
        self.AINode.setAngularFactor(Vec3(0, 0, 0))
        render.attachNewNode(self.AINode)

        self.AIChar = self.worldNP.attachNewNode(self.AINode)
        self.AIModel.reparentTo(self.AIChar)
        self.AIChar.setPos(x, y, z)
        bulletWorld.attachRigidBody(self.AIChar.node())

    #This method needs to be called on your AIChar object to determine what type of AI you want.
    #Takes in a type string; either flee or seek and also a target object.
    def setBehavior(self, type, target):
        if (type == "flee"):
            self.type = type
            self.target = target
            print("Type set to flee")
        elif (type == "seek"):
            self.type = type
            self.target = target
            print("Type set to seek")
        else:
            print("Error @ Incorrect Type!")

    def moveTo(self, target):
        self.moveTo = True
        self.target = target

    def flee(self):
        h = 1
        hx = 1
        hy = 1
        if (self.AIChar.getDistance(self.target) < 40.0):
            if (self.AINode.getLinearVelocity() > self.maxSpeed):
                if (self.AINode.getLinearVelocity() < 100):
                    self.AIChar.setH(self.target.getH())
                    h = self.AIChar.getH()
                else:
                    hx = sin(h * DEG_TO_RAD) * 10
                    hy = cos(h * DEG_TO_RAD) * 10
                    self.AINode.applyForce(
                        Vec3(-hx * self.AISpeed * globalClock.getDt(),
                             hy * self.AISpeed * globalClock.getDt(), 0), PNT)
                # else:
                # self.AINode.applyForce(Vec3(-hx * self.AISpeed * globalClock.getDt(), hy * self.AISpeed * globalClock.getDt(), 0), PNT)

    def seek(self):
        if (self.AIChar.getDistance(self.target) > 20.0):
            if (self.AINode.getLinearVelocity() > self.maxSpeed):
                self.AIChar.lookAt(self.target)
                h = self.AIChar.getH()
                hx = sin(h * DEG_TO_RAD) * 10
                hy = cos(h * DEG_TO_RAD) * 10
                self.AINode.applyForce(
                    Vec3(-hx * self.AISpeed * globalClock.getDt(),
                         hy * self.AISpeed * globalClock.getDt(), 0), PNT)

    def moveToRun(self):
        self.seek()
        # if(self.target.getX()+5 <= self.AIChar.getX() and self.target.getX()-5 >= self.AIChar.getX() and self.target.getY()+5 <= self.AIChar.getY() and self.target.getY()-5 >= self.AIChar.getY()):
        # print("It's stopped!")
        # self.AIChar.clearForces()
        # self.AIChar.setLinearVelocity(0)
        # else:
        # self.AINode.clearForces()
        # self.AIChar.lookAt(self.target)
        # self.AINode.setLinearVelocity(self.AISpeed)

    #Gets called on every AIChar in the world's update method to allow the AI to function at all.
    def AIUpdate(self):
        if (self.moveTo == True):
            self.moveToRun()

        if (self.type == "seek"):
            self.seek()
        elif (self.type == "flee"):
            self.flee()
        else:
            print("Error @ No AI Type")
Ejemplo n.º 2
0
class DodgeShooter(EnemyUnit):
    """Dodge with a machine gun unit.

    Represents an enemy unit, which attacks with
    long pauses, but also deals a lot of damage.

    Args:
        model (actor.Actor): Enemy character model.
        id_ (int): Enemy unit id.
        y_positions (list): Free positions along Y.
        enemy_handler (CollisionHandlerEvent): Enemy collisions handler.
        class_data (dict): This unit class description.
    """
    def __init__(self, model, id_, y_positions, enemy_handler, class_data):
        EnemyUnit.__init__(
            self,
            id_,
            "Gun Dodge",
            class_data,
            model,
            y_positions,
            enemy_handler,
        )

        self._col_node = self._init_col_node(
            SHOT_RANGE_MASK,
            MOUSE_MASK,
            CollisionBox(Point3(-0.04, -0.12, -0.02), Point3(0.04, 0.11,
                                                             0.06)),
        )
        base.common_ctrl.traverser.addCollider(  # noqa: F821
            self._col_node, enemy_handler)
        self._shoot_seq = self._set_shoot_anim()
        self._explosion = base.effects_mgr.explosion_big(self)  # noqa: F821
        self._smoke = base.effects_mgr.burn_smoke(self)  # noqa: F821

    def _set_shoot_anim(self):
        """Prepare machine gun shooting animation for this unit.

        Returns:
            direct.interval.MetaInterval.Sequence:
                Shooting animation and sounds sequence.
        """
        shot_snd = base.sound_mgr.loadSfx(  # noqa: F821
            "sounds/combat/machine_gun_shot1.ogg")
        base.sound_mgr.attachSoundToObject(shot_snd, self.model)  # noqa: F821

        fire = loader.loadModel(address("gun_fire2"))  # noqa: F821
        fire.reparentTo(self.model)
        fire.setScale(1, 0.0001, 1)
        if self._y_pos > 0:
            fire.setPos(-0.055, -0.008, 0.076)
            fire.setH(180)
        else:
            fire.setPos(0.065, -0.008, 0.076)

        shoot_par = Parallel(
            Sequence(
                LerpScaleInterval(fire, 0.07, (1, 1, 1)),
                LerpScaleInterval(fire, 0.07, (1, 0.0001, 1)),
                Wait(0.12),
            ),
            SoundInterval(shot_snd, duration=0.25),
        )
        return Sequence(*(shoot_par, ) * 20)

    def capture_train(self):
        """The Train got critical damage - stop near it."""
        EnemyUnit.capture_train(self)

        self._stop_tasks("_shoot_at_train", "_do_damage_to_train",
                         "_stop_doing_damage")

    def enter_the_part(self, part):
        """Start fighting in the given part.

        Args:
            part (train.part.TrainPart): Train part this enemy entered.
        """
        self.current_part = part

        self.model.play("turn_right" if self._y_pos < 0 else "turn_left")

        taskMgr.doMethodLater(  # noqa: F821
            2, self._shoot_at_train, self.id + "_shoot_at_train")

    def leave_the_part(self, _):
        """Stop fighting in the current part."""
        self._stop_tasks("_shoot_at_train", "_do_damage_to_train",
                         "_stop_doing_damage")
        self.current_part = None

    def _shoot_at_train(self, task):
        """Start shooting volley, including logic, animations, sounds."""
        self._shoot_seq.start()
        taskMgr.doMethodLater(  # noqa: F821
            0.5, self._do_damage_to_train, self.id + "_do_damage_to_train")
        taskMgr.doMethodLater(  # noqa: F821
            6,
            taskMgr.remove,  # noqa: F821
            self.id + "_stop_doing_damage",
            extraArgs=[self.id + "_do_damage_to_train"],
        )
        task.delayTime = random.randint(15, 18)
        return task.again

    def _do_damage_to_train(self, task):
        """Deal machine gun damage to the Train."""
        if self.current_part.is_covered:
            if chance(40):
                base.train.get_damage(2)  # noqa: F821
        else:
            base.train.get_damage(2)  # noqa: F821

        base.train.get_shot(self._y_pos > 0)  # noqa: F821
        return task.again

    def _explode(self):
        """Play explosion sequence of effects and sounds.

        Also includes explosion physics.
        """
        self._explosion.play()
        self._smoke.play()

        self._rb_node = BulletRigidBodyNode(self.id + "_physics")
        self._rb_node.setMass(100)
        self._rb_node.addShape(BulletBoxShape(Vec3(0.06, 0.1, 0.028)))
        self._rb_node.deactivation_enabled = False

        phys_node = self.node.attachNewNode(self._rb_node)  # noqa: F821

        self.model.reparentTo(phys_node)
        self.model.setPos(0, 0, -0.03)
        base.world.phys_mgr.attachRigidBody(self._rb_node)  # noqa: F821

        # boom impulse
        angle = round(self.model.getH(render))  # noqa: F821
        x = 0
        y = 0
        if angle == 0:
            y = random.randint(6500, 8500)
        elif angle == 90:
            x = -random.randint(6500, 8500)
        elif angle == -90:
            x = random.randint(6500, 8500)

        self._rb_node.applyForce(Vec3(x, y, random.randint(1500, 2500)),
                                 Point3(0, -0.1, 0))
        self._rb_node.applyTorque(
            Vec3(
                random.randint(-30, 30),
                random.randint(-30, 30),
                random.randint(-30, 30),
            ))

    def _die(self):
        """Die actions for this shooter.

        Returns:
            bool: True, if this shooter dies for the first time.
        """
        if EnemyUnit._die(self):
            self._shoot_seq.finish()
            self._stop_tasks("_shoot_at_train", "_stop_doing_damage",
                             "_do_damage_to_train")
Ejemplo n.º 3
0
class SMAI():
	#This constructs the nods tree needed for an AIChar object.
	#Takes in a model as a string, a speed double, a world object, a bullet physics world and n x, y and z positions
	def __init__(self, model, speed, world, worldNP, x, y, z):
		self.AISpeed = 80000
		self.maxSpeed = speed
		self.AIX = x
		self.AIY = y
		self.AIZ = z
		self.worldNP = worldNP
		bulletWorld = world
		self.type = ""
		self.AIModel = loader.loadModel(model)
		self.AIModel.setScale(0.5)
		self.AIModel.reparentTo(render)
		
		AIShape = BulletBoxShape(Vec3(3, 3, 1))
		self.AINode = BulletRigidBodyNode('AIChar')
		self.AINode.setMass(100)
		self.AINode.addShape(AIShape)
		
		self.AINode.setDeactivationEnabled(False)
		self.AINode.setAngularFactor(Vec3(0,0,0))
		render.attachNewNode(self.AINode)
		
		self.AIChar = self.worldNP.attachNewNode(self.AINode)
		self.AIModel.reparentTo(self.AIChar)
		self.AIChar.setPos(x, y, z)
		bulletWorld.attachRigidBody(self.AIChar.node())

	#This method needs to be called on your AIChar object to determine what type of AI you want.
	#Takes in a type string; either flee or seek and also a target object.
	def setBehavior(self, type, target):
		if(type == "flee"):
			self.type = type
			self.target = target
			print("Type set to flee")
		elif(type == "seek"):
			self.type = type
			self.target = target
			print("Type set to seek")
		else:
			print("Error @ Incorrect Type!")

	def moveTo(self, target):
		self.moveTo = True
		self.target = target
			
	def flee(self):
		h = 1
		hx = 1
		hy = 1
		if(self.AIChar.getDistance(self.target) < 40.0):
			if(self.AINode.getLinearVelocity() > self.maxSpeed):
				if(self.AINode.getLinearVelocity() < 100):
					self.AIChar.setH(self.target.getH())
					h = self.AIChar.getH()
				else:
					hx = sin(h * DEG_TO_RAD) * 10
					hy = cos(h * DEG_TO_RAD) * 10
					self.AINode.applyForce(Vec3(-hx * self.AISpeed * globalClock.getDt(), hy * self.AISpeed * globalClock.getDt(), 0), PNT)
				# else:
					# self.AINode.applyForce(Vec3(-hx * self.AISpeed * globalClock.getDt(), hy * self.AISpeed * globalClock.getDt(), 0), PNT)

	def seek(self):
		if(self.AIChar.getDistance(self.target) > 20.0):
			if(self.AINode.getLinearVelocity() > self.maxSpeed):
				self.AIChar.lookAt(self.target)
				h = self.AIChar.getH()
				hx = sin(h * DEG_TO_RAD) * 10
				hy = cos(h * DEG_TO_RAD) * 10
				self.AINode.applyForce(Vec3(-hx * self.AISpeed * globalClock.getDt(), hy * self.AISpeed * globalClock.getDt(), 0), PNT)
		
	def moveToRun(self):
		self.seek()
		# if(self.target.getX()+5 <= self.AIChar.getX() and self.target.getX()-5 >= self.AIChar.getX() and self.target.getY()+5 <= self.AIChar.getY() and self.target.getY()-5 >= self.AIChar.getY()):
			# print("It's stopped!")
			# self.AIChar.clearForces()
			# self.AIChar.setLinearVelocity(0)
		# else:
			# self.AINode.clearForces()
			# self.AIChar.lookAt(self.target)
			# self.AINode.setLinearVelocity(self.AISpeed)
	
	#Gets called on every AIChar in the world's update method to allow the AI to function at all.
	def AIUpdate(self):
		if(self.moveTo == True):
			self.moveToRun()
			
		if(self.type == "seek"):
			self.seek()
		elif(self.type == "flee"):
			self.flee()
		else:
			print("Error @ No AI Type")
Ejemplo n.º 4
0
class EnemyMotorcyclist(EnemyUnit):
    """Enemy unit on motorcycle base class.

    Includes a motocycle explosion effect and a
    collision node appropriate for any motorcyclist.

    Args:
        id_ (int): Enemy unit id.
        class_ (str): Enemy class name.
        class_data (dict): Enemy class description.
        model (actor.Actor): Enemy character model.
        y_positions (list): Free positions along Y.
        enemy_handler (CollisionHandlerEvent): Enemy collisions handler.
    """
    def __init__(self, id_, class_, class_data, model, y_positions,
                 enemy_handler):
        EnemyUnit.__init__(self, id_, class_, class_data, model, y_positions,
                           enemy_handler)
        if chance(50):
            taskMgr.doMethodLater(  # noqa: F821
                random.randint(26, 28), self._play_idle_anim,
                self.id + "_idle")
            self._cry_snd = base.sound_mgr.loadSfx(  # noqa: F821
                "sounds/combat/enemy_cry{num}.ogg".format(
                    num=random.randint(1, 3)))
            self._cry_snd.setVolume(0.4)
            base.sound_mgr.attachSoundToObject(self._cry_snd,
                                               self.model)  # noqa: F821
        else:
            self._cry_snd = None

        taskMgr.doMethodLater(  # noqa: F821
            random.randint(27, 29),
            base.world.play_fight_music,  # noqa: F821
            "play_music",
        )
        self._col_node = self._init_col_node(SHOT_RANGE_MASK, MOUSE_MASK,
                                             CollisionSphere(0, 0, 0.05, 0.05))
        base.common_ctrl.traverser.addCollider(  # noqa: F821
            self._col_node, enemy_handler)
        self._explosion = base.effects_mgr.explosion(self)  # noqa: F821

    def _explode(self):
        """Play explosion sequence of effects and sounds.

        Also includes explosion physics.
        """
        self._explosion.play()

        self._rb_node = BulletRigidBodyNode(self.id + "_physics")
        self._rb_node.setMass(80)
        self._rb_node.addShape(BulletBoxShape(Vec3(0.005, 0.04, 0.028)))
        self._rb_node.deactivation_enabled = False

        phys_node = self.node.attachNewNode(self._rb_node)  # noqa: F821

        self.model.reparentTo(phys_node)
        self.model.setPos(0, -0.01, -0.025)
        base.world.phys_mgr.attachRigidBody(self._rb_node)  # noqa: F821

        # boom impulse
        angle = self.model.getH(render)  # noqa: F821
        x = 0
        y = 0
        if angle == 0:
            y = random.randint(6500, 8500)
        elif angle == 90:
            x = -random.randint(6500, 8500)
        elif angle == -90:
            x = random.randint(6500, 8500)

        self._rb_node.applyForce(Vec3(x, y, random.randint(1500, 2500)),
                                 Point3(0))
        self._rb_node.applyTorque(
            Vec3(
                random.randint(-35, 35),
                random.randint(-35, 35),
                random.randint(-35, 35),
            ))

    def _play_idle_anim(self, task):
        """Play enemy unit idle animation."""
        self.model.play(random.choice(("idle1", "idle2")))
        if self._cry_snd is not None:
            self._cry_snd.play()

        return task.done