💿🐜 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.

530 lines
18 KiB

2 years ago
  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/components/celestial-body.hpp"
  26. #include "entity/components/tool.hpp"
  27. #include "entity/systems/astronomy.hpp"
  28. #include "animation/screen-transition.hpp"
  29. #include "animation/ease.hpp"
  30. #include "resources/resource-manager.hpp"
  31. #include "entity/components/camera.hpp"
  32. #include "entity/components/constraints/spring-to.hpp"
  33. #include "entity/components/constraints/three-dof.hpp"
  34. #include "entity/components/constraint-stack.hpp"
  35. #include "application.hpp"
  36. #include "game/tools.hpp"
  37. namespace game {
  38. namespace state {
  39. namespace forage {
  40. static void setup_camera(game::context* ctx);
  41. static void setup_tools(game::context* ctx);
  42. static void setup_controls(game::context* ctx);
  43. void enter(game::context* ctx)
  44. {
  45. setup_camera(ctx);
  46. setup_tools(ctx);
  47. setup_controls(ctx);
  48. // Find planet EID by name
  49. entity::id planet_eid = ctx->entities["planet"];
  50. // Create biome terrain component
  51. entity::component::terrain biome_terrain;
  52. biome_terrain.max_lod = 18;
  53. biome_terrain.patch_material = ctx->resource_manager->load<render::material>("desert-terrain.mtl");
  54. biome_terrain.elevation = [](double, double) -> double
  55. {
  56. return 0.0;
  57. };
  58. // Replace planet terrain component with biome terrain component
  59. ctx->entity_registry->replace<entity::component::terrain>(planet_eid, biome_terrain);
  60. // Create observer
  61. entity::id observer_eid = ctx->entity_registry->create();
  62. {
  63. entity::component::observer observer;
  64. observer.reference_body_eid = planet_eid;
  65. observer.elevation = 0.0;
  66. observer.latitude = 0.0;
  67. observer.longitude = 0.0;
  68. observer.camera = ctx->surface_camera;
  69. ctx->entity_registry->assign<entity::component::observer>(observer_eid, observer);
  70. // Set reference location of astronomy system
  71. //ctx->astronomy_system->set_reference_body(planet_eid);
  72. ctx->astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude});
  73. }
  74. // Create larva
  75. {
  76. entity::archetype* larva_archetype = ctx->resource_manager->load<entity::archetype>("ant-larva.ent");
  77. auto larva_eid = larva_archetype->create(*ctx->entity_registry);
  78. entity::command::warp_to(*ctx->entity_registry, larva_eid, {50, 0.1935f, 0});
  79. entity::command::assign_render_layers(*ctx->entity_registry, larva_eid, 0b10);
  80. }
  81. // Create cocoon
  82. {
  83. entity::archetype* cocoon_archetype = ctx->resource_manager->load<entity::archetype>("ant-cocoon.ent");
  84. auto cocoon_eid = cocoon_archetype->create(*ctx->entity_registry);
  85. entity::command::warp_to(*ctx->entity_registry, cocoon_eid, {-50, 0.1935f, 0});
  86. entity::command::assign_render_layers(*ctx->entity_registry, cocoon_eid, 0b10);
  87. }
  88. // Create moon
  89. {
  90. entity::archetype* moon_archetype = ctx->resource_manager->load<entity::archetype>("moon.ent");
  91. auto moon_eid = moon_archetype->create(*ctx->entity_registry);
  92. entity::command::warp_to(*ctx->entity_registry, moon_eid, {50.0f, 50.0f, 50.0f});
  93. entity::command::assign_render_layers(*ctx->entity_registry, moon_eid, 0b10);
  94. entity::command::set_scale(*ctx->entity_registry, moon_eid, float3{1.0f, 1.0f, 1.0f} * 10.0f);
  95. }
  96. ctx->surface_scene->update_tweens();
  97. // Start fade in
  98. ctx->fade_transition->transition(1.0f, true, ease<float>::in_quad);
  99. }
  100. void exit(game::context* ctx)
  101. {}
  102. void setup_camera(game::context* ctx)
  103. {
  104. // Switch to surface camera
  105. ctx->underground_camera->set_active(false);
  106. ctx->surface_camera->set_active(true);
  107. // Create surface camera entity
  108. if (!ctx->entities.count("surface_cam"))
  109. {
  110. // Create camera target entity
  111. entity::id target_eid = ctx->entity_registry->create();
  112. ctx->entities["surface_cam_target"] = target_eid;
  113. {
  114. // Transform
  115. entity::component::transform target_transform;
  116. target_transform.local = math::identity_transform<float>;
  117. target_transform.world = target_transform.local;
  118. target_transform.warp = true;
  119. ctx->entity_registry->assign<entity::component::transform>(target_eid, target_transform);
  120. }
  121. // Create camera entity
  122. entity::id camera_eid = ctx->entity_registry->create();
  123. ctx->entities["surface_cam"] = camera_eid;
  124. // Create camera transform component
  125. entity::component::transform transform;
  126. transform.local = math::identity_transform<float>;
  127. transform.world = transform.local;
  128. transform.warp = true;
  129. ctx->entity_registry->assign<entity::component::transform>(camera_eid, transform);
  130. // Create camera camera component
  131. entity::component::camera camera;
  132. camera.object = ctx->surface_camera;
  133. ctx->entity_registry->assign<entity::component::camera>(camera_eid, camera);
  134. // Create camera 3DOF constraint entity
  135. entity::id three_dof_constraint_eid = ctx->entity_registry->create();
  136. ctx->entities["surface_cam_3dof"] = three_dof_constraint_eid;
  137. {
  138. // Create 3DOF to constraint
  139. entity::component::constraint::three_dof three_dof;
  140. three_dof.yaw = 0.0f;
  141. three_dof.pitch = 0.0f;
  142. three_dof.roll = 0.0f;
  143. ctx->entity_registry->assign<entity::component::constraint::three_dof>(three_dof_constraint_eid, three_dof);
  144. // Create constraint stack node component
  145. entity::component::constraint_stack_node node;
  146. node.active = true;
  147. node.weight = 1.0f;
  148. node.next = entt::null;
  149. ctx->entity_registry->assign<entity::component::constraint_stack_node>(three_dof_constraint_eid, node);
  150. }
  151. // Create camera spring to constraint entity
  152. entity::id spring_constraint_eid = ctx->entity_registry->create();
  153. {
  154. // Create spring to constraint
  155. entity::component::constraint::spring_to spring;
  156. spring.target = target_eid;
  157. 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>};
  158. spring.translation.w = hz_to_rads(8.0f);
  159. spring.spring_translation = true;
  160. spring.spring_rotation = false;
  161. ctx->entity_registry->assign<entity::component::constraint::spring_to>(spring_constraint_eid, spring);
  162. // Create constraint stack node component
  163. entity::component::constraint_stack_node node;
  164. node.active = true;
  165. node.weight = 1.0f;
  166. node.next = three_dof_constraint_eid;
  167. ctx->entity_registry->assign<entity::component::constraint_stack_node>(spring_constraint_eid, node);
  168. }
  169. // Create camera constraint stack component
  170. entity::component::constraint_stack constraint_stack;
  171. constraint_stack.head = spring_constraint_eid;
  172. ctx->entity_registry->assign<entity::component::constraint_stack>(camera_eid, constraint_stack);
  173. }
  174. ctx->surface_camera->set_exposure(-14.5f);
  175. }
  176. void setup_tools(game::context* ctx)
  177. {
  178. ctx->entities["camera_tool"] = build_camera_tool(ctx);
  179. ctx->entities["time_tool"] = build_time_tool(ctx);
  180. // Set active tool
  181. ctx->entities["active_tool"] = ctx->entities["time_tool"];
  182. }
  183. void setup_controls(game::context* ctx)
  184. {
  185. // Get underground camera entity
  186. entity::id camera_eid = ctx->entities["surface_cam"];
  187. entity::id target_eid = ctx->entities["surface_cam_target"];
  188. entity::id three_dof_eid = ctx->entities["surface_cam_3dof"];
  189. const float dolly_speed = 20.0f;
  190. const float truck_speed = dolly_speed;
  191. const float pedestal_speed = 30.0f;
  192. float mouse_tilt_sensitivity = 1.0f;
  193. float mouse_pan_sensitivity = 1.0f;
  194. bool mouse_invert_tilt = false;
  195. bool mouse_invert_pan = false;
  196. float gamepad_tilt_sensitivity = 1.0f;
  197. float gamepad_pan_sensitivity = 1.0f;
  198. bool gamepad_invert_tilt = false;
  199. bool gamepad_invert_pan = false;
  200. bool mouse_look_toggle = false;
  201. ctx->mouse_look = false;
  202. if (ctx->config->contains("mouse_tilt_sensitivity"))
  203. mouse_tilt_sensitivity = math::radians((*ctx->config)["mouse_tilt_sensitivity"].get<float>());
  204. if (ctx->config->contains("mouse_pan_sensitivity"))
  205. mouse_pan_sensitivity = math::radians((*ctx->config)["mouse_pan_sensitivity"].get<float>());
  206. if (ctx->config->contains("mouse_invert_tilt"))
  207. mouse_invert_tilt = math::radians((*ctx->config)["mouse_invert_tilt"].get<bool>());
  208. if (ctx->config->contains("mouse_invert_pan"))
  209. mouse_invert_pan = math::radians((*ctx->config)["mouse_invert_pan"].get<bool>());
  210. if (ctx->config->contains("mouse_look_toggle"))
  211. mouse_look_toggle = math::radians((*ctx->config)["mouse_look_toggle"].get<bool>());
  212. if (ctx->config->contains("gamepad_tilt_sensitivity"))
  213. gamepad_tilt_sensitivity = math::radians((*ctx->config)["gamepad_tilt_sensitivity"].get<float>());
  214. if (ctx->config->contains("gamepad_pan_sensitivity"))
  215. gamepad_pan_sensitivity = math::radians((*ctx->config)["gamepad_pan_sensitivity"].get<float>());
  216. if (ctx->config->contains("gamepad_invert_tilt"))
  217. gamepad_invert_tilt = math::radians((*ctx->config)["gamepad_invert_tilt"].get<bool>());
  218. if (ctx->config->contains("gamepad_invert_pan"))
  219. gamepad_invert_pan = math::radians((*ctx->config)["gamepad_invert_pan"].get<bool>());
  220. const input::control* move_slow = ctx->controls["move_slow"];
  221. const input::control* move_fast = ctx->controls["move_fast"];
  222. const input::control* mouse_look = ctx->controls["mouse_look"];
  223. float mouse_tilt_factor = mouse_tilt_sensitivity * (mouse_invert_tilt ? -1.0f : 1.0f);
  224. float mouse_pan_factor = mouse_pan_sensitivity * (mouse_invert_pan ? -1.0f : 1.0f);
  225. float gamepad_tilt_factor = gamepad_tilt_sensitivity * (gamepad_invert_tilt ? -1.0f : 1.0f);
  226. float gamepad_pan_factor = gamepad_pan_sensitivity * (gamepad_invert_pan ? -1.0f : 1.0f);
  227. ctx->controls["dolly_forward"]->set_active_callback
  228. (
  229. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  230. {
  231. if (move_slow->is_active())
  232. value *= 0.25f;
  233. if (move_fast->is_active())
  234. value *= 4.0f;
  235. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  236. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  237. const float3 movement = {0.0f, 0.0f, -truck_speed * value * (1.0f / 60.0f)};
  238. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  239. }
  240. );
  241. // Dolly backward
  242. ctx->controls["dolly_backward"]->set_active_callback
  243. (
  244. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  245. {
  246. if (move_slow->is_active())
  247. value *= 0.25f;
  248. if (move_fast->is_active())
  249. value *= 4.0f;
  250. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  251. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  252. const float3 movement = {0.0f, 0.0f, truck_speed * value * (1.0f / 60.0f)};
  253. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  254. }
  255. );
  256. // Truck right
  257. ctx->controls["truck_right"]->set_active_callback
  258. (
  259. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  260. {
  261. if (move_slow->is_active())
  262. value *= 0.25f;
  263. if (move_fast->is_active())
  264. value *= 4.0f;
  265. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  266. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  267. const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  268. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  269. }
  270. );
  271. // Truck left
  272. ctx->controls["truck_left"]->set_active_callback
  273. (
  274. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  275. {
  276. if (move_slow->is_active())
  277. value *= 0.25f;
  278. if (move_fast->is_active())
  279. value *= 4.0f;
  280. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  281. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  282. const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  283. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  284. }
  285. );
  286. // Pedestal up
  287. ctx->controls["pedestal_up"]->set_active_callback
  288. (
  289. [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value)
  290. {
  291. if (move_slow->is_active())
  292. value *= 0.25f;
  293. if (move_fast->is_active())
  294. value *= 4.0f;
  295. const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  296. entity::command::translate(*ctx->entity_registry, target_eid, movement);
  297. }
  298. );
  299. // Pedestal down
  300. ctx->controls["pedestal_down"]->set_active_callback
  301. (
  302. [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value)
  303. {
  304. if (move_slow->is_active())
  305. value *= 0.25f;
  306. if (move_fast->is_active())
  307. value *= 4.0f;
  308. const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  309. entity::command::translate(*ctx->entity_registry, target_eid, movement);
  310. }
  311. );
  312. // Mouse rotate
  313. ctx->controls["mouse_look"]->set_activated_callback
  314. (
  315. [ctx, mouse_look_toggle]()
  316. {
  317. if (mouse_look_toggle)
  318. ctx->mouse_look = !ctx->mouse_look;
  319. else
  320. ctx->mouse_look = true;
  321. ctx->app->set_relative_mouse_mode(ctx->mouse_look);
  322. }
  323. );
  324. ctx->controls["mouse_look"]->set_deactivated_callback
  325. (
  326. [ctx, mouse_look_toggle]()
  327. {
  328. if (!mouse_look_toggle)
  329. {
  330. ctx->mouse_look = false;
  331. ctx->app->set_relative_mouse_mode(false);
  332. }
  333. }
  334. );
  335. // Pan left
  336. ctx->controls["pan_left_gamepad"]->set_active_callback
  337. (
  338. [ctx, three_dof_eid, gamepad_pan_factor](float value)
  339. {
  340. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  341. three_dof.yaw += gamepad_pan_factor * value * (1.0f / 60.0f);
  342. }
  343. );
  344. ctx->controls["pan_left_mouse"]->set_active_callback
  345. (
  346. [ctx, three_dof_eid, mouse_pan_factor](float value)
  347. {
  348. if (!ctx->mouse_look)
  349. return;
  350. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  351. three_dof.yaw += mouse_pan_factor * value * (1.0f / 60.0f);
  352. }
  353. );
  354. // Pan right
  355. ctx->controls["pan_right_gamepad"]->set_active_callback
  356. (
  357. [ctx, three_dof_eid, gamepad_pan_factor](float value)
  358. {
  359. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  360. three_dof.yaw -= gamepad_pan_factor * value * (1.0f / 60.0f);
  361. }
  362. );
  363. ctx->controls["pan_right_mouse"]->set_active_callback
  364. (
  365. [ctx, three_dof_eid, mouse_pan_factor](float value)
  366. {
  367. if (!ctx->mouse_look)
  368. return;
  369. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  370. three_dof.yaw -= mouse_pan_factor * value * (1.0f / 60.0f);
  371. }
  372. );
  373. // Tilt up
  374. ctx->controls["tilt_up_gamepad"]->set_active_callback
  375. (
  376. [ctx, three_dof_eid, gamepad_tilt_factor](float value)
  377. {
  378. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  379. three_dof.pitch -= gamepad_tilt_factor * value * (1.0f / 60.0f);
  380. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  381. }
  382. );
  383. ctx->controls["tilt_up_mouse"]->set_active_callback
  384. (
  385. [ctx, three_dof_eid, mouse_tilt_factor](float value)
  386. {
  387. if (!ctx->mouse_look)
  388. return;
  389. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  390. three_dof.pitch -= mouse_tilt_factor * value * (1.0f / 60.0f);
  391. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  392. }
  393. );
  394. // Tilt down
  395. ctx->controls["tilt_down_gamepad"]->set_active_callback
  396. (
  397. [ctx, three_dof_eid, gamepad_tilt_factor](float value)
  398. {
  399. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  400. three_dof.pitch += gamepad_tilt_factor * value * (1.0f / 60.0f);
  401. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  402. }
  403. );
  404. ctx->controls["tilt_down_mouse"]->set_active_callback
  405. (
  406. [ctx, three_dof_eid, mouse_tilt_factor](float value)
  407. {
  408. if (!ctx->mouse_look)
  409. return;
  410. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  411. three_dof.pitch += mouse_tilt_factor * value * (1.0f / 60.0f);
  412. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  413. }
  414. );
  415. // Use tool
  416. ctx->controls["use_tool"]->set_activated_callback
  417. (
  418. [ctx]()
  419. {
  420. if (ctx->entities.count("active_tool"))
  421. {
  422. entity::id tool_eid = ctx->entities["active_tool"];
  423. const auto& tool = ctx->entity_registry->get<entity::component::tool>(tool_eid);
  424. if (tool.activated)
  425. tool.activated();
  426. }
  427. }
  428. );
  429. ctx->controls["use_tool"]->set_deactivated_callback
  430. (
  431. [ctx]()
  432. {
  433. if (ctx->entities.count("active_tool"))
  434. {
  435. entity::id tool_eid = ctx->entities["active_tool"];
  436. const auto& tool = ctx->entity_registry->get<entity::component::tool>(tool_eid);
  437. if (tool.deactivated)
  438. tool.deactivated();
  439. }
  440. }
  441. );
  442. ctx->controls["use_tool"]->set_active_callback
  443. (
  444. [ctx](float value)
  445. {
  446. if (ctx->entities.count("active_tool"))
  447. {
  448. entity::id tool_eid = ctx->entities["active_tool"];
  449. const auto& tool = ctx->entity_registry->get<entity::component::tool>(tool_eid);
  450. if (tool.active)
  451. tool.active();
  452. }
  453. }
  454. );
  455. /*
  456. auto [mouse_x, mouse_y] = ctx->app->get_mouse()->get_current_position();
  457. ctx->logger->log("tool used (" + std::to_string(mouse_x) + ", " + std::to_string(mouse_y) + ")");
  458. entity::id planet_eid = ctx->entities["planet"];
  459. entity::component::celestial_body& body = ctx->entity_registry->get<entity::component::celestial_body>(planet_eid);
  460. body.axial_tilt += math::radians(30.0f) * 1.0f / 60.0f;
  461. */
  462. }
  463. } // namespace forage
  464. } // namespace state
  465. } // namespace game