kinematics.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include <r3d/r3d.h>
  2. #include <raymath.h>
  3. #include <stddef.h>
  4. #ifndef RESOURCES_PATH
  5. #define RESOURCES_PATH "./"
  6. #endif
  7. #define GRAVITY -15.0f
  8. #define MOVE_SPEED 5.0f
  9. #define JUMP_FORCE 8.0f
  10. #define CAPSULE_CENTER(caps) Vector3Scale(Vector3Add((caps).start, (caps).end), 0.5f)
  11. #define BOX_CENTER(box) Vector3Scale(Vector3Add((box).min, (box).max), 0.5f)
  12. int main(void)
  13. {
  14. InitWindow(800, 450, "[r3d] - Kinematics Example");
  15. SetTargetFPS(60);
  16. R3D_Init(GetScreenWidth(), GetScreenHeight());
  17. R3D_SetTextureFilter(TEXTURE_FILTER_ANISOTROPIC_8X);
  18. R3D_Cubemap sky = R3D_GenCubemapSky(4096, R3D_CUBEMAP_SKY_BASE);
  19. R3D_AmbientMap ambient = R3D_GenAmbientMap(sky, R3D_AMBIENT_ILLUMINATION | R3D_AMBIENT_REFLECTION);
  20. R3D_ENVIRONMENT_SET(background.sky, sky);
  21. R3D_ENVIRONMENT_SET(ambient.map, ambient);
  22. R3D_Light light = R3D_CreateLight(R3D_LIGHT_DIR);
  23. R3D_SetLightDirection(light, (Vector3) {-1, -1, -1});
  24. R3D_SetLightRange(light, 16.0f);
  25. R3D_SetLightActive(light, true);
  26. R3D_EnableShadow(light);
  27. R3D_SetShadowDepthBias(light, 0.005f);
  28. // Load materials
  29. R3D_AlbedoMap baseAlbedo = R3D_LoadAlbedoMap(RESOURCES_PATH "images/placeholder.png", WHITE);
  30. R3D_Material groundMat = R3D_GetDefaultMaterial();
  31. groundMat.uvScale = (Vector2) {250.0f, 250.0f};
  32. groundMat.albedo = baseAlbedo;
  33. R3D_Material slopeMat = R3D_GetDefaultMaterial();
  34. slopeMat.albedo.color = (Color) {255,255,0,255};
  35. slopeMat.albedo.texture = baseAlbedo.texture;
  36. // Ground
  37. R3D_Mesh groundMesh = R3D_GenMeshPlane(1000, 1000, 1, 1);
  38. BoundingBox groundBox = {.min = {-500, -1, -500}, .max = {500, 0, 500}};
  39. // Slope obstacle
  40. R3D_MeshData slopeMeshData = R3D_GenMeshDataSlope(2, 2, 2, (Vector3) {0, 1, -1});
  41. R3D_Mesh slopeMesh = R3D_LoadMesh(R3D_PRIMITIVE_TRIANGLES, slopeMeshData, NULL, R3D_STATIC_MESH);
  42. Matrix slopeTransform = MatrixTranslate(0, 1, 5);
  43. // Player capsule
  44. R3D_Capsule capsule = {.start = {0, 0.5f, 0}, .end = {0, 1.5f, 0}, .radius = 0.5f};
  45. R3D_Mesh capsMesh = R3D_GenMeshCapsule(0.5f, 1.0f, 64, 32);
  46. Vector3 velocity = {0, 0, 0};
  47. // Camera
  48. float cameraAngle = 0.0f;
  49. float cameraPitch = 30.0f;
  50. Camera3D camera = {
  51. .position = {0, 5, 5},
  52. .target = CAPSULE_CENTER(capsule),
  53. .up = {0, 1, 0},
  54. .fovy = 60
  55. };
  56. DisableCursor();
  57. while (!WindowShouldClose())
  58. {
  59. float dt = GetFrameTime();
  60. // Camera rotation
  61. Vector2 mouseDelta = GetMouseDelta();
  62. cameraAngle -= mouseDelta.x * 0.15f;
  63. cameraPitch = Clamp(cameraPitch + mouseDelta.y * 0.15f, -7.5f, 80.0f);
  64. // Movement input relative to camera
  65. int dx = IsKeyDown(KEY_A) - IsKeyDown(KEY_D);
  66. int dz = IsKeyDown(KEY_W) - IsKeyDown(KEY_S);
  67. Vector3 moveInput = {0};
  68. if (dx != 0 || dz != 0) {
  69. float angleRad = cameraAngle * DEG2RAD;
  70. Vector3 right = {cosf(angleRad), 0, -sinf(angleRad)};
  71. Vector3 forward = {sinf(angleRad), 0, cosf(angleRad)};
  72. moveInput = Vector3Normalize(Vector3Add(Vector3Scale(right, dx), Vector3Scale(forward, dz)));
  73. }
  74. // Check grounded
  75. bool isGrounded = R3D_IsCapsuleGroundedBox(capsule, 0.01f, groundBox, NULL) ||
  76. R3D_IsCapsuleGroundedMesh(capsule, 0.3f, slopeMeshData, slopeTransform, NULL);
  77. // Jump and apply gravity
  78. if (isGrounded && IsKeyPressed(KEY_SPACE)) velocity.y = JUMP_FORCE;
  79. if (!isGrounded) velocity.y += GRAVITY * dt;
  80. else if (velocity.y < 0) velocity.y = 0;
  81. // Calculate total movement
  82. Vector3 movement = Vector3Scale(moveInput, MOVE_SPEED * dt);
  83. movement.y = velocity.y * dt;
  84. // Apply movement with collision
  85. movement = R3D_SlideCapsuleMesh(capsule, movement, slopeMeshData, slopeTransform, NULL);
  86. capsule.start = Vector3Add(capsule.start, movement);
  87. capsule.end = Vector3Add(capsule.end, movement);
  88. // Ground clamp
  89. if (capsule.start.y < 0.5f) {
  90. float correction = 0.5f - capsule.start.y;
  91. capsule.start.y += correction;
  92. capsule.end.y += correction;
  93. velocity.y = 0;
  94. }
  95. // Update camera position
  96. Vector3 target = CAPSULE_CENTER(capsule);
  97. float pitchRad = cameraPitch * DEG2RAD;
  98. float angleRad = cameraAngle * DEG2RAD;
  99. camera.position = (Vector3) {
  100. target.x - sinf(angleRad) * cosf(pitchRad) * 5.0f,
  101. target.y + sinf(pitchRad) * 5.0f,
  102. target.z - cosf(angleRad) * cosf(pitchRad) * 5.0f
  103. };
  104. camera.target = target;
  105. BeginDrawing();
  106. ClearBackground(BLACK);
  107. R3D_Begin(camera);
  108. R3D_DrawMeshPro(slopeMesh, slopeMat, slopeTransform);
  109. R3D_DrawMesh(groundMesh, groundMat, Vector3Zero(), 1.0f);
  110. R3D_DrawMesh(capsMesh, R3D_MATERIAL_BASE, CAPSULE_CENTER(capsule), 1.0f);
  111. R3D_End();
  112. DrawFPS(10, 10);
  113. DrawText(isGrounded ? "GROUNDED" : "AIRBORNE", 10, GetScreenHeight() - 30, 20, isGrounded ? LIME : YELLOW);
  114. EndDrawing();
  115. }
  116. R3D_UnloadMeshData(slopeMeshData);
  117. R3D_UnloadMesh(groundMesh);
  118. R3D_UnloadMesh(slopeMesh);
  119. R3D_UnloadMesh(capsMesh);
  120. R3D_Close();
  121. CloseWindow();
  122. return 0;
  123. }