Vector_Force_Object_Tiles.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #define MAX_UNITS 64
  2. #define MAX_VFO 64
  3. #include "raylib.h"
  4. #include <math.h>
  5. // 0 is passable 1 is blocked
  6. static int map[20][20] = { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
  7. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  8. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  9. {1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1},
  10. {1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  11. {1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  12. {1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  13. {1,0,0,1,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,0,0,0,0,0,0,0,0,1},
  16. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  17. {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},
  18. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
  19. {1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1},
  20. {1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1},
  21. {1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1},
  22. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1},
  23. {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1},
  24. {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};
  25. static float tileWidth,tileHeight;
  26. static int mapWidth,mapHeight;
  27. typedef struct vfo{ // force vector object (repulse objects from this point.
  28. bool active;
  29. Vector2 position;
  30. }vfo;
  31. typedef struct unit{
  32. bool active;
  33. bool controlled;
  34. float x,y;
  35. int targetx,targety;
  36. }unit;
  37. static struct unit arr_unit[MAX_UNITS];
  38. static struct vfo arr_vfo[MAX_VFO];
  39. static float getangle(float x1,float y1,float x2, float y2);
  40. static float distance(float x1,float y1,float x2, float y2);
  41. static bool utc(int unit,int offsetx,int offsety); //unit tile collision
  42. static bool uuc(int unit1,int offx,int offy); //unit vs all units collision
  43. static bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2);
  44. int main(void)
  45. {
  46. // Initialization
  47. //--------------------------------------------------------------------------------------
  48. const int screenWidth = 800;
  49. const int screenHeight = 450;
  50. mapWidth = 20;
  51. mapHeight = 20;
  52. tileWidth = abs((float)screenWidth/(float)mapWidth);
  53. tileHeight = abs((float)screenHeight/(float)mapHeight);
  54. InitWindow(screenWidth, screenHeight, "raylib example.");
  55. //
  56. // initiate a number of units.
  57. for(int i=0;i<MAX_UNITS;i++){ // all units to false
  58. arr_unit[i].active = false;
  59. }
  60. int num=0;
  61. for(int y=8;y<12;y++){ // create a number of units.
  62. for(int x=8;x<12;x++){
  63. arr_unit[num].active = true;
  64. arr_unit[num].controlled = false;
  65. arr_unit[num].x = x*tileWidth;
  66. arr_unit[num].y = y*tileHeight;
  67. arr_unit[num].targetx = -1;
  68. arr_unit[num].targety = -1;
  69. num++;
  70. }}
  71. arr_unit[0].controlled = true;
  72. // Our Force Vector Object [0] is the one in front of our player.
  73. arr_vfo[0].active = true;
  74. for(int i=1;i<MAX_VFO;i++){
  75. arr_vfo[i].active=false;
  76. }
  77. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  78. //--------------------------------------------------------------------------------------
  79. // Main game loop
  80. while (!WindowShouldClose()) // Detect window close button or ESC key
  81. {
  82. // Update
  83. //----------------------------------------------------------------------------------
  84. // Force Vector Object [0] is in front of our player contoller unit.
  85. arr_vfo[0].position.x = arr_unit[0].x+tileWidth/2;
  86. arr_vfo[0].position.y = arr_unit[0].y+tileHeight/2;
  87. // Move our unit and position the force vector object.
  88. if(IsKeyDown(KEY_UP)){
  89. if(uuc(0,0,-1)==false && utc(0,0,-1)==false){
  90. arr_unit[0].y-=1;
  91. arr_vfo[0].position.y -= tileHeight;
  92. }
  93. }
  94. if(IsKeyDown(KEY_DOWN)){
  95. if(uuc(0,0,1)==false && utc(0,0,1)==false){
  96. arr_unit[0].y+=1;
  97. arr_vfo[0].position.y += tileHeight;
  98. }
  99. }
  100. if(IsKeyDown(KEY_LEFT)){
  101. if(uuc(0,-1,0)==false && utc(0,-1,0)==false){
  102. arr_unit[0].x-=1;
  103. arr_vfo[0].position.x -= tileWidth/2+tileWidth/2;
  104. }
  105. }
  106. if(IsKeyDown(KEY_RIGHT)){
  107. if(uuc(0,1,0)==false && utc(0,1,0)==false){
  108. arr_unit[0].x+=1;
  109. arr_vfo[0].position.x += tileWidth;
  110. }
  111. }
  112. // Position a Force Vector Object under the mouse!
  113. if(IsMouseButtonPressed(0)){
  114. arr_vfo[1].active = true;
  115. arr_vfo[1].position.x = GetMouseX();
  116. arr_vfo[1].position.y = GetMouseY();
  117. }
  118. //
  119. // Move units away from each other.
  120. for(int i=0;i<MAX_UNITS;i++){
  121. for(int ii=0;ii<MAX_UNITS;ii++){
  122. if(arr_unit[i].active==false || arr_unit[ii].active==false || i==ii)continue;
  123. float d = distance(arr_unit[i].x,arr_unit[i].y,arr_unit[ii].x,arr_unit[ii].y);
  124. if(d>64)continue;
  125. float an=getangle(arr_unit[i].x,arr_unit[i].y,arr_unit[ii].x,arr_unit[ii].y);
  126. // Store positions of units to be moved here
  127. int oldx1 = arr_unit[i].x;
  128. int oldy1 = arr_unit[i].y;
  129. int oldx2 = arr_unit[ii].x;
  130. int oldy2 = arr_unit[ii].y;
  131. // Move the units here.
  132. if(arr_unit[i].controlled==false)arr_unit[i].x -= cos(an)*1;
  133. if(arr_unit[i].controlled==false)arr_unit[i].y -= sin(an)*1;
  134. if(arr_unit[ii].controlled==false)arr_unit[ii].x += cos(an)*1;
  135. if(arr_unit[ii].controlled==false)arr_unit[ii].y += sin(an)*1;
  136. // if collide with map then restore old position.
  137. if(utc(i,0,0) || uuc(i,0,0)){
  138. arr_unit[i].x = oldx1;
  139. arr_unit[i].y = oldy1;
  140. }
  141. if(utc(ii,0,0) || uuc(ii,0,0)){
  142. arr_unit[ii].x = oldx2;
  143. arr_unit[ii].y = oldy2;
  144. }
  145. }
  146. }
  147. // Move units away from force vector object
  148. for(int i=1;i<MAX_VFO;i++){ //force vector object 0 is for user controlled
  149. for(int ii=0;ii<MAX_UNITS;ii++){
  150. if(arr_unit[ii].active==false || arr_unit[ii].controlled==true)continue;
  151. if(distance(arr_vfo[i].position.x,arr_vfo[i].position.y,arr_unit[ii].x+tileWidth/2,arr_unit[ii].y+tileHeight/2)>64)continue;
  152. float an=getangle(arr_vfo[i].position.x,arr_vfo[i].position.y,arr_unit[ii].x+tileWidth/2,arr_unit[ii].y+tileHeight/2);
  153. // store old unit position
  154. int oldx=arr_unit[ii].x;
  155. int oldy=arr_unit[ii].y;
  156. // Move unit
  157. arr_unit[ii].x += cos(an)*1;
  158. arr_unit[ii].y += sin(an)*1;
  159. // if collide with map then restore old position.
  160. if(utc(ii,0,0) || uuc(ii,0,0)){ // unit tile collision
  161. arr_unit[ii].x = oldx;
  162. arr_unit[ii].y = oldy;
  163. }
  164. }
  165. }
  166. //----------------------------------------------------------------------------------
  167. // Draw
  168. //----------------------------------------------------------------------------------
  169. BeginDrawing();
  170. ClearBackground(RAYWHITE);
  171. // Draw Map
  172. for(int y=0;y<mapHeight;y++){
  173. for(int x=0;x<mapWidth;x++){
  174. if(map[y][x]==1){
  175. DrawRectangle(x*tileWidth,y*tileHeight,tileWidth,tileHeight,GREEN);
  176. }
  177. }
  178. }
  179. // draw units
  180. for(int i=0;i<MAX_UNITS;i++){
  181. if(arr_unit[i].active){
  182. Color MYCOL=(Color){255,255,0,255};
  183. if(i==0)MYCOL=(Color){255,0,0,255};
  184. DrawRectangle(arr_unit[i].x,arr_unit[i].y,tileWidth,tileHeight,BLACK);
  185. DrawRectangle(arr_unit[i].x+1,arr_unit[i].y+1,tileWidth-2,tileHeight-2,MYCOL);
  186. }
  187. }
  188. // Draw vfo points.
  189. for(int i=0;i<MAX_VFO;i++){
  190. if(arr_vfo[i].active==false)continue;
  191. DrawCircle(arr_vfo[i].position.x,arr_vfo[i].position.y,1,RED);
  192. }
  193. //
  194. DrawText("Use Cursor keys to control unit. Press Mouse to Scatter units.",0,0,20,DARKGRAY);
  195. EndDrawing();
  196. //----------------------------------------------------------------------------------
  197. }
  198. // De-Initialization
  199. //--------------------------------------------------------------------------------------
  200. CloseWindow(); // Close window and OpenGL context
  201. //--------------------------------------------------------------------------------------
  202. return 0;
  203. }
  204. //' Return the angle from - to in float
  205. float getangle(float x1,float y1,float x2,float y2){
  206. return (float)atan2(y2-y1, x2-x1);
  207. }
  208. // Manhattan Distance (less precise)
  209. float distance(float x1,float y1,float x2,float y2){
  210. return (float)abs(x2-x1)+abs(y2-y1);
  211. }
  212. //Unit collide with solid blocks true/false
  213. bool utc(int unit,int offsetx,int offsety){
  214. int cx = (arr_unit[unit].x+offsetx)/tileWidth;
  215. int cy = (arr_unit[unit].y+offsety)/tileHeight;
  216. for(int y2=cy-1; y2<cy+5;y2++){
  217. for(int x2=cx-1; x2<cx+5;x2++){
  218. if(x2>=0 && x2<mapWidth && y2>=0 && y2<mapHeight){
  219. if(map[y2][x2] == 1){
  220. int x3 = (x2)*tileWidth-tileWidth;
  221. int y3 = (y2)*tileHeight;
  222. if(rectsoverlap(arr_unit[unit].x-tileWidth+offsetx,arr_unit[unit].y+offsety,tileWidth,tileHeight,x3,y3,tileWidth,tileHeight)){
  223. return true;
  224. }
  225. }
  226. }
  227. }}
  228. return false;
  229. }
  230. // Unit collides with Other units. offset x and y.
  231. bool uuc(int unit,int offx,int offy){
  232. for(int i=1;i<MAX_UNITS;i++){
  233. if(i==unit)continue;
  234. if(rectsoverlap( arr_unit[unit].x+offx,
  235. arr_unit[unit].y+offy,
  236. tileWidth,
  237. tileHeight,
  238. arr_unit[i].x,
  239. arr_unit[i].y,
  240. tileWidth,
  241. tileHeight)){
  242. return true;
  243. }
  244. }
  245. return false;
  246. }
  247. // Rectangles overlap
  248. bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){
  249. if(x1 >= (x2 + w2) || (x1 + w1) <= x2) return false;
  250. if(y1 >= (y2 + h2) || (y1 + h1) <= y2) return false;
  251. return true;
  252. }