2
0
Rudy Boudewijn van Etten 4 жил өмнө
parent
commit
be7a197b47

+ 185 - 0
Books/GenAlg_MachL/Swarm01.c

@@ -0,0 +1,185 @@
+/*
+
+
+    Particle Swarm
+    
+    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 240
+
+// 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];
+
+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 );
+    
+int main(void)
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    const int screenWidth = 800;
+    const int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raylib example.");
+ 
+    SetTargetFPS(120);               // 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 here=0;
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        
+        //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
+        
+        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);
+            }
+        }
+        //----------------------------------------------------------------------------------
+        // 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);
+            }
+            DrawText(FormatText("%i",here),0,0,20,BLACK);
+
+        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] */
+}