| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- namespace MultiAgentSystemPCL
- {
- public class FishAgent : ObjectInWorld
- {
- protected const double STEP = 3;
- protected const double DISTANCE_MIN = 5;
- protected const double SQUARE_DISTANCE_MIN = 25;
- //protected const double DISTANCE_MAX = 40;
- protected const double SQUARE_DISTANCE_MAX = 1600;
- protected double speedX;
- public double SpeedX { get { return speedX; } }
- protected double speedY;
- public double SpeedY { get { return speedY; } }
- internal FishAgent(double _x, double _y, double _dir)
- {
- PosX = _x;
- PosY = _y;
- speedX = Math.Cos(_dir);
- speedY = Math.Sin(_dir);
- }
- internal void UpdatePosition()
- {
- PosX += STEP * SpeedX;
- PosY += STEP * SpeedY;
- }
- private bool Near(FishAgent _fish)
- {
- double squareDistance = SquareDistanceTo(_fish);
- return squareDistance < SQUARE_DISTANCE_MAX && squareDistance > SQUARE_DISTANCE_MIN;
- }
- internal double DistanceToWall(double _wallXMin, double _wallYMin, double _wallXMax, double _wallYMax)
- {
- double min = double.MaxValue;
- min = Math.Min(min, PosX - _wallXMin);
- min = Math.Min(min, PosY - _wallYMin);
- min = Math.Min(min, _wallYMax - PosY);
- min = Math.Min(min, _wallXMax - PosX);
- return min;
- }
- internal void ComputeAverageDirection(FishAgent[] _fishList)
- {
- List<FishAgent> fishUsed = _fishList.Where(x => Near(x)).ToList();
- int nbFish = fishUsed.Count;
- if (nbFish >= 1)
- {
- double speedXTotal = 0;
- double speedYTotal = 0;
- foreach (FishAgent neighbour in fishUsed)
- {
- speedXTotal += neighbour.SpeedX;
- speedYTotal += neighbour.SpeedY;
- }
- speedX = (speedXTotal / nbFish + speedX) /2;
- speedY = (speedYTotal / nbFish + speedY) /2;
- Normalize();
- }
- }
- protected void Normalize()
- {
- double speedLength = Math.Sqrt(SpeedX * SpeedX + SpeedY * SpeedY);
- speedX /= speedLength;
- speedY /= speedLength;
- }
- internal bool AvoidWalls(double _wallXMin, double _wallYMin, double _wallXMax, double _wallYMax)
- {
- // S'arrêter aux murs
- if (PosX < _wallXMin)
- {
- PosX = _wallXMin;
- }
- if (PosY < _wallYMin)
- {
- PosY = _wallYMin;
- }
- if (PosX > _wallXMax)
- {
- PosX = _wallXMax;
- }
- if (PosY > _wallYMax)
- {
- PosY = _wallYMax;
- }
- // Changer de direction
- double distance = DistanceToWall(_wallXMin, _wallYMin, _wallXMax, _wallYMax);
- if (distance < DISTANCE_MIN)
- {
- if (distance == (PosX - _wallXMin))
- {
- speedX += 0.3;
- }
- else if (distance == (PosY - _wallYMin))
- {
- speedY += 0.3;
- }
- else if (distance == (_wallXMax - PosX))
- {
- speedX -= 0.3;
- }
- else if (distance == (_wallYMax - PosY))
- {
- speedY -= 0.3;
- }
- Normalize();
- return true;
- }
- return false;
- }
- internal bool AvoidFish(FishAgent _fishAgent)
- {
- double squareDistanceToFish = SquareDistanceTo(_fishAgent);
- if (squareDistanceToFish < SQUARE_DISTANCE_MIN)
- {
- double diffX = (_fishAgent.PosX - PosX) / Math.Sqrt(squareDistanceToFish);
- double diffY = (_fishAgent.PosY - PosY) / Math.Sqrt(squareDistanceToFish);
- speedX = SpeedX - diffX/4;
- speedY = SpeedY - diffY/4;
- Normalize();
- return true;
- }
- return false;
- }
- internal bool AvoidObstacle(List<BadZone> _obstacles)
- {
- BadZone nearestObstacle = _obstacles.Where(x => SquareDistanceTo(x) < x.Radius*x.Radius).FirstOrDefault();
- if (nearestObstacle != null)
- {
- double distanceToObstacle = DistanceTo(nearestObstacle);
- double diffX = (nearestObstacle.PosX - PosX) / distanceToObstacle;
- double diffY = (nearestObstacle.PosY - PosY) / distanceToObstacle;
- speedX = SpeedX - diffX/2;
- speedY = SpeedY - diffY/2;
- Normalize();
- return true;
- }
- return false;
- }
- internal void Update(FishAgent[] _fishList, List<BadZone> _obstacles, double _max_width, double _max_height)
- {
- if (!AvoidWalls(0, 0, _max_width, _max_height))
- {
- if (!AvoidObstacle(_obstacles))
- {
- double squareDistanceMin = _fishList.Where(x => !x.Equals(this)).Min(x => x.SquareDistanceTo(this));
- if (!AvoidFish(_fishList.Where(x => x.SquareDistanceTo(this) == squareDistanceMin).FirstOrDefault()))
- {
- ComputeAverageDirection(_fishList);
- }
- }
- }
- UpdatePosition();
- }
- }
- }
|