path_walker.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // SuperTux
  2. // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. #include "object/path_walker.hpp"
  17. #include <math.h>
  18. #include <assert.h>
  19. #include "editor/editor.hpp"
  20. #include "editor/object_option.hpp"
  21. #include "math/bezier.hpp"
  22. #include "math/random.hpp"
  23. #include "object/path_gameobject.hpp"
  24. #include "supertux/d_scope.hpp"
  25. #include "supertux/sector.hpp"
  26. #include "util/gettext.hpp"
  27. #include "math/easing.hpp"
  28. Vector
  29. PathWalker::Handle::get_pos(const Sizef& size, const Vector& pos) const
  30. {
  31. return pos - Vector(size.width * m_scalar_pos.x, size.height * m_scalar_pos.y) - m_pixel_offset;
  32. }
  33. PathWalker::PathWalker(UID path_uid, bool running_) :
  34. m_path_uid(path_uid),
  35. m_running(running_),
  36. m_current_node_nr(0),
  37. m_next_node_nr(),
  38. m_stop_at_node_nr(m_running ? -1 : 0),
  39. m_node_time(0),
  40. m_node_mult(),
  41. m_walking_speed(1.0)
  42. {
  43. Path* path = get_path();
  44. if (!path) return;
  45. if (!path->is_valid()) return;
  46. m_next_node_nr = path->m_nodes.size() > 1 ? 1 : 0;
  47. m_node_mult = 1 / path->m_nodes[0].time;
  48. }
  49. PathWalker::~PathWalker()
  50. {
  51. }
  52. Path*
  53. PathWalker::get_path() const
  54. {
  55. if (!d_sector) return nullptr;
  56. auto path_gameobject = d_sector->get_object_by_uid<PathGameObject>(m_path_uid);
  57. if (!path_gameobject)
  58. {
  59. return nullptr;
  60. }
  61. else
  62. {
  63. return &path_gameobject->get_path();
  64. }
  65. }
  66. void
  67. PathWalker::update(float dt_sec)
  68. {
  69. Path* path = get_path();
  70. if (!path) return;
  71. if (!path->is_valid()) return;
  72. if (Editor::is_active()) return;
  73. if (!m_running) return;
  74. float delta = fabsf(m_walking_speed) * dt_sec;
  75. while (m_node_time + delta * m_node_mult >= 1) {
  76. delta -= (1 - m_node_time) / m_node_mult;
  77. if (m_walking_speed > 0) {
  78. advance_node();
  79. } else if (m_walking_speed < 0) {
  80. goback_node();
  81. }
  82. auto current_node = & (path->m_nodes[m_current_node_nr]);
  83. m_node_time = 0;
  84. if (m_walking_speed > 0) {
  85. m_node_mult = 1 / current_node->time;
  86. } else {
  87. m_node_mult = 1 / path->m_nodes[m_next_node_nr].time;
  88. }
  89. }
  90. m_node_time += delta * m_node_mult;
  91. }
  92. Vector
  93. PathWalker::get_pos(const Sizef& object_size, const Handle& handle) const
  94. {
  95. Path* path = get_path();
  96. if (!path) return Vector(0, 0);
  97. if (!path->is_valid()) return Vector(0, 0);
  98. if (Editor::is_active()) return path->m_nodes.begin()->position;
  99. if (!m_running) return path->m_nodes[m_current_node_nr].position;
  100. const Path::Node* current_node = &(path->m_nodes[m_current_node_nr]);
  101. const Path::Node* next_node = & (path->m_nodes[m_next_node_nr]);
  102. easing easeFunc = m_walking_speed > 0 ?
  103. getEasingByName(current_node->easing) :
  104. getEasingByName(get_reverse_easing(next_node->easing));
  105. float progress = static_cast<float>(easeFunc(static_cast<double>(m_node_time)));
  106. Vector p1 = current_node->position,
  107. p2 = m_walking_speed > 0 ? current_node->bezier_after : current_node->bezier_before,
  108. p3 = m_walking_speed > 0 ? next_node->bezier_before : next_node->bezier_after,
  109. p4 = next_node->position;
  110. Vector position = path->m_adapt_speed ?
  111. Bezier::get_point(p1, p2, p3, p4, progress) :
  112. Bezier::get_point_by_length(p1, p2, p3, p4, progress);
  113. return handle.get_pos(object_size, position);
  114. }
  115. void
  116. PathWalker::goto_node(int node_idx)
  117. {
  118. const Path* path = get_path();
  119. if (!path) return;
  120. if (node_idx == m_stop_at_node_nr) return;
  121. m_running = true;
  122. m_stop_at_node_nr = node_idx;
  123. }
  124. void
  125. PathWalker::jump_to_node(int node_idx, bool instantaneous)
  126. {
  127. Path* path = get_path();
  128. if (!path) return;
  129. if (node_idx >= static_cast<int>(path->get_nodes().size())) return;
  130. m_next_node_nr = static_cast<size_t>(node_idx);
  131. if (instantaneous || m_walking_speed == 0) {
  132. m_current_node_nr = m_next_node_nr;
  133. }
  134. if (m_walking_speed > 0) {
  135. advance_node();
  136. } else if (m_walking_speed < 0) {
  137. goback_node();
  138. }
  139. m_node_time = 0.f;
  140. }
  141. void
  142. PathWalker::start_moving()
  143. {
  144. m_running = true;
  145. m_stop_at_node_nr = -1;
  146. }
  147. void
  148. PathWalker::stop_moving()
  149. {
  150. m_stop_at_node_nr = static_cast<int>(m_next_node_nr);
  151. }
  152. void
  153. PathWalker::advance_node()
  154. {
  155. Path* path = get_path();
  156. if (!path) return;
  157. if (!path->is_valid()) return;
  158. m_current_node_nr = m_next_node_nr;
  159. if (static_cast<int>(m_current_node_nr) == m_stop_at_node_nr) m_running = false;
  160. if (m_next_node_nr + 1 < path->m_nodes.size()) {
  161. m_next_node_nr++;
  162. return;
  163. }
  164. switch (path->m_mode) {
  165. case WalkMode::ONE_SHOT:
  166. m_next_node_nr = path->m_nodes.size() - 1;
  167. m_walking_speed = 0;
  168. return;
  169. case WalkMode::PING_PONG:
  170. m_walking_speed = -m_walking_speed;
  171. m_next_node_nr = path->m_nodes.size() > 1 ? path->m_nodes.size() - 2 : 0;
  172. return;
  173. case WalkMode::CIRCULAR:
  174. m_next_node_nr = 0;
  175. return;
  176. }
  177. // we shouldn't get here
  178. assert(false);
  179. m_next_node_nr = path->m_nodes.size() - 1;
  180. m_walking_speed = 0;
  181. }
  182. void
  183. PathWalker::goback_node()
  184. {
  185. Path* path = get_path();
  186. if (!path) return;
  187. if (!path->is_valid()) return;
  188. m_current_node_nr = m_next_node_nr;
  189. if (m_next_node_nr > 0) {
  190. m_next_node_nr--;
  191. return;
  192. }
  193. switch (path->m_mode) {
  194. case WalkMode::PING_PONG:
  195. m_walking_speed = -m_walking_speed;
  196. m_next_node_nr = path->m_nodes.size() > 1 ? 1 : 0;
  197. return;
  198. default:
  199. break;
  200. }
  201. assert(false);
  202. m_next_node_nr = 0;
  203. m_walking_speed = 0;
  204. }
  205. /* EOF */