Files
2025-09-14 22:35:32 +02:00

78 lines
3.0 KiB
Python

import arcade, arcade.math, random, math
class Boid(arcade.Sprite):
def __init__(self, boid_num, x, y):
super().__init__(arcade.load_texture("assets/graphics/boid.png"), center_x=x, center_y=y)
random_angle = random.randint(0, 361)
self.boid_num = boid_num
self.direction = arcade.math.Vec2(math.cos(random_angle), math.sin(random_angle))
self.velocity = 5
self.radius = 10
self.w_separation = 1.0
self.w_cohesion = 1.0
self.w_alignment = 1.0
self.small_radius = 100
self.large_radius = 250
def calculate_separation(self, neighbours):
steeraway_vectors = [arcade.math.Vec2(*self.position) - neighbour[2] for neighbour in neighbours]
if not steeraway_vectors:
return self.direction
return (sum(steeraway_vectors) / len(steeraway_vectors)).normalize()
def calculate_alignment(self, neighbours):
directions = [neighbour[1] for neighbour in neighbours]
if not directions:
return self.direction
return (sum(directions) / len(directions)).normalize()
def calculate_cohesion(self, neighbours):
positions = [neighbour[2] for neighbour in neighbours]
if not positions:
return self.direction
return ((sum(positions) / len(positions)) - self.position).normalize()
def update(self, window_width, window_height, boids):
small_radius_neighbours, large_radius_neighbours = [], []
for boid_data in boids:
distance = boid_data[2].distance(arcade.math.Vec2(*self.position))
if boid_data[0] == self.boid_num or distance > self.large_radius:
continue
if distance <= self.small_radius:
small_radius_neighbours.append(boid_data)
large_radius_neighbours.append(boid_data)
self.direction = self.w_separation * self.calculate_separation(small_radius_neighbours) + self.w_alignment * self.calculate_alignment(large_radius_neighbours) + self.w_cohesion * self.calculate_cohesion(large_radius_neighbours)
if self.direction.length() > 1:
self.direction = self.direction.normalize()
self.position += self.direction * self.velocity
self.angle = 90 - math.degrees(self.direction.heading())
if self.center_x <= self.radius:
self.center_x = self.radius
self.direction = self.direction.reflect(arcade.math.Vec2(1, 0))
elif self.center_x >= (window_width * 0.8) - self.radius:
self.center_x = (window_width * 0.8) - self.radius
self.direction = self.direction.reflect(arcade.math.Vec2(-1, 0))
if self.center_y <= self.radius:
self.center_y = self.radius
self.direction = self.direction.reflect(arcade.math.Vec2(0, 1))
elif self.center_y >= window_height - self.radius:
self.center_y = window_height - self.radius
self.direction = self.direction.reflect(arcade.math.Vec2(0, -1))