def apply_force(self):


        # behavior:
        #
        # 1. position
        # a) go to closest fish
        # b) avoid other predators
        # c) random walk
        #
        # 2. angle
        # a) rotate so that we move into direction

        preys = [ f for f in self.mode.swarm.fishes if (f.position - self.position).length < c.PREDATOR_SENSES]
        if self.target:
            preys.append(self.target)

        go_to_prey = self.random_walk_direction
        if preys:
            new_target = sorted(preys, key=lambda p: (p.position - self.position).length_squared)[0]
            if self.target != new_target:
                self.mode.game.audio.play("attack")

            self.target = new_target

            go_to_prey = self.target.position - self.position

            if new_target.swarm.swarm_mode == -1:
                go_to_prey = go_to_prey * -1

        neighbors = [ p for p in self.mode.predators if (p.position - self.position).length < c.PREDATOR_REPEL_DISTANCE ]
        repel_sum = m.Vector(0, 0)
        for n in neighbors:
            repel = self.position - n.position
            repel_sum += repel * (c.PREDATOR_REPEL_STRENGTH / (1 + repel.length))

        self.target_direction = go_to_prey * c.PREDATOR_W_GO_TO_PREY + repel_sum * c.PREDATOR_W_REPEL
        self.target_direction = self.target_direction.clamp()

        self.target_angle = math.atan2(self.target_direction.y, self.target_direction.x)
        self.target_angle %= math.pi * 2

        self.target_rotation = u.angle_steer(self.target_angle, self.angle)

        self.angular_velocity -= self.target_rotation * c.PREDATOR_ANGULAR_ACCELERATION
        acc = m.Vector(math.cos(self.angle), math.sin(self.angle))

        acceleration = c.PREDATOR_HUNT_ACCELERATION if self.target else c.PREDATOR_ACCELERATION
        self.acceleration += acc *  (acc * self.target_direction.clamp()) * acceleration
示例#2
0
    def apply_force(self):

        # behavior:
        #
        # 1. position
        # a) go to at least c.SWARM_MIN_DISTANCE units from swarm center
        # b) avoid other fish
        #
        # 2. angle
        # a) align with other fish
        # b) rotate so that we move into direction

        go_to_swarm = self.swarm.position - self.position
        if go_to_swarm.length < c.SWARM_MIN_DISTANCE:
            go_to_swarm = m.VECTOR_NULL

        snd_squared = c.SWARM_NEIGHBOR_DISTANCE ** 2


        flee_from_predator_sum = m.Vector(0, 0)
        pd_squared = c.FISH_AVOID_PREDATOR_DISTANCE ** 2
        predators = [ p for p in self.swarm.mode.predators if (p.position - self.position).length_squared < pd_squared]
        for p in predators:
            flee_from_predator_sum += (self.position - p.position)


        neighbors = [ n for n in self.swarm.fishes if (n.position - self.position).length_squared < snd_squared]
        neighbors_direction = sum(  (n.angle + 2*math.pi) % (2*math.pi) for n in neighbors ) / len(neighbors)

        neighbors_direction = neighbors_direction % (2*math.pi)

        fd_squared = c.FISH_FOOD_DISTANCE ** 2

        foods = [ f for f in self.mode.foods if (f.position - self.position).length_squared < fd_squared]
        if foods and go_to_swarm.length < c.SWARM_MAX_DISTANCE:
            closest_food = sorted(foods, key=lambda f: (f.position - self.position).length_squared)[0]

            go_to_swarm = closest_food.position - self.position

            if go_to_swarm.length < c.FISH_EAT_DISTANCE * 0.2:
                go_to_swarm = m.VECTOR_NULL

            if go_to_swarm.length < c.FISH_EAT_DISTANCE:
                closest_food.nutrition_value -= c.FISH_EAT_DAMAGE
                self.modify_food(c.FISH_EAT_DAMAGE)
                self.mode.food_eaten += c.FISH_EAT_DAMAGE

                self.mode.game.audio.play("eat")

                if self.food:
                    color_ratio = 1 / self.food

                    for i in range(3):
                        self.color[i] = (1-color_ratio) * self.color[i] + color_ratio * closest_food.color[i]
                        if self.color[i] > 255: self.color[i] = 255
                        if self.color[i] < 0: self.color[i] = 0

                if closest_food.nutrition_value <= 0:
                    self.mode.foods.remove(closest_food)


        repel_sum = m.Vector(0, 0)


        rd_squared = c.SWARM_NEIGHBOR_REPEL_DISTANCE ** 2

        if self.swarm.swarm_mode == -1:
            rd_squared = c.SWARM_NEIGHBOR_REPEL_DISTANCE_SMALL ** 2
        elif self.swarm.swarm_mode == 1:
            rd_squared = c.SWARM_NEIGHBOR_REPEL_DISTANCE_LARGE ** 2

        for n in neighbors:
            repel = self.position - n.position
            if repel.length_squared <= rd_squared:
                repel_sum += repel * ( c.FISH_REPEL_STRENGTH / (1 + repel.length))

        self.target_direction = flee_from_predator_sum * c.FISH_W_FLEE +  go_to_swarm * c.FISH_W_GO_TO_SWARM + repel_sum * c.FISH_W_REPEL
        self.target_direction = self.target_direction.clamp()

        move_angle = math.atan2(self.target_direction.y, self.target_direction.x)

        #self.target_angle = move_angle
        self.target_angle = neighbors_direction * c.FISH_W_ALIGN + move_angle * (1 - c.FISH_W_ALIGN) + math.pi * 2
        self.target_angle %= math.pi * 2

        self.target_rotation = u.angle_steer(self.target_angle, self.angle)

        #self.acceleration += self.target_direction * c.FISH_ACCELERATION

        self.angular_velocity -= self.target_rotation * c.FISH_ANGULAR_ACCELERATION
        acc = m.Vector(math.cos(self.angle), math.sin(self.angle))

        self.acceleration += acc *  (acc * self.target_direction.clamp()) * c.FISH_ACCELERATION