Example_-_AiRadar_movetotarget.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. //
  2. #include "raylib.h"
  3. #include <math.h>
  4. #define MAX_PATH 1024
  5. #define MAX_AGENT 32 // Maximum number of ai entities
  6. #define SPEED 1
  7. enum terrain{TREE=1,GROUND=0,PLAYER=2,AIPLAYER=3,GOAL=4,GOALREACHED=5};
  8. enum flag{UP,DOWN,LEFT,RIGHT,WAIT};
  9. //
  10. // You can set any number of 3 and 2 on the map. more 4's untested. keep the borders(1) intact(memory errors)
  11. //
  12. //1=border(TREE),2=PLAYER,3=AIPLAYER,4=Path finding objective(GOAL)
  13. int map1[10][10] = { {1,1,1,1,1,1,1,1,1,1},
  14. {1,0,0,0,0,1,0,0,3,1},
  15. {1,0,0,0,0,1,0,0,0,1},
  16. {1,3,0,0,0,1,0,0,0,1},
  17. {1,0,0,0,0,1,1,0,1,1},
  18. {1,0,0,0,0,1,0,0,0,1},
  19. {1,1,1,0,1,1,0,0,0,1},
  20. {1,0,0,0,0,0,2,0,0,1},
  21. {1,0,0,0,0,0,0,0,0,1},
  22. {1,1,1,1,1,1,1,1,1,1}
  23. };
  24. int map[10][10] = {0};
  25. int dijkstramap[10][10]={0};
  26. typedef struct pathnode{
  27. int x;
  28. int y;
  29. }pathnode;
  30. typedef struct agent{
  31. bool active;
  32. Vector2 position;
  33. Vector2 size;
  34. Vector2 ray;
  35. float rayangle;
  36. }agent;
  37. static struct agent arr_agent[MAX_AGENT];
  38. typedef struct player{
  39. Vector2 position;
  40. Vector2 size;
  41. }player;
  42. player myPlayer = {0};
  43. void makedijkstramap();
  44. static float distance(float x1,float y1,float x2,float y2);
  45. static float edistance(float x1,float y1,float x2,float y2);
  46. //Unit collide with solid blocks true/false
  47. bool recttilecollide(int x, int y, int w, int h, int offsetx,int offsety);
  48. // Our rectsoverlap function. Returns true/false.
  49. static bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2);
  50. void updateplayer();
  51. void updateagents();
  52. int topdijkstralen=0;
  53. int screenWidth;
  54. int screenHeight;
  55. int tileWidth,tileHeight,mapWidth,mapHeight;
  56. int main(void)
  57. {
  58. // Initialization
  59. //--------------------------------------------------------------------------------------
  60. screenWidth = 800;
  61. screenHeight = 600;
  62. mapWidth = 10;
  63. mapHeight = 10;
  64. tileWidth = ceil((float)screenWidth/(float)mapWidth);
  65. tileHeight = ceil((float)screenHeight/(float)mapHeight);
  66. InitWindow(screenWidth, screenHeight, "raylib example.");
  67. SetTargetFPS(200); // Set our game to run at 60 frames-per-second
  68. //--------------------------------------------------------------------------------------
  69. //makedijkstramap(); // The 4 = the goal that gets flooded from...
  70. //
  71. // Copy our original map into the active map...
  72. for(int y=0;y<mapHeight;y++){
  73. for(int x=0;x<mapHeight;x++){
  74. map[y][x]= map1[y][x];
  75. }}
  76. // set our player up..
  77. for(int y=0;y<mapHeight;y++){
  78. for(int x=0;x<mapHeight;x++){
  79. if(map[y][x]==PLAYER){
  80. myPlayer.position = (Vector2){x*tileWidth,y*tileHeight};
  81. myPlayer.size = (Vector2){tileWidth/2,tileHeight/2};
  82. map[y][x]=GROUND;
  83. }
  84. }}
  85. // set our agents(ai) up..
  86. int agentcount=0;
  87. for(int y=0;y<mapHeight;y++){
  88. for(int x=0;x<mapHeight;x++){
  89. if(map[y][x]==AIPLAYER){
  90. arr_agent[agentcount].active=true;
  91. arr_agent[agentcount].position = (Vector2){x*tileWidth,y*tileHeight};
  92. arr_agent[agentcount].size = (Vector2){tileWidth/2,tileHeight/2};
  93. map[y][x]=GROUND;
  94. agentcount++;
  95. }
  96. }}
  97. // Main game loop
  98. while (!WindowShouldClose()) // Detect window close button or ESC key
  99. {
  100. // Update
  101. //----------------------------------------------------------------------------------
  102. updateplayer();
  103. updateagents();
  104. //----------------------------------------------------------------------------------
  105. // Draw
  106. //----------------------------------------------------------------------------------
  107. BeginDrawing();
  108. ClearBackground(RAYWHITE);
  109. //drawmap (tile positions)
  110. for(int y=0;y<10;y++){
  111. for(int x =0;x<10;x++){
  112. int m=map[y][x];
  113. if(m==TREE){
  114. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,(Color){40,90,20,255});
  115. DrawCircle(x*tileWidth+tileWidth/1.5,y*tileHeight+tileHeight/1.5,tileWidth/5,(Color){20,50,20,255});
  116. DrawRectangle(x*tileWidth+tileWidth/2.2,y*tileHeight+tileHeight/2,tileWidth/8,tileHeight/3,BROWN);
  117. DrawCircle(x*tileWidth+tileWidth/2,y*tileHeight+tileHeight/3,tileWidth/4,(Color){120,250,20,255});
  118. DrawCircle(x*tileWidth+tileWidth/2.2,y*tileHeight+tileHeight/4,tileWidth/9,(Color){220,255,220,155});
  119. }
  120. if(m==GROUND){
  121. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,DARKGREEN);
  122. DrawRectangle(x*tileWidth+5,y*tileHeight+10,2,1,GREEN);
  123. DrawRectangle(x*tileWidth+tileWidth/6,y*tileHeight+tileHeight/6,2,1,GREEN);
  124. DrawRectangle(x*tileWidth+tileWidth/1.5,y*tileHeight+tileHeight/1.5,2,1,GREEN);
  125. DrawRectangle(x*tileWidth+tileWidth/2,y*tileHeight+tileHeight/2,2,1,GREEN);
  126. }
  127. if(m==PLAYER){
  128. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,BLUE);
  129. DrawText("Player",x*tileWidth,y*tileHeight+tileHeight/4,16,BLACK);
  130. }
  131. if(m==AIPLAYER){
  132. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,RED);
  133. DrawText("Ai_Player",x*tileWidth,y*tileHeight+tileHeight/4,16,WHITE);
  134. }
  135. if(m==GOAL){
  136. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,WHITE);
  137. DrawText("City",x*tileWidth+tileWidth/4,y*tileHeight+tileHeight/4,26,BLACK);
  138. }
  139. if(m==GOALREACHED){
  140. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,YELLOW);
  141. DrawText("Captured",x*tileWidth+4,y*tileHeight+tileHeight/4,16,BLACK);
  142. }
  143. DrawText(FormatText("%i",dijkstramap[y][x]),x*tileWidth+tileWidth/2-10,y*tileHeight+tileHeight/2-10,20,BLACK);
  144. }
  145. }
  146. // Draw our agents..
  147. for(int i=0;i<MAX_AGENT;i++){
  148. int x = arr_agent[i].position.x;
  149. int y = arr_agent[i].position.y;
  150. int w = arr_agent[i].size.x;
  151. int h = arr_agent[i].size.y;
  152. DrawRectangle(x,y,w,h,RED);
  153. DrawText(FormatText("Agent %i",i),x,y+h/8,h/8,WHITE);
  154. // Draw our agents ray
  155. Vector2 p1 = (Vector2){ arr_agent[i].position.x+arr_agent[i].size.x/2,
  156. arr_agent[i].position.y+arr_agent[i].size.y/2};
  157. Vector2 p2 = (Vector2){ arr_agent[i].ray.x,
  158. arr_agent[i].ray.y};
  159. DrawLineEx(p1,p2,4,GRAY);
  160. }
  161. // Draw our player..
  162. int x = myPlayer.position.x;
  163. int y = myPlayer.position.y;
  164. int w = myPlayer.size.x;
  165. int h = myPlayer.size.y;
  166. DrawRectangle(x,y,w,h,BLUE);
  167. DrawText("Player",x,y+h/8,h/4,BLACK);
  168. DrawText("Cursors U/D/L/R",10,10,26,BLACK);
  169. DrawText("Cursors U/D/L/R",9,9,26,WHITE);
  170. EndDrawing();
  171. //----------------------------------------------------------------------------------
  172. }
  173. // De-Initialization
  174. //--------------------------------------------------------------------------------------
  175. CloseWindow(); // Close window and OpenGL context
  176. //--------------------------------------------------------------------------------------
  177. return 0;
  178. }
  179. void updateagents(){
  180. for(int i=0;i<MAX_AGENT;i++){
  181. if(arr_agent[i].active==false)continue;
  182. arr_agent[i].rayangle+=.005;
  183. arr_agent[i].ray = (Vector2){ arr_agent[i].position.x+arr_agent[i].size.x/2,
  184. arr_agent[i].position.y+arr_agent[i].size.y/2};
  185. for(int dist=0;dist<400;dist+=5){
  186. int w = 5;
  187. int h = 5;
  188. float x1 = arr_agent[i].ray.x;
  189. float y1 = arr_agent[i].ray.y;
  190. if(recttilecollide(x1,y1,w,h,0,0)==true){
  191. break;
  192. }
  193. arr_agent[i].ray.x+=cos(arr_agent[i].rayangle)*5;
  194. arr_agent[i].ray.y+=sin(arr_agent[i].rayangle)*5;
  195. }
  196. }
  197. }
  198. void updateplayer(){
  199. for(int sp=0;sp<SPEED;sp++){ // our movement speed (makes to check collision every step)
  200. Vector2 oldpos = myPlayer.position;
  201. if(IsKeyDown(KEY_LEFT)){
  202. myPlayer.position.x-=1;
  203. }
  204. if(IsKeyDown(KEY_RIGHT)){
  205. myPlayer.position.x+=1;
  206. }
  207. if(recttilecollide(myPlayer.position.x,myPlayer.position.y,tileWidth/2,tileHeight/2,0,0)){
  208. myPlayer.position = oldpos;
  209. }
  210. oldpos = myPlayer.position;
  211. if(IsKeyDown(KEY_UP)){
  212. myPlayer.position.y-=1;
  213. }
  214. if(IsKeyDown(KEY_DOWN)){
  215. myPlayer.position.y+=1;
  216. }
  217. if(recttilecollide(myPlayer.position.x,myPlayer.position.y,tileWidth/2,tileHeight/2,0,0)){
  218. myPlayer.position = oldpos;
  219. }
  220. }
  221. }
  222. void makedijkstramap(){
  223. int startx;
  224. int starty;
  225. // First make sure every map value is 0.
  226. for(int y=0;y<mapHeight;y++){
  227. for(int x=0;x<mapWidth;x++){
  228. dijkstramap[y][x] = 0;
  229. if(map1[y][x]==1)dijkstramap[y][x]=-1;
  230. if(map1[y][x]==4){
  231. startx = x;
  232. starty = y;
  233. }
  234. }}
  235. //
  236. //
  237. // Flood the map with distances from the start.
  238. //
  239. // We store the distance on each map cell if there is no wall there.
  240. //
  241. struct pathnode list[MAX_PATH];
  242. dijkstramap[starty][startx]=1;
  243. int listlen=0;
  244. list[listlen].x=startx;
  245. list[listlen].y=starty;
  246. listlen+=1;
  247. int failed=0;
  248. // 4 way search! left/up/down/right
  249. int dx[8]={ -1,0,1,-1,1,-1,0,1};
  250. int dy[8]={-1,-1,-1,0,0,1,1,1};
  251. // While we have a list to work with
  252. while(listlen>0){
  253. // Take the first value from the array.
  254. int x1=list[0].x;
  255. int y1=list[0].y;
  256. // shift all up.
  257. for(int i=0;i<listlen;i++){
  258. list[i].x = list[i+1].x;
  259. list[i].y = list[i+1].y;
  260. }
  261. // Decrease list length
  262. listlen-=1;
  263. //
  264. // Here we check around our current position.
  265. for(int i=0;i<8;i++){
  266. int nx = x1+dx[i];
  267. int ny = y1+dy[i];
  268. if(nx<0 || ny<0 || nx>= mapWidth || ny>= mapHeight)continue;
  269. // If we can get there then put the new distance there and add this position
  270. // to the list.
  271. if(dijkstramap[ny][nx]==0 && map[ny][ny]!=1){
  272. dijkstramap[ny][nx]=dijkstramap[y1][x1]+1;
  273. if(dijkstramap[ny][nx]>topdijkstralen)topdijkstralen=dijkstramap[ny][nx];
  274. // add to last
  275. //
  276. list[listlen].x = nx;
  277. list[listlen].y = ny;
  278. listlen++;
  279. //
  280. }
  281. }
  282. // Error?
  283. failed+=1;
  284. if(failed>160000)return;
  285. }
  286. }
  287. // Manhattan Distance (less precise)
  288. float distance(float x1,float y1,float x2,float y2){
  289. return (float)abs(x2-x1)+abs(y2-y1);
  290. }
  291. // Euclidean distance (more precise)
  292. float edistance(float x1,float y1,float x2,float y2){
  293. return sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) );
  294. }
  295. //Unit collide with solid blocks true/false
  296. bool recttilecollide(int x, int y,int w, int h, int offsetx,int offsety){
  297. //y+=abs(mapy);//for scrolling
  298. int cx = (x+offsetx)/tileWidth;
  299. int cy = (y+offsety)/tileHeight;
  300. for(int y2=cy-1; y2<cy+2;y2++){//Note that the - and + are to be set differently with differently sized players
  301. for(int x2=cx-1; x2<cx+2;x2++){
  302. if(x2>=0 && x2<mapWidth && y2>=0 && y2<mapHeight){
  303. if(map[y2][x2] == 1){
  304. int x3 = (x2)*tileWidth;
  305. int y3 = (y2)*tileHeight;
  306. if(rectsoverlap(x+offsetx,y+offsety,w,h,x3,y3,tileWidth,tileHeight)){
  307. return true;
  308. }
  309. }
  310. }
  311. }}
  312. return false;
  313. }
  314. // Rectangles overlap
  315. bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){
  316. if(x1 >= (x2 + w2) || (x1 + w1) <= x2) return false;
  317. if(y1 >= (y2 + h2) || (y1 + h1) <= y2) return false;
  318. return true;
  319. }