main.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. #define SAF_PROGRAM_NAME "tpe1"
  2. #define SAF_PLATFORM_POKITTO
  3. #define SAF_SETTING_ENABLE_SOUND 0
  4. #define SAF_SETTING_ENABLE_SAVES 0
  5. #define S3L_RESOLUTION_X SAF_SCREEN_WIDTH
  6. #define S3L_RESOLUTION_Y SAF_SCREEN_HEIGHT
  7. #define S3L_PIXEL_FUNCTION s3l_drawPixel
  8. #include "saf.h"
  9. #define S3L_Z_BUFFER 0
  10. #define S3L_SORT 1
  11. #define S3L_FLAT 1
  12. #define S3L_NEAR_CROSS_STRATEGY 1
  13. #define MAP_BOUND 15000
  14. //#define TPE_RESHAPE_ITERATIONS 2
  15. #define TPE_APPROXIMATE_NET_SPEED 1
  16. #define ACCELERATION (TPE_F / 13)
  17. #define TURN_RATE (3 * TPE_F / 4)
  18. #define TURN_FRICTION (3 * TPE_F / 4)
  19. #define FORW_FRICTION (TPE_F / 14)
  20. #include "../tinyphysicsengine.h"
  21. #include "../programs/small3dlib.h"
  22. #include "carModel.h"
  23. TPE_World tpe_world;
  24. TPE_Joint tpe_joints[5];
  25. TPE_Connection tpe_connections[10];
  26. TPE_Body tpe_body;
  27. S3L_Scene s3l_scene;
  28. uint8_t debugDraw = 0;
  29. #define PYRAMID_VERTICES 5
  30. const S3L_Unit pyramidVertices[PYRAMID_VERTICES * 3] =
  31. {
  32. 512,0,-512,
  33. 512,0,512,
  34. -512,0,512,
  35. -512,0,-512,
  36. 0,512,0
  37. };
  38. #define PYRAMID_TRIANGLES 4
  39. const S3L_Index pyramidTriangles[PYRAMID_TRIANGLES * 3] =
  40. {
  41. 0,1,4,
  42. 1,2,4,
  43. 2,3,4,
  44. 3,0,4
  45. };
  46. #define RAMP_VERTICES 4
  47. const S3L_Unit rampVertices[RAMP_VERTICES * 3] =
  48. {
  49. 512,0,-512,
  50. 512,512,512,
  51. -512,512,512,
  52. -512,0,-512
  53. };
  54. #define RAMP_TRIANGLES 4
  55. const S3L_Index rampTriangles[RAMP_TRIANGLES * 3] =
  56. {
  57. 0,1,2,
  58. 2,3,0,
  59. 1,0,2,
  60. 3,2,0
  61. };
  62. S3L_Model3D models[4];
  63. void tpe_debugDrawPixel(uint16_t x, uint16_t y, uint8_t color)
  64. {
  65. SAF_drawPixel(x,y,(color + 2) * 32 + color);
  66. }
  67. const TPE_Unit rampPoits[6] = { 0,0, -2400,1400, -2400,0 };
  68. TPE_Vec3 tpe_environmentDistance(TPE_Vec3 p, TPE_Unit maxD)
  69. {
  70. TPE_ENV_START (TPE_envGround(p,0), p)
  71. TPE_ENV_NEXT (TPE_envSphere(p,TPE_vec3(0,0,-4000),1000), p)
  72. TPE_ENV_NEXT( TPE_envAATriPrism(p,TPE_vec3(-6500,0,0),rampPoits,5000,2),p )
  73. TPE_ENV_END
  74. }
  75. void s3l_drawPixel(S3L_PixelInfo *p)
  76. {
  77. SAF_drawPixel(p->x,p->y,(p->triangleIndex + 100) % 256);
  78. }
  79. uint8_t steering = 0;
  80. uint8_t jointCollisions;
  81. uint8_t jointCollisionsPrev;
  82. TPE_Vec3 carForw, carSide, carUp, carPos, carRot;
  83. uint8_t collisionCallback(uint16_t b1, uint16_t j1, uint16_t b2, uint16_t j2,
  84. TPE_Vec3 p)
  85. {
  86. if (b1 == 0 && b1 == b2 && j1 < 4)
  87. jointCollisions |= 0x01 << j1;
  88. return 1;
  89. }
  90. void carReset(void)
  91. {
  92. TPE_bodyStop(&tpe_body);
  93. tpe_joints[3].position = TPE_vec3(0,3000,10000);
  94. tpe_joints[2].position = TPE_vec3(512,3000,9500);
  95. tpe_joints[1].position = TPE_vec3(-512,3000,9500);
  96. tpe_joints[0].position = TPE_vec3(512,3000,10500);
  97. tpe_joints[4].position = TPE_vec3(512,3500,10500);
  98. s3l_scene.camera.transform.translation.z = tpe_body.joints[4].position.z + 3000;
  99. }
  100. void SAF_init(void)
  101. {
  102. carModelInit();
  103. models[0] = carModel;
  104. S3L_model3DInit(pyramidVertices,PYRAMID_VERTICES,pyramidTriangles,PYRAMID_TRIANGLES,&models[1]);
  105. models[1].transform.translation.z = -4000;
  106. models[1].transform.scale.x = 1300;
  107. models[1].transform.scale.y = models[1].transform.scale.x;
  108. models[1].transform.scale.z = models[1].transform.scale.x;
  109. S3L_model3DInit(rampVertices,RAMP_VERTICES,rampTriangles,RAMP_TRIANGLES,&models[2]);
  110. models[2].transform.translation.x = -6500;
  111. models[2].transform.translation.z = -800;
  112. models[2].transform.scale.x = 2500;
  113. models[2].transform.scale.y = 1300;
  114. models[2].transform.scale.z = 1200;
  115. models[2].transform.rotation.y = 255;
  116. S3L_sceneInit(models,3,&s3l_scene);
  117. s3l_scene.camera.transform.rotation.x -= TPE_F / 14;
  118. TPE_makeCenterRectFull(tpe_joints,tpe_connections,1000,1800,400);
  119. tpe_joints[4].position.y += 600;
  120. tpe_joints[4].sizeDivided *= 4;
  121. tpe_joints[4].sizeDivided /= 3;
  122. TPE_bodyInit(&tpe_body,tpe_joints,5,tpe_connections,10,TPE_F / 2);
  123. tpe_body.elasticity = TPE_F / 100;
  124. tpe_body.friction = FORW_FRICTION;
  125. tpe_body.flags |= TPE_BODY_FLAG_ALWAYS_ACTIVE;
  126. carReset();
  127. TPE_worldInit(&tpe_world,&tpe_body,1,tpe_environmentDistance);
  128. tpe_world.collisionCallback = collisionCallback;
  129. }
  130. uint8_t SAF_loop(void)
  131. {
  132. SAF_clearScreen(SAF_COLOR_GRAY);
  133. for (uint8_t i = 0; i < 4; ++i)
  134. {
  135. S3L_Vec4 boundPoint, screenPoint;
  136. S3L_vec4Set(&boundPoint,
  137. i % 2 == 0 ? -1 * MAP_BOUND : MAP_BOUND,0,
  138. i / 2 == 0 ? -1 * MAP_BOUND : MAP_BOUND,1024);
  139. S3L_project3DPointToScreen(boundPoint,s3l_scene.camera,&screenPoint);
  140. if (screenPoint.w != 0)
  141. SAF_drawPixel(screenPoint.x,screenPoint.y,SAF_COLOR_RED);
  142. }
  143. jointCollisions = 0;
  144. if (SAF_buttonPressed(SAF_BUTTON_RIGHT))
  145. steering = 1;
  146. else if (SAF_buttonPressed(SAF_BUTTON_LEFT))
  147. steering = 2;
  148. else
  149. steering = 0;
  150. TPE_worldStep(&tpe_world);
  151. TPE_bodyApplyGravity(&tpe_body,TPE_F / 50);
  152. carPos = TPE_bodyGetCenterOfMass(&tpe_body);
  153. carForw = TPE_vec3Normalized(
  154. TPE_vec3Minus(tpe_body.joints[2].position,tpe_body.joints[0].position));
  155. carSide = TPE_vec3Normalized(
  156. TPE_vec3Minus(tpe_body.joints[1].position,tpe_body.joints[0].position));
  157. carUp = TPE_vec3Cross(carForw,carSide);
  158. for (int i = 0; i < 4; ++i)
  159. if (jointCollisions & (0x01 << i))
  160. {
  161. TPE_Vec3 jv = TPE_vec3(
  162. tpe_body.joints[i].velocity[0],
  163. tpe_body.joints[i].velocity[1],
  164. tpe_body.joints[i].velocity[2]);
  165. TPE_Vec3 ja = carSide;
  166. if (i >= 2 && steering)
  167. {
  168. if (steering == 2)
  169. ja = TPE_vec3Plus(TPE_vec3Times(carForw,TURN_RATE),carSide);
  170. else
  171. ja = TPE_vec3Minus(TPE_vec3Times(carForw,TURN_RATE),carSide);
  172. ja = TPE_vec3Normalized(ja);
  173. }
  174. TPE_Vec3 fric = TPE_vec3Times(ja,(TPE_vec3Dot(ja,jv) * TURN_FRICTION)
  175. / TPE_F);
  176. jv = TPE_vec3Minus(jv,fric);
  177. tpe_body.joints[i].velocity[0] = jv.x;
  178. tpe_body.joints[i].velocity[1] = jv.y;
  179. tpe_body.joints[i].velocity[2] = jv.z;
  180. }
  181. if (TPE_vec3Dot(carUp,TPE_vec3Minus(tpe_body.joints[4].position,
  182. tpe_body.joints[0].position)) < 0)
  183. tpe_body.joints[4].position = TPE_vec3Plus(TPE_vec3Times(carUp,300),
  184. tpe_body.joints[0].position);
  185. if ((jointCollisions | jointCollisionsPrev) & 0x03) // back wheels on ground?
  186. {
  187. if (SAF_buttonPressed(SAF_BUTTON_UP))
  188. {
  189. tpe_body.joints[0].velocity[0] += (carForw.x * ACCELERATION) / TPE_F;
  190. tpe_body.joints[0].velocity[1] += (carForw.y * ACCELERATION) / TPE_F;
  191. tpe_body.joints[0].velocity[2] += (carForw.z * ACCELERATION) / TPE_F;
  192. tpe_body.joints[1].velocity[0] += (carForw.x * ACCELERATION) / TPE_F;
  193. tpe_body.joints[1].velocity[1] += (carForw.y * ACCELERATION) / TPE_F;
  194. tpe_body.joints[1].velocity[2] += (carForw.z * ACCELERATION) / TPE_F;
  195. }
  196. else if (SAF_buttonPressed(SAF_BUTTON_DOWN))
  197. {
  198. tpe_body.joints[0].velocity[0] -= (carForw.x * ACCELERATION) / TPE_F;
  199. tpe_body.joints[0].velocity[1] -= (carForw.y * ACCELERATION) / TPE_F;
  200. tpe_body.joints[0].velocity[2] -= (carForw.z * ACCELERATION) / TPE_F;
  201. tpe_body.joints[1].velocity[0] -= (carForw.x * ACCELERATION) / TPE_F;
  202. tpe_body.joints[1].velocity[1] -= (carForw.y * ACCELERATION) / TPE_F;
  203. tpe_body.joints[1].velocity[2] -= (carForw.z * ACCELERATION) / TPE_F;
  204. }
  205. }
  206. if (SAF_buttonJustPressed(SAF_BUTTON_B))
  207. carReset();
  208. jointCollisionsPrev = jointCollisions;
  209. carRot = TPE_bodyGetRotation(&tpe_body,0,2,1);
  210. S3L_newFrame();
  211. models[0].transform.translation.x = carPos.x;
  212. models[0].transform.translation.y = carPos.y;
  213. models[0].transform.translation.z = carPos.z;
  214. models[0].transform.rotation.x = carRot.x;
  215. models[0].transform.rotation.y = carRot.y;
  216. models[0].transform.rotation.z = carRot.z;
  217. if (carPos.x > MAP_BOUND)
  218. {
  219. TPE_bodyMoveBy(&tpe_body,TPE_vec3(-2 * MAP_BOUND,0,0));
  220. s3l_scene.camera.transform.translation.x -= 2 * MAP_BOUND;
  221. }
  222. else if (carPos.x < -1 * MAP_BOUND)
  223. {
  224. TPE_bodyMoveBy(&tpe_body,TPE_vec3(2 * MAP_BOUND,0,0));
  225. s3l_scene.camera.transform.translation.x += 2 * MAP_BOUND;
  226. }
  227. if (carPos.z > MAP_BOUND)
  228. {
  229. TPE_bodyMoveBy(&tpe_body,TPE_vec3(0,0,-2 * MAP_BOUND));
  230. s3l_scene.camera.transform.translation.z -= 2 * MAP_BOUND;
  231. }
  232. else if (carPos.z < -1 * MAP_BOUND)
  233. {
  234. TPE_bodyMoveBy(&tpe_body,TPE_vec3(0,0,2 * MAP_BOUND));
  235. s3l_scene.camera.transform.translation.z += 2 * MAP_BOUND;
  236. }
  237. S3L_drawScene(s3l_scene);
  238. if (SAF_buttonJustPressed(SAF_BUTTON_C))
  239. debugDraw = !debugDraw;
  240. if (debugDraw)
  241. TPE_worldDebugDraw(&tpe_world,tpe_debugDrawPixel,
  242. TPE_vec3(
  243. s3l_scene.camera.transform.translation.x,
  244. s3l_scene.camera.transform.translation.y,
  245. s3l_scene.camera.transform.translation.z),
  246. TPE_vec3(s3l_scene.camera.transform.rotation.x,s3l_scene.camera.transform.rotation.y,0),
  247. TPE_vec3(SAF_SCREEN_WIDTH,SAF_SCREEN_HEIGHT,TPE_F),4,TPE_F);
  248. s3l_scene.camera.transform.translation.y = carPos.y + 900;
  249. TPE_Vec3 v = TPE_vec3KeepWithinDistanceBand(
  250. TPE_vec3(
  251. s3l_scene.camera.transform.translation.x,
  252. s3l_scene.camera.transform.translation.y,
  253. s3l_scene.camera.transform.translation.z
  254. ),tpe_body.joints[4].position,2 * TPE_F,4 * TPE_F);
  255. s3l_scene.camera.transform.translation.x = v.x;
  256. s3l_scene.camera.transform.translation.y = v.y;
  257. s3l_scene.camera.transform.translation.z = v.z;
  258. S3L_Vec4 toCar;
  259. toCar.x = carPos.x - s3l_scene.camera.transform.translation.x;
  260. toCar.y = carPos.y - s3l_scene.camera.transform.translation.y;
  261. toCar.z = carPos.z - s3l_scene.camera.transform.translation.z;
  262. toCar.w = 0;
  263. TPE_Unit angleDiff = s3l_scene.camera.transform.rotation.y -
  264. (TPE_vec2Angle(toCar.x,toCar.z) - 128);
  265. s3l_scene.camera.transform.rotation.y -=
  266. (angleDiff < 100 && angleDiff > -100) ? angleDiff / 2 : angleDiff;
  267. return 1;
  268. }