#include "fish.h" Fish::Fish(const int x, const int y, const float vx, const float vy, std::vector &school, const int id, const int width, const int height, SDL_Renderer* renderer, int biasdir, SDL_Texture* texture) : x(x), y(y), vx(vx), vy(vy), school(school), id(id), width(width), height(height), biasdir(biasdir), texture(texture) { // Constructor implementation } Fish::Fish(const Fish& other) : x(other.x), y(other.y), vx(other.vx), vy(other.vy), school(other.school), id(other.id), texture(other.texture), width(other.width), height(other.height), biasdir(other.biasdir) { // Additional initialization if needed } Fish& Fish::operator=(const Fish& other) { if (this != &other) { x = other.x; y = other.y; vx = other.vx; vy = other.vy; school = other.school; id = other.id; texture = other.texture; width = other.width; height = other.height; biasdir = other.biasdir; } return *this; } void Fish::drawArrow(SDL_Renderer *renderer, int x, int y, float vx, float vy) { const int arrowLength = 30; // Augmenter la longueur de la flèche const int arrowWidth = 10; // Garder la largeur de la flèche constante SDL_Point points[4]; if (vx == 0 && vy == 0) return; float angle = atan2(vy, vx); points[0] = {x + static_cast(arrowLength * cos(angle)), y + static_cast(arrowLength * sin(angle))}; points[1] = { x + static_cast(arrowWidth * cos(angle + M_PI / 6)), y + static_cast(arrowWidth * sin(angle + M_PI / 6)) }; points[2] = { x + static_cast(arrowWidth * cos(angle - M_PI / 6)), y + static_cast(arrowWidth * sin(angle - M_PI / 6)) }; points[3] = points[0]; SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); // Vert SDL_RenderDrawLines(renderer, points, 4); } void Fish::draw(SDL_Renderer *renderer) { Camera &camera = Camera::getInstance(); int cameraX = camera.getX(); int cameraY = camera.getY(); SDL_Rect rect = {static_cast(x) - cameraX, static_cast(y) - cameraY, width, height}; float angle = atan2(vy, vx) * 180 / M_PI; // Convert angle to degrees if (texture) { SDL_RenderCopyEx(renderer, texture, nullptr, &rect, angle, nullptr, SDL_FLIP_NONE); } else { SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // Red SDL_RenderFillRect(renderer, &rect); } //drawArrow(renderer, x + width / 2, y + height / 2, vx, vy); } bool Fish::isInView(Fish &other) { return (other.getX() >= x - VISUAL_RANGE && other.getX() <= x + VISUAL_RANGE && other.getY() >= y - VISUAL_RANGE && other.getY() <= y + VISUAL_RANGE); } bool Fish::isClose(Fish &other) { return (other.getX() >= x - PROTECTED_RANGE && other.getX() <= x + PROTECTED_RANGE && other.getY() >= y - PROTECTED_RANGE && other.getY() <= y + PROTECTED_RANGE); } void Fish::checkNeighborhood(Fish &other,float &xpos_avg, float &ypos_avg, float &xvel_avg, float &yvel_avg, int &neighboring_boids, float &close_dx, float &close_dy) { if (isInView(other)) { if (isClose(other)) { close_dx += x - other.getX(); close_dy += y - other.getY(); } xpos_avg += other.getX(); ypos_avg += other.getY(); xvel_avg += other.getVx(); yvel_avg += other.getVy(); neighboring_boids++; } } void Fish::insertionSort(std::vector& school) { for (size_t i = 1; i < school.size(); ++i) { Fish key = school[i]; int j = i - 1; while (j >= 0 && Fish::SortByX(key, school[j])) { school[j + 1] = school[j]; --j; } school[j + 1] = key; } } void Fish::cycle(int iter) { int neighboring_boids = 0; float xvel_avg = 0, yvel_avg = 0, xpos_avg = 0, ypos_avg = 0, close_dx = 0, close_dy = 0; for (int i = iter; i < school.size(); i++) { if (school[i].getId() != id) { if (school[i].getX() - VISUAL_RANGE > x + VISUAL_RANGE) { break; } checkNeighborhood(school[i], xpos_avg, ypos_avg, xvel_avg, yvel_avg, neighboring_boids, close_dx, close_dy); } } for (int i = iter - 1; i >= 0; i--) { if (school[i].getId() != id) { if (school[i].getX() + VISUAL_RANGE < x - VISUAL_RANGE) { break; } checkNeighborhood(school[i], xpos_avg, ypos_avg, xvel_avg, yvel_avg, neighboring_boids, close_dx, close_dy); } } if (neighboring_boids > 0) { xpos_avg /= neighboring_boids; ypos_avg /= neighboring_boids; xvel_avg /= neighboring_boids; yvel_avg /= neighboring_boids; vx += (xpos_avg - x) * CENTERING_FACTOR + (xvel_avg - vx) * MATCHING_FACTOR; vy += (ypos_avg - y) * CENTERING_FACTOR + (yvel_avg - vy) * MATCHING_FACTOR; } vx += close_dx * AVOIDANCE_FORCE; vy += close_dy * AVOIDANCE_FORCE; if (y <= 0) { vy += TURN_FACTOR; } if (y >= (ENV_WIDTH - MARGIN_HEIGHT)) { vy -= TURN_FACTOR; } if (x <= 0) { vx += TURN_FACTOR; } if (x >= (ENV_WIDTH - MARGIN_WIDTH)) { vx -= TURN_FACTOR; } if (biasdir == 1) { vx = (1 - BIASVALUE) * vx + (BIASVALUE * 1); } else if (biasdir == 0) { vx = (1 - BIASVALUE) * vx + (BIASVALUE * -1); } float speed = sqrt(vx * vx + vy * vy); if (speed > MAX_SPEED) { vx = vx / speed * MAX_SPEED; vy = vy / speed * MAX_SPEED; } else if (speed < MIN_SPEED) { vx = vx / speed * MIN_SPEED; vy = vy / speed * MIN_SPEED; } x += vx; y += vy; }