VectorForceObject.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // In the book Pro Html5 Games one of the games learned to program there is a rts. To be honest I do not really understand
  2. // much of how to code a complete rts like shown in that book but I was looking through it again and had learned more about
  3. // vectors. (search: the coding train)
  4. // Force vector object in this book are used to be placed on a path to push away units. I tried to code this myself here but only
  5. // used a couple of these vfo's myself.
  6. //
  7. // What the code does is create a set of units on the map. One routine is to move all units apart from each other. The Force
  8. // vector object code moves away units from that force vector object position. I find the angle from vector vs unit and move
  9. // the unit in the opposite direction of that point.
  10. //
  11. // These vfo's can (one) be placed under the mouse. One is positioned in the movement direction of the player controlled
  12. // unit.
  13. // It seems to work..
  14. //
  15. #define MAX_UNITS 64
  16. #define MAX_VFO 64
  17. #include "raylib.h"
  18. #include <math.h>
  19. static float tileWidth,tileHeight;
  20. typedef struct vfo{ // force vector object (repulse objects from this point.
  21. bool active;
  22. Vector2 position;
  23. }vfo;
  24. typedef struct unit{
  25. bool active;
  26. bool controlled;
  27. float x,y;
  28. int targetx,targety;
  29. }unit;
  30. static struct unit arr_unit[MAX_UNITS];
  31. static struct vfo arr_vfo[MAX_VFO];
  32. static float getangle(float x1,float y1,float x2, float y2);
  33. static float distance(float x1,float y1,float x2, float y2);
  34. int main(void)
  35. {
  36. // Initialization
  37. //--------------------------------------------------------------------------------------
  38. const int screenWidth = 800;
  39. const int screenHeight = 450;
  40. const int mapWidth = 20;
  41. const int mapHeight = 20;
  42. tileWidth = abs((float)screenHeight/(float)mapWidth);
  43. tileHeight = abs((float)screenHeight/(float)mapHeight);
  44. InitWindow(screenWidth, screenHeight, "raylib example.");
  45. //
  46. // initiate a number of units.
  47. for(int i=0;i<MAX_UNITS;i++){ // all units to false
  48. arr_unit[i].active = false;
  49. }
  50. int num=0;
  51. for(int y=8;y<12;y++){ // create a number of units.
  52. for(int x=8;x<12;x++){
  53. arr_unit[num].active = true;
  54. arr_unit[num].controlled = false;
  55. arr_unit[num].x = 8*tileWidth;
  56. arr_unit[num].y = 8*tileHeight+GetRandomValue(-5,5);
  57. arr_unit[num].targetx = -1;
  58. arr_unit[num].targety = -1;
  59. num++;
  60. }}
  61. arr_unit[0].controlled = true;
  62. // Our Force Vector Object [0] is the one in front of our player.
  63. arr_vfo[0].active = true;
  64. for(int i=1;i<MAX_VFO;i++){
  65. arr_vfo[i].active=false;
  66. }
  67. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  68. //--------------------------------------------------------------------------------------
  69. // Main game loop
  70. while (!WindowShouldClose()) // Detect window close button or ESC key
  71. {
  72. // Update
  73. //----------------------------------------------------------------------------------
  74. // Force Vector Object [0] is in front of our player contoller unit.
  75. arr_vfo[0].position.x = arr_unit[0].x+tileWidth/2;
  76. arr_vfo[0].position.y = arr_unit[0].y+tileHeight/2;
  77. // Move our unit and position the force vector object.
  78. if(IsKeyDown(KEY_UP)){
  79. arr_unit[0].y-=1;
  80. arr_vfo[0].position.y -= tileHeight;
  81. }
  82. if(IsKeyDown(KEY_DOWN)){
  83. arr_unit[0].y+=1;
  84. arr_vfo[0].position.y += tileHeight;
  85. }
  86. if(IsKeyDown(KEY_LEFT)){
  87. arr_unit[0].x-=1;
  88. arr_vfo[0].position.x -= tileWidth/2+tileWidth/2;
  89. }
  90. if(IsKeyDown(KEY_RIGHT)){
  91. arr_unit[0].x+=1;
  92. arr_vfo[0].position.x += tileWidth;
  93. }
  94. // Position a Force Vector Object under the mouse!
  95. if(IsMouseButtonPressed(0)){
  96. arr_vfo[1].active = true;
  97. arr_vfo[1].position.x = GetMouseX();
  98. arr_vfo[1].position.y = GetMouseY();
  99. }
  100. //----------------------------------------------------------------------------------
  101. // Draw
  102. //----------------------------------------------------------------------------------
  103. BeginDrawing();
  104. ClearBackground(RAYWHITE);
  105. // draw units
  106. for(int i=0;i<MAX_UNITS;i++){
  107. if(arr_unit[i].active){
  108. Color MYCOL=(Color){255,255,0,255};
  109. if(i==0)MYCOL=(Color){255,0,0,255};
  110. DrawRectangle(arr_unit[i].x,arr_unit[i].y,tileWidth,tileHeight,BLACK);
  111. DrawRectangle(arr_unit[i].x+1,arr_unit[i].y+1,tileWidth-2,tileHeight-2,MYCOL);
  112. }
  113. }
  114. //
  115. // Move units away from each other.
  116. for(int i=0;i<MAX_UNITS;i++){
  117. for(int ii=0;ii<MAX_UNITS;ii++){
  118. if(arr_unit[i].active==false || arr_unit[ii].active==false || i==ii)continue;
  119. float d = distance(arr_unit[i].x,arr_unit[i].y,arr_unit[ii].x,arr_unit[ii].y);
  120. if(d>64)continue;
  121. float an=getangle(arr_unit[i].x,arr_unit[i].y,arr_unit[ii].x,arr_unit[ii].y);
  122. if(arr_unit[i].controlled==false)arr_unit[i].x -= cos(an)*2;
  123. if(arr_unit[i].controlled==false)arr_unit[i].y -= sin(an)*2;
  124. if(arr_unit[ii].controlled==false)arr_unit[ii].x += cos(an)*2;
  125. if(arr_unit[ii].controlled==false)arr_unit[ii].y += sin(an)*2;
  126. }
  127. }
  128. // Move units away from force vector object
  129. for(int i=1;i<MAX_VFO;i++){ //force vector object 0 is for user controlled
  130. for(int ii=0;ii<MAX_UNITS;ii++){
  131. if(arr_unit[ii].active==false || arr_unit[ii].controlled==true)continue;
  132. 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;
  133. 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);
  134. arr_unit[ii].x += cos(an)*2;
  135. arr_unit[ii].y += sin(an)*2;
  136. }
  137. }
  138. // Draw vfo points.
  139. for(int i=0;i<MAX_VFO;i++){
  140. if(arr_vfo[i].active==false)continue;
  141. DrawCircle(arr_vfo[i].position.x,arr_vfo[i].position.y,1,RED);
  142. }
  143. //
  144. DrawText("Use Cursor keys to control unit. Press Mouse to Scatter units.",0,0,20,DARKGRAY);
  145. EndDrawing();
  146. //----------------------------------------------------------------------------------
  147. }
  148. // De-Initialization
  149. //--------------------------------------------------------------------------------------
  150. CloseWindow(); // Close window and OpenGL context
  151. //--------------------------------------------------------------------------------------
  152. return 0;
  153. }
  154. //' Return the angle from - to in float
  155. float getangle(float x1,float y1,float x2,float y2){
  156. return (float)atan2(y2-y1, x2-x1);
  157. }
  158. // Manhattan Distance (less precise)
  159. float distance(float x1,float y1,float x2,float y2){
  160. return (float)abs(x2-x1)+abs(y2-y1);
  161. }