mirror of
https://github.com/csd4ni3l/simulator-games.git
synced 2026-01-01 12:23:44 +01:00
78 lines
3.0 KiB
Python
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))
|