Browse Source

Create Example_-_AiRadar_movetotarget.c

Rudy Boudewijn van Etten 4 years ago
parent
commit
a2467eb1a9
1 changed files with 378 additions and 0 deletions
  1. 378 0
      Example_-_AiRadar_movetotarget.c

+ 378 - 0
Example_-_AiRadar_movetotarget.c

@@ -0,0 +1,378 @@
+//
+
+#include "raylib.h"
+#include <math.h>
+
+#define MAX_PATH 1024
+#define MAX_AGENT 32 // Maximum number of ai entities
+
+#define SPEED 1
+
+enum terrain{TREE=1,GROUND=0,PLAYER=2,AIPLAYER=3,GOAL=4,GOALREACHED=5};
+enum flag{UP,DOWN,LEFT,RIGHT,WAIT};
+
+//
+// You can set any number of 3 and 2 on the map. more 4's untested. keep the borders(1) intact(memory errors)
+//
+//1=border(TREE),2=PLAYER,3=AIPLAYER,4=Path finding objective(GOAL)
+int map1[10][10] = {    {1,1,1,1,1,1,1,1,1,1},
+                        {1,0,0,0,0,1,0,0,3,1},
+                        {1,0,0,0,0,1,0,0,0,1},
+                        {1,3,0,0,0,1,0,0,0,1},
+                        {1,0,0,0,0,1,1,0,1,1},
+                        {1,0,0,0,0,1,0,0,0,1},
+                        {1,1,1,0,1,1,0,0,0,1},
+                        {1,0,0,0,0,0,2,0,0,1},
+                        {1,0,0,0,0,0,0,0,0,1},
+                        {1,1,1,1,1,1,1,1,1,1}
+                        };  
+int map[10][10] = {0};
+
+int dijkstramap[10][10]={0};
+
+
+typedef struct pathnode{
+    int x;
+    int y;    
+}pathnode;
+
+typedef struct agent{
+    bool active;
+    Vector2 position;
+    Vector2 size;
+    Vector2 ray;
+    float rayangle;
+}agent;
+
+static struct agent arr_agent[MAX_AGENT];
+
+typedef struct player{
+    Vector2 position;
+    Vector2 size;
+}player;
+
+player myPlayer = {0};
+
+void makedijkstramap();
+static float distance(float x1,float y1,float x2,float y2);
+static float edistance(float x1,float y1,float x2,float y2);
+//Unit collide with solid blocks true/false
+bool recttilecollide(int x, int y, int w, int h, int offsetx,int offsety);
+// Our rectsoverlap function. Returns true/false.
+static bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2);
+void updateplayer();
+void updateagents();
+    
+int topdijkstralen=0;
+int screenWidth;
+int screenHeight;
+int tileWidth,tileHeight,mapWidth,mapHeight;
+
+
+
+int main(void)
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    screenWidth = 800;
+    screenHeight = 600;
+    mapWidth = 10;
+    mapHeight = 10;
+    tileWidth = ceil((float)screenWidth/(float)mapWidth);
+    tileHeight = ceil((float)screenHeight/(float)mapHeight);
+    
+    InitWindow(screenWidth, screenHeight, "raylib example.");
+ 
+    SetTargetFPS(200);               // Set our game to run at 60 frames-per-second
+    //--------------------------------------------------------------------------------------
+    //makedijkstramap(); // The 4 = the goal that gets flooded from...
+
+    //
+    // Copy our original map into the active map...
+    for(int y=0;y<mapHeight;y++){
+    for(int x=0;x<mapHeight;x++){
+        map[y][x]= map1[y][x];
+    }}
+    
+    // set our player up..
+    for(int y=0;y<mapHeight;y++){
+    for(int x=0;x<mapHeight;x++){
+        if(map[y][x]==PLAYER){
+            myPlayer.position = (Vector2){x*tileWidth,y*tileHeight};
+            myPlayer.size = (Vector2){tileWidth/2,tileHeight/2};
+            map[y][x]=GROUND;
+        }
+    }}    
+
+    // set our agents(ai) up..
+    int agentcount=0;
+    for(int y=0;y<mapHeight;y++){
+    for(int x=0;x<mapHeight;x++){
+        if(map[y][x]==AIPLAYER){
+            arr_agent[agentcount].active=true;
+            arr_agent[agentcount].position = (Vector2){x*tileWidth,y*tileHeight};
+            arr_agent[agentcount].size = (Vector2){tileWidth/2,tileHeight/2};
+            map[y][x]=GROUND;
+            agentcount++;
+        }
+    }}    
+
+
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        
+        updateplayer();
+        updateagents();
+        //----------------------------------------------------------------------------------
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(RAYWHITE);
+            //drawmap (tile positions)
+            for(int y=0;y<10;y++){
+                for(int x =0;x<10;x++){
+                    int m=map[y][x];
+                    if(m==TREE){
+                        
+                        DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,(Color){40,90,20,255});
+                        DrawCircle(x*tileWidth+tileWidth/1.5,y*tileHeight+tileHeight/1.5,tileWidth/5,(Color){20,50,20,255});
+                        DrawRectangle(x*tileWidth+tileWidth/2.2,y*tileHeight+tileHeight/2,tileWidth/8,tileHeight/3,BROWN);
+                        
+                        DrawCircle(x*tileWidth+tileWidth/2,y*tileHeight+tileHeight/3,tileWidth/4,(Color){120,250,20,255});
+                        DrawCircle(x*tileWidth+tileWidth/2.2,y*tileHeight+tileHeight/4,tileWidth/9,(Color){220,255,220,155});
+                    }
+                    if(m==GROUND){
+                        DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,DARKGREEN);                        
+                        DrawRectangle(x*tileWidth+5,y*tileHeight+10,2,1,GREEN);                        
+                        DrawRectangle(x*tileWidth+tileWidth/6,y*tileHeight+tileHeight/6,2,1,GREEN);                        
+                        DrawRectangle(x*tileWidth+tileWidth/1.5,y*tileHeight+tileHeight/1.5,2,1,GREEN);                        
+                        DrawRectangle(x*tileWidth+tileWidth/2,y*tileHeight+tileHeight/2,2,1,GREEN);                        
+                        
+                    }
+                    if(m==PLAYER){
+                        DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,BLUE);                        
+                        DrawText("Player",x*tileWidth,y*tileHeight+tileHeight/4,16,BLACK);                        
+                    }
+                    if(m==AIPLAYER){
+                        DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,RED); 
+                        DrawText("Ai_Player",x*tileWidth,y*tileHeight+tileHeight/4,16,WHITE);
+                    }
+                    if(m==GOAL){
+                       DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,WHITE);      
+                       DrawText("City",x*tileWidth+tileWidth/4,y*tileHeight+tileHeight/4,26,BLACK);                        
+                    }
+                    if(m==GOALREACHED){
+                        DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,YELLOW);                        
+                        DrawText("Captured",x*tileWidth+4,y*tileHeight+tileHeight/4,16,BLACK);                        
+                    }
+                    DrawText(FormatText("%i",dijkstramap[y][x]),x*tileWidth+tileWidth/2-10,y*tileHeight+tileHeight/2-10,20,BLACK);
+
+              }
+            }
+            
+            // Draw our agents..
+            for(int i=0;i<MAX_AGENT;i++){
+                int x = arr_agent[i].position.x;
+                int y = arr_agent[i].position.y;
+                int w = arr_agent[i].size.x;
+                int h = arr_agent[i].size.y;
+                DrawRectangle(x,y,w,h,RED); 
+                DrawText(FormatText("Agent %i",i),x,y+h/8,h/8,WHITE);
+                // Draw our agents ray
+                Vector2 p1 = (Vector2){ arr_agent[i].position.x+arr_agent[i].size.x/2,
+                                        arr_agent[i].position.y+arr_agent[i].size.y/2};
+                Vector2 p2 = (Vector2){ arr_agent[i].ray.x,
+                                        arr_agent[i].ray.y};
+                DrawLineEx(p1,p2,4,GRAY);
+            }
+  
+ 
+            // Draw our player..
+            int x = myPlayer.position.x;
+            int y = myPlayer.position.y;
+            int w = myPlayer.size.x;
+            int h = myPlayer.size.y;
+            DrawRectangle(x,y,w,h,BLUE);                        
+            DrawText("Player",x,y+h/8,h/4,BLACK);                        
+            
+            
+            DrawText("Cursors U/D/L/R",10,10,26,BLACK);
+            DrawText("Cursors U/D/L/R",9,9,26,WHITE);
+            
+            
+            
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+
+
+}
+
+void updateagents(){
+    for(int i=0;i<MAX_AGENT;i++){
+        if(arr_agent[i].active==false)continue;
+        arr_agent[i].rayangle+=.005;
+        arr_agent[i].ray = (Vector2){   arr_agent[i].position.x+arr_agent[i].size.x/2,
+                                        arr_agent[i].position.y+arr_agent[i].size.y/2};
+        for(int dist=0;dist<400;dist+=5){
+            int w = 5;
+            int h = 5;
+            float x1 = arr_agent[i].ray.x;
+            float y1 = arr_agent[i].ray.y;
+            if(recttilecollide(x1,y1,w,h,0,0)==true){
+                break;
+            }
+            arr_agent[i].ray.x+=cos(arr_agent[i].rayangle)*5;
+            arr_agent[i].ray.y+=sin(arr_agent[i].rayangle)*5;
+        }
+    }
+}
+
+void updateplayer(){
+    for(int sp=0;sp<SPEED;sp++){ // our movement speed (makes to check collision every step)
+        Vector2 oldpos = myPlayer.position;
+        if(IsKeyDown(KEY_LEFT)){
+            myPlayer.position.x-=1;
+        }
+        if(IsKeyDown(KEY_RIGHT)){
+            myPlayer.position.x+=1;
+        }
+        if(recttilecollide(myPlayer.position.x,myPlayer.position.y,tileWidth/2,tileHeight/2,0,0)){
+            myPlayer.position = oldpos;
+        }
+        oldpos = myPlayer.position;
+        if(IsKeyDown(KEY_UP)){
+            myPlayer.position.y-=1;
+        }
+        if(IsKeyDown(KEY_DOWN)){
+            myPlayer.position.y+=1;
+        }
+        if(recttilecollide(myPlayer.position.x,myPlayer.position.y,tileWidth/2,tileHeight/2,0,0)){
+            myPlayer.position = oldpos;
+        }
+
+    }
+}
+
+void makedijkstramap(){
+    
+    int startx;
+    int starty;
+    // First make sure every map value is 0.
+    for(int y=0;y<mapHeight;y++){
+    for(int x=0;x<mapWidth;x++){
+        dijkstramap[y][x] = 0;
+        if(map1[y][x]==1)dijkstramap[y][x]=-1;
+        if(map1[y][x]==4){
+            startx = x;
+            starty = y;
+        }
+    }}
+    
+    //
+    
+    //
+    // Flood the map with distances from the start.
+    //
+    
+    // We store the distance on each map cell if there is no wall there.
+    //
+    struct pathnode list[MAX_PATH];
+    dijkstramap[starty][startx]=1;
+    int listlen=0;    
+    list[listlen].x=startx;
+    list[listlen].y=starty;
+    listlen+=1;        
+    int failed=0;
+    // 4 way search! left/up/down/right
+    int dx[8]={ -1,0,1,-1,1,-1,0,1};
+    int dy[8]={-1,-1,-1,0,0,1,1,1};    
+    // While we have a list to work with
+    while(listlen>0){
+        // Take the first value from the array.
+        int x1=list[0].x;
+        int y1=list[0].y;
+        
+        // shift all up.
+        for(int i=0;i<listlen;i++){
+            list[i].x = list[i+1].x;
+            list[i].y = list[i+1].y;
+        }
+        // Decrease list length
+        listlen-=1;
+        //
+        // Here we check around our current position.
+        for(int i=0;i<8;i++){
+            int nx = x1+dx[i];
+            int ny = y1+dy[i];
+            if(nx<0 || ny<0 || nx>= mapWidth || ny>= mapHeight)continue;            
+            // If we can get there then put the new distance there and add this position
+            // to the list.
+            if(dijkstramap[ny][nx]==0 && map[ny][ny]!=1){
+                dijkstramap[ny][nx]=dijkstramap[y1][x1]+1;
+                if(dijkstramap[ny][nx]>topdijkstralen)topdijkstralen=dijkstramap[ny][nx];
+                // add to last
+                //
+                list[listlen].x = nx;
+                list[listlen].y = ny;
+                listlen++;
+                //                
+            }
+        }
+        // Error?
+        failed+=1;
+        if(failed>160000)return;
+        
+    }
+    
+ 
+}
+
+// Manhattan Distance (less precise)
+float distance(float x1,float y1,float x2,float y2){
+    return (float)abs(x2-x1)+abs(y2-y1);
+}
+
+// Euclidean distance (more precise)
+float edistance(float x1,float y1,float x2,float y2){
+    return sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) );
+}
+
+//Unit collide with solid blocks true/false
+bool recttilecollide(int x, int y,int w, int h, int offsetx,int offsety){
+    //y+=abs(mapy);//for scrolling
+    int cx = (x+offsetx)/tileWidth;
+    int cy = (y+offsety)/tileHeight;
+    for(int y2=cy-1; y2<cy+2;y2++){//Note that the - and + are to be set differently with differently sized players
+    for(int x2=cx-1; x2<cx+2;x2++){
+        if(x2>=0 && x2<mapWidth && y2>=0 && y2<mapHeight){
+            if(map[y2][x2] == 1){
+                int x3 = (x2)*tileWidth;
+                int y3 = (y2)*tileHeight;
+                if(rectsoverlap(x+offsetx,y+offsety,w,h,x3,y3,tileWidth,tileHeight)){
+                    return true;
+                }
+            }
+        }
+    }}
+    return false;
+}
+
+// Rectangles overlap
+bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){
+    if(x1 >= (x2 + w2) || (x1 + w1) <= x2) return false;
+    if(y1 >= (y2 + h2) || (y1 + h1) <= y2) return false;
+    return true;
+}