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

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