formation_calculator.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "formation_calculator.h"
  2. #include <cmath>
  3. namespace Render::GL {
  4. auto RomanInfantryFormation::calculate_offset(
  5. int idx, int row, int col, int rows, int cols, float spacing,
  6. uint32_t seed) const -> FormationOffset {
  7. float const offset_x = (col - (cols - 1) * 0.5F) * spacing;
  8. float const offset_z = (row - (rows - 1) * 0.5F) * spacing;
  9. return {offset_x, offset_z};
  10. }
  11. auto RomanCavalryFormation::calculate_offset(
  12. int idx, int row, int col, int rows, int cols, float spacing,
  13. uint32_t seed) const -> FormationOffset {
  14. float const spacing_multiplier = 1.05F;
  15. float const offset_x =
  16. (col - (cols - 1) * 0.5F) * spacing * spacing_multiplier;
  17. float const offset_z =
  18. (row - (rows - 1) * 0.5F) * spacing * spacing_multiplier;
  19. return {offset_x, offset_z};
  20. }
  21. auto CarthageInfantryFormation::calculate_offset(
  22. int idx, int row, int col, int rows, int cols, float spacing,
  23. uint32_t seed) const -> FormationOffset {
  24. float const row_normalized = float(row) / float(rows > 1 ? rows - 1 : 1);
  25. float const col_normalized =
  26. float(col - (cols - 1) * 0.5F) / float(cols > 1 ? (cols - 1) * 0.5F : 1);
  27. float const spread_factor = 1.0F + row_normalized * 0.3F;
  28. float const row_spacing = spacing * (1.0F + row_normalized * 0.15F);
  29. float offset_x = (col - (cols - 1) * 0.5F) * spacing * spread_factor;
  30. float offset_z = (row - (rows - 1) * 0.5F) * row_spacing;
  31. if (row % 2 == 1) {
  32. offset_x += spacing * 0.35F;
  33. }
  34. float const rank_wave = std::sin(col_normalized * 3.14159F) * spacing *
  35. 0.12F * (1.0F + row_normalized);
  36. offset_z += rank_wave;
  37. float const center_push = (1.0F - std::abs(col_normalized)) * spacing * 0.2F;
  38. offset_z -= center_push;
  39. uint32_t variation_seed = seed ^ (uint32_t(idx) * 2654435761U);
  40. float const phase = float(variation_seed & 0xFFU) / 255.0F * 6.28318F;
  41. float const jitter_scale = spacing * 0.08F * (1.0F + row_normalized * 0.5F);
  42. float const jitter_x = std::sin(phase) * jitter_scale;
  43. float const jitter_z = std::cos(phase * 1.3F) * jitter_scale * 0.7F;
  44. offset_x += jitter_x;
  45. offset_z += jitter_z;
  46. int const cluster_id = idx / 4;
  47. float const cluster_phase = float(cluster_id * 137 + (seed & 0xFFU)) * 0.1F;
  48. float const cluster_pull = spacing * 0.06F;
  49. offset_x += std::sin(cluster_phase) * cluster_pull;
  50. offset_z += std::cos(cluster_phase * 0.7F) * cluster_pull;
  51. return {offset_x, offset_z};
  52. }
  53. auto CarthageCavalryFormation::calculate_offset(
  54. int idx, int row, int col, int rows, int cols, float spacing,
  55. uint32_t seed) const -> FormationOffset {
  56. float const spacing_multiplier = 1.2F;
  57. float offset_x = (col - (cols - 1) * 0.5F) * spacing * spacing_multiplier;
  58. float offset_z = (row - (rows - 1) * 0.5F) * spacing * spacing_multiplier;
  59. uint32_t rng_state = seed ^ (uint32_t(idx) * 7919U);
  60. auto fast_random = [](uint32_t &state) -> float {
  61. state = state * 1664525U + 1013904223U;
  62. return float(state & 0x7FFFFFU) / float(0x7FFFFFU);
  63. };
  64. float const jitter_x =
  65. (fast_random(rng_state) - 0.5F) * spacing * spacing_multiplier * 0.25F;
  66. float const jitter_z =
  67. (fast_random(rng_state) - 0.5F) * spacing * spacing_multiplier * 0.25F;
  68. offset_x += jitter_x;
  69. offset_z += jitter_z;
  70. float const cluster_x =
  71. std::sin(float(idx) * 0.7F) * spacing * spacing_multiplier * 0.10F;
  72. float const cluster_z =
  73. std::cos(float(idx) * 0.5F) * spacing * spacing_multiplier * 0.10F;
  74. offset_x += cluster_x;
  75. offset_z += cluster_z;
  76. return {offset_x, offset_z};
  77. }
  78. auto BuilderCircleFormation::calculate_offset(
  79. int idx, int row, int col, int rows, int cols, float spacing,
  80. uint32_t seed) const -> FormationOffset {
  81. int const total_units = rows * cols;
  82. float const angle =
  83. (float(idx) / float(total_units)) * 2.0F * 3.14159265358979F;
  84. float const radius = spacing * 1.8F;
  85. float offset_x = std::cos(angle) * radius;
  86. float offset_z = std::sin(angle) * radius;
  87. uint32_t rng_state = seed ^ (uint32_t(idx) * 2654435761U);
  88. auto fast_random = [](uint32_t &state) -> float {
  89. state = state * 1664525U + 1013904223U;
  90. return float(state & 0x7FFFFFU) / float(0x7FFFFFU);
  91. };
  92. float const jitter = spacing * 0.08F;
  93. offset_x += (fast_random(rng_state) - 0.5F) * jitter;
  94. offset_z += (fast_random(rng_state) - 0.5F) * jitter;
  95. return {offset_x, offset_z};
  96. }
  97. RomanInfantryFormation FormationCalculatorFactory::s_roman_infantry;
  98. RomanCavalryFormation FormationCalculatorFactory::s_roman_cavalry;
  99. CarthageInfantryFormation FormationCalculatorFactory::s_carthage_infantry;
  100. CarthageCavalryFormation FormationCalculatorFactory::s_carthage_cavalry;
  101. BuilderCircleFormation FormationCalculatorFactory::s_builder_circle;
  102. auto FormationCalculatorFactory::get_calculator(
  103. Nation nation, UnitCategory category) -> const IFormationCalculator * {
  104. if (category == UnitCategory::BuilderConstruction) {
  105. return &s_builder_circle;
  106. }
  107. switch (nation) {
  108. case Nation::Roman:
  109. switch (category) {
  110. case UnitCategory::Infantry:
  111. return &s_roman_infantry;
  112. case UnitCategory::Cavalry:
  113. return &s_roman_cavalry;
  114. case UnitCategory::BuilderConstruction:
  115. return &s_builder_circle;
  116. }
  117. break;
  118. case Nation::Carthage:
  119. switch (category) {
  120. case UnitCategory::Infantry:
  121. return &s_carthage_infantry;
  122. case UnitCategory::Cavalry:
  123. return &s_carthage_cavalry;
  124. case UnitCategory::BuilderConstruction:
  125. return &s_builder_circle;
  126. }
  127. break;
  128. }
  129. return &s_roman_infantry;
  130. }
  131. } // namespace Render::GL