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.

226 lines
8.7 KiB

  1. /*******************************************************************************************
  2. *
  3. * raylib [easings] example - Easings Testbed
  4. *
  5. * This example has been created using raylib 2.5 (www.raylib.com)
  6. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  7. *
  8. * Example contributed by Juan Miguel López (@flashback-fx) and reviewed by Ramon Santamaria (@raysan5)
  9. *
  10. * Copyright (c) 2019 Juan Miguel López (@flashback-fx ) and Ramon Santamaria (@raysan5)
  11. *
  12. ********************************************************************************************/
  13. #include <raylib.h>
  14. #include "easings.h"
  15. #define FONT_SIZE 20
  16. #define D_STEP 20.0f
  17. #define D_STEP_FINE 2.0f
  18. #define D_MIN 1.0f
  19. #define D_MAX 10000.0f
  20. // Easing types
  21. enum EasingTypes {
  22. EASE_LINEAR_NONE = 0,
  23. EASE_LINEAR_IN,
  24. EASE_LINEAR_OUT,
  25. EASE_LINEAR_IN_OUT,
  26. EASE_SINE_IN,
  27. EASE_SINE_OUT,
  28. EASE_SINE_IN_OUT,
  29. EASE_CIRC_IN,
  30. EASE_CIRC_OUT,
  31. EASE_CIRC_IN_OUT,
  32. EASE_CUBIC_IN,
  33. EASE_CUBIC_OUT,
  34. EASE_CUBIC_IN_OUT,
  35. EASE_QUAD_IN,
  36. EASE_QUAD_OUT,
  37. EASE_QUAD_IN_OUT,
  38. EASE_EXPO_IN,
  39. EASE_EXPO_OUT,
  40. EASE_EXPO_IN_OUT,
  41. EASE_BACK_IN,
  42. EASE_BACK_OUT,
  43. EASE_BACK_IN_OUT,
  44. EASE_BOUNCE_OUT,
  45. EASE_BOUNCE_IN,
  46. EASE_BOUNCE_IN_OUT,
  47. EASE_ELASTIC_IN,
  48. EASE_ELASTIC_OUT,
  49. EASE_ELASTIC_IN_OUT,
  50. NUM_EASING_TYPES,
  51. EASING_NONE = NUM_EASING_TYPES
  52. };
  53. static float NoEase(float t, float b, float c, float d); // NoEase function declaration, function used when "no easing" is selected for any axis
  54. // Easing functions reference data
  55. static const struct {
  56. const char *name;
  57. float (*func)(float, float, float, float);
  58. } Easings[] = {
  59. [EASE_LINEAR_NONE] = { .name = "EaseLinearNone", .func = EaseLinearNone },
  60. [EASE_LINEAR_IN] = { .name = "EaseLinearIn", .func = EaseLinearIn },
  61. [EASE_LINEAR_OUT] = { .name = "EaseLinearOut", .func = EaseLinearOut },
  62. [EASE_LINEAR_IN_OUT] = { .name = "EaseLinearInOut", .func = EaseLinearInOut },
  63. [EASE_SINE_IN] = { .name = "EaseSineIn", .func = EaseSineIn },
  64. [EASE_SINE_OUT] = { .name = "EaseSineOut", .func = EaseSineOut },
  65. [EASE_SINE_IN_OUT] = { .name = "EaseSineInOut", .func = EaseSineInOut },
  66. [EASE_CIRC_IN] = { .name = "EaseCircIn", .func = EaseCircIn },
  67. [EASE_CIRC_OUT] = { .name = "EaseCircOut", .func = EaseCircOut },
  68. [EASE_CIRC_IN_OUT] = { .name = "EaseCircInOut", .func = EaseCircInOut },
  69. [EASE_CUBIC_IN] = { .name = "EaseCubicIn", .func = EaseCubicIn },
  70. [EASE_CUBIC_OUT] = { .name = "EaseCubicOut", .func = EaseCubicOut },
  71. [EASE_CUBIC_IN_OUT] = { .name = "EaseCubicInOut", .func = EaseCubicInOut },
  72. [EASE_QUAD_IN] = { .name = "EaseQuadIn", .func = EaseQuadIn },
  73. [EASE_QUAD_OUT] = { .name = "EaseQuadOut", .func = EaseQuadOut },
  74. [EASE_QUAD_IN_OUT] = { .name = "EaseQuadInOut", .func = EaseQuadInOut },
  75. [EASE_EXPO_IN] = { .name = "EaseExpoIn", .func = EaseExpoIn },
  76. [EASE_EXPO_OUT] = { .name = "EaseExpoOut", .func = EaseExpoOut },
  77. [EASE_EXPO_IN_OUT] = { .name = "EaseExpoInOut", .func = EaseExpoInOut },
  78. [EASE_BACK_IN] = { .name = "EaseBackIn", .func = EaseBackIn },
  79. [EASE_BACK_OUT] = { .name = "EaseBackOut", .func = EaseBackOut },
  80. [EASE_BACK_IN_OUT] = { .name = "EaseBackInOut", .func = EaseBackInOut },
  81. [EASE_BOUNCE_OUT] = { .name = "EaseBounceOut", .func = EaseBounceOut },
  82. [EASE_BOUNCE_IN] = { .name = "EaseBounceIn", .func = EaseBounceIn },
  83. [EASE_BOUNCE_IN_OUT] = { .name = "EaseBounceInOut", .func = EaseBounceInOut },
  84. [EASE_ELASTIC_IN] = { .name = "EaseElasticIn", .func = EaseElasticIn },
  85. [EASE_ELASTIC_OUT] = { .name = "EaseElasticOut", .func = EaseElasticOut },
  86. [EASE_ELASTIC_IN_OUT] = { .name = "EaseElasticInOut", .func = EaseElasticInOut },
  87. [EASING_NONE] = { .name = "None", .func = NoEase },
  88. };
  89. int main(void)
  90. {
  91. // Initialization
  92. //--------------------------------------------------------------------------------------
  93. const int screenWidth = 800;
  94. const int screenHeight = 450;
  95. InitWindow(screenWidth, screenHeight, "raylib [easings] example - easings testbed");
  96. Vector2 ballPosition = { 100.0f, 200.0f };
  97. float t = 0.0f; // Current time (in any unit measure, but same unit as duration)
  98. float d = 300.0f; // Total time it should take to complete (duration)
  99. bool paused = true;
  100. bool boundedT = true; // If true, t will stop when d >= td, otherwise t will keep adding td to its value every loop
  101. int easingX = EASING_NONE; // Easing selected for x axis
  102. int easingY = EASING_NONE; // Easing selected for y axis
  103. SetTargetFPS(60);
  104. //--------------------------------------------------------------------------------------
  105. // Main game loop
  106. while (!WindowShouldClose()) // Detect window close button or ESC key
  107. {
  108. // Update
  109. //----------------------------------------------------------------------------------
  110. if (IsKeyPressed(KEY_T)) boundedT = !boundedT;
  111. // Choose easing for the X axis
  112. if (IsKeyPressed(KEY_RIGHT))
  113. {
  114. easingX++;
  115. if (easingX > EASING_NONE) easingX = 0;
  116. }
  117. else if (IsKeyPressed(KEY_LEFT))
  118. {
  119. if (easingX == 0) easingX = EASING_NONE;
  120. else easingX--;
  121. }
  122. // Choose easing for the Y axis
  123. if (IsKeyPressed(KEY_DOWN))
  124. {
  125. easingY++;
  126. if (easingY > EASING_NONE) easingY = 0;
  127. }
  128. else if (IsKeyPressed(KEY_UP))
  129. {
  130. if (easingY == 0) easingY = EASING_NONE;
  131. else easingY--;
  132. }
  133. // Change d (duration) value
  134. if (IsKeyPressed(KEY_W) && d < D_MAX - D_STEP) d += D_STEP;
  135. else if (IsKeyPressed(KEY_Q) && d > D_MIN + D_STEP) d -= D_STEP;
  136. if (IsKeyDown(KEY_S) && d < D_MAX - D_STEP_FINE) d += D_STEP_FINE;
  137. else if (IsKeyDown(KEY_A) && d > D_MIN + D_STEP_FINE) d -= D_STEP_FINE;
  138. // Play, pause and restart controls
  139. if (IsKeyPressed(KEY_SPACE) || IsKeyPressed(KEY_T) ||
  140. IsKeyPressed(KEY_RIGHT) || IsKeyPressed(KEY_LEFT) ||
  141. IsKeyPressed(KEY_DOWN) || IsKeyPressed(KEY_UP) ||
  142. IsKeyPressed(KEY_W) || IsKeyPressed(KEY_Q) ||
  143. IsKeyDown(KEY_S) || IsKeyDown(KEY_A) ||
  144. (IsKeyPressed(KEY_ENTER) && (boundedT == true) && (t >= d)))
  145. {
  146. t = 0.0f;
  147. ballPosition.x = 100.0f;
  148. ballPosition.y = 100.0f;
  149. paused = true;
  150. }
  151. if (IsKeyPressed(KEY_ENTER)) paused = !paused;
  152. // Movement computation
  153. if (!paused && ((boundedT && t < d) || !boundedT))
  154. {
  155. ballPosition.x = Easings[easingX].func(t, 100.0f, 700.0f - 100.0f, d);
  156. ballPosition.y = Easings[easingY].func(t, 100.0f, 400.0f - 100.0f, d);
  157. t += 1.0f;
  158. }
  159. //----------------------------------------------------------------------------------
  160. // Draw
  161. //----------------------------------------------------------------------------------
  162. BeginDrawing();
  163. ClearBackground(RAYWHITE);
  164. // Draw information text
  165. DrawText(TextFormat("Easing x: %s", Easings[easingX].name), 0, FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
  166. DrawText(TextFormat("Easing y: %s", Easings[easingY].name), 0, FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
  167. DrawText(TextFormat("t (%c) = %.2f d = %.2f", (boundedT == true)? 'b' : 'u', t, d), 0, FONT_SIZE*4, FONT_SIZE, LIGHTGRAY);
  168. // Draw instructions text
  169. DrawText("Use ENTER to play or pause movement, use SPACE to restart", 0, GetScreenHeight() - FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
  170. DrawText("Use D and W or A and S keys to change duration", 0, GetScreenHeight() - FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
  171. DrawText("Use LEFT or RIGHT keys to choose easing for the x axis", 0, GetScreenHeight() - FONT_SIZE*4, FONT_SIZE, LIGHTGRAY);
  172. DrawText("Use UP or DOWN keys to choose easing for the y axis", 0, GetScreenHeight() - FONT_SIZE*5, FONT_SIZE, LIGHTGRAY);
  173. // Draw ball
  174. DrawCircleV(ballPosition, 16.0f, MAROON);
  175. EndDrawing();
  176. //----------------------------------------------------------------------------------
  177. }
  178. // De-Initialization
  179. //--------------------------------------------------------------------------------------
  180. CloseWindow();
  181. //--------------------------------------------------------------------------------------
  182. return 0;
  183. }
  184. // NoEase function, used when "no easing" is selected for any axis. It just ignores all parameters besides b.
  185. static float NoEase(float t, float b, float c, float d)
  186. {
  187. float burn = t + b + c + d; // Hack to avoid compiler warning (about unused variables)
  188. d += burn;
  189. return b;
  190. }