FishAgent.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace MultiAgentSystemPCL
  5. {
  6. public class FishAgent : ObjectInWorld
  7. {
  8. protected const double STEP = 3;
  9. protected const double DISTANCE_MIN = 5;
  10. protected const double SQUARE_DISTANCE_MIN = 25;
  11. //protected const double DISTANCE_MAX = 40;
  12. protected const double SQUARE_DISTANCE_MAX = 1600;
  13. protected double speedX;
  14. public double SpeedX { get { return speedX; } }
  15. protected double speedY;
  16. public double SpeedY { get { return speedY; } }
  17. internal FishAgent(double _x, double _y, double _dir)
  18. {
  19. PosX = _x;
  20. PosY = _y;
  21. speedX = Math.Cos(_dir);
  22. speedY = Math.Sin(_dir);
  23. }
  24. internal void UpdatePosition()
  25. {
  26. PosX += STEP * SpeedX;
  27. PosY += STEP * SpeedY;
  28. }
  29. private bool Near(FishAgent _fish)
  30. {
  31. double squareDistance = SquareDistanceTo(_fish);
  32. return squareDistance < SQUARE_DISTANCE_MAX && squareDistance > SQUARE_DISTANCE_MIN;
  33. }
  34. internal double DistanceToWall(double _wallXMin, double _wallYMin, double _wallXMax, double _wallYMax)
  35. {
  36. double min = double.MaxValue;
  37. min = Math.Min(min, PosX - _wallXMin);
  38. min = Math.Min(min, PosY - _wallYMin);
  39. min = Math.Min(min, _wallYMax - PosY);
  40. min = Math.Min(min, _wallXMax - PosX);
  41. return min;
  42. }
  43. internal void ComputeAverageDirection(FishAgent[] _fishList)
  44. {
  45. List<FishAgent> fishUsed = _fishList.Where(x => Near(x)).ToList();
  46. int nbFish = fishUsed.Count;
  47. if (nbFish >= 1)
  48. {
  49. double speedXTotal = 0;
  50. double speedYTotal = 0;
  51. foreach (FishAgent neighbour in fishUsed)
  52. {
  53. speedXTotal += neighbour.SpeedX;
  54. speedYTotal += neighbour.SpeedY;
  55. }
  56. speedX = (speedXTotal / nbFish + speedX) /2;
  57. speedY = (speedYTotal / nbFish + speedY) /2;
  58. Normalize();
  59. }
  60. }
  61. protected void Normalize()
  62. {
  63. double speedLength = Math.Sqrt(SpeedX * SpeedX + SpeedY * SpeedY);
  64. speedX /= speedLength;
  65. speedY /= speedLength;
  66. }
  67. internal bool AvoidWalls(double _wallXMin, double _wallYMin, double _wallXMax, double _wallYMax)
  68. {
  69. // S'arrêter aux murs
  70. if (PosX < _wallXMin)
  71. {
  72. PosX = _wallXMin;
  73. }
  74. if (PosY < _wallYMin)
  75. {
  76. PosY = _wallYMin;
  77. }
  78. if (PosX > _wallXMax)
  79. {
  80. PosX = _wallXMax;
  81. }
  82. if (PosY > _wallYMax)
  83. {
  84. PosY = _wallYMax;
  85. }
  86. // Changer de direction
  87. double distance = DistanceToWall(_wallXMin, _wallYMin, _wallXMax, _wallYMax);
  88. if (distance < DISTANCE_MIN)
  89. {
  90. if (distance == (PosX - _wallXMin))
  91. {
  92. speedX += 0.3;
  93. }
  94. else if (distance == (PosY - _wallYMin))
  95. {
  96. speedY += 0.3;
  97. }
  98. else if (distance == (_wallXMax - PosX))
  99. {
  100. speedX -= 0.3;
  101. }
  102. else if (distance == (_wallYMax - PosY))
  103. {
  104. speedY -= 0.3;
  105. }
  106. Normalize();
  107. return true;
  108. }
  109. return false;
  110. }
  111. internal bool AvoidFish(FishAgent _fishAgent)
  112. {
  113. double squareDistanceToFish = SquareDistanceTo(_fishAgent);
  114. if (squareDistanceToFish < SQUARE_DISTANCE_MIN)
  115. {
  116. double diffX = (_fishAgent.PosX - PosX) / Math.Sqrt(squareDistanceToFish);
  117. double diffY = (_fishAgent.PosY - PosY) / Math.Sqrt(squareDistanceToFish);
  118. speedX = SpeedX - diffX/4;
  119. speedY = SpeedY - diffY/4;
  120. Normalize();
  121. return true;
  122. }
  123. return false;
  124. }
  125. internal bool AvoidObstacle(List<BadZone> _obstacles)
  126. {
  127. BadZone nearestObstacle = _obstacles.Where(x => SquareDistanceTo(x) < x.Radius*x.Radius).FirstOrDefault();
  128. if (nearestObstacle != null)
  129. {
  130. double distanceToObstacle = DistanceTo(nearestObstacle);
  131. double diffX = (nearestObstacle.PosX - PosX) / distanceToObstacle;
  132. double diffY = (nearestObstacle.PosY - PosY) / distanceToObstacle;
  133. speedX = SpeedX - diffX/2;
  134. speedY = SpeedY - diffY/2;
  135. Normalize();
  136. return true;
  137. }
  138. return false;
  139. }
  140. internal void Update(FishAgent[] _fishList, List<BadZone> _obstacles, double _max_width, double _max_height)
  141. {
  142. if (!AvoidWalls(0, 0, _max_width, _max_height))
  143. {
  144. if (!AvoidObstacle(_obstacles))
  145. {
  146. double squareDistanceMin = _fishList.Where(x => !x.Equals(this)).Min(x => x.SquareDistanceTo(this));
  147. if (!AvoidFish(_fishList.Where(x => x.SquareDistanceTo(this) == squareDistanceMin).FirstOrDefault()))
  148. {
  149. ComputeAverageDirection(_fishList);
  150. }
  151. }
  152. }
  153. UpdatePosition();
  154. }
  155. }
  156. }