player.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /** Demo showing a simple first person movement. */
  2. #define S3L_NEAR_CROSS_STRATEGY 2
  3. #define S3L_PERSPECTIVE_CORRECTION 2
  4. #include "helper.h"
  5. #include "levelModel.h"
  6. TPE_Unit elevatorHeight;
  7. TPE_Unit ramp[6] = { 1600,0, -500,1400, -700,0 };
  8. TPE_Unit ramp2[6] = { 2000,-5000, 1500,1700, -5000,-500 };
  9. TPE_Vec3 environmentDistance(TPE_Vec3 p, TPE_Unit maxD)
  10. {
  11. // manually created environment to match the 3D model of it
  12. TPE_ENV_START( TPE_envAABoxInside(p,TPE_vec3(0,2450,-2100),TPE_vec3(12600,5000,10800)),p )
  13. TPE_ENV_NEXT( TPE_envAABox(p,TPE_vec3(-5693,0,-6580),TPE_vec3(4307,20000,3420)),p )
  14. TPE_ENV_NEXT( TPE_envAABox(p,TPE_vec3(-10000,-1000,-10000),TPE_vec3(11085,2500,9295)),p )
  15. TPE_ENV_NEXT( TPE_envAATriPrism(p,TPE_vec3(-5400,0,0),ramp,3000,2), p)
  16. TPE_ENV_NEXT( TPE_envAATriPrism(p,TPE_vec3(2076,651,-6780),ramp2,3000,0), p)
  17. TPE_ENV_NEXT( TPE_envAABox(p,TPE_vec3(7000,0,-8500),TPE_vec3(3405,2400,3183)),p )
  18. TPE_ENV_NEXT( TPE_envSphere(p,TPE_vec3(2521,-100,-3799),1200),p )
  19. TPE_ENV_NEXT( TPE_envAABox(p,TPE_vec3(5300,elevatorHeight,-4400),TPE_vec3(1000,elevatorHeight,1000)),p )
  20. TPE_ENV_NEXT( TPE_envHalfPlane(p,TPE_vec3(5051,0,1802),TPE_vec3(-255,0,-255)),p )
  21. TPE_ENV_NEXT( TPE_envInfiniteCylinder(p,TPE_vec3(320,0,170),TPE_vec3(0,255,0),530),p )
  22. TPE_ENV_END
  23. }
  24. int jumpCountdown = 0, onGround = 0;
  25. TPE_Unit playerRotation = 0, groundDist;
  26. TPE_Vec3 ballRot, ballPreviousPos, playerDirectionVec;
  27. TPE_Body *playerBody = 0;
  28. void updateDirection(void) // updates player direction vector
  29. {
  30. playerDirectionVec.x = TPE_sin(playerRotation);
  31. playerDirectionVec.z = TPE_cos(playerRotation);
  32. playerDirectionVec.y = 0;
  33. }
  34. int main(void)
  35. {
  36. helper_init();
  37. levelModelInit();
  38. updateDirection();
  39. ballRot = TPE_vec3(0,0,0);
  40. tpe_world.environmentFunction = environmentDistance;
  41. /* normally player bodies are approximated with capsules -- since we don't
  42. have these, we'll use a body consisting of two spheres: */
  43. helper_add2Line(400,300,400);
  44. playerBody = &(tpe_world.bodies[0]);
  45. TPE_bodyMoveBy(&tpe_world.bodies[0],TPE_vec3(1000,1000,1500));
  46. TPE_bodyRotateByAxis(&tpe_world.bodies[0],TPE_vec3(0,0,TPE_F / 4));
  47. playerBody->elasticity = 0;
  48. playerBody->friction = 0;
  49. playerBody->flags |= TPE_BODY_FLAG_NONROTATING; // make it always upright
  50. playerBody->flags |= TPE_BODY_FLAG_ALWAYS_ACTIVE;
  51. groundDist = TPE_JOINT_SIZE(playerBody->joints[0]) + 30;
  52. // add two interactive bodies:
  53. helper_addBall(1000,100);
  54. TPE_bodyMoveBy(&tpe_world.bodies[1],TPE_vec3(-1000,1000,0));
  55. tpe_world.bodies[1].elasticity = 400;
  56. tpe_world.bodies[1].friction = 100;
  57. ballPreviousPos = tpe_world.bodies[1].joints[0].position;
  58. helper_addCenterRect(600,600,400,50);
  59. TPE_bodyMoveBy(&tpe_world.bodies[2],TPE_vec3(-3000,1000,2000));
  60. tpe_world.bodies[2].elasticity = 100;
  61. tpe_world.bodies[2].friction = 50;
  62. while (helper_running)
  63. {
  64. helper_frameStart();
  65. TPE_worldStep(&tpe_world);
  66. if (jumpCountdown > 0)
  67. jumpCountdown--;
  68. TPE_Vec3 groundPoint =
  69. environmentDistance(playerBody->joints[0].position,groundDist);
  70. onGround = (playerBody->flags & TPE_BODY_FLAG_DEACTIVATED) ||
  71. (TPE_DISTANCE(playerBody->joints[0].position,groundPoint)
  72. <= groundDist && groundPoint.y < playerBody->joints[0].position.y - groundDist / 2);
  73. if (!onGround)
  74. {
  75. /* it's possible that the closest point is e.g. was a perpend wall so also
  76. additionally check directly below */
  77. onGround = TPE_DISTANCE( playerBody->joints[0].position,
  78. TPE_castEnvironmentRay(playerBody->joints[0].position,
  79. TPE_vec3(0,-1 * TPE_F,0),tpe_world.environmentFunction,
  80. 128,512,512)) <= groundDist;
  81. }
  82. elevatorHeight = (1250 * (TPE_sin(helper_frame * 4) + TPE_F)) / (2 * TPE_F);
  83. s3l_scene.camera.transform.translation.x = playerBody->joints[0].position.x;
  84. s3l_scene.camera.transform.translation.z = playerBody->joints[0].position.z;
  85. s3l_scene.camera.transform.translation.y = TPE_keepInRange(
  86. s3l_scene.camera.transform.translation.y,
  87. playerBody->joints[1].position.y,
  88. playerBody->joints[1].position.y + 10);
  89. TPE_bodyMultiplyNetSpeed(&tpe_world.bodies[0],onGround ? 300 : 505);
  90. s3l_scene.camera.transform.rotation.y = -1 * playerRotation;
  91. // fake the sphere rotation (since a single joint doesn't rotate itself):
  92. TPE_Vec3 ballRoll = TPE_fakeSphereRotation(ballPreviousPos,
  93. tpe_world.bodies[1].joints[0].position,1000);
  94. ballRot = TPE_rotationRotateByAxis(ballRot,ballRoll);
  95. ballPreviousPos = tpe_world.bodies[1].joints[0].position;
  96. for (int i = 0; i < tpe_world.bodyCount; ++i)
  97. TPE_bodyApplyGravity(&tpe_world.bodies[i],5);
  98. if (onGround)
  99. {
  100. if (sdl_keyboard[SDL_SCANCODE_SPACE] && jumpCountdown == 0)
  101. {
  102. playerBody->joints[0].velocity[1] = 90;
  103. jumpCountdown = 8;
  104. }
  105. #define D 15 // just some vector divisor to make the speed slower
  106. if (sdl_keyboard[SDL_SCANCODE_UP] || sdl_keyboard[SDL_SCANCODE_W])
  107. {
  108. playerBody->joints[0].velocity[0] += playerDirectionVec.x / D;
  109. playerBody->joints[0].velocity[2] += playerDirectionVec.z / D;
  110. }
  111. else if (sdl_keyboard[SDL_SCANCODE_DOWN] || sdl_keyboard[SDL_SCANCODE_S])
  112. {
  113. playerBody->joints[0].velocity[0] -= playerDirectionVec.x / D;
  114. playerBody->joints[0].velocity[2] -= playerDirectionVec.z / D;
  115. }
  116. if (sdl_keyboard[SDL_SCANCODE_A])
  117. {
  118. playerBody->joints[0].velocity[2] += playerDirectionVec.x / D;
  119. playerBody->joints[0].velocity[0] -= playerDirectionVec.z / D;
  120. }
  121. else if (sdl_keyboard[SDL_SCANCODE_D])
  122. {
  123. playerBody->joints[0].velocity[2] -= playerDirectionVec.x / D;
  124. playerBody->joints[0].velocity[0] += playerDirectionVec.z / D;
  125. }
  126. #undef D
  127. }
  128. updateDirection();
  129. if (sdl_keyboard[SDL_SCANCODE_LEFT])
  130. playerRotation -= 8;
  131. else if (sdl_keyboard[SDL_SCANCODE_RIGHT])
  132. playerRotation += 8;
  133. if (helper_frame % 64 == 0)
  134. {
  135. helper_printCPU();
  136. helper_printCamera();
  137. }
  138. // draw the 3D environment
  139. helper_set3DColor(200,200,200);
  140. helper_drawModel(&levelModel,TPE_vec3(0,0,0),TPE_vec3(600,600,600),
  141. TPE_vec3(0,0,0));
  142. helper_draw3DBox(TPE_vec3(5300,elevatorHeight,-4400),
  143. TPE_vec3(2000,2 * elevatorHeight,2000),TPE_vec3(0,0,0));
  144. helper_set3DColor(200,50,0);
  145. helper_draw3DBox(TPE_bodyGetCenterOfMass(&tpe_world.bodies[2]),
  146. TPE_vec3(1200,800,1200),TPE_bodyGetRotation(&tpe_world.bodies[2],0,2,1));
  147. helper_draw3DSphere(tpe_world.bodies[1].joints[0].position,
  148. TPE_vec3(1000,1000,1000),ballRot);
  149. if (helper_debugDrawOn)
  150. helper_debugDraw(1);
  151. helper_frameEnd();
  152. }
  153. helper_end();
  154. return 0;
  155. }