💿🐜 Antkeeper source code https://antkeeper.com
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.

500 lines
16 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "game/states/forage.hpp"
  20. #include "entity/archetype.hpp"
  21. #include "entity/commands.hpp"
  22. #include "entity/components/observer.hpp"
  23. #include "entity/components/terrain.hpp"
  24. #include "entity/components/transform.hpp"
  25. #include "entity/systems/astronomy.hpp"
  26. #include "animation/screen-transition.hpp"
  27. #include "animation/ease.hpp"
  28. #include "resources/resource-manager.hpp"
  29. #include "entity/components/camera.hpp"
  30. #include "entity/components/constraints/spring-to.hpp"
  31. #include "entity/components/constraints/three-dof.hpp"
  32. #include "entity/components/constraint-stack.hpp"
  33. #include "application.hpp"
  34. namespace game {
  35. namespace state {
  36. namespace forage {
  37. static void setup_camera(game::context* ctx);
  38. static void setup_tools(game::context* ctx);
  39. static void setup_controls(game::context* ctx);
  40. void enter(game::context* ctx)
  41. {
  42. setup_camera(ctx);
  43. setup_controls(ctx);
  44. // Find planet EID by name
  45. entity::id planet_eid = ctx->entities["planet"];
  46. // Create biome terrain component
  47. entity::component::terrain biome_terrain;
  48. biome_terrain.max_lod = 18;
  49. biome_terrain.patch_material = ctx->resource_manager->load<material>("desert-terrain.mtl");
  50. biome_terrain.elevation = [](double, double) -> double
  51. {
  52. return 0.0;
  53. };
  54. // Replace planet terrain component with biome terrain component
  55. ctx->entity_registry->replace<entity::component::terrain>(planet_eid, biome_terrain);
  56. // Create observer
  57. entity::id observer_eid = ctx->entity_registry->create();
  58. {
  59. entity::component::observer observer;
  60. observer.reference_body_eid = planet_eid;
  61. observer.elevation = 0.0;
  62. observer.latitude = 0.0;
  63. observer.longitude = 0.0;
  64. observer.camera = ctx->surface_camera;
  65. ctx->entity_registry->assign<entity::component::observer>(observer_eid, observer);
  66. // Set reference location of astronomy system
  67. ctx->astronomy_system->set_reference_body(planet_eid);
  68. ctx->astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude});
  69. }
  70. // Create larva
  71. {
  72. entity::archetype* larva_archetype = ctx->resource_manager->load<entity::archetype>("ant-larva.ent");
  73. auto larva_eid = larva_archetype->create(*ctx->entity_registry);
  74. entity::command::warp_to(*ctx->entity_registry, larva_eid, {50, 0.1935f, 0});
  75. entity::command::assign_render_layers(*ctx->entity_registry, larva_eid, 0b10);
  76. }
  77. // Create cocoon
  78. {
  79. entity::archetype* cocoon_archetype = ctx->resource_manager->load<entity::archetype>("ant-cocoon.ent");
  80. auto cocoon_eid = cocoon_archetype->create(*ctx->entity_registry);
  81. entity::command::warp_to(*ctx->entity_registry, cocoon_eid, {-50, 0.1935f, 0});
  82. entity::command::assign_render_layers(*ctx->entity_registry, cocoon_eid, 0b10);
  83. }
  84. ctx->surface_scene->update_tweens();
  85. // Start fade in
  86. ctx->fade_transition->transition(1.0f, true, ease<float>::in_quad);
  87. }
  88. void exit(game::context* ctx)
  89. {}
  90. void setup_camera(game::context* ctx)
  91. {
  92. // Switch to surface camera
  93. ctx->underground_camera->set_active(false);
  94. ctx->surface_camera->set_active(true);
  95. // Create surface camera entity
  96. if (!ctx->entities.count("surface_cam"))
  97. {
  98. // Create camera target entity
  99. entity::id target_eid = ctx->entity_registry->create();
  100. ctx->entities["surface_cam_target"] = target_eid;
  101. {
  102. // Transform
  103. entity::component::transform target_transform;
  104. target_transform.local = math::identity_transform<float>;
  105. target_transform.world = target_transform.local;
  106. target_transform.warp = true;
  107. ctx->entity_registry->assign<entity::component::transform>(target_eid, target_transform);
  108. }
  109. // Create camera entity
  110. entity::id camera_eid = ctx->entity_registry->create();
  111. ctx->entities["surface_cam"] = camera_eid;
  112. // Create camera transform component
  113. entity::component::transform transform;
  114. transform.local = math::identity_transform<float>;
  115. transform.world = transform.local;
  116. transform.warp = true;
  117. ctx->entity_registry->assign<entity::component::transform>(camera_eid, transform);
  118. // Create camera camera component
  119. entity::component::camera camera;
  120. camera.object = ctx->surface_camera;
  121. ctx->entity_registry->assign<entity::component::camera>(camera_eid, camera);
  122. // Create camera 3DOF constraint entity
  123. entity::id three_dof_constraint_eid = ctx->entity_registry->create();
  124. ctx->entities["surface_cam_3dof"] = three_dof_constraint_eid;
  125. {
  126. // Create 3DOF to constraint
  127. entity::component::constraint::three_dof three_dof;
  128. three_dof.yaw = 0.0f;
  129. three_dof.pitch = 0.0f;
  130. three_dof.roll = 0.0f;
  131. ctx->entity_registry->assign<entity::component::constraint::three_dof>(three_dof_constraint_eid, three_dof);
  132. // Create constraint stack node component
  133. entity::component::constraint_stack_node node;
  134. node.active = true;
  135. node.weight = 1.0f;
  136. node.next = entt::null;
  137. ctx->entity_registry->assign<entity::component::constraint_stack_node>(three_dof_constraint_eid, node);
  138. }
  139. // Create camera spring to constraint entity
  140. entity::id spring_constraint_eid = ctx->entity_registry->create();
  141. {
  142. // Create spring to constraint
  143. entity::component::constraint::spring_to spring;
  144. spring.target = target_eid;
  145. spring.translation = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 1.0f, math::two_pi<float>};
  146. spring.translation.w = hz_to_rads(8.0f);
  147. spring.spring_translation = true;
  148. spring.spring_rotation = false;
  149. ctx->entity_registry->assign<entity::component::constraint::spring_to>(spring_constraint_eid, spring);
  150. // Create constraint stack node component
  151. entity::component::constraint_stack_node node;
  152. node.active = true;
  153. node.weight = 1.0f;
  154. node.next = three_dof_constraint_eid;
  155. ctx->entity_registry->assign<entity::component::constraint_stack_node>(spring_constraint_eid, node);
  156. }
  157. // Create camera constraint stack component
  158. entity::component::constraint_stack constraint_stack;
  159. constraint_stack.head = spring_constraint_eid;
  160. ctx->entity_registry->assign<entity::component::constraint_stack>(camera_eid, constraint_stack);
  161. }
  162. ctx->surface_camera->set_exposure(-14.5f);
  163. }
  164. void setup_tools(game::context* ctx)
  165. {
  166. if (!ctx->entities.count("move_tool"))
  167. {
  168. entity::id tool_eid = ctx->entity_registry->create();
  169. ctx->entities["move_tool"] = tool_eid;
  170. }
  171. if (!ctx->entities.count("paint_tool"))
  172. {
  173. entity::id tool_eid = ctx->entity_registry->create();
  174. ctx->entities["paint_tool"] = tool_eid;
  175. }
  176. if (!ctx->entities.count("flip_tool"))
  177. {
  178. entity::id tool_eid = ctx->entity_registry->create();
  179. ctx->entities["flip_tool"] = tool_eid;
  180. }
  181. if (!ctx->entities.count("poke_tool"))
  182. {
  183. entity::id tool_eid = ctx->entity_registry->create();
  184. ctx->entities["poke_tool"] = tool_eid;
  185. }
  186. if (!ctx->entities.count("inspect_tool"))
  187. {
  188. entity::id tool_eid = ctx->entity_registry->create();
  189. ctx->entities["inspect_tool"] = tool_eid;
  190. }
  191. if (!ctx->entities.count("label_tool"))
  192. {
  193. entity::id tool_eid = ctx->entity_registry->create();
  194. ctx->entities["label_tool"] = tool_eid;
  195. }
  196. if (!ctx->entities.count("wait_tool"))
  197. {
  198. entity::id tool_eid = ctx->entity_registry->create();
  199. ctx->entities["wait_tool"] = tool_eid;
  200. }
  201. // Set move tool as active tool
  202. ctx->entities["active_tool"] = ctx->entities["move_tool"];
  203. }
  204. void setup_controls(game::context* ctx)
  205. {
  206. // Get underground camera entity
  207. entity::id camera_eid = ctx->entities["surface_cam"];
  208. entity::id target_eid = ctx->entities["surface_cam_target"];
  209. entity::id three_dof_eid = ctx->entities["surface_cam_3dof"];
  210. const float dolly_speed = 20.0f;
  211. const float truck_speed = dolly_speed;
  212. const float pedestal_speed = 30.0f;
  213. const float pan_speed_mouse = math::radians(8.0f);
  214. const float tilt_speed_mouse = pan_speed_mouse;
  215. const float pan_speed = math::radians(110.0f);
  216. const float tilt_speed = pan_speed;
  217. const input::control* move_slow = ctx->controls["move_slow"];
  218. const input::control* move_fast = ctx->controls["move_fast"];
  219. const input::control* mouse_rotate = ctx->controls["mouse_rotate"];
  220. ctx->controls["dolly_forward"]->set_active_callback
  221. (
  222. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  223. {
  224. if (move_slow->is_active())
  225. value *= 0.25f;
  226. if (move_fast->is_active())
  227. value *= 4.0f;
  228. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  229. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  230. const float3 movement = {0.0f, 0.0f, -truck_speed * value * (1.0f / 60.0f)};
  231. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  232. }
  233. );
  234. // Dolly backward
  235. ctx->controls["dolly_backward"]->set_active_callback
  236. (
  237. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  238. {
  239. if (move_slow->is_active())
  240. value *= 0.25f;
  241. if (move_fast->is_active())
  242. value *= 4.0f;
  243. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  244. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  245. const float3 movement = {0.0f, 0.0f, truck_speed * value * (1.0f / 60.0f)};
  246. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  247. }
  248. );
  249. // Truck right
  250. ctx->controls["truck_right"]->set_active_callback
  251. (
  252. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  253. {
  254. if (move_slow->is_active())
  255. value *= 0.25f;
  256. if (move_fast->is_active())
  257. value *= 4.0f;
  258. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  259. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  260. const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  261. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  262. }
  263. );
  264. // Truck left
  265. ctx->controls["truck_left"]->set_active_callback
  266. (
  267. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  268. {
  269. if (move_slow->is_active())
  270. value *= 0.25f;
  271. if (move_fast->is_active())
  272. value *= 4.0f;
  273. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  274. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  275. const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  276. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  277. }
  278. );
  279. // Pedestal up
  280. ctx->controls["pedestal_up"]->set_active_callback
  281. (
  282. [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value)
  283. {
  284. if (move_slow->is_active())
  285. value *= 0.25f;
  286. if (move_fast->is_active())
  287. value *= 4.0f;
  288. const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  289. entity::command::translate(*ctx->entity_registry, target_eid, movement);
  290. }
  291. );
  292. // Pedestal down
  293. ctx->controls["pedestal_down"]->set_active_callback
  294. (
  295. [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value)
  296. {
  297. if (move_slow->is_active())
  298. value *= 0.25f;
  299. if (move_fast->is_active())
  300. value *= 4.0f;
  301. const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  302. entity::command::translate(*ctx->entity_registry, target_eid, movement);
  303. }
  304. );
  305. // Mouse rotate
  306. ctx->controls["mouse_rotate"]->set_activated_callback
  307. (
  308. [ctx]()
  309. {
  310. ctx->app->set_relative_mouse_mode(true);
  311. }
  312. );
  313. ctx->controls["mouse_rotate"]->set_deactivated_callback
  314. (
  315. [ctx]()
  316. {
  317. ctx->app->set_relative_mouse_mode(false);
  318. }
  319. );
  320. // Pan left
  321. ctx->controls["pan_left"]->set_active_callback
  322. (
  323. [ctx, three_dof_eid, pan_speed](float value)
  324. {
  325. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  326. three_dof.yaw += pan_speed * value * (1.0f / 60.0f);
  327. }
  328. );
  329. ctx->controls["pan_left_mouse"]->set_active_callback
  330. (
  331. [ctx, three_dof_eid, pan_speed_mouse, mouse_rotate](float value)
  332. {
  333. if (!mouse_rotate->is_active())
  334. return;
  335. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  336. three_dof.yaw += pan_speed_mouse * value * (1.0f / 60.0f);
  337. }
  338. );
  339. // Pan right
  340. ctx->controls["pan_right"]->set_active_callback
  341. (
  342. [ctx, three_dof_eid, pan_speed](float value)
  343. {
  344. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  345. three_dof.yaw -= pan_speed * value * (1.0f / 60.0f);
  346. }
  347. );
  348. ctx->controls["pan_right_mouse"]->set_active_callback
  349. (
  350. [ctx, three_dof_eid, pan_speed_mouse, mouse_rotate](float value)
  351. {
  352. if (!mouse_rotate->is_active())
  353. return;
  354. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  355. three_dof.yaw -= pan_speed_mouse * value * (1.0f / 60.0f);
  356. }
  357. );
  358. // Tilt up
  359. ctx->controls["tilt_up"]->set_active_callback
  360. (
  361. [ctx, three_dof_eid, tilt_speed](float value)
  362. {
  363. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  364. three_dof.pitch -= tilt_speed * value * (1.0f / 60.0f);
  365. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  366. }
  367. );
  368. ctx->controls["tilt_up_mouse"]->set_active_callback
  369. (
  370. [ctx, three_dof_eid, tilt_speed_mouse, mouse_rotate](float value)
  371. {
  372. if (!mouse_rotate->is_active())
  373. return;
  374. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  375. three_dof.pitch -= tilt_speed_mouse * value * (1.0f / 60.0f);
  376. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  377. }
  378. );
  379. // Tilt down
  380. ctx->controls["tilt_down"]->set_active_callback
  381. (
  382. [ctx, three_dof_eid, tilt_speed](float value)
  383. {
  384. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  385. three_dof.pitch += tilt_speed * value * (1.0f / 60.0f);
  386. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  387. }
  388. );
  389. ctx->controls["tilt_down_mouse"]->set_active_callback
  390. (
  391. [ctx, three_dof_eid, tilt_speed_mouse, mouse_rotate](float value)
  392. {
  393. if (!mouse_rotate->is_active())
  394. return;
  395. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  396. three_dof.pitch += tilt_speed_mouse * value * (1.0f / 60.0f);
  397. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  398. }
  399. );
  400. // Use tool
  401. ctx->controls["use_tool"]->set_activated_callback
  402. (
  403. [ctx]()
  404. {
  405. if (ctx->entities["active_tool"] == ctx->entities["move_tool"])
  406. {
  407. // Project mouse position into scene and grab selectable entity
  408. auto [mouse_x, mouse_y] = ctx->app->get_mouse()->get_current_position();
  409. }
  410. }
  411. );
  412. ctx->controls["use_tool"]->set_deactivated_callback
  413. (
  414. [ctx]()
  415. {
  416. if (ctx->entities["active_tool"] == ctx->entities["move_tool"])
  417. {
  418. }
  419. }
  420. );
  421. ctx->controls["use_tool"]->set_active_callback
  422. (
  423. [ctx](float value)
  424. {
  425. auto [mouse_x, mouse_y] = ctx->app->get_mouse()->get_current_position();
  426. ctx->logger->log("tool used (" + std::to_string(mouse_x) + ", " + std::to_string(mouse_y) + ")");
  427. }
  428. );
  429. }
  430. } // namespace forage
  431. } // namespace state
  432. } // namespace game