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
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