Example_-_Agents_ChaseDoorPath.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. //
  2. // Player and ai agents.
  3. //
  4. //
  5. // Working on this one at the moment...
  6. //
  7. //
  8. #include "raylib.h"
  9. #include <math.h>
  10. #define MAX_PATH 1024
  11. #define MAX_AGENT 16 // Maximum number of ai entities
  12. #define MAX_UNSTUCKPATH 3
  13. #define AGENT_RADARSPEED 0.1f
  14. #define SPEED 3
  15. enum agentstate{STAND,MOVETO,WAIT};
  16. enum agentsubstate{SUBNOTHING,SUBSTUCK,SUBMOVETO};
  17. enum terrain{TREE=1,GROUND=0,PLAYER=2,AIPLAYER=3,GOAL=4,GOALREACHED=5};
  18. //enum flag{UP,DOWN,LEFT,RIGHT,WAIT};
  19. //
  20. // You can set any number of 3 and 2 on the map. more 4's untested. keep the borders(1) intact(memory errors)
  21. //
  22. //1=border(TREE),2=PLAYER,3=AIPLAYER,4=Path finding objective(GOAL)
  23. int map1[10][10] = { {1,1,1,1,1,1,1,1,1,1},
  24. {1,0,0,0,0,1,0,0,3,1},
  25. {1,0,0,3,0,1,0,0,0,1},
  26. {1,3,0,0,0,1,0,0,0,1},
  27. {1,0,0,0,3,1,1,0,1,1},
  28. {1,0,0,0,0,1,0,0,0,1},
  29. {1,1,1,0,1,1,0,0,0,1},
  30. {1,0,0,0,0,0,2,0,0,1},
  31. {1,0,0,0,0,0,0,0,0,1},
  32. {1,1,1,1,1,1,1,1,1,1}
  33. };
  34. int map[10][10] = {0};
  35. int dijkstramap[10][10]={0};
  36. typedef struct pathnode{
  37. int x;
  38. int y;
  39. }pathnode;
  40. typedef struct agent{
  41. bool active;
  42. Vector2 position;
  43. Vector2 size;
  44. Vector2 ray;
  45. float rayangle;
  46. int state;
  47. int waittimer;
  48. int substate;
  49. Vector2 target;
  50. Vector2 subtarget;
  51. Vector2 unstuckpath[MAX_UNSTUCKPATH];
  52. int unstuckpathindex;
  53. int unstuckpathtop;
  54. }agent;
  55. static struct agent arr_agent[MAX_AGENT];
  56. typedef struct player{
  57. Vector2 position;
  58. Vector2 size;
  59. }player;
  60. player myPlayer = {0};
  61. void makedijkstramap(int startx,int starty);
  62. float distance(float x1,float y1,float x2,float y2);
  63. //static float distance(float x1,float y1,float x2,float y2);
  64. static float edistance(float x1,float y1,float x2,float y2);
  65. //Unit collide with solid blocks true/false
  66. bool recttilecollide(int x, int y, int w, int h, int offsetx,int offsety);
  67. // Our rectsoverlap function. Returns true/false.
  68. static bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2);
  69. bool rectplayercollide(int x, int y, int w, int h);
  70. void updateplayer();
  71. void updateagents();
  72. float getangle(float x1,float y1,float x2,float y2);
  73. int topdijkstralen=0;
  74. int screenWidth;
  75. int screenHeight;
  76. int tileWidth,tileHeight,mapWidth,mapHeight;
  77. int debug=0;
  78. int debugx=0;
  79. int debugy=0;
  80. int main(void)
  81. {
  82. // Initialization
  83. //--------------------------------------------------------------------------------------
  84. screenWidth = 800;
  85. screenHeight = 600;
  86. mapWidth = 10;
  87. mapHeight = 10;
  88. tileWidth = ceil((float)screenWidth/(float)mapWidth);
  89. tileHeight = ceil((float)screenHeight/(float)mapHeight);
  90. InitWindow(screenWidth, screenHeight, "raylib example.");
  91. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  92. //--------------------------------------------------------------------------------------
  93. //makedijkstramap(); // The 4 = the goal that gets flooded from...
  94. //
  95. // Copy our original map into the active map...
  96. for(int y=0;y<mapHeight;y++){
  97. for(int x=0;x<mapHeight;x++){
  98. map[y][x]= map1[y][x];
  99. }}
  100. // set our player up..
  101. for(int y=0;y<mapHeight;y++){
  102. for(int x=0;x<mapHeight;x++){
  103. if(map[y][x]==PLAYER){
  104. myPlayer.position = (Vector2){x*tileWidth,y*tileHeight};
  105. myPlayer.size = (Vector2){tileWidth/2,tileHeight/2};
  106. map[y][x]=GROUND;
  107. }
  108. }}
  109. // set our agents(ai) up..
  110. int agentcount=0;
  111. for(int y=0;y<mapHeight;y++){
  112. for(int x=0;x<mapHeight;x++){
  113. if(map[y][x]==AIPLAYER){
  114. arr_agent[agentcount].active=true;
  115. arr_agent[agentcount].position = (Vector2){x*tileWidth,y*tileHeight};
  116. arr_agent[agentcount].size = (Vector2){tileWidth/2,tileHeight/2};
  117. map[y][x]=GROUND;
  118. arr_agent[agentcount].state = STAND;
  119. agentcount++;
  120. }
  121. }}
  122. // Main game loop
  123. while (!WindowShouldClose()) // Detect window close button or ESC key
  124. {
  125. // Update
  126. //----------------------------------------------------------------------------------
  127. for(int i=0;i<SPEED;i++){
  128. updateplayer();
  129. updateagents();
  130. }
  131. //----------------------------------------------------------------------------------
  132. // Draw
  133. //----------------------------------------------------------------------------------
  134. BeginDrawing();
  135. ClearBackground(RAYWHITE);
  136. //drawmap (tile positions)
  137. for(int y=0;y<10;y++){
  138. for(int x =0;x<10;x++){
  139. int m=map[y][x];
  140. if(m==TREE){
  141. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,(Color){40,90,20,255});
  142. DrawCircle(x*tileWidth+tileWidth/1.5,y*tileHeight+tileHeight/1.5,tileWidth/5,(Color){20,50,20,255});
  143. DrawRectangle(x*tileWidth+tileWidth/2.2,y*tileHeight+tileHeight/2,tileWidth/8,tileHeight/3,BROWN);
  144. DrawCircle(x*tileWidth+tileWidth/2,y*tileHeight+tileHeight/3,tileWidth/4,(Color){120,250,20,255});
  145. DrawCircle(x*tileWidth+tileWidth/2.2,y*tileHeight+tileHeight/4,tileWidth/9,(Color){220,255,220,155});
  146. }
  147. if(m==GROUND){
  148. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,DARKGREEN);
  149. DrawRectangle(x*tileWidth+5,y*tileHeight+10,2,1,GREEN);
  150. DrawRectangle(x*tileWidth+tileWidth/6,y*tileHeight+tileHeight/6,2,1,GREEN);
  151. DrawRectangle(x*tileWidth+tileWidth/1.5,y*tileHeight+tileHeight/1.5,2,1,GREEN);
  152. DrawRectangle(x*tileWidth+tileWidth/2,y*tileHeight+tileHeight/2,2,1,GREEN);
  153. }
  154. if(m==PLAYER){
  155. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,BLUE);
  156. DrawText("Player",x*tileWidth,y*tileHeight+tileHeight/4,16,BLACK);
  157. }
  158. if(m==AIPLAYER){
  159. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,RED);
  160. DrawText("Ai_Player",x*tileWidth,y*tileHeight+tileHeight/4,16,WHITE);
  161. }
  162. if(m==GOAL){
  163. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,WHITE);
  164. DrawText("City",x*tileWidth+tileWidth/4,y*tileHeight+tileHeight/4,26,BLACK);
  165. }
  166. if(m==GOALREACHED){
  167. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,YELLOW);
  168. DrawText("Captured",x*tileWidth+4,y*tileHeight+tileHeight/4,16,BLACK);
  169. }
  170. DrawText(FormatText("%i",dijkstramap[y][x]),x*tileWidth+tileWidth/2-10,y*tileHeight+tileHeight/2-10,20,BLACK);
  171. }
  172. }
  173. // Draw our agents..
  174. for(int i=0;i<MAX_AGENT;i++){
  175. int x = arr_agent[i].position.x;
  176. int y = arr_agent[i].position.y;
  177. int w = arr_agent[i].size.x;
  178. int h = arr_agent[i].size.y;
  179. DrawRectangle(
  180. x,y,w,h,RED);
  181. DrawText(FormatText("Agent %i",i),x,y+h/8,h/8,WHITE);
  182. // Draw our agents ray
  183. Vector2 p1 = (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. Vector2 p2 = (Vector2){ arr_agent[i].ray.x,
  186. arr_agent[i].ray.y};
  187. DrawLineEx(p1,p2,4,GRAY);
  188. }
  189. // Draw our player..
  190. int x = myPlayer.position.x;
  191. int y = myPlayer.position.y;
  192. int w = myPlayer.size.x;
  193. int h = myPlayer.size.y;
  194. DrawRectangle(x,y,w,h,BLUE);
  195. DrawText("Player",x,y+h/8,h/4,BLACK);
  196. DrawText("Cursors U/D/L/R",10,10,26,BLACK);
  197. DrawText("Cursors U/D/L/R",9,9,26,WHITE);
  198. // Draw the unstuck path for ai agent 0
  199. for(int q=0;q<MAX_UNSTUCKPATH;q++){
  200. //debug = arr_agent[0].unstuckpath[0].y;
  201. int x=arr_agent[0].unstuckpath[q].x;
  202. int y=arr_agent[0].unstuckpath[q].y;
  203. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,(Color){255,0,255,128});
  204. }
  205. /*
  206. DrawRectangle(0,0,800,50,BLACK);
  207. if(arr_agent[0].state==MOVETO){
  208. DrawText("MAIN STATE MOVE",620,10,20,WHITE);
  209. //DrawRectangle(arr_agent[0].subtarget.x,arr_agent[0].subtarget.y,tileWidth/2,tileHeight/2,WHITE);
  210. //DrawRectangle(arr_agent[0].target.x,arr_agent[0].target.y,tileWidth/4,tileHeight/4,RED);
  211. }
  212. if(arr_agent[0].substate==SUBMOVETO){
  213. DrawText("SUBMOVETO",320,10,20,WHITE);
  214. //DrawRectangle(arr_agent[0].subtarget.x,arr_agent[0].subtarget.y,tileWidth/2,tileHeight/2,WHITE);
  215. //DrawRectangle(arr_agent[0].target.x,arr_agent[0].target.y,tileWidth/4,tileHeight/4,RED);
  216. }
  217. if(arr_agent[0].substate==SUBSTUCK){
  218. if(arr_agent[0].state==MOVETO)DrawText(FormatText("MOVETO",arr_agent[0].position.x),0,10,20,WHITE);
  219. if(arr_agent[0].state==WAIT)DrawText(FormatText("WAIT",arr_agent[0].position.x),0,10,20,WHITE);
  220. DrawText(FormatText("SUBSTUCK c %i",arr_agent[0].position.x),120,10,20,WHITE);
  221. DrawText(FormatText("a %i , b %i",arr_agent[0].unstuckpath[0].x,arr_agent[0].unstuckpath[0].y),120,40,20,WHITE);
  222. DrawText(FormatText("%i , %i",arr_agent[0].unstuckpathtop,arr_agent[0].unstuckpathindex),120,60,20,WHITE);
  223. DrawRectangle(arr_agent[0].target.x,arr_agent[0].target.y,tileWidth/4,tileHeight/4,BLUE);
  224. }
  225. if(arr_agent[0].substate==SUBNOTHING){
  226. DrawText("SUBNOTHING",420,10,20,WHITE);
  227. if(arr_agent[0].state==MOVETO)DrawText(FormatText("MOVETO",arr_agent[0].position.x),0,10,20,WHITE);
  228. if(arr_agent[0].state==WAIT)DrawText(FormatText("WAIT",arr_agent[0].position.x),0,10,20,WHITE);
  229. //DrawRectangle(arr_agent[0].subtarget.x,arr_agent[0].subtarget.y,tileWidth/2,tileHeight/2,WHITE);
  230. //DrawRectangle(arr_agent[0].target.x,arr_agent[0].target.y,tileWidth/4,tileHeight/4,BLUE);
  231. }
  232. if(recttilecollide(arr_agent[0].position.x,arr_agent[0].position.y,tileWidth/2,tileHeight/2,0,0)==true){
  233. DrawText("STUCKORS",420,10,20,WHITE);
  234. }
  235. DrawText(FormatText("%i",debug),20,400,30,WHITE);
  236. DrawText(FormatText("%i",debugx),20,430,30,WHITE);
  237. DrawText(FormatText("%i",debugy),20,460,30,WHITE);
  238. */
  239. EndDrawing();
  240. //----------------------------------------------------------------------------------
  241. }
  242. // De-Initialization
  243. //--------------------------------------------------------------------------------------
  244. CloseWindow(); // Close window and OpenGL context
  245. //--------------------------------------------------------------------------------------
  246. return 0;
  247. }
  248. void updateagents(){
  249. for(int i=0;i<MAX_AGENT;i++){
  250. if(arr_agent[i].active==false)continue;
  251. //
  252. // RADAR
  253. //
  254. if(arr_agent[i].state==STAND){
  255. arr_agent[i].rayangle+=AGENT_RADARSPEED;
  256. if(arr_agent[i].rayangle>PI*2.0f)arr_agent[i].rayangle=0;
  257. if(arr_agent[i].rayangle<0)arr_agent[i].rayangle=PI*2.0f;
  258. arr_agent[i].ray = (Vector2){ arr_agent[i].position.x+arr_agent[i].size.x/2,
  259. arr_agent[i].position.y+arr_agent[i].size.y/2};
  260. //debug = (int)arr_agent[i].rayangle;
  261. for(int dist=0;dist<400;dist+=5){
  262. int w = 1;
  263. int h = 1;
  264. float x1 = arr_agent[i].ray.x;
  265. float y1 = arr_agent[i].ray.y;
  266. if(recttilecollide(x1,y1,w,h,0,0)==true){
  267. break;
  268. }
  269. if(rectplayercollide(x1,y1,w,h)==true){
  270. arr_agent[i].state = MOVETO;
  271. arr_agent[i].target.x = x1;
  272. arr_agent[i].target.y = y1;
  273. break;
  274. }
  275. arr_agent[i].ray.x+=cos(arr_agent[i].rayangle)*5;
  276. arr_agent[i].ray.y+=sin(arr_agent[i].rayangle)*5;
  277. }
  278. }
  279. }
  280. //
  281. // WAIT
  282. //
  283. for(int i=0;i<MAX_AGENT;i++){
  284. if(arr_agent[i].active==false)continue;
  285. if(arr_agent[i].state==WAIT){
  286. if(arr_agent[i].waittimer>-1)arr_agent[i].waittimer--;
  287. if(arr_agent[i].waittimer<0){
  288. arr_agent[i].state = STAND;
  289. arr_agent[i].substate=SUBNOTHING;
  290. }
  291. }
  292. }
  293. //
  294. // Movement
  295. //
  296. for(int i=0;i<MAX_AGENT;i++){
  297. if(arr_agent[i].active==false)continue;
  298. //
  299. // Move our agent...
  300. //
  301. if(arr_agent[i].state==MOVETO && arr_agent[i].substate==SUBNOTHING){
  302. Vector2 oldpos=arr_agent[i].position;
  303. float angle = getangle( arr_agent[i].position.x,
  304. arr_agent[i].position.y,
  305. arr_agent[i].target.x,
  306. arr_agent[i].target.y);
  307. arr_agent[i].position.x += cos(angle)*1;
  308. arr_agent[i].position.y += sin(angle)*1;
  309. arr_agent[i].substate = SUBNOTHING;
  310. if(rectsoverlap( arr_agent[i].position.x,
  311. arr_agent[i].position.y,
  312. arr_agent[i].size.x,
  313. arr_agent[i].size.y,
  314. arr_agent[i].target.x,
  315. arr_agent[i].target.y,
  316. tileWidth/2,tileHeight/2)){
  317. arr_agent[i].state = WAIT;
  318. arr_agent[i].substate = SUBNOTHING;
  319. arr_agent[i].waittimer = 10;
  320. }
  321. if(recttilecollide( arr_agent[i].position.x,
  322. arr_agent[i].position.y,
  323. arr_agent[i].size.x,
  324. arr_agent[i].size.y,
  325. 0,0)==true){
  326. arr_agent[i].position = oldpos;
  327. arr_agent[i].substate = SUBSTUCK;
  328. debug = GetRandomValue(0,100);
  329. }
  330. }
  331. //
  332. // Here we get unstuck
  333. //
  334. if(arr_agent[i].state==MOVETO && arr_agent[i].substate==SUBSTUCK){
  335. for(int z=0;z<MAX_UNSTUCKPATH;z++){
  336. arr_agent[i].unstuckpath[z] = (Vector2){0,0};
  337. }
  338. makedijkstramap(arr_agent[i].target.x/tileWidth,arr_agent[i].target.y/tileHeight);
  339. Vector2 pos = (Vector2){11001,11001};
  340. pos.x = arr_agent[i].position.x/tileWidth;
  341. pos.y = arr_agent[i].position.y/tileHeight;
  342. int val = dijkstramap[(int)pos.y][(int)pos.x];
  343. if(val==1){
  344. arr_agent[i].target = myPlayer.position;
  345. makedijkstramap(arr_agent[i].target.x/tileWidth,arr_agent[i].target.y/tileHeight);
  346. val = dijkstramap[(int)pos.y][(int)pos.x];
  347. }
  348. int dx[4]={-1,0,0,1};
  349. int dy[4]={0,-1,1,0};
  350. arr_agent[i].unstuckpathtop = MAX_UNSTUCKPATH;
  351. arr_agent[i].unstuckpath[0].x = (int)pos.x;
  352. arr_agent[i].unstuckpath[0].y = (int)pos.y;
  353. for(int un=1;un<MAX_UNSTUCKPATH;un++){
  354. for(int qq=0;qq<4;qq++){
  355. int x2 = pos.x+dx[qq];
  356. int y2 = pos.y+dy[qq];
  357. if(dijkstramap[y2][x2]!=-1 && dijkstramap[y2][x2]<val){
  358. //debug = GetRandomValue(0,100);
  359. val=dijkstramap[y2][x2];
  360. if(val==1)arr_agent[i].unstuckpathtop=un;
  361. pos.x = x2;
  362. pos.y = y2;
  363. arr_agent[i].unstuckpath[un] = (Vector2){x2,y2};
  364. break;
  365. }
  366. }
  367. }
  368. arr_agent[i].substate = SUBMOVETO;
  369. arr_agent[i].unstuckpathindex = 0;
  370. //arr_agent[i].position.x = arr_agent[i].unstuckpath[0].x*tileWidth;
  371. //arr_agent[i].position.y = arr_agent[i].unstuckpath[0].y*tileHeight;
  372. //makedijkstramap(5,2);
  373. }
  374. //
  375. // Here we move the unstuck path
  376. //
  377. if(arr_agent[i].state==MOVETO && arr_agent[i].substate==SUBMOVETO){
  378. int x = arr_agent[i].unstuckpath[arr_agent[i].unstuckpathindex].x*tileWidth;
  379. int y = arr_agent[i].unstuckpath[arr_agent[i].unstuckpathindex].y*tileHeight;
  380. int px = arr_agent[i].position.x;
  381. int py = arr_agent[i].position.y;
  382. if(px<x)arr_agent[i].position.x++;
  383. if(px>x)arr_agent[i].position.x--;
  384. if(py<y)arr_agent[i].position.y++;
  385. if(py>y)arr_agent[i].position.y--;
  386. if(rectsoverlap( arr_agent[i].position.x-1,arr_agent[i].position.y-1,2,2,
  387. x-1,y-1,2,2)){
  388. arr_agent[i].unstuckpathindex++;
  389. }
  390. if(arr_agent[i].unstuckpathindex>=MAX_UNSTUCKPATH || arr_agent[i].unstuckpathindex>=arr_agent[i].unstuckpathtop){
  391. arr_agent[i].substate=SUBNOTHING;
  392. arr_agent[i].state = WAIT;
  393. arr_agent[i].unstuckpathindex = 0;
  394. }
  395. if(rectsoverlap(arr_agent[i].position.x,arr_agent[i].position.y,10,10,arr_agent[i].target.x,arr_agent[i].target.y,10,10)){
  396. //arr_agent[i].state = WAIT;
  397. //arr_agent[i].substate = SUBNOTHING;
  398. //arr_agent[i].waittimer = 10;
  399. }
  400. }
  401. }
  402. }
  403. void updateplayer(){
  404. Vector2 oldpos = myPlayer.position;
  405. if(IsKeyDown(KEY_LEFT)){
  406. myPlayer.position.x-=1;
  407. }
  408. if(IsKeyDown(KEY_RIGHT)){
  409. myPlayer.position.x+=1;
  410. }
  411. if(recttilecollide(myPlayer.position.x,myPlayer.position.y,tileWidth/2,tileHeight/2,0,0)){
  412. myPlayer.position = oldpos;
  413. }
  414. oldpos = myPlayer.position;
  415. if(IsKeyDown(KEY_UP)){
  416. myPlayer.position.y-=1;
  417. }
  418. if(IsKeyDown(KEY_DOWN)){
  419. myPlayer.position.y+=1;
  420. }
  421. if(recttilecollide(myPlayer.position.x,myPlayer.position.y,tileWidth/2,tileHeight/2,0,0)){
  422. myPlayer.position = oldpos;
  423. }
  424. }
  425. void makedijkstramap(int startx, int starty){
  426. // int startx;
  427. // int starty;
  428. // First make sure every map value is 0.
  429. for(int y=0;y<mapHeight;y++){
  430. for(int x=0;x<mapWidth;x++){
  431. if(map[y][x]==GROUND){
  432. dijkstramap[y][x] = map[y][x];
  433. }else{
  434. dijkstramap[y][x] = -1;
  435. }
  436. }}
  437. // if(map1[y][x]==1)dijkstramap[y][x]=-1;
  438. // if(map1[y][x]==4){
  439. // startx = x;
  440. // starty = y;
  441. // }
  442. // }}
  443. //
  444. //
  445. // Flood the map with distances from the start.
  446. //
  447. // We store the distance on each map cell if there is no wall there.
  448. //
  449. struct pathnode list[MAX_PATH];
  450. dijkstramap[starty][startx]=1;
  451. int listlen=0;
  452. list[listlen].x=startx;
  453. list[listlen].y=starty;
  454. listlen+=1;
  455. int failed=0;
  456. // 4 way search! left/up/down/right
  457. int dx[4]={-1,0,0,1};
  458. int dy[4]={0,-1,1,0};
  459. // While we have a list to work with
  460. while(listlen>0){
  461. // Take the first value from the array.
  462. int x1=list[0].x;
  463. int y1=list[0].y;
  464. // shift all up.
  465. for(int i=0;i<listlen;i++){
  466. list[i].x = list[i+1].x;
  467. list[i].y = list[i+1].y;
  468. }
  469. // Decrease list length+
  470. listlen-=1;
  471. //
  472. // Here we check around our current position.
  473. for(int i=0;i<4;i++){
  474. int nx = x1+dx[i];
  475. int ny = y1+dy[i];
  476. if(nx<0 || ny<0 || nx>= mapWidth || ny>= mapHeight)continue;
  477. // If we can get there then put the new distance there and add this position
  478. // to the list.
  479. if(dijkstramap[ny][nx]==GROUND){
  480. dijkstramap[ny][nx]=dijkstramap[y1][x1]+1;
  481. if(dijkstramap[ny][nx]>topdijkstralen)topdijkstralen=dijkstramap[ny][nx];
  482. // add to last
  483. //
  484. list[listlen].x = nx;
  485. list[listlen].y = ny;
  486. listlen++;
  487. //
  488. }
  489. }
  490. // Error?
  491. failed+=1;
  492. if(failed>160000)return;
  493. }
  494. }
  495. // Manhattan Distance (less precise)
  496. float distance(float x1,float y1,float x2,float y2){
  497. return (float)abs(x2-x1)+abs(y2-y1);
  498. }
  499. // Euclidean distance (more precise)
  500. float edistance(float x1,float y1,float x2,float y2){
  501. return sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) );
  502. }
  503. bool rectplayercollide(int x, int y, int w, int h){
  504. if(rectsoverlap(x,y,w,h,myPlayer.position.x,myPlayer.position.y,myPlayer.size.x,myPlayer.size.y)==true){
  505. return true;
  506. }
  507. return false;
  508. }
  509. //Unit collide with solid blocks true/false
  510. bool recttilecollide(int x, int y,int w, int h, int offsetx,int offsety){
  511. //y+=abs(mapy);//for scrolling
  512. int cx = (x+offsetx)/tileWidth;
  513. int cy = (y+offsety)/tileHeight;
  514. for(int y2=cy-1; y2<cy+2;y2++){//Note that the - and + are to be set differently with differently sized players
  515. for(int x2=cx-1; x2<cx+2;x2++){
  516. if(x2>=0 && x2<mapWidth && y2>=0 && y2<mapHeight){
  517. if(map[y2][x2] == 1){
  518. int x3 = (x2)*tileWidth;
  519. int y3 = (y2)*tileHeight;
  520. if(rectsoverlap(x+offsetx,y+offsety,w,h,x3,y3,tileWidth,tileHeight)){
  521. return true;
  522. }
  523. }
  524. }
  525. }}
  526. return false;
  527. }
  528. // Rectangles overlap
  529. bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){
  530. if(x1 >= (x2 + w2) || (x1 + w1) <= x2) return false;
  531. if(y1 >= (y2 + h2) || (y1 + h1) <= y2) return false;
  532. return true;
  533. }
  534. // Return the angle from - to in float
  535. float getangle(float x1,float y1,float x2,float y2){
  536. return (float)atan2(y2-y1, x2-x1);
  537. }