Swarm02.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. Particle Swarm (UNOPTIMIZED!)
  3. Note : I'm not sure, but there is something wrong with the random. I have to do a -1.7 .. 1 for the
  4. swarm to stay in one spot. Not sure what I did wrong to cause that. ????
  5. Update: I added a float_rand function from the internet and this seemed to have fixed the problem.
  6. Optimalization : create a array[y][x][MAX_PARTICLES] of struct which contain
  7. the particles on that location.
  8. */
  9. #include "raylib.h"
  10. #include <math.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #define MAX_PARTICLES 128//500/10 is slow here on my laptop(2021)
  14. #define MAX_MOVESPEED 25
  15. // This is out collision map. It is a array for each spot a particle can be on.
  16. // It is true if there is a particle there or false if not.
  17. // Before moving a particle we can check if there is a particle there already so
  18. // not to move there.
  19. //
  20. // We need to check this map every time a particle gets moved (uncheck move check)
  21. //
  22. // Functions : setcollisionmap and checkcollisionmap
  23. bool collisionmap[1024][1024]={false};
  24. typedef struct particle{
  25. Vector2 position;
  26. }particle;
  27. struct particle arr_particle[MAX_PARTICLES];
  28. Vector2 targetposition;
  29. static float edistance(float x1,float y1,float x2,float y2);
  30. void setcollisionmap(Vector2 position,bool value);
  31. bool checkcollisionmap(Vector2 position);
  32. float float_rand( float min, float max );
  33. void moveparticles();
  34. void movetoneigbours();
  35. void movetotarget();
  36. int main(void)
  37. {
  38. // Initialization
  39. //--------------------------------------------------------------------------------------
  40. const int screenWidth = 800;
  41. const int screenHeight = 450;
  42. InitWindow(screenWidth, screenHeight, "raylib example.");
  43. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  44. //--------------------------------------------------------------------------------------
  45. //create a set of particles
  46. Vector2 p = (Vector2){200,200};
  47. for(int i=0;i<MAX_PARTICLES;i++){
  48. Vector2 pos=(Vector2){GetRandomValue(p.x-35,p.x+35),GetRandomValue(p.y-35,p.y+35)};
  49. while(checkcollisionmap(pos)==true){
  50. pos=(Vector2){GetRandomValue(p.x-35,p.x+35),GetRandomValue(p.y-35,p.y+35)};
  51. }
  52. arr_particle[i].position = pos;
  53. setcollisionmap(arr_particle[i].position,true);
  54. }
  55. int renew=0;
  56. // Main game loop
  57. while (!WindowShouldClose()) // Detect window close button or ESC key
  58. {
  59. // Update
  60. //----------------------------------------------------------------------------------
  61. if(renew<=0){
  62. targetposition.x = GetRandomValue(50,screenWidth-50);
  63. targetposition.y = GetRandomValue(50,screenHeight-50);
  64. renew=500;
  65. }
  66. renew--;
  67. for(int i=0;i<MAX_MOVESPEED;i++){
  68. moveparticles();
  69. movetoneigbours();
  70. movetotarget();
  71. }
  72. //----------------------------------------------------------------------------------
  73. // Draw
  74. //----------------------------------------------------------------------------------
  75. BeginDrawing();
  76. ClearBackground(RAYWHITE);
  77. // Draw particles
  78. for(int i=0;i<MAX_PARTICLES;i++){
  79. Vector2 p = arr_particle[i].position;
  80. DrawCircle(p.x,p.y,2,RED);
  81. }
  82. // Draw target position
  83. DrawCircle(targetposition.x,targetposition.y,20,(Color){255,0,0,100});
  84. EndDrawing();
  85. //----------------------------------------------------------------------------------
  86. }
  87. // De-Initialization
  88. //--------------------------------------------------------------------------------------
  89. CloseWindow(); // Close window and OpenGL context
  90. //--------------------------------------------------------------------------------------
  91. return 0;
  92. }
  93. // Euclidean distance (more precise)
  94. float edistance(float x1,float y1,float x2,float y2){
  95. return sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) );
  96. }
  97. void setcollisionmap(Vector2 position,bool value){
  98. if(position.x<0)return;
  99. if(position.x>1023)return;
  100. if(position.y<0)return;
  101. if(position.y>1023)return;
  102. collisionmap[(int)position.x][(int)position.y]=value;;
  103. }
  104. bool checkcollisionmap(Vector2 position){
  105. if(position.x<0)return true;
  106. if(position.x>1023)return true;
  107. if(position.y<0)return true;
  108. if(position.y>1023)return true;
  109. return (collisionmap[(int)position.x][(int)position.y]);
  110. }
  111. float float_rand( float min, float max ){
  112. float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
  113. return min + scale * ( max - min ); /* [min, max] */
  114. }
  115. void moveparticles(){
  116. //update particles
  117. //move random
  118. for(int i=0;i<MAX_PARTICLES;i++){
  119. Vector2 np = arr_particle[i].position;
  120. //np.x+=floatuniform(-1.72,1);
  121. //np.y+=floatuniform(-1.72,1);
  122. np.x += float_rand(-1,1);
  123. np.y += float_rand(-1,1);
  124. if(checkcollisionmap(np)==false){
  125. setcollisionmap(arr_particle[i].position,false);
  126. arr_particle[i].position=np;
  127. setcollisionmap(arr_particle[i].position,true);
  128. }
  129. }
  130. //move to midpoint nearest
  131. }
  132. void movetoneigbours(){
  133. for(int i=0;i<MAX_PARTICLES;i++){
  134. // find neigbours (3 of them)
  135. Vector2 p1 = arr_particle[i].position;
  136. int d1=0;
  137. int cnt=0;
  138. int timeout=0;
  139. Vector2 midpoint = (Vector2){0,0};
  140. while(cnt<5 && timeout<1000){
  141. for(int j=0;j<MAX_PARTICLES;j++){
  142. if(j==i || cnt>4)continue;
  143. Vector2 p2 = arr_particle[j].position;
  144. int d2 = (int)edistance(p1.x,p1.y,p2.x,p2.y);
  145. if(d2==d1 && cnt<5){
  146. if(cnt==0){
  147. midpoint.x = p2.x;
  148. midpoint.y = p2.y;
  149. }else{
  150. midpoint.x += p2.x;
  151. midpoint.y += p2.y;
  152. }
  153. cnt++;
  154. }
  155. }
  156. d1++;
  157. timeout++;
  158. }
  159. midpoint.x /= 5.0f;
  160. midpoint.y /= 5.0f;
  161. float angle=atan2(midpoint.y-p1.y,midpoint.x-p1.x);
  162. Vector2 newposition = (Vector2){ arr_particle[i].position.x + cos(angle)*.3,
  163. arr_particle[i].position.y + sin(angle)*.3};
  164. if( checkcollisionmap(newposition)==false ){
  165. setcollisionmap(arr_particle[i].position,false);
  166. arr_particle[i].position.x += cos(angle)*.3;
  167. arr_particle[i].position.y += sin(angle)*.3;
  168. setcollisionmap(newposition,true);
  169. }
  170. }
  171. }
  172. void movetotarget(){
  173. for(int i=0;i<MAX_PARTICLES;i++){
  174. //
  175. // Move to target
  176. //
  177. Vector2 p1 = arr_particle[i].position;
  178. float targetangle=atan2(targetposition.y-p1.y,targetposition.x-p1.x);
  179. Vector2 newposition = (Vector2){ arr_particle[i].position.x + cos(targetangle)*.4,
  180. arr_particle[i].position.y + sin(targetangle)*.4};
  181. if( checkcollisionmap(newposition)==false ){
  182. setcollisionmap(arr_particle[i].position,false);
  183. arr_particle[i].position.x += cos(targetangle)*.4;
  184. arr_particle[i].position.y += sin(targetangle)*.4;
  185. setcollisionmap(newposition,true);
  186. }
  187. }
  188. }