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.

118 lines
3.4 KiB

  1. use glc::vector::{Angle, Vector2f, Vector4f};
  2. use space_crush_common::{
  3. components::{Fleet, Orbit, Player, Position},
  4. constants::SHIP_ORBIT_DISTANCE_MAX,
  5. continue_if_none,
  6. misc::LogResult,
  7. return_if_none,
  8. };
  9. use specs::{prelude::*, ReadExpect, ReadStorage, System, World, WriteExpect};
  10. use crate::{
  11. misc::{HorizontalAlign, Text, TextManager, VerticalAlign},
  12. resources::{Camera, Geometry, PlayerState},
  13. Error,
  14. };
  15. pub struct Fleets {
  16. text: Text,
  17. }
  18. #[derive(SystemData)]
  19. pub struct FleetData<'a> {
  20. player_state: ReadExpect<'a, PlayerState>,
  21. geometry: WriteExpect<'a, Geometry>,
  22. camera: ReadExpect<'a, Camera>,
  23. positions: ReadStorage<'a, Position>,
  24. players: ReadStorage<'a, Player>,
  25. orbits: ReadStorage<'a, Orbit>,
  26. fleets: ReadStorage<'a, Fleet>,
  27. }
  28. impl Fleets {
  29. pub fn new(manager: &TextManager) -> Result<Self, Error> {
  30. let cache = manager.create_cache()?;
  31. let text = cache
  32. .new_text()
  33. .scale(20.0)
  34. .font("resources/fonts/DroidSansMono.ttf")
  35. .color(0.7, 0.7, 0.7, 1.0)
  36. .vert_align(VerticalAlign::Center)
  37. .horz_align(HorizontalAlign::Center)
  38. .text("")
  39. .build()?;
  40. Ok(Self { text })
  41. }
  42. }
  43. impl<'a> System<'a> for Fleets {
  44. type SystemData = FleetData<'a>;
  45. fn run(&mut self, data: Self::SystemData) {
  46. let FleetData {
  47. player_state,
  48. mut geometry,
  49. camera,
  50. positions,
  51. players,
  52. orbits,
  53. fleets,
  54. } = data;
  55. let player = return_if_none!(players.get(player_state.player_id));
  56. gl::enable(gl::BLEND);
  57. for (position, orbit) in (&positions, &orbits).join() {
  58. let fleet_id = continue_if_none!(orbit.fleets.get(player.index));
  59. let fleet_id = continue_if_none!(fleet_id);
  60. let fleet = continue_if_none!(fleets.get(*fleet_id));
  61. gl::blend_func(gl::SRC_ALPHA, gl::ONE);
  62. gl::blend_equation(gl::FUNC_ADD);
  63. geometry.render_lines(
  64. Vector4f::new(0.5, 0.5, 0.5, 0.05),
  65. &create_circle(position.pos, orbit.min),
  66. );
  67. geometry.render_lines(
  68. Vector4f::new(0.5, 0.5, 0.5, 0.05),
  69. &create_circle(position.pos, orbit.max),
  70. );
  71. geometry.render_lines(
  72. Vector4f::new(0.5, 0.5, 0.5, 0.05),
  73. &create_circle(position.pos, SHIP_ORBIT_DISTANCE_MAX * orbit.max),
  74. );
  75. gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
  76. gl::blend_equation(gl::FUNC_SUBTRACT);
  77. self.text
  78. .update(
  79. 0,
  80. format!(
  81. "F:{}\nB:{}\nT:{}",
  82. fleet.count.fighter, fleet.count.bomber, fleet.count.transporter
  83. ),
  84. )
  85. .panic("Unable to update text")
  86. .render_offset(&camera.world_to_window(position.pos));
  87. }
  88. gl::blend_equation(gl::FUNC_ADD);
  89. gl::disable(gl::BLEND);
  90. }
  91. }
  92. fn create_circle(p: Vector2f, r: f32) -> Vec<Vector2f> {
  93. let mut points = Vec::new();
  94. for i in 0..=180 {
  95. points.push(Vector2f::new(
  96. p.x + r * Angle::Deg(i as f32 * 2.0).cos(),
  97. p.y + r * Angle::Deg(i as f32 * 2.0).sin(),
  98. ));
  99. }
  100. points
  101. }