formation_calculator.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "formation_calculator.h"
  2. #include <cmath>
  3. namespace Render::GL {
  4. auto RomanInfantryFormation::calculateOffset(
  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::calculateOffset(
  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::calculateOffset(
  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::calculateOffset(
  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. RomanInfantryFormation FormationCalculatorFactory::s_romanInfantry;
  79. RomanCavalryFormation FormationCalculatorFactory::s_romanCavalry;
  80. CarthageInfantryFormation FormationCalculatorFactory::s_carthageInfantry;
  81. CarthageCavalryFormation FormationCalculatorFactory::s_carthageCavalry;
  82. auto FormationCalculatorFactory::getCalculator(
  83. Nation nation, UnitCategory category) -> const IFormationCalculator * {
  84. switch (nation) {
  85. case Nation::Roman:
  86. switch (category) {
  87. case UnitCategory::Infantry:
  88. return &s_romanInfantry;
  89. case UnitCategory::Cavalry:
  90. return &s_romanCavalry;
  91. }
  92. break;
  93. case Nation::Carthage:
  94. switch (category) {
  95. case UnitCategory::Infantry:
  96. return &s_carthageInfantry;
  97. case UnitCategory::Cavalry:
  98. return &s_carthageCavalry;
  99. }
  100. break;
  101. }
  102. return &s_romanInfantry;
  103. }
  104. } // namespace Render::GL