2
0

FlowFieldTest.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. //
  2. // FLOW fields - work in progress
  3. //
  4. #define MAX_AGENTS 50
  5. #include "raylib.h"
  6. #include <math.h>
  7. // This is our tile map.
  8. int map[10][20] = { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  9. {1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,1,1},
  10. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1},
  11. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  12. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  13. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  14. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  15. {1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1},
  16. {1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1},
  17. {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};
  18. static float tileWidth;
  19. static float tileHeight;
  20. static int mapWidth;
  21. static int mapHeight;
  22. typedef struct player{
  23. Vector2 position;
  24. int width;
  25. int height;
  26. }player;
  27. static player myplayer = {0};
  28. static float flowfieldmap[10][20] = {0};
  29. typedef struct agent{
  30. Vector2 position;
  31. int width;
  32. int height;
  33. Vector2 target;
  34. float speed;
  35. int pausetime;
  36. }agent;
  37. static struct agent arr_agent[MAX_AGENTS];
  38. // uses the myplayer.position coordinates.
  39. // If offsetx is 1 then it checks if the player x position PLus 1 is colliding with a tile.
  40. static bool playertilecollide(int offsetx,int offsety);
  41. static bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2);
  42. static float getangle(float x1,float y1,float x2,float y2);
  43. int main(void)
  44. {
  45. // Initialization
  46. //--------------------------------------------------------------------------------------
  47. const int screenWidth = 800;
  48. const int screenHeight = 450;
  49. mapWidth = 20;
  50. mapHeight = 10;
  51. // Our tile width and height. We use the screen dimension and the map dimension to
  52. // get tile dimensions that fill up the entire screen.
  53. tileWidth = (float)screenWidth/(float)mapWidth;
  54. tileHeight = (float)screenHeight/(float)mapHeight;
  55. InitWindow(screenWidth, screenHeight, "raylib example.");
  56. // Our player setup
  57. myplayer.position = (Vector2){4*tileWidth,6*tileHeight};
  58. myplayer.width = tileWidth/2;
  59. myplayer.height = tileHeight/2;
  60. for(int y=0;y<mapHeight;y++){
  61. for(int x=0;x<mapWidth;x++){
  62. flowfieldmap[y][x]=GetRandomValue(0,3);
  63. }
  64. }
  65. // add units to the screen
  66. int y=0;
  67. int x=0;
  68. int sq=0;
  69. for(int i=0;i<MAX_AGENTS;i++){
  70. arr_agent[i].position = (Vector2){100+x,100+y};
  71. arr_agent[i].width = 10;
  72. arr_agent[i].height = 10;
  73. arr_agent[i].speed = 1.0f;
  74. arr_agent[i].target = (Vector2){400,200};
  75. arr_agent[i].pausetime = 0;
  76. x+=12;
  77. sq++;
  78. if(sq == 4){
  79. sq=0;
  80. y+=12;
  81. x=0;
  82. }
  83. }
  84. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  85. //--------------------------------------------------------------------------------------
  86. // Main game loop
  87. while (!WindowShouldClose()) // Detect window close button or ESC key
  88. {
  89. // Update
  90. //----------------------------------------------------------------------------------
  91. // Below here we read the key. If the l/r/u/d cursor is pressed then we check the new position is inside
  92. // the array bounds and then we check if the collision map on the new position is not set to flag true on that tile.
  93. if(IsKeyDown(KEY_RIGHT)&& myplayer.position.x+1<(mapWidth-1)*tileWidth){
  94. if(playertilecollide(1,0)==false){
  95. myplayer.position.x+=1;
  96. }
  97. }
  98. if(IsKeyDown(KEY_LEFT) && myplayer.position.x-1>-1){
  99. if(playertilecollide(-1,0)==false){
  100. myplayer.position.x-=1;
  101. }
  102. }
  103. if(IsKeyDown(KEY_UP)&& myplayer.position.y-1>-1){
  104. if(playertilecollide(0,-1)==false){
  105. myplayer.position.y-=1;
  106. }
  107. }
  108. if(IsKeyDown(KEY_DOWN) && myplayer.position.y+1<(mapHeight-1)*tileHeight){
  109. if(playertilecollide(0,1)==false){
  110. myplayer.position.y+=1;
  111. }
  112. }
  113. if(IsMouseButtonPressed(0)){
  114. for(int i=0;i<MAX_AGENTS;i++){
  115. int posx = GetMouseX()/tileWidth;
  116. int posy = GetMouseY()/tileHeight;
  117. //if(map[posy][posx]==0){
  118. arr_agent[i].target = GetMousePosition();
  119. //}
  120. }
  121. }
  122. //reset flowfieldmap
  123. if(GetRandomValue(0,20)==1){
  124. for(int y=0;y<mapHeight;y++){
  125. for(int x=0;x<mapWidth;x++){
  126. flowfieldmap[y][x]=0;
  127. }}
  128. }
  129. // Move the units.
  130. for(int i=0;i<MAX_AGENTS;i++){
  131. if(arr_agent[i].pausetime>0){
  132. arr_agent[i].pausetime--;
  133. }
  134. if(arr_agent[i].pausetime>0)continue;
  135. float angle = getangle(arr_agent[i].position.x,arr_agent[i].position.y,arr_agent[i].target.x,arr_agent[i].target.y);
  136. Vector2 oldPos = arr_agent[i].position;
  137. int posx=arr_agent[i].position.x/tileWidth;
  138. int posy=arr_agent[i].position.y/tileHeight;
  139. arr_agent[i].position.x+= cos(angle);
  140. arr_agent[i].position.y+= sin(angle);
  141. if(flowfieldmap[posy][posx]!=0){
  142. arr_agent[i].position.x+= cos(flowfieldmap[posy][posx])/1.5;
  143. arr_agent[i].position.y+= sin(flowfieldmap[posy][posx])/1.5;
  144. }
  145. for(int j=0;j<MAX_AGENTS;j++){
  146. if(j==i)continue;
  147. if(rectsoverlap(arr_agent[i].position.x,arr_agent[i].position.y,arr_agent[i].width,arr_agent[i].height,
  148. arr_agent[j].position.x,arr_agent[j].position.y,arr_agent[j].width,arr_agent[j].height)){
  149. arr_agent[i].position = oldPos;
  150. arr_agent[i].pausetime = GetRandomValue(0,5);
  151. float an2=getangle(arr_agent[i].position.x,arr_agent[i].position.y,arr_agent[j].position.x,arr_agent[j].position.y);
  152. int px = arr_agent[j].position.x/tileWidth;
  153. int py = arr_agent[j].position.y/tileHeight;
  154. flowfieldmap[py][px]=an2+GetRandomValue(-1.5f,1.5f);
  155. }
  156. }
  157. }
  158. //----------------------------------------------------------------------------------
  159. // Draw
  160. //----------------------------------------------------------------------------------
  161. BeginDrawing();
  162. ClearBackground(RAYWHITE);
  163. // Draw our tilemap.
  164. for(int y=0;y<10;y++){
  165. for(int x=0;x<20;x++){
  166. if(map[y][x]==1){
  167. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,BLACK);
  168. }
  169. }
  170. }
  171. // Draw out agents
  172. for(int i=0;i<MAX_AGENTS;i++){
  173. DrawRectangle(arr_agent[i].position.x,arr_agent[i].position.y,arr_agent[i].width,arr_agent[i].height,BLUE);
  174. }
  175. // Draw our player
  176. DrawRectangle(myplayer.position.x,myplayer.position.y,myplayer.width,myplayer.height,RED);
  177. DrawText("Use Cursor Keys to move around..",0,0,20,WHITE);
  178. EndDrawing();
  179. //----------------------------------------------------------------------------------
  180. }
  181. // De-Initialization
  182. //--------------------------------------------------------------------------------------
  183. CloseWindow(); // Close window and OpenGL context
  184. //--------------------------------------------------------------------------------------
  185. return 0;
  186. }
  187. //Unit collide with solid blocks true/false
  188. bool playertilecollide(int offsetx,int offsety){
  189. int cx = (myplayer.position.x+offsetx)/tileWidth;
  190. int cy = (myplayer.position.y+offsety)/tileHeight;
  191. for(int y2=cy-1; y2<cy+2;y2++){//Note that the - and + are to be set differently with differently sized players
  192. for(int x2=cx-1; x2<cx+2;x2++){
  193. if(x2>=0 && x2<mapWidth && y2>=0 && y2<mapHeight){
  194. if(map[y2][x2] == 1){
  195. int x3 = (x2)*tileWidth;
  196. int y3 = (y2)*tileHeight;
  197. if(rectsoverlap(myplayer.position.x+offsetx,myplayer.position.y+offsety,myplayer.width,myplayer.height,x3,y3,tileWidth,tileHeight)){
  198. return true;
  199. }
  200. }
  201. }
  202. }}
  203. return false;
  204. }
  205. // Rectangles overlap
  206. bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){
  207. if(x1 >= (x2 + w2) || (x1 + w1) <= x2) return false;
  208. if(y1 >= (y2 + h2) || (y1 + h1) <= y2) return false;
  209. return true;
  210. }
  211. // Return the angle from - to in float
  212. float getangle(float x1,float y1,float x2,float y2){
  213. return (float)atan2(y2-y1, x2-x1);
  214. }