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

290 lines
9.2 KiB

  1. /*
  2. * Copyright (C) 2017 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 "play-state.hpp"
  20. #include "../application.hpp"
  21. #include "../camera-controller.hpp"
  22. #include "../game/colony.hpp"
  23. #include "../game/ant.hpp"
  24. #include "../ui/toolbar.hpp"
  25. #include <cmath>
  26. PlayState::PlayState(Application* application):
  27. ApplicationState(application)
  28. {}
  29. PlayState::~PlayState()
  30. {}
  31. void PlayState::enter()
  32. {
  33. // Hide level selector
  34. application->levelSelectorContainer->setVisible(false);
  35. application->levelSelectorContainer->setActive(false);
  36. // Setup HUD
  37. application->pauseButtonImage->setVisible(false);
  38. application->pauseButtonImage->setActive(false);
  39. application->playButtonImage->setVisible(false);
  40. application->playButtonImage->setActive(false);
  41. application->rectangularPaletteImage->setVisible(true);
  42. application->rectangularPaletteImage->setActive(true);
  43. application->toolbar->getContainer()->setVisible(true);
  44. application->toolbar->getContainer()->setActive(true);
  45. // Setup tools
  46. application->forcepsClosed = false;
  47. // Add background
  48. //application->backgroundLayer->addObject(&application->bgCamera);
  49. //application->backgroundLayer->addObject(&application->bgBatch);
  50. // Create terrain model instances
  51. application->terrain.getSurfaceModel()->getGroup(0)->material = application->materialLoader->load("data/materials/debug-terrain-surface.mtl");
  52. terrainSurface.setModel(application->terrain.getSurfaceModel());
  53. terrainSurface.setTranslation(Vector3(0, 0, 0));
  54. terrainSubsurface.setModel(application->terrain.getSubsurfaceModel());
  55. terrainSubsurface.setTranslation(Vector3(0, 0, 0));
  56. // Add terrain to scene
  57. application->defaultLayer->addObject(&terrainSurface);
  58. application->defaultLayer->addObject(&terrainSubsurface);
  59. // Add forceps to scene
  60. application->defaultLayer->addObject(&application->forcepsModelInstance);
  61. // Spawn ants
  62. Navmesh* navmesh = application->terrain.getSurfaceNavmesh();
  63. for (int i = 0; i < 50; ++i)
  64. {
  65. Navmesh::Triangle* triangle = (*navmesh->getTriangles())[0];
  66. Ant* ant = application->colony->spawn(navmesh, triangle, normalize_barycentric(Vector3(0.5f)));
  67. Vector3 forward = glm::normalize(triangle->edge->vertex->position - triangle->edge->next->vertex->position);
  68. Vector3 up = triangle->normal;
  69. ant->setOrientation(forward, up);
  70. application->defaultLayer->addObject(ant->getModelInstance());
  71. ant->setState(Ant::State::WANDER);
  72. }
  73. // Setup camera controller
  74. application->surfaceCam->setCamera(&application->camera);
  75. application->surfaceCam->setFocalPoint(Vector3(0.0f));
  76. application->surfaceCam->setFocalDistance(250.0f);
  77. application->surfaceCam->setElevation(glm::radians(35.0f));
  78. application->surfaceCam->setAzimuth(glm::radians(-45.0f));
  79. application->surfaceCam->setTargetFocalPoint(application->surfaceCam->getFocalPoint());
  80. application->surfaceCam->setTargetFocalDistance(application->surfaceCam->getFocalDistance());
  81. application->surfaceCam->setTargetElevation(application->surfaceCam->getElevation());
  82. application->surfaceCam->setTargetAzimuth(application->surfaceCam->getAzimuth());
  83. application->surfaceCam->update(0.0f);
  84. application->simulationPaused = false;
  85. application->mouse->addMouseButtonObserver(this);
  86. pickAnt = nullptr;
  87. }
  88. void PlayState::execute()
  89. {
  90. /*
  91. else
  92. {
  93. Plane plane;
  94. plane.set(Vector3(0, 1, 0), Vector3(0.0f));
  95. auto result = pickingRay.intersects(plane);
  96. pick = pickingRay.extrapolate(std::get<1>(result));
  97. }
  98. */
  99. static float rotationTime = 0.0f;
  100. float iconRotation = std::sin(rotationTime * 3.0f) * glm::radians(10.0f);
  101. rotationTime += application->dt;
  102. //application->blaImage->setRotation(iconRotation);
  103. // Move camera
  104. Vector2 movementVector(0.0f);
  105. if (application->cameraMoveLeft.isTriggered())
  106. movementVector.x -= application->cameraMoveLeft.getCurrentValue();
  107. if (application->cameraMoveRight.isTriggered())
  108. movementVector.x += application->cameraMoveRight.getCurrentValue();
  109. if (application->cameraMoveForward.isTriggered())
  110. movementVector.y -= application->cameraMoveForward.getCurrentValue();
  111. if (application->cameraMoveBack.isTriggered())
  112. movementVector.y += application->cameraMoveBack.getCurrentValue();
  113. if (movementVector.x != 0.0f || movementVector.y != 0.0f)
  114. {
  115. movementVector *= 0.005f * application->surfaceCam->getFocalDistance() * application->dt / (1.0f / 60.0f);
  116. application->surfaceCam->move(movementVector);
  117. Vector3 focal = application->surfaceCam->getFocalPoint();
  118. }
  119. // Zoom camera
  120. float zoomFactor = application->surfaceCam->getFocalDistance() / 10.0f * application->dt / (1.0f / 60.0f);
  121. if (application->cameraZoomIn.isTriggered())
  122. application->surfaceCam->zoom(zoomFactor * application->cameraZoomIn.getCurrentValue());
  123. if (application->cameraZoomOut.isTriggered())
  124. application->surfaceCam->zoom(-zoomFactor * application->cameraZoomOut.getCurrentValue());
  125. // Rotate camera
  126. if (application->cameraRotateCW.isTriggered() && !application->cameraRotateCW.wasTriggered())
  127. {
  128. application->surfaceCam->rotate(glm::radians(-45.0f));
  129. }
  130. if (application->cameraRotateCCW.isTriggered() && !application->cameraRotateCCW.wasTriggered())
  131. {
  132. application->surfaceCam->rotate(glm::radians(45.0f));
  133. }
  134. // Update camera
  135. application->surfaceCam->update(application->dt);
  136. // Picking
  137. glm::ivec2 mousePosition = application->mouse->getCurrentPosition();
  138. mousePosition.y = application->height - mousePosition.y;
  139. Vector4 viewport(0.0f, 0.0f, application->width, application->height);
  140. Vector3 mouseNear = application->camera.unproject(Vector3(mousePosition.x, mousePosition.y, 0.0f), viewport);
  141. Vector3 mouseFar = application->camera.unproject(Vector3(mousePosition.x, mousePosition.y, 1.0f), viewport);
  142. pickingRay.origin = mouseNear;
  143. pickingRay.direction = glm::normalize(mouseFar - mouseNear);
  144. std::list<Navmesh::Triangle*> triangles;
  145. application->terrain.getSurfaceOctree()->query(pickingRay, &triangles);
  146. auto result = intersects(pickingRay, triangles);
  147. if (std::get<0>(result))
  148. {
  149. pick = pickingRay.extrapolate(std::get<1>(result));
  150. std::size_t triangleIndex = std::get<3>(result);
  151. pickTriangle = (*application->terrain.getSurfaceNavmesh()->getTriangles())[triangleIndex];
  152. float forcepsDistance = (application->forcepsClosed) ? 0.0f : 0.5f;
  153. //Quaternion rotation = glm::rotation(Vector3(0, 1, 0), triangle->normal);
  154. Quaternion rotation = glm::angleAxis(application->surfaceCam->getAzimuth(), Vector3(0, 1, 0)) *
  155. glm::angleAxis(glm::radians(15.0f), Vector3(0, 0, -1));
  156. Vector3 translation = pick + rotation * Vector3(0, forcepsDistance, 0);
  157. // Set tool position
  158. application->forcepsModelInstance.setTranslation(translation);
  159. application->forcepsModelInstance.setRotation(rotation);
  160. }
  161. if (pickAnt != nullptr)
  162. {
  163. pickAnt->getModelInstance()->setTranslation(pick);
  164. }
  165. // Update colony
  166. if (!application->simulationPaused)
  167. {
  168. application->colony->update(application->dt);
  169. }
  170. // Pause simulation
  171. if (application->togglePause.isTriggered() && !application->togglePause.wasTriggered())
  172. {
  173. if (application->simulationPaused)
  174. {
  175. application->unpauseSimulation();
  176. }
  177. else
  178. {
  179. application->pauseSimulation();
  180. }
  181. }
  182. }
  183. void PlayState::exit()
  184. {
  185. // Remove background
  186. //application->backgroundLayer->removeObject(&application->bgCamera);
  187. //application->backgroundLayer->removeObject(&application->bgBatch);
  188. application->mouse->removeMouseButtonObserver(this);
  189. }
  190. void PlayState::mouseButtonPressed(int button, int x, int y)
  191. {
  192. if (button == 1)
  193. {
  194. application->forcepsClosed = true;
  195. Sphere forcepsSphere = Sphere(pick, 0.35f);
  196. std::list<Agent*> ants;
  197. pickAnt = nullptr;
  198. float closestDistance = std::numeric_limits<float>::infinity();
  199. application->colony->queryAnts(forcepsSphere, &ants);
  200. for (Agent* agent: ants)
  201. {
  202. Ant* ant = static_cast<Ant*>(agent);
  203. Vector3 difference = ant->getPosition() - pick;
  204. float distanceSquared = glm::dot(difference, difference);
  205. if (distanceSquared < closestDistance)
  206. {
  207. closestDistance = distanceSquared;
  208. pickAnt = ant;
  209. }
  210. }
  211. if (pickAnt != nullptr)
  212. {
  213. pickAnt->setState(Ant::State::DEAD);
  214. }
  215. }
  216. }
  217. void PlayState::mouseButtonReleased(int button, int x, int y)
  218. {
  219. if (button == 1)
  220. {
  221. application->forcepsClosed = false;
  222. if (pickAnt != nullptr)
  223. {
  224. auto result = intersects(pickingRay, pickTriangle);
  225. if (std::get<0>(result))
  226. {
  227. Vector3 barycentricPosition = Vector3(std::get<2>(result), std::get<3>(result), 1.0f - std::get<2>(result) - std::get<3>(result));
  228. pickAnt->setPosition(pickTriangle, barycentricPosition);
  229. }
  230. pickAnt->setState(Ant::State::WANDER);
  231. pickAnt = nullptr;
  232. }
  233. }
  234. }