formation_system.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #pragma once
  2. #include "../units/troop_type.h"
  3. #include <QVector3D>
  4. #include <memory>
  5. #include <string>
  6. #include <unordered_map>
  7. #include <vector>
  8. namespace Engine::Core {
  9. using EntityID = unsigned int;
  10. class World;
  11. } // namespace Engine::Core
  12. namespace Game::Systems {
  13. enum class FormationType { Roman, Barbarian, Carthage };
  14. struct UnitFormationInfo {
  15. Engine::Core::EntityID entity_id;
  16. Game::Units::TroopType troop_type;
  17. QVector3D current_position;
  18. };
  19. struct FormationPosition {
  20. QVector3D position;
  21. float facing_angle;
  22. Engine::Core::EntityID entity_id{0};
  23. };
  24. } // namespace Game::Systems
  25. namespace std {
  26. template <> struct hash<Game::Systems::FormationType> {
  27. auto operator()(const Game::Systems::FormationType &ft) const -> std::size_t {
  28. return std::hash<int>()(static_cast<int>(ft));
  29. }
  30. };
  31. } // namespace std
  32. namespace Game::Systems {
  33. class IFormation {
  34. public:
  35. virtual ~IFormation() = default;
  36. [[nodiscard]] virtual auto calculate_positions(
  37. int unit_count, const QVector3D &center,
  38. float base_spacing = 1.0F) const -> std::vector<QVector3D> = 0;
  39. [[nodiscard]] virtual auto calculate_formation_positions(
  40. const std::vector<UnitFormationInfo> &units, const QVector3D &center,
  41. float base_spacing = 1.0F) const -> std::vector<FormationPosition> = 0;
  42. [[nodiscard]] virtual auto get_type() const -> FormationType = 0;
  43. };
  44. class RomanFormation : public IFormation {
  45. public:
  46. [[nodiscard]] auto calculate_positions(
  47. int unit_count, const QVector3D &center,
  48. float base_spacing = 1.0F) const -> std::vector<QVector3D> override;
  49. [[nodiscard]] auto
  50. calculate_formation_positions(const std::vector<UnitFormationInfo> &units,
  51. const QVector3D &center,
  52. float base_spacing = 1.0F) const
  53. -> std::vector<FormationPosition> override;
  54. [[nodiscard]] auto get_type() const -> FormationType override {
  55. return FormationType::Roman;
  56. }
  57. };
  58. class BarbarianFormation : public IFormation {
  59. public:
  60. [[nodiscard]] auto calculate_positions(
  61. int unit_count, const QVector3D &center,
  62. float base_spacing = 1.0F) const -> std::vector<QVector3D> override;
  63. [[nodiscard]] auto
  64. calculate_formation_positions(const std::vector<UnitFormationInfo> &units,
  65. const QVector3D &center,
  66. float base_spacing = 1.0F) const
  67. -> std::vector<FormationPosition> override;
  68. [[nodiscard]] auto get_type() const -> FormationType override {
  69. return FormationType::Barbarian;
  70. }
  71. };
  72. class CarthageFormation : public IFormation {
  73. public:
  74. [[nodiscard]] auto calculate_positions(
  75. int unit_count, const QVector3D &center,
  76. float base_spacing = 1.0F) const -> std::vector<QVector3D> override;
  77. [[nodiscard]] auto
  78. calculate_formation_positions(const std::vector<UnitFormationInfo> &units,
  79. const QVector3D &center,
  80. float base_spacing = 1.0F) const
  81. -> std::vector<FormationPosition> override;
  82. [[nodiscard]] auto get_type() const -> FormationType override {
  83. return FormationType::Carthage;
  84. }
  85. };
  86. class FormationSystem {
  87. public:
  88. static auto instance() -> FormationSystem &;
  89. auto
  90. get_formation_positions(FormationType type, int unit_count,
  91. const QVector3D &center,
  92. float base_spacing = 1.0F) -> std::vector<QVector3D>;
  93. auto get_formation_positions_with_facing(
  94. FormationType type, const std::vector<UnitFormationInfo> &units,
  95. const QVector3D &center,
  96. float base_spacing = 1.0F) -> std::vector<FormationPosition>;
  97. void register_formation(FormationType type,
  98. std::unique_ptr<IFormation> formation);
  99. auto get_formation(FormationType type) const -> const IFormation *;
  100. private:
  101. FormationSystem();
  102. void initialize_defaults();
  103. std::unordered_map<FormationType, std::unique_ptr<IFormation>> m_formations;
  104. };
  105. } // namespace Game::Systems