浏览代码

Create AgentsCoverHeatmapGFX.c

Rudy Boudewijn van Etten 5 年之前
父节点
当前提交
39073c39e5
共有 1 个文件被更改,包括 840 次插入0 次删除
  1. 840 0
      ai/AgentsCoverHeatmapGFX.c

+ 840 - 0
ai/AgentsCoverHeatmapGFX.c

@@ -0,0 +1,840 @@
+// Agents take Cover.
+
+// Todo :   
+            //gfx
+            // agents shoot back
+            // collision bullets vs entities
+            
+#include "raylib.h"
+#include <math.h>
+
+enum tiles{FLOOR,WALL};
+
+#define MAP_WIDTH 40
+#define MAP_HEIGHT 20
+#define MAX_TURRETS 1
+#define TURRET_TURNSPEED 0.01
+#define MAX_BULLETS 128
+#define BULLET_SPEED 3
+#define TURRET_TARGET_TIME 600
+#define MAX_AGENTS 15
+#define MAX_PATH 100024 
+
+static int screenWidth,screenHeight;
+
+// This is our tile map. Note that [y][x]!!
+// 1 = wall
+int tempmap[10][20] =            {  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
+                                    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
+                                    {1,0,0,1,1,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1},
+                                    {1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1},
+                                    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
+                                    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
+                                    {1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1},
+                                    {1,0,0,1,1,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1},
+                                    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
+                                    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};  
+int map[MAP_HEIGHT][MAP_WIDTH]={0};
+// heat map..
+// The heat map is used here to let the agents know the map area heated is dangerous and not
+// to be traveled on. (influence mapping.)
+float hmap[MAP_HEIGHT][MAP_WIDTH]={0};
+// cover position map..
+// The cover map is a map where positions are where bullets from the enemy do not have effect. (behind walls)
+// I find them by simulating the turret shooting in every angle.
+bool cmap[MAP_HEIGHT][MAP_WIDTH]={0};
+// coverislands 
+// coverspots connected to each other have a unique number.
+// These are used to let the agents run from one island to another
+int cimap[MAP_HEIGHT][MAP_WIDTH]={0};
+static int numislands;
+
+//path map
+int pathmap[MAP_HEIGHT][MAP_WIDTH]={0};
+
+
+float tileWidth,tileHeight;
+
+
+typedef struct turret{
+    float x,y;
+    float angle;    
+    float direction;
+    int burst;
+    bool targetactive;
+    int targetx,targety;
+    int targettime;
+}turret;
+
+static struct turret arr_turret[MAX_TURRETS];
+
+typedef struct bullet{
+    bool active;
+    float x,y;
+    float angle;
+    int speed;
+}bullet;
+
+static struct bullet arr_bullet[MAX_BULLETS];
+
+typedef struct agent{
+    bool active;
+    float x,y;
+    int speed;
+    int pathx[1024];
+    int pathy[1024];
+    int pathloc;
+    int pathlen;
+    int myisland;
+}agent;
+
+static struct agent arr_agent[MAX_AGENTS];
+
+typedef struct pathnode{
+    int x;
+    int y;
+    
+}pathnode;
+
+static pathnode arr_path[MAX_PATH];
+static int arr_path_len;
+
+
+
+static void drawmap();
+static void drawturrets();
+static void updateturrets();
+static void drawbullets();
+static void updatebullets();
+static void shootbullet(int x, int y, float angle);
+static bool recttilecollide(int x,int y,int w, int h, int offsetx,int offsety);
+static bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2);
+static void drawheatmap();
+static void updateheatmap();
+static int orientation(int ax,int ay,int bx, int by, int cx, int cy);
+static void createcovermap();
+static void drawcovermap();
+static void drawcoverislands();    
+static void createcoverislands();
+static void drawagents();    
+static void updateagents();
+static bool agentfindpath(int agent, int island);
+        
+int main(void)
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    screenWidth = 800;
+    screenHeight = 450;
+    tileWidth = ceil((float)screenWidth/(float)MAP_WIDTH);
+    tileHeight = ceil((float)screenHeight/(float)MAP_HEIGHT);
+    
+    // first let us copy the temp map into the main map(double size)
+    for (int y=0;y<MAP_HEIGHT/2;y++){
+    for(int x=0;x<MAP_WIDTH/2;x++){
+        map[y*2][x*2]=tempmap[y][x];
+        map[y*2+1][x*2]=tempmap[y][x];
+        map[y*2][x*2+1]=tempmap[y][x];
+        map[y*2+1][x*2+1]=tempmap[y][x];
+
+    }
+    }
+    
+    InitWindow(screenWidth, screenHeight, "raylib example.");
+ 
+    SetTargetFPS(60);               // Set our game to run at 60 frames-per-second
+    //--------------------------------------------------------------------------------------
+
+    // Our turret is placed in the center..
+    arr_turret[0].x = 20;
+
+    arr_turret[0].y = 10;
+    arr_turret[0].angle = 0;
+    arr_turret[0].direction = TURRET_TURNSPEED;
+    arr_turret[0].burst=0;
+    arr_turret[0].targetactive = true;
+    arr_turret[0].targetx = 12;
+    arr_turret[0].targety = 3;
+    arr_turret[0].targettime=TURRET_TARGET_TIME;
+    // create our covermap
+    createcovermap();
+    createcoverislands();
+    
+  
+for (int i=0;i<MAX_AGENTS;i++){
+    arr_agent[i].active = true;
+    arr_agent[i].x = 3*tileWidth;
+    arr_agent[i].y = 3*tileHeight;
+    arr_agent[i].speed = 2;
+    arr_agent[i].myisland=1;
+    arr_agent[i].pathloc=-1;
+    arr_agent[i].pathlen=-1;
+}    
+/*    arr_agent[0].active = true;
+    arr_agent[0].x = 3*tileWidth;
+    arr_agent[0].y = 3*tileHeight;
+    arr_agent[0].speed = 2;
+    arr_agent[0].myisland=1;
+    arr_agent[0].pathloc=-1;
+    arr_agent[0].pathlen=-1;
+*/
+
+    // Main game loop
+    while (!WindowShouldClose())    // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        updateturrets();
+        updatebullets();
+        updateheatmap();
+        updateagents();
+        
+        // If the user presses the mouse then place new target on map at mpos;
+        if(IsMouseButtonDown(0)){
+            arr_turret[0].targetactive=true;
+            arr_turret[0].targetx = GetMouseX()/tileWidth;
+            arr_turret[0].targety = GetMouseY()/tileHeight;
+            arr_turret[0].targettime=TURRET_TARGET_TIME;
+        }
+
+
+
+        //----------------------------------------------------------------------------------
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(RAYWHITE);
+            drawheatmap();
+            drawcovermap();
+            drawcoverislands();
+            drawmap();
+            drawturrets();
+            drawbullets();
+            //draw the path..
+            for(int i=0;i<arr_path_len-1;i++){
+                DrawRectangle(arr_path[i].x*tileWidth,arr_path[i].y*tileHeight,tileWidth,tileHeight,YELLOW);
+            }
+            drawagents();
+                            
+            DrawText("Press mouse to place target.. Space to path..",0,0,20,GRAY);
+            
+            DrawRectangle(0,screenHeight-44,screenWidth,28,DARKGRAY);
+            DrawText("Heatmap",130,screenHeight-40,20,WHITE);
+            DrawRectangle(100,screenHeight-40,20,20,RED);
+            DrawRectangle(screenWidth/2,screenHeight-40,20,20,GREEN);
+            DrawText("Covermap",screenWidth/2+30,screenHeight-40,20,WHITE);
+
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+
+
+}
+
+void drawmap(){
+    for(int y=0;y<MAP_HEIGHT;y++){
+    for(int x=0;x<MAP_WIDTH;x++){
+        if(map[y][x]==1){
+            DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,BLACK);
+        }
+    }
+    }
+}
+
+void drawturrets(){
+    for(int i=0;i<MAX_TURRETS;i++){
+        int x = arr_turret[i].x*tileWidth;
+        int y = arr_turret[i].y*tileHeight;
+        float angle = arr_turret[i].angle;
+        int x1 = x+tileWidth/2;
+        int y1 = y+tileHeight/2;
+        int x2 = x1+cos(angle)*(tileWidth);
+        int y2 = y1+sin(angle)*(tileHeight);
+        DrawRectangle(x,y,tileWidth,tileHeight,BLUE);
+        DrawLineEx((Vector2){x1,y1},(Vector2){x2,y2},6,RED);
+        // draw target if active
+        if(arr_turret[i].targetactive){
+            x = arr_turret[i].targetx*tileWidth;
+            y = arr_turret[i].targety*tileHeight;
+            DrawRectangle(x,y,tileWidth,tileHeight,BLUE);
+        }
+    }
+}
+
+void updateturrets(){
+    for(int i=0;i<MAX_TURRETS;i++){
+        
+        // If there is no target the turn randomly
+        if(arr_turret[i].targetactive==false && GetRandomValue(0,500)<2){
+            arr_turret[i].direction = -arr_turret[i].direction;
+        }
+        // If there is a target then turn towards taget.
+        if(arr_turret[i].targetactive){
+            int x=(arr_turret[i].x*tileWidth);
+            int y=(arr_turret[i].y*tileHeight);
+            int oriented=orientation(       x,
+                                            y,
+                                            x+cos(arr_turret[i].angle)*tileWidth*12,
+                                            y+sin(arr_turret[i].angle)*tileHeight*12,
+                                            arr_turret[i].targetx*tileWidth,
+                                            arr_turret[i].targety*tileHeight);
+            if(oriented==-1){                        
+                        arr_turret[i].direction=-TURRET_TURNSPEED;
+                        }else if(oriented==1){
+                            arr_turret[i].direction=TURRET_TURNSPEED;
+                        }
+        }
+        // rotate the turret
+        arr_turret[i].angle+=arr_turret[i].direction;        
+        if(arr_turret[i].angle>PI*2.0f){
+            arr_turret[i].angle=0;
+        }
+
+        if(arr_turret[i].angle<0){
+            arr_turret[i].angle=PI*2.0f;
+        }
+        // shoot bullets
+        if(GetRandomValue(0,60)<2 || arr_turret[i].burst>0){            
+            if(arr_turret[i].burst>0){
+                arr_turret[i].burst-=1;
+            }else{
+                if(GetRandomValue(0,20)<2)arr_turret[i].burst=5;
+            }
+            int bx = arr_turret[i].x*tileWidth;
+            int by = arr_turret[i].y*tileHeight;
+            shootbullet(    (bx+tileWidth/2)+(cos(arr_turret[i].angle)*tileWidth),
+                            (by+tileHeight/2)+(sin(arr_turret[i].angle)*tileHeight),
+                            arr_turret[i].angle);
+        }
+        // if target is active then decrease that time
+        if(arr_turret[i].targetactive){
+            arr_turret[i].targettime-=1;
+            if(arr_turret[i].targettime<=0){
+                arr_turret[i].targetactive = false;
+            }
+        }
+
+        
+    }
+}
+
+void drawbullets(){
+    for(int i=0;i<MAX_BULLETS;i++){
+        if(arr_bullet[i].active==false)continue;
+        DrawRectangle(arr_bullet[i].x,arr_bullet[i].y,tileWidth/4,tileHeight/4,BLACK);
+        DrawRectangle(arr_bullet[i].x+1,arr_bullet[i].y+1,tileWidth/4-2,tileHeight/4-2,YELLOW);
+    }
+}
+
+void updatebullets(){
+    for(int i=0;i<MAX_BULLETS;i++){
+        if(arr_bullet[i].active==false)continue;
+ 
+        for(int speed=0;speed<arr_bullet[i].speed;speed++){
+            arr_bullet[i].x += cos(arr_bullet[i].angle)*1;
+            arr_bullet[i].y += sin(arr_bullet[i].angle)*1;
+            // if outside screen then disable bullet.
+            if(     arr_bullet[i].x<0 || 
+                    arr_bullet[i].x>screenWidth || 
+                    arr_bullet[i].y<0 || 
+                    arr_bullet[i].y>screenHeight){
+                arr_bullet[i].active = false;
+            }
+            if(recttilecollide( arr_bullet[i].x,
+                                arr_bullet[i].y,
+                                tileWidth/4,
+                                tileHeight/4,
+                                0,0)){
+                arr_bullet[i].active=false;
+            }
+        }
+    }    
+}
+
+void shootbullet(int x,int y,float angle){
+    for(int i=0;i<MAX_BULLETS;i++){
+        if(arr_bullet[i].active==false){
+            arr_bullet[i].active = true;
+            arr_bullet[i].x = x;
+            arr_bullet[i].y = y;
+            arr_bullet[i].angle = angle;
+            arr_bullet[i].speed = BULLET_SPEED;
+            return;
+        }
+    }
+}
+
+//Unit collide with solid blocks true/false
+bool recttilecollide(int x,int y,int w, int h, int offsetx,int offsety){
+    int cx = (x+offsetx)/tileWidth;
+    int cy = (y+offsety)/tileHeight;
+    for(int y2=cy-1; y2<cy+5;y2++){
+    for(int x2=cx-1; x2<cx+5;x2++){
+        if(x2>=0 && x2<MAP_WIDTH && y2>=0 && y2<MAP_HEIGHT){
+            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;
+}
+
+void updateheatmap(){
+    // increase heat below bullets
+    for(int i=0;i<MAX_BULLETS;i++){
+        if(arr_bullet[i].active==false)continue;
+        int x=arr_bullet[i].x/tileWidth;
+        int y=arr_bullet[i].y/tileHeight;
+        if(hmap[y][x]<255)hmap[y][x]+=5;        
+        if(hmap[y-1][x]<255)hmap[y-1][x]+=1.5;        
+        if(hmap[y][x+1]<255)hmap[y][x+1]+=1.5;        
+        if(hmap[y+1][x]<255)hmap[y+1][x]+=1.5;        
+        if(hmap[y][x-1]<255)hmap[y][x-1]+=1.5;        
+        if(hmap[y-2][x]<255)hmap[y-2][x]+=1.0;        
+        if(hmap[y][x+2]<255)hmap[y][x+2]+=1.0;        
+        if(hmap[y+2][x]<255)hmap[y+2][x]+=1.0;        
+        if(hmap[y][x-2]<255)hmap[y][x-2]+=1.0;        
+
+    }
+    // decrease the heat..
+    for(int y=0;y<MAP_HEIGHT;y++){
+    for(int x=0;x<MAP_WIDTH;x++){
+        if(hmap[y][x]==0)continue;
+        hmap[y][x]-=0.5;
+        if(hmap[y][x]<0.1)hmap[y][x]=0;
+    }}    
+}
+void drawheatmap(){
+    for(int y=0;y<MAP_HEIGHT;y++){
+    for(int x=0;x<MAP_WIDTH;x++){
+        if(hmap[y][x]==0)continue;
+        Color col = {hmap[y][x],0,0,25};
+        DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,col);
+    }
+    }
+}
+
+//
+// This is the orientation function. It returns -1 if the point is left of the inputted line.
+// 0 if on the same and 1 if on the right of the line.
+// aa,bb,point
+int orientation(int ax,int ay,int bx, int by, int cx, int cy){
+	if(((bx-ax)*(cy-ay)-(by-ay)*(cx-ax))<0)return -1;
+    if(((bx-ax)*(cy-ay)-(by-ay)*(cx-ax))>0)return 1;
+    return 0;
+}
+
+
+void createcovermap(){
+    for(int i=0;i<MAX_TURRETS;i++){
+        
+        // Find all cover positions
+        for(float angle=0;angle<PI*2.0f;angle+=0.03f){
+            float x=(float)arr_turret[i].x*tileWidth;
+            float y=(float)arr_turret[i].y*tileHeight;
+            for(int z=0;z<300;z++){
+                x+=cos(angle);
+                y+=sin(angle);
+                int x2 = (float)x/(float)tileWidth;
+                int y2 = (float)y/(float)tileHeight;
+                if(x2<1 || y2<1 || x2>=MAP_WIDTH || y2>=MAP_HEIGHT){
+                    goto LABEL;
+                }
+                if(recttilecollide(x,y,1,1,0,0)){                    
+                    while(recttilecollide(x,y,1,1,0,0)){
+                        x+=cos(angle);
+                        y+=sin(angle);
+                        x2 = (float)x/(float)tileWidth;
+                        y2 = (float)y/(float)tileHeight;
+                        if(x2<1 || y2<1 || x2>=MAP_WIDTH || y2>=MAP_HEIGHT){
+                            goto LABEL;
+                        }                    
+                    }
+                    cmap[y2][x2] = true;
+                    goto LABEL;
+                }
+            }
+            LABEL:{}
+        }
+        
+        // Remove edge cases.
+        for(float angle=0;angle<PI*2.0f;angle+=0.03f){
+            float x=(float)arr_turret[i].x*tileWidth;
+            float y=(float)arr_turret[i].y*tileHeight;
+            for(int z=0;z<300;z++){
+                x+=cos(angle);
+                y+=sin(angle);
+                int x2 = (float)x/(float)tileWidth;
+                int y2 = (float)y/(float)tileHeight;
+                if(x2<0 || y2<0 || x2>=MAP_WIDTH || y2>=MAP_HEIGHT){
+                    goto LABEL2;
+                }
+                cmap[y2][x2]=false;
+                if(recttilecollide(x,y,1,1,0,0)){                    
+                    goto LABEL2;
+                }
+            }
+            LABEL2:{}
+        }
+
+    }
+}
+
+void drawcovermap(){
+    for(int y=0;y<MAP_HEIGHT;y++){
+    for(int x=0;x<MAP_WIDTH;x++){
+        if(cmap[y][x]==false)continue;        
+        DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,GREEN);
+    }
+    }
+}
+
+void drawcoverislands(){
+    for(int y=0;y<MAP_HEIGHT;y++){
+    for(int x=0;x<MAP_WIDTH;x++){
+        if(cimap[y][x]==0)continue;
+        DrawText(FormatText("%i",cimap[y][x]),x*tileWidth,y*tileHeight,15,BLACK);
+    }}
+}
+
+void createcoverislands(){
+    int island=1;
+    for(int y=0;y<MAP_HEIGHT;y++){
+    for(int x=0;x<MAP_WIDTH;x++){
+        if(cmap[y][x]==true && cimap[y][x]==0){
+            //flood
+            cimap[y][x]=island;
+            int mx[200];
+            int my[200];
+            int mc=0;
+            mx[mc]=x;
+            my[mc]=y;
+            mc++;
+            while(mc>0){
+                mc--;
+                int fx=mx[mc];
+                int fy=my[mc];
+                
+                for(int zy=fy-1;zy<fy+2;zy++){
+                for(int zx=fx-1;zx<fx+2;zx++){
+                    if(zx<0 || zy<0 || zx>=MAP_WIDTH || zy>MAP_HEIGHT)continue;
+                    if(cmap[zy][zx]==true && cimap[zy][zx]==0){                                                
+                        mx[mc]=zx;
+                        my[mc]=zy;
+                        cimap[zy][zx]=island;
+                        mc++;
+                    }
+                }
+                }
+            }
+            island++;
+            numislands=island;
+        }
+        
+    }}    
+}
+
+void drawagents(){
+    for(int i=0;i<MAX_AGENTS;i++){
+        if(arr_agent[i].active==false)continue;        
+        DrawRectangle(arr_agent[i].x,arr_agent[i].y,tileWidth,tileHeight,RED);
+    }
+}
+
+void updateagents(){
+    for(int a=0;a<MAX_AGENTS;a++){
+        if(arr_agent[a].active==false)continue;
+        // Move agent from path location to next path location(smooth)
+        if(arr_agent[a].pathloc>=0){
+            for(int spd=0;spd<arr_agent[a].speed;spd++){
+                if(arr_agent[a].x<arr_agent[a].pathx[arr_agent[a].pathloc]*tileWidth)arr_agent[a].x+=1;
+                if(arr_agent[a].x>arr_agent[a].pathx[arr_agent[a].pathloc]*tileWidth)arr_agent[a].x-=1;
+                if(arr_agent[a].y<arr_agent[a].pathy[arr_agent[a].pathloc]*tileHeight)arr_agent[a].y+=1;
+                if(arr_agent[a].y>arr_agent[a].pathy[arr_agent[a].pathloc]*tileHeight)arr_agent[a].y-=1;
+                if(     arr_agent[a].x==arr_agent[a].pathx[arr_agent[a].pathloc]*tileWidth && 
+                        arr_agent[a].y==arr_agent[a].pathy[arr_agent[a].pathloc]*tileHeight){
+                    arr_agent[a].pathloc--;                    
+                    break;
+                }
+            }
+        }
+        // If the agent is at the end of its path.
+        // move to next cover position.
+        bool planpath = false;
+        if(arr_agent[a].pathloc == -1 && GetRandomValue(0,1000)<10 )planpath=true;
+        if(planpath==true){
+            
+            for(int shuffle=0;shuffle<5;shuffle++){
+                int i=GetRandomValue(1,numislands);
+                if(arr_agent[a].myisland!=i && agentfindpath(a,i)==true){
+                    arr_agent[a].myisland = i;
+                    arr_agent[a].pathlen = arr_path_len;
+                    arr_agent[a].pathloc = arr_path_len-1;
+                    for(int p=0;p<arr_path_len;p++){
+                        arr_agent[a].pathx[p] = arr_path[p].x;
+                        arr_agent[a].pathy[p] = arr_path[p].y;
+                    }                    
+                    return;
+                }    
+            }
+        }
+    }
+}
+bool agentfindpath(int agent, int island){
+    // 4 way search! left/up/down/right
+//    int dx[4]={ 0,1,0,-1};
+//    int dy[4]={-1,0,1,0};    
+    // 8 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};    
+
+    //find closest cover position that we are currently not ontop of.
+    //
+    // find a start and end location.
+    //
+    for(int y=0;y<MAP_HEIGHT;y++){
+        for(int x=0;x<MAP_WIDTH;x++){
+            pathmap[y][x]=0;
+    }}
+
+    int startx,starty,endx,endy;
+
+
+    //flood to find closest cover position
+    startx = arr_agent[agent].x/tileWidth;    
+    starty = arr_agent[agent].y/tileHeight;    
+    // find the destination coordinates.
+    bool exitloop=false;
+    int failloop=0; 
+    while(exitloop==false){
+        int x = GetRandomValue(0,MAP_WIDTH);
+        int y = GetRandomValue(0,MAP_HEIGHT);
+        if(cimap[y][x]==island){
+            endx = x;
+            endy = y;
+            exitloop=true;
+        }
+        failloop++;
+        if(failloop>1000000)return false;
+    }
+    
+        
+    //
+    // Flood the map with distances from the start.
+    //
+    
+    struct pathnode list[MAX_PATH];
+    //
+    // We store the distance on each map cell if there is no wall there.
+    //
+    pathmap[starty][startx]=1;
+    int listlen=0;    
+    list[listlen].x=startx;
+    list[listlen].y=starty;
+    listlen+=1;        
+    int failed=0;
+    // 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;
+        }
+        if(x1==endx && y1==endy){                    
+            break;
+        }
+
+        // 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>= MAP_WIDTH || ny>= MAP_HEIGHT)continue;            
+            // If we can get there then put the new distance there and add this position
+            // to the list.
+            if(pathmap[ny][nx]==0 && map[ny][nx]==0){
+                pathmap[ny][nx]=pathmap[y1][x1]+1;
+                // add to last
+                //
+                list[listlen].x = nx;
+                list[listlen].y = ny;
+                listlen++;
+                //                
+            }
+        }
+        // Error?
+        failed+=1;
+        if(failed>160000)return;
+        
+    }
+    
+    //
+    // Here we create the actual path.
+    //
+    arr_path_len = 0;
+    int x1=endx;
+    int y1=endy;
+    arr_path[0].x = x1;
+    arr_path[0].y = y1;
+    arr_path_len+=1;
+    failed=0;
+    // While distance is greater than 1
+    while(pathmap[y1][x1]>1){
+        
+        int nx=0;
+        int ny=0;
+        // Get the current distance
+        int lowest = pathmap[y1][x1];
+        for(int i=0;i<8;i++){
+            int x2=x1+dx[i];
+            int y2=y1+dy[i];
+            if(x2<0 || y2 <0 || x2>=MAP_WIDTH || y2>= MAP_HEIGHT )continue; // stay in bounds of array
+            if(pathmap[y2][x2]>0 && pathmap[y2][x2]<lowest){ //if there is a map distance and if it is lower than the lowest variable
+                lowest = pathmap[y2][x2];
+                nx = x2;
+                ny = y2;
+            }                
+        }
+
+        // store our new location
+        x1 = nx;
+        y1 = ny;
+        if(hmap[y1][x1]>0){
+            arr_path_len=0;
+            return false;
+        }
+        // add to the path struct
+        arr_path[arr_path_len].x = nx;
+        arr_path[arr_path_len].y = ny;
+        // add to length
+        arr_path_len+=1;
+        // error?
+        failed+=1;
+        if(failed>15000)return;
+    }
+    arr_agent[agent].x = startx*tileWidth;
+    arr_agent[agent].y = starty*tileHeight;
+    
+    
+    return true;
+}
+ 
+
+void inisprites(){
+int sprite_right[8][8] = {
+{0,0,2,2,2,2,0,0},
+{0,23,27,25,27,23,23,1},
+{0,1,29,23,27,24,1,1},
+{0,0,21,23,25,2,0,0},
+{0,0,21,23,25,2,0,0},
+{0,23,22,21,24,23,23,1},
+{0,1,22,27,22,25,1,1},
+{0,0,21,0,21,0,0,0}};
+
+int sprite_left[8][8] = {
+{0,0,21,0,21,0,0,0},
+{0,1,22,27,22,25,1,1},
+{0,23,22,21,24,23,23,1},
+{0,0,21,23,25,2,0,0},
+{0,0,21,23,25,2,0,0},
+{0,1,29,23,27,24,1,1},
+{0,23,27,25,27,23,23,1},
+{0,0,2,2,2,2,0,0}};
+
+int sprite_down[8][8] = {
+{0,0,0,0,0,0,0,0},
+{1,25,2,1,1,2,25,1},
+{0,2,25,27,28,27,27,0},
+{2,2,24,24,22,21,22,21},
+{2,2,24,24,22,21,1,0},
+{0,2,25,27,22,21,22,21},
+{1,25,2,1,1,2,25,1},
+{0,0,0,0,0,0,0,0}};
+
+int sprite_up[8][8] = {
+{0,0,0,0,0,0,0,0},
+{1,25,2,1,1,2,25,1},
+{0,27,27,28,27,25,2,0},
+{21,22,21,22,24,24,2,2},
+{0,1,21,22,24,24,2,2},
+{21,22,21,22,27,25,2,0},
+{1,25,2,1,1,2,25,1},
+{0,0,0,0,0,0,0,0}};
+
+int sprite_rightdown[8][8] = {
+{0,0,1,25,0,0,0,0},
+{0,2,2,1,0,0,0,0},
+{1,2,27,27,2,0,0,0},
+{24,1,22,22,27,2,0,0},
+{0,0,21,22,22,27,1,25},
+{0,0,0,21,22,27,20,1},
+{0,0,0,0,1,20,2,0},
+{0,0,0,0,24,1,0,0}};
+
+int sprite_leftdown[8][8] = {
+{0,0,0,0,24,1,0,0},
+{0,0,0,0,1,20,2,0},
+{0,0,0,21,22,27,20,1},
+{0,0,21,22,22,27,1,25},
+{24,1,22,22,27,2,0,0},
+{1,2,27,27,2,0,0,0},
+{0,2,2,1,0,0,0,0},
+{0,0,1,25,0,0,0,0}};
+
+int sprite_rightup[8][8] = {
+{0,0,0,0,25,1,0,0},
+{0,0,0,0,1,2,2,0},
+{0,0,0,2,27,27,2,1},
+{0,0,2,27,22,22,1,24},
+{25,1,27,22,22,21,0,0},
+{1,20,27,22,21,0,0,0},
+{0,2,20,1,0,0,0,0},
+{0,0,1,24,0,0,0,0}};
+
+int sprite_leftup[8][8] = {
+{0,0,1,24,0,0,0,0},
+{0,2,20,1,0,0,0,0},
+{1,20,27,22,21,0,0,0},
+{25,1,27,22,22,21,0,0},
+{0,0,2,27,22,22,1,24},
+{0,0,0,2,27,27,2,1},
+{0,0,0,0,1,2,2,0},
+{0,0,0,0,25,1,0,0}};
+
+int sprite_desert1[8][8] = {
+{5,5,5,5,5,5,5,5},
+{5,31,5,5,5,5,31,5},
+{5,5,5,5,5,5,5,5},
+{5,5,5,5,31,5,5,5},
+{5,5,5,5,5,5,5,5},
+{5,5,5,5,5,5,31,5},
+{5,5,31,5,5,5,5,5},
+{5,5,5,5,5,5,5,5}};
+
+}