Browse Source

Create Swarm02.c

Rudy Boudewijn van Etten 4 years ago
parent
commit
68bb4ff477
1 changed files with 227 additions and 0 deletions
  1. 227 0
      Books/GenAlg_MachL/Swarm02.c

+ 227 - 0
Books/GenAlg_MachL/Swarm02.c

@@ -0,0 +1,227 @@
+/*
+    Particle Swarm (UNOPTIMIZED!)
+    
+    Note : I'm not sure, but there is something wrong with the random. I have to do a -1.7 .. 1 for the
+    swarm to stay in one spot. Not sure what I did wrong to cause that. ????
+    Update: I added a float_rand function from the internet and this seemed to have fixed the problem.
+    
+    
+    
+    Optimalization : create a array[y][x][MAX_PARTICLES] of struct which contain
+    the particles on that location.
+*/
+
+#include "raylib.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAX_PARTICLES 128//500/10 is slow here on my laptop(2021)
+#define MAX_MOVESPEED 25
+
+// This is out collision map. It is a array for each spot a particle can be on.
+// It is true if there is a particle there or false if not.
+// Before moving a particle we can check if there is a particle there already so
+// not to move there.
+//
+// We need to check this map every time a particle gets moved (uncheck move check)
+//
+// Functions : setcollisionmap and checkcollisionmap
+bool collisionmap[1024][1024]={false};
+
+typedef struct particle{
+    Vector2 position;
+}particle;
+
+struct particle arr_particle[MAX_PARTICLES];
+
+Vector2 targetposition;
+
+
+static float edistance(float x1,float y1,float x2,float y2);
+void setcollisionmap(Vector2 position,bool value);
+bool checkcollisionmap(Vector2 position);
+float float_rand( float min, float max );
+void moveparticles();
+void movetoneigbours();
+void movetotarget();    
+
+int main(void)
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    const int screenWidth = 800;
+    const int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raylib example.");
+ 
+    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second
+    //--------------------------------------------------------------------------------------
+
+    //create a set of particles
+    Vector2 p = (Vector2){200,200};
+    for(int i=0;i<MAX_PARTICLES;i++){
+        Vector2 pos=(Vector2){GetRandomValue(p.x-35,p.x+35),GetRandomValue(p.y-35,p.y+35)};
+        
+        while(checkcollisionmap(pos)==true){
+            pos=(Vector2){GetRandomValue(p.x-35,p.x+35),GetRandomValue(p.y-35,p.y+35)};
+        }
+        arr_particle[i].position = pos;
+        setcollisionmap(arr_particle[i].position,true);
+        
+        
+    }
+
+    int renew=0;
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        if(renew<=0){
+            targetposition.x = GetRandomValue(50,screenWidth-50);
+            targetposition.y = GetRandomValue(50,screenHeight-50);
+            renew=500;
+        }
+        renew--;
+
+        for(int i=0;i<MAX_MOVESPEED;i++){
+            moveparticles();
+            movetoneigbours();
+            movetotarget();
+        }
+        //----------------------------------------------------------------------------------
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(RAYWHITE);
+                
+            // Draw particles
+            for(int i=0;i<MAX_PARTICLES;i++){
+                Vector2 p = arr_particle[i].position;
+                DrawCircle(p.x,p.y,2,RED);
+            }
+            
+            // Draw target position
+            DrawCircle(targetposition.x,targetposition.y,20,(Color){255,0,0,100});
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+
+
+}
+
+// Euclidean distance (more precise)
+float edistance(float x1,float y1,float x2,float y2){
+    return sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) );
+}
+void setcollisionmap(Vector2 position,bool value){
+        if(position.x<0)return;
+        if(position.x>1023)return;
+        if(position.y<0)return;
+        if(position.y>1023)return;
+
+        collisionmap[(int)position.x][(int)position.y]=value;;
+}
+bool checkcollisionmap(Vector2 position){
+    if(position.x<0)return true;
+    if(position.x>1023)return true;
+    if(position.y<0)return true;
+    if(position.y>1023)return true;
+
+    return (collisionmap[(int)position.x][(int)position.y]);
+}
+
+float float_rand( float min, float max ){
+    float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
+    return min + scale * ( max - min );      /* [min, max] */
+}
+
+void moveparticles(){
+    //update particles
+    //move random
+    for(int i=0;i<MAX_PARTICLES;i++){            
+        Vector2 np = arr_particle[i].position;                                       
+        //np.x+=floatuniform(-1.72,1);
+        //np.y+=floatuniform(-1.72,1);
+        np.x += float_rand(-1,1);
+        np.y += float_rand(-1,1);
+        if(checkcollisionmap(np)==false){
+            setcollisionmap(arr_particle[i].position,false);
+            arr_particle[i].position=np;
+            setcollisionmap(arr_particle[i].position,true);
+        }
+    }
+    //move to midpoint nearest
+}
+
+void movetoneigbours(){    
+    for(int i=0;i<MAX_PARTICLES;i++){
+        // find neigbours (3 of them)
+        Vector2 p1 = arr_particle[i].position;
+        int d1=0;
+        int cnt=0;
+        int timeout=0;
+        Vector2 midpoint = (Vector2){0,0};
+        while(cnt<5 && timeout<1000){
+            for(int j=0;j<MAX_PARTICLES;j++){
+                if(j==i || cnt>4)continue;                   
+                Vector2 p2 = arr_particle[j].position;
+                int d2 = (int)edistance(p1.x,p1.y,p2.x,p2.y);
+                if(d2==d1 && cnt<5){                        
+                    if(cnt==0){                            
+                        midpoint.x = p2.x;
+                        midpoint.y = p2.y;
+                    }else{
+                        midpoint.x += p2.x;
+                        midpoint.y += p2.y;
+                    }
+                    cnt++;                        
+                }
+            }
+            d1++;
+            timeout++;
+            
+        }
+        midpoint.x /= 5.0f;
+        midpoint.y /= 5.0f;
+        float angle=atan2(midpoint.y-p1.y,midpoint.x-p1.x);            
+        
+        Vector2 newposition = (Vector2){    arr_particle[i].position.x + cos(angle)*.3,
+                                            arr_particle[i].position.y + sin(angle)*.3};
+        if( checkcollisionmap(newposition)==false ){                
+            setcollisionmap(arr_particle[i].position,false);
+            arr_particle[i].position.x += cos(angle)*.3;
+            arr_particle[i].position.y += sin(angle)*.3;
+            setcollisionmap(newposition,true);
+        }
+    }    
+}
+
+void movetotarget(){
+
+    for(int i=0;i<MAX_PARTICLES;i++){        
+        //
+        // Move to target            
+        //
+        Vector2 p1 = arr_particle[i].position;
+        float targetangle=atan2(targetposition.y-p1.y,targetposition.x-p1.x);            
+        Vector2 newposition = (Vector2){    arr_particle[i].position.x + cos(targetangle)*.4,
+                                            arr_particle[i].position.y + sin(targetangle)*.4};
+        if( checkcollisionmap(newposition)==false ){                
+            setcollisionmap(arr_particle[i].position,false);
+            arr_particle[i].position.x += cos(targetangle)*.4;
+            arr_particle[i].position.y += sin(targetangle)*.4;
+            setcollisionmap(newposition,true);
+        }
+    }
+}