You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
9.9 KiB

  1. /*******************************************************************************************
  2. *
  3. * raylib [physac] example - Forces
  4. *
  5. * This example has been created using raylib 1.5 (www.raylib.com)
  6. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  7. *
  8. * NOTE: This example requires raylib module [rlgl]
  9. *
  10. * Compile example using:
  11. * cmd /c IF NOT EXIST pthreadGC2.dll copy C:\raylib\raylib\src\external\pthread\pthreadGC2.dll $(CURRENT_DIRECTORY) /Y
  12. *
  13. * Copyright (c) 2016 Victor Fisac and Ramon Santamaria (@raysan5)
  14. *
  15. ********************************************************************************************/
  16. #include "raylib.h"
  17. #define PHYSAC_IMPLEMENTATION
  18. #include "physac.h"
  19. #define FORCE_AMOUNT 5.0f
  20. #define FORCE_RADIUS 150
  21. #define LINE_LENGTH 75
  22. #define TRIANGLE_LENGTH 12
  23. int main()
  24. {
  25. // Initialization
  26. //--------------------------------------------------------------------------------------
  27. int screenWidth = 800;
  28. int screenHeight = 450;
  29. InitWindow(screenWidth, screenHeight, "raylib [physac] example - forces");
  30. InitPhysics((Vector2){ 0.0f, -9.81f/2 }); // Initialize physics module
  31. // Global variables
  32. Vector2 mousePosition;
  33. bool isDebug = false;
  34. // Create rectangle physic objects
  35. PhysicBody rectangles[3];
  36. for (int i = 0; i < 3; i++)
  37. {
  38. rectangles[i] = CreatePhysicBody((Vector2){ screenWidth/4*(i+1), (((i % 2) == 0) ? (screenHeight/3) : (screenHeight/1.5f)) }, 0.0f, (Vector2){ 50, 50 });
  39. rectangles[i]->rigidbody.enabled = true; // Enable physic object rigidbody behaviour
  40. rectangles[i]->rigidbody.friction = 0.1f;
  41. }
  42. // Create circles physic objects
  43. // NOTE: when creating circle physic objects, transform.scale must be { 0, 0 } and object radius must be defined in collider.radius and use this value to draw the circle.
  44. PhysicBody circles[3];
  45. for (int i = 0; i < 3; i++)
  46. {
  47. circles[i] = CreatePhysicBody((Vector2){ screenWidth/4*(i+1), (((i % 2) == 0) ? (screenHeight/1.5f) : (screenHeight/4)) }, 0.0f, (Vector2){ 0, 0 });
  48. circles[i]->rigidbody.enabled = true; // Enable physic object rigidbody behaviour
  49. circles[i]->rigidbody.friction = 0.1f;
  50. circles[i]->collider.type = COLLIDER_CIRCLE;
  51. circles[i]->collider.radius = 25;
  52. }
  53. // Create walls physic objects
  54. PhysicBody leftWall = CreatePhysicBody((Vector2){ -25, screenHeight/2 }, 0.0f, (Vector2){ 50, screenHeight });
  55. PhysicBody rightWall = CreatePhysicBody((Vector2){ screenWidth + 25, screenHeight/2 }, 0.0f, (Vector2){ 50, screenHeight });
  56. PhysicBody topWall = CreatePhysicBody((Vector2){ screenWidth/2, -25 }, 0.0f, (Vector2){ screenWidth, 50 });
  57. PhysicBody bottomWall = CreatePhysicBody((Vector2){ screenWidth/2, screenHeight + 25 }, 0.0f, (Vector2){ screenWidth, 50 });
  58. SetTargetFPS(60);
  59. //--------------------------------------------------------------------------------------
  60. // Main game loop
  61. while (!WindowShouldClose()) // Detect window close button or ESC key
  62. {
  63. // Update
  64. //----------------------------------------------------------------------------------
  65. // Update mouse position value
  66. mousePosition = GetMousePosition();
  67. // Check force input
  68. if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) ApplyForceAtPosition(mousePosition, FORCE_AMOUNT, FORCE_RADIUS);
  69. // Check reset input
  70. if (IsKeyPressed('R'))
  71. {
  72. // Reset rectangle physic objects positions
  73. for (int i = 0; i < 3; i++)
  74. {
  75. rectangles[i]->transform.position = (Vector2){ screenWidth/4*(i+1) - rectangles[i]->transform.scale.x/2, (((i % 2) == 0) ? (screenHeight/3) : (screenHeight/1.5f)) - rectangles[i]->transform.scale.y/2 };
  76. rectangles[i]->rigidbody.velocity =(Vector2){ 0.0f, 0.0f };
  77. }
  78. // Reset circles physic objects positions
  79. for (int i = 0; i < 3; i++)
  80. {
  81. circles[i]->transform.position = (Vector2){ screenWidth/4*(i+1), (((i % 2) == 0) ? (screenHeight/1.5f) : (screenHeight/4)) };
  82. circles[i]->rigidbody.velocity =(Vector2){ 0.0f, 0.0f };
  83. }
  84. }
  85. // Check debug switch input
  86. if (IsKeyPressed('P')) isDebug = !isDebug;
  87. //----------------------------------------------------------------------------------
  88. // Draw
  89. //----------------------------------------------------------------------------------
  90. BeginDrawing();
  91. ClearBackground(RAYWHITE);
  92. // Draw rectangles
  93. for (int i = 0; i < 3; i++)
  94. {
  95. // Convert transform values to rectangle data type variable
  96. DrawRectangleRec(TransformToRectangle(rectangles[i]->transform), RED);
  97. if (isDebug) DrawRectangleLines(rectangles[i]->collider.bounds.x, rectangles[i]->collider.bounds.y, rectangles[i]->collider.bounds.width, rectangles[i]->collider.bounds.height, GREEN);
  98. // Draw force radius
  99. DrawCircleLines(mousePosition.x, mousePosition.y, FORCE_RADIUS, BLACK);
  100. // Draw direction lines
  101. if (CheckCollisionPointCircle((Vector2){ rectangles[i]->transform.position.x + rectangles[i]->transform.scale.x/2, rectangles[i]->transform.position.y + rectangles[i]->transform.scale.y/2 }, mousePosition, FORCE_RADIUS))
  102. {
  103. Vector2 direction = { rectangles[i]->transform.position.x + rectangles[i]->transform.scale.x/2 - mousePosition.x, rectangles[i]->transform.position.y + rectangles[i]->transform.scale.y/2 - mousePosition.y };
  104. float angle = atan2l(direction.y, direction.x);
  105. // Calculate arrow start and end positions
  106. Vector2 startPosition = { rectangles[i]->transform.position.x + rectangles[i]->transform.scale.x/2, rectangles[i]->transform.position.y + rectangles[i]->transform.scale.y/2 };
  107. Vector2 endPosition = { rectangles[i]->transform.position.x + rectangles[i]->transform.scale.x/2 + (cos(angle)*LINE_LENGTH), rectangles[i]->transform.position.y + rectangles[i]->transform.scale.y/2 + (sin(angle)*LINE_LENGTH) };
  108. // Draw arrow line
  109. DrawLineV(startPosition, endPosition, BLACK);
  110. // Draw arrow triangle
  111. DrawTriangleLines((Vector2){ endPosition.x - cos(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH, endPosition.y - sin(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH },
  112. (Vector2){ endPosition.x + cos(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH, endPosition.y + sin(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH },
  113. (Vector2){ endPosition.x + cos(angle)*LINE_LENGTH/TRIANGLE_LENGTH*2, endPosition.y + sin(angle)*LINE_LENGTH/TRIANGLE_LENGTH*2 }, BLACK);
  114. }
  115. }
  116. // Draw circles
  117. for (int i = 0; i < 3; i++)
  118. {
  119. DrawCircleV(circles[i]->transform.position, circles[i]->collider.radius, BLUE);
  120. if (isDebug) DrawCircleLines(circles[i]->transform.position.x, circles[i]->transform.position.y, circles[i]->collider.radius, GREEN);
  121. // Draw force radius
  122. DrawCircleLines(mousePosition.x, mousePosition.y, FORCE_RADIUS, BLACK);
  123. // Draw direction lines
  124. if (CheckCollisionPointCircle((Vector2){ circles[i]->transform.position.x, circles[i]->transform.position.y }, mousePosition, FORCE_RADIUS))
  125. {
  126. Vector2 direction = { circles[i]->transform.position.x - mousePosition.x, circles[i]->transform.position.y - mousePosition.y };
  127. float angle = atan2l(direction.y, direction.x);
  128. // Calculate arrow start and end positions
  129. Vector2 startPosition = { circles[i]->transform.position.x, circles[i]->transform.position.y };
  130. Vector2 endPosition = { circles[i]->transform.position.x + (cos(angle)*LINE_LENGTH), circles[i]->transform.position.y + (sin(angle)*LINE_LENGTH) };
  131. // Draw arrow line
  132. DrawLineV(startPosition, endPosition, BLACK);
  133. // Draw arrow triangle
  134. DrawTriangleLines((Vector2){ endPosition.x - cos(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH, endPosition.y - sin(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH },
  135. (Vector2){ endPosition.x + cos(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH, endPosition.y + sin(angle + 90*DEG2RAD)*LINE_LENGTH/TRIANGLE_LENGTH },
  136. (Vector2){ endPosition.x + cos(angle)*LINE_LENGTH/TRIANGLE_LENGTH*2, endPosition.y + sin(angle)*LINE_LENGTH/TRIANGLE_LENGTH*2 }, BLACK);
  137. }
  138. }
  139. // Draw help messages
  140. DrawText("Use LEFT MOUSE BUTTON to apply a force", screenWidth/2 - MeasureText("Use LEFT MOUSE BUTTON to apply a force", 20)/2, screenHeight*0.075f, 20, LIGHTGRAY);
  141. DrawText("Use R to reset objects position", screenWidth/2 - MeasureText("Use R to reset objects position", 20)/2, screenHeight*0.875f, 20, GRAY);
  142. DrawFPS(10, 10);
  143. EndDrawing();
  144. //----------------------------------------------------------------------------------
  145. }
  146. // De-Initialization
  147. //--------------------------------------------------------------------------------------
  148. ClosePhysics(); // Unitialize physics module
  149. CloseWindow(); // Close window and OpenGL context
  150. //--------------------------------------------------------------------------------------
  151. return 0;
  152. }