Example_-_MakePathFloodFill.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. // Generate a (simple) random map and add start and end position. Then flood the map with distances from start until reach end.
  2. // Then create path from start to end.
  3. #define MAPWIDTH 30
  4. #define MAPHEIGHT 30
  5. #define MAX_PATH 10024 //; On large or/and complex maps increase this value.
  6. #include "raylib.h"
  7. #include <math.h>
  8. typedef struct pathnode{
  9. int x;
  10. int y;
  11. }pathnode;
  12. static int map[MAPWIDTH][MAPHEIGHT];
  13. static pathnode arr_path[MAX_PATH];
  14. static int arr_path_len;
  15. static int mapWidth = MAPWIDTH;
  16. static int mapHeight = MAPHEIGHT;
  17. static float tileWidth ;
  18. static float tileHeight;
  19. // Start and end of our path.
  20. static int startx;
  21. static int starty;
  22. static int endx;
  23. static int endy;
  24. static void newmapandpath(void);
  25. int main(void)
  26. {
  27. // Initialization
  28. //--------------------------------------------------------------------------------------
  29. const int screenWidth = 800;
  30. const int screenHeight = 450;
  31. InitWindow(screenWidth, screenHeight, "raylib example.");
  32. // Make sure the tile dimensions fill up the entire map if the entire map is drawn.
  33. tileWidth = abs((float)screenWidth/(float)mapWidth);
  34. tileHeight = abs((float)screenHeight/(float)mapHeight);
  35. newmapandpath();
  36. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  37. //--------------------------------------------------------------------------------------
  38. // Main game loop
  39. while (!WindowShouldClose()) // Detect window close button or ESC key
  40. {
  41. // Update
  42. //----------------------------------------------------------------------------------
  43. if(IsKeyPressed(KEY_SPACE))newmapandpath();
  44. //----------------------------------------------------------------------------------
  45. // Draw
  46. //----------------------------------------------------------------------------------
  47. BeginDrawing();
  48. ClearBackground(RAYWHITE);
  49. // Draw start and end position.
  50. DrawRectangle(startx*tileWidth,starty*tileHeight,tileWidth,tileHeight,GREEN);
  51. DrawRectangle(endx*tileWidth,endy*tileHeight,tileWidth,tileHeight,RED);
  52. // Draw our map.
  53. for(int y=0;y<MAPHEIGHT;y++){
  54. for(int x=0;x<MAPWIDTH;x++){
  55. if(map[x][y]==-1){
  56. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,BLACK);
  57. }
  58. if(map[x][y]>0){
  59. DrawText(FormatText("%i",map[x][y]),x*tileWidth,y*tileHeight,10,BLACK);
  60. }
  61. }}
  62. //draw the path..
  63. for(int i=0;i<arr_path_len;i++){
  64. DrawRectangle(arr_path[i].x*tileWidth,arr_path[i].y*tileHeight,tileWidth,tileHeight,(Color){100,100,0,100});
  65. }
  66. DrawText("Press space for new map and path.",11,1,30,BLACK);
  67. DrawText(FormatText("Current path len is : %i",arr_path_len),11,39,30,BLACK);
  68. DrawText("Press space for new map and path.",10,00,30,RED);
  69. DrawText(FormatText("Current path len is : %i",arr_path_len),10,40,30,RED);
  70. //DrawText(FormatText("%i",MAPHEIGHT),0,20,20,RED);
  71. EndDrawing();
  72. //----------------------------------------------------------------------------------
  73. }
  74. // De-Initialization
  75. //--------------------------------------------------------------------------------------
  76. CloseWindow(); // Close window and OpenGL context
  77. //--------------------------------------------------------------------------------------
  78. return 0;
  79. }
  80. void newmapandpath(){
  81. //
  82. // Generate random map....
  83. //
  84. // First make sure every map value is 0.
  85. for(int y=0;y<mapHeight;y++){
  86. for(int x=0;x<mapWidth;x++){
  87. map[x][y] = 0;
  88. }}
  89. // Draw some lines on the map.
  90. for(int x=0;x< mapWidth;x+=5){
  91. if(GetRandomValue(0,3)<2){
  92. for(int y=2;y< mapHeight-2;y++){
  93. map[x][y] = -1;
  94. }
  95. }
  96. }
  97. //
  98. //draw some rectangles on the map
  99. for(int i=0;i<mapWidth;i++){
  100. int x1=GetRandomValue(0,mapWidth-5);
  101. int y1=GetRandomValue(0,mapHeight-5);
  102. for(int x2=0;x2<4;x2++){
  103. for(int y2=0;y2<4;y2++){
  104. map[x1+x2][y1+y2] = -1;
  105. }}
  106. }
  107. // Draw some passages on the map.
  108. for(int y=0;y<mapHeight;y+=5){
  109. for(int x=0;x<mapWidth;x++){
  110. map[x][y] = 0;
  111. }}
  112. //
  113. // find a start and end location.
  114. //
  115. bool found=false;
  116. int failed=0;
  117. while(found==false){
  118. found = true;
  119. startx = GetRandomValue(1,mapWidth-1);
  120. starty = GetRandomValue(1,mapHeight-1);
  121. endx = GetRandomValue(1,mapWidth-1);
  122. endy = GetRandomValue(1,mapHeight-1);
  123. // If below any start or end position than try again.
  124. if(map[startx][starty]!=0 || map[endx][endy]!=0)found=false;
  125. failed+=1;
  126. if(failed>500000)return; // If we just can not find any start and end position then exit.
  127. }
  128. //
  129. // Flood the map with distances from the start.
  130. //
  131. struct pathnode list[MAX_PATH];
  132. //
  133. // We store the distance on each map cell if there is no wall there.
  134. //
  135. map[startx][starty]=1;
  136. int listlen=0;
  137. list[listlen].x=startx;
  138. list[listlen].y=starty;
  139. listlen+=1;
  140. failed=0;
  141. // 4 way search! left/up/down/right
  142. int dx[4]={ 0,1,0,-1};
  143. int dy[4]={-1,0,1,0};
  144. // While we have a list to work with
  145. while(listlen>0){
  146. // Take the first value from the array.
  147. int x1=list[0].x;
  148. int y1=list[0].y;
  149. // shift all up.
  150. for(int i=0;i<listlen;i++){
  151. list[i].x = list[i+1].x;
  152. list[i].y = list[i+1].y;
  153. }
  154. if(x1==endx && y1==endy){
  155. break;
  156. }
  157. // Decrease list length
  158. listlen-=1;
  159. //
  160. // Here we check around our current position.
  161. for(int i=0;i<4;i++){
  162. int nx = x1+dx[i];
  163. int ny = y1+dy[i];
  164. if(nx<0 || ny<0 || nx>= mapWidth || ny>= mapHeight)continue;
  165. // If we can get there then put the new distance there and add this position
  166. // to the list.
  167. if(map[nx][ny]==0){
  168. map[nx][ny]=map[x1][y1]+1;
  169. // add to last
  170. //
  171. list[listlen].x = nx;
  172. list[listlen].y = ny;
  173. listlen++;
  174. //
  175. }
  176. }
  177. // Error?
  178. failed+=1;
  179. if(failed>160000)return;
  180. }
  181. //
  182. // Here we create the actual path.
  183. //
  184. arr_path_len = 0;
  185. int x1=endx;
  186. int y1=endy;
  187. arr_path[0].x = x1;
  188. arr_path[0].y = y1;
  189. arr_path_len+=1;
  190. failed=0;
  191. // While distance is greater than 1
  192. while(map[x1][y1]>1){
  193. int nx=0;
  194. int ny=0;
  195. // Get the current distance
  196. int lowest = map[x1][y1];
  197. for(int i=0;i<4;i++){
  198. int x2=x1+dx[i];
  199. int y2=y1+dy[i];
  200. if(x2<0 || y2 <0 || x2>=mapWidth || y2>= mapHeight )continue; // stay in bounds of array
  201. if(map[x2][y2]>0 && map[x2][y2]<lowest){ //if there is a map distance and if it is lower than the lowest variable
  202. lowest = map[x2][y2];
  203. nx = x2;
  204. ny = y2;
  205. }
  206. }
  207. // store our new location
  208. x1 = nx;
  209. y1 = ny;
  210. // add to the path struct
  211. arr_path[arr_path_len].x = nx;
  212. arr_path[arr_path_len].y = ny;
  213. // add to length
  214. arr_path_len+=1;
  215. // error?
  216. failed+=1;
  217. if(failed>15000)return;
  218. }
  219. }