You are on page 1of 16

# -*- coding: utf-8 -*-

"""

Created on Wed Feb 28 20:20:49 2024

@author: Maintenant Pret

"""

import numpy as np

import os

import networkx as nx

import pygame

import sys

import random

from scipy.spatial.distance import cdist

import math

thorus=True

#create random fish world

new_working_directory = r'C:\Users\Maintenant Pret\OneDrive\Bureau\projet prog'

# Change the working directory

os.chdir(new_working_directory)

X=1920

Y=1080

Z=1000

numb_fish = 100
numb_pred = 0

predators_repulsion=1000

threshold_angle = np.radians(70)

turn_probability=20

pygame.display.set_caption("Sliders")

WIDTH, HEIGHT = X,Y

# Colors

WHITE = (255, 255, 255)

BLACK = (0, 0, 0)

RED = (255, 0, 0)

# Slider parameters

slider_width = 200

slider_height = 20

slider_x = 50

slider_spacing = 40

slider_min = 0

slider_max = 500

# Function to draw sliders

slider_x = WIDTH - slider_width - 50 # Adjust as needed for spacing from the right edge

# Function to draw sliders with updated x-coordinate

def draw_slider(name, value, y):

# Draw slider label

label = font.render(name + ': ' + str(value), True, BLACK)


screen.blit(label, (WIDTH - slider_width - 10, y)) # Adjust x-coordinate

# Draw slider

pygame.draw.rect(screen, BLACK, (slider_x, y + 30, slider_width, slider_height))

pygame.draw.rect(screen, RED, (slider_x, y + 30, (value / slider_max) * slider_width, slider_height))

def rotate_vector(vector, angle):

axis=random.randint(1,3)

angle_radians = math.radians(angle)

if axis == 1:

rotation_matrix = np.array([[1, 0, 0], [0, math.cos(angle_radians), -math.sin(angle_radians)],[0,


math.sin(angle_radians), math.cos(angle_radians)]])

elif axis == 2:

rotation_matrix = np.array([[math.cos(angle_radians), 0, math.sin(angle_radians)], [0, 1, 0],[-


math.sin(angle_radians), 0, math.cos(angle_radians)]])

elif axis == 3:

rotation_matrix = np.array([[math.cos(angle_radians), -math.sin(angle_radians), 0],


[math.sin(angle_radians), math.cos(angle_radians), 0],[0, 0, 1]])

rotated_vector = np.dot(rotation_matrix, vector)

return rotated_vector

def in_vision_field(animal1,animal2,half_angle):

apex_to_point=np.array([animal2.x,animal2.y,animal2.z])-np.array([animal1.x,animal.y,animal.z])

cos_angle = np.dot(apex_to_point, animal1.direction) / (np.linalg.norm(apex_to_point) *


np.linalg.norm(animal1.direction))

angle = np.arccos(np.clip(cos_angle, -1, 1))

if angle <= np.radians(half_angle):

return True
else:

return False

class fish:

speed = 30

color = (255,255,255)

def __init__(self, x, y,z, direction):

self.x = x

self.y = y

self.z=z

self.direction = direction

self.direction_vectors = []

def draw(self, screen):

size_adjust = (self.z / Z)+0.5

if np.linalg.norm(self.direction) != 1.0:

self.direction = self.direction / np.linalg.norm(self.direction)

dx, dy = self.direction[:2]

vertices = [

np.array([self.x, self.y])-20*size_adjust *np.array([dx, dy]),

np.array([self.x, self.y])+ 3*np.array([dy, -dx])*size_adjust,

np.array([self.x, self.y])+3*np.array([-dy, dx])*size_adjust

head = np.linalg.norm(np.array([dy, -dx]) )*size_adjust

# Scale the RGB components based on z


r = min(255, max(0, int(fish.color[0] * (self.z / Z))))

g = min(255, max(0, int(fish.color[1] * (self.z / Z))))

b = min(255, max(0, int(fish.color[2] * (self.z / Z))))

pygame.draw.polygon(screen, (r, g, b), vertices)

pygame.draw.circle(screen, (r, g, b), (self.x, self.y), 4*head)

class predator:

speed=10

color=(255,0,255)

def __init__(self, x, y,z, direction):

self.x = x

self.y = y

self.z=z

self.direction = direction

self.direction_vectors=[]

def draw(self, screen):

size_adjust = (self.z / Z)+0.5

if np.linalg.norm(self.direction) != 1.0:

self.direction = self.direction / np.linalg.norm(self.direction)

# Scale the RGB components based on z

r = min(255, max(0, int(predator.color[0] * (1 - self.z / Z))))

g = min(255, max(0, int(predator.color[1] * (1 - self.z / Z))))

b = min(255, max(0, int(predator.color[2] * (1 - self.z / Z))))

pygame.draw.circle(screen, (r,g,b), (self.x, self.y), 6.5/size_adjust)


def update(self):

chance=random.randint(1,10)

if chance==1:

self.direction = rotate_vector(self.direction,30)

elif chance==2:

self.direction = rotate_vector(self.direction,-30)

total_direction = np.sum(self.direction_vectors, axis=0)

if np.linalg.norm(total_direction) > 0:

total_direction = total_direction / np.linalg.norm(total_direction)

if isinstance(total_direction,np.ndarray):

self.direction = total_direction

updated_position = np.array([self.x, self.y, self.z]) + np.array(self.direction) * predator.speed


self.x = updated_position[0]

self.y = updated_position[1]

self.z = updated_position[2]

if thorus==True:

if self.x>X:

self.x=0

if self.y>Y:

self.y=0

if self.z>Z:

self.z=0

if self.x<0:

self.x=X

if self.y<0:

self.y=Y

if self.z<0:

self.z=Z

else:

if self.x>X:

self.direction[0]=-self.direction[0]

if self.y>Y:

self.direction[1]=-self.direction[1]

if self.z>Z:

self.direction[2]=-self.direction[2]

if self.x<0:

self.direction[0]=-self.direction[0]

if self.y<0:

self.direction[1]=-self.direction[1]

if self.z<0:

self.direction[2]=-self.direction[2]
animals = []

distx = random.randint(1, X)

disty = random.randint(1, Y)

distz = random.randint(1, Z)

length = math.sqrt(distx ** 2 + disty ** 2 + distz**2)

for n in range(numb_fish):

distx = random.randint(1, X)

disty = random.randint(1, Y)

distz = random.randint(1, Z)

length = math.sqrt(distx ** 2 + disty ** 2 + distz**2)

animals.append(fish(x=random.randint(1, X,), y=random.randint(1, Y),


z=random.randint(1,Z),direction=np.array([distx / length, disty / length, distz/length])))

for n in range(numb_pred):

distx = random.randint(1, X)

disty = random.randint(1, Y)

distz = random.randint(1, Z)

length = math.sqrt(distx ** 2 + disty ** 2 + distz**2)

animals.append(predator(x=random.randint(1, X), y=random.randint(1, Y),


z=random.randint(1,Z),direction=np.array([distx / length, disty / length, distz/length])))

def fish_update(attraction,repulsion,alignment,half_angle):
coordinates = np.array([[animal.x, animal.y, animal.z] for animal in animals])

distances = cdist(coordinates, coordinates, metric='euclidean')

indices = np.triu_indices(distances.shape[0], k=1)

all_indices = np.vstack((indices[0], indices[1]))

for animal in animals:

animal.direction_vectors = []

for i, j in zip(*all_indices):

if isinstance(animals[i], fish):

if in_vision_field(animals[i], animals[j], half_angle) and (thorus==True) or (thorus==False and


animals[i].x<X-5 and animals[i].y<Y-5 and animals[i].z<Z-5):

if isinstance(animals[j],fish):

#repulsion

if distances[i, j] < repulsion and distances[i, j] >0:

rep = np.array([(animals[i].x - animals[j].x) / (distances[i, j]), (animals[i].y - animals[j].y) /


(distances[i, j]),(animals[i].z - animals[j].z) / (distances[i, j])])

rep = rep / np.linalg.norm(rep)

animals[i].direction_vectors.append(rep)

animals[j].direction_vectors.append(-rep)
#alignement

elif distances[i, j] < alignment:

al = np.array([(animals[i].x + animals[j].x), animals[i].y + animals[j].y, animals[i].z +


animals[j].z])

al = al / np.linalg.norm(al)

animals[i].direction_vectors.append(al)

alj = np.array([(animals[i].x + animals[j].x), animals[i].y + animals[j].y, animals[i].z +


animals[j].z])

alj = alj / np.linalg.norm(alj)

print(np.linalg.norm(alj))

#attraction

elif distances[i, j] <= attraction and distances[i, j] > 0:

attr = np.array([(animals[j].x - animals[i].x) / distances[i, j], (animals[j].y - animals[i].y) /


distances[i, j], (animals[j].z - animals[i].z) / distances[i, j]])

attr = attr / np.linalg.norm(attr)

animals[i].direction_vectors.append(attr)

animals[j].direction_vectors.append(-attr)

elif distances[i, j] < predators_repulsion:

prep = np.array([(animals[i].x - animals[j].x) / (distances[i, j]), (animals[i].y -


animals[j].y) / (distances[i, j]),(animals[i].z - animals[j].z) / (distances[i, j])])

prep = prep / np.linalg.norm(prep)

animals[i].direction_vectors.append(prep)
if isinstance(animals[j],predator) and isinstance(animals[i],fish) and in_vision_field(animals[j],
animals[i], variables['Vision Angle']):

if distances[i, j] < predators_repulsion:

patt = np.array([(animals[i].x - animals[j].x) / (distances[i, j]), (animals[i].y - animals[j].y) /


(distances[i, j]),(animals[i].z - animals[j].z) / (distances[i, j])])

patt = patt / np.linalg.norm(patt)

animals[j].direction_vectors.append(patt)

for animal in animals:

if isinstance(animal,fish):

total_direction = np.sum(animal.direction_vectors, axis=0)

if np.linalg.norm(total_direction) > 0:

total_direction = total_direction / np.linalg.norm(total_direction)

chance=random.randint(1,turn_probability)

if chance==2 and (thorus==True) or (thorus==False and animals[i].x<X-5 and animals[i].y<Y-5


and animals[i].z<Z-5):

total_direction = rotate_vector(animal.direction,29)
elif chance==3 and (thorus==True) or (thorus==False and animals[i].x<X-5 and animals[i].y<Y-5
and animals[i].z<Z-5):

total_direction = rotate_vector(animal.direction,-29)

else:

pass

angle_between = np.arccos(np.dot(animal.direction, total_direction) /


(np.linalg.norm(animal.direction) * np.linalg.norm(total_direction)))

if np.any(angle_between >= threshold_angle):

rotation_axis = np.cross(animal.direction, total_direction)

rotation_axis /= np.linalg.norm(rotation_axis)

rotation_matrix = np.array([[np.cos(threshold_angle) + rotation_axis[0]**2 * (1 -


np.cos(threshold_angle)), rotation_axis[0] * rotation_axis[1] * (1 - np.cos(threshold_angle)) -
rotation_axis[2] * np.sin(threshold_angle), rotation_axis[0] * rotation_axis[2] * (1 -
np.cos(threshold_angle)) + rotation_axis[1] * np.sin(threshold_angle)], [rotation_axis[1] *
rotation_axis[0] * (1 - np.cos(threshold_angle)) + rotation_axis[2] * np.sin(threshold_angle),
np.cos(threshold_angle) + rotation_axis[1]**2 * (1 - np.cos(threshold_angle)), rotation_axis[1] *
rotation_axis[2] * (1 - np.cos(threshold_angle)) - rotation_axis[0] * np.sin(threshold_angle)],
[rotation_axis[2] * rotation_axis[0] * (1 - np.cos(threshold_angle)) - rotation_axis[1] *
np.sin(threshold_angle), rotation_axis[2] * rotation_axis[1] * (1 - np.cos(threshold_angle)) +
rotation_axis[0] * np.sin(threshold_angle), np.cos(threshold_angle) + rotation_axis[2]**2 * (1 -
np.cos(threshold_angle))]])

total_direction = np.dot(rotation_matrix, animal.direction)

if isinstance(total_direction,np.ndarray):

animal.direction = total_direction

updated_position = np.array([animal.x, animal.y, animal.z]) + animal.direction * animal.speed

animal.x = updated_position[0]

animal.y = updated_position[1]

animal.z = updated_position[2]
if thorus==True:

if animal.x>X:

animal.x=0

if animal.y>Y:

animal.y=0

if animal.z>Z:

animal.z=0

if animal.x<0:

animal.x=X

if animal.y<0:

animal.y=Y

if animal.z<0:

animal.z=Z

else:

if animal.x>X:

animal.direction[0]=-animal.direction[0]

animal.x=X

animals[i].direction_vectors.append(np.array([-1,0,0]))

if animal.y>Y:

animal.direction[1]=-animal.direction[1]

animal.y=Y

animals[i].direction_vectors.append(np.array([0,-1,0]))

if animal.z>Z:

animal.direction[2]=-animal.direction[2]

animal.z=Z

animals[i].direction_vectors.append(np.array([0,0,-1]))

if animal.x<0:

animal.direction[0]=-animal.direction[0]

animal.x=0

animals[i].direction_vectors.append(np.array([1,0,0]))
if animal.y<0:

animal.direction[1]=-animal.direction[1]

animal.y=0

animals[i].direction_vectors.append(np.array([0,1,0]))

if animal.z<0:

animal.direction[2]=-animal.direction[2]

animal.z=0

animals[i].direction_vectors.append(np.array([0,0,1]))

else:

animal.update()

for animal in animals:

if isinstance(animal,type(fish)):

animal.direction_vectors = [vec / np.linalg.norm(vec) for vec in animal.direction_vectors]

# Initialize Pygame

pygame.init()

pygame.font.init()

# Font

font = pygame.font.SysFont(None, 30)

# Variables

variables = {

'Vision Angle': 50,

'Repulsion': 50,

'Alignment': 50,

'Attraction': 50

# Set up the screen


screen = pygame.display.set_mode((WIDTH, HEIGHT))

pygame.display.set_caption("animals")

# Colors

WHITE = (255, 255, 255)

BLUE = (0,25,50)

# Set up the clock

clock = pygame.time.Clock()

# Game loop

running = True

while running:

# Handle events

for event in pygame.event.get():

if event.type == pygame.QUIT:

running = False

elif event.type == pygame.MOUSEBUTTONDOWN:

if slider_x <= event.pos[0] <= slider_x + slider_width:

for idx, name in enumerate(variables):

y = 50 + idx * slider_spacing

if y + 30 <= event.pos[1] <= y + 30 + slider_height:

variables[name] = int((event.pos[0] - slider_x) / slider_width * slider_max)

screen.fill(BLUE)

fish_update(variables['Attraction'],variables['Repulsion'],variables['Alignment'],variables['Vision
Angle'])

# Draw sliders
y = 50

for name, value in variables.items():

draw_slider(name, value, y)

y += slider_spacing

for animal in animals:

animal.draw(screen)

# Update the display

pygame.display.flip()

# Cap the frame rate

clock.tick(60)

# Quit Pygame

pygame.quit()

sys.exit()

You might also like