pub fn draw_action_arrows(
  mut commands: Commands,
  pending: Query<
    (&TilePos, &EntityPendingAction),
    (Changed<EntityPendingAction>, With<PlayerStatus>),
  >,
  active_turn: Query<&TurnDisplayer>,
) {
  // Don't want to draw arrows while a turn is being animated
  if !active_turn.is_empty() {
    return;
  }

  pending
    .iter()
    .filter_map(
      |(center, action)| match (action.is_ready, action.action.to_owned()) {
        (true, EntityAction::Move((a, b))) => Some((true, a, b)),
        (
          true,
          EntityAction::Attack(PendingAttack {
            enemy_position: target,
            ..
          }),
        ) => Some((false, center.to_owned(), target)),
        _ => None,
      },
    )
    .for_each(|(is_moving, start, end)| {
      // a new pending action has been added, but the turn is not yet animating
      // so, let's draw an arrow to show the intended action
      let start_point = utils::initial_map_drawing_position(
        &TileSize(constants::TILE_SIZE, constants::TILE_SIZE),
        &start,
        0.,
      )
      .truncate();
      let end_point = utils::initial_map_drawing_position(
        &TileSize(constants::TILE_SIZE, constants::TILE_SIZE),
        &end,
        0.,
      )
      .truncate();

      // We create an arrow by finding the angle of the action vector, and the drawing to smaller lines
      // with slightly offset angles from the end of the vector.
      let hyp = end_point - start_point;
      if hyp.x == 0. && hyp.y == 0. {
        return;
      }
      let angle = hyp.angle_between(Vec2::X).abs();
      let upper_angle = angle + 0.4;
      let lower_angle = angle - 0.4;
      let mut upper_vec =
        Vec2::new(1., upper_angle.tan()).normalize() * (constants::TILE_SIZE - 2.);
      let mut lower_vec =
        Vec2::new(1., lower_angle.tan()).normalize() * (constants::TILE_SIZE - 2.);
      // TODO: surely I could simplify this with better math
      if hyp.x < 0. && hyp.y >= 0. {
        upper_vec = upper_vec * -1.;
        lower_vec = lower_vec * -1.;
      } else if hyp.y < 0. && hyp.x > 0. {
        upper_vec.y = upper_vec.y * -1.;
        lower_vec.y = lower_vec.y * -1.;
      } else if hyp.y < 0. && hyp.x < 0. {
        upper_vec.x = upper_vec.x * -1.;
        lower_vec.x = lower_vec.x * -1.;
      } else if hyp.y < 0. && hyp.x == 0. {
        lower_vec = lower_vec * -1.;
      } else if hyp.x == 0. && hyp.y > 0. {
        upper_vec = upper_vec * -1.;
      }
      let upper_ch_end = end_point - upper_vec;
      let lower_ch_end = end_point - lower_vec;

      let arrow_line = shapes::Line(start_point, end_point);
      let upper_chevron = shapes::Line(end_point, upper_ch_end);
      let lower_chevron = shapes::Line(end_point, lower_ch_end);

      let mut transform: Transform = Default::default();
      transform.translation.z = constants::MAP_INDICATOR_Z_LEVEL;

      // The arrow indicators are their own entities, rather than being attached to players,
      // because they have some duplicate components with the player's sprites.
      commands
        .spawn_bundle(
          GeometryBuilder::new()
            .add(&arrow_line)
            .add(&upper_chevron)
            .add(&lower_chevron)
            .build(
              DrawMode::Stroke(StrokeMode::new(
                if is_moving {
                  constants::MOVE_INDICATION_ARROW_COLOR
                } else {
                  constants::ATTACK_INDICATION_ARROW_COLOR
                },
                3.,
              )),
              transform,
            ),
        )
        .insert(ActionIndicationMarker)
        .insert(start.clone());
    });
}
/// Inserts action arrows for pending player actions.
/// Only add the arrows when the action has been fully chosen `(EntityPendingAction::is_ready == true)`
Inserts action arrows for pending player actions.
Only add the arrows when the action has been fully chosen `(EntityPendingAction::is_ready == true)`
Inserts action arrows for pending player actions . Only add the arrows when the action has been fully chosen ` ( EntityPendingAction :: is_ready == true ) `
pub fn draw_action_arrows(
  mut commands: Commands,
  pending: Query<
    (&TilePos, &EntityPendingAction),
    (Changed<EntityPendingAction>, With<PlayerStatus>),
  >,
  active_turn: Query<&TurnDisplayer>,
) {
  // Don't want to draw arrows while a turn is being animated
  if !active_turn.is_empty() {
    return;
  }
  pending
    .iter()
    .filter_map(
      |(center, action)| match (action.is_ready, action.action.to_owned()) {
        (true, EntityAction::Move((a, b))) => Some((true, a, b)),
        (
          true,
          EntityAction::Attack(PendingAttack {
            enemy_position: target,
            ..
          }),
        ) => Some((false, center.to_owned(), target)),
        _ => None,
      },
    )
    .for_each(|(is_moving, start, end)| {
      // a new pending action has been added, but the turn is not yet animating
      // so, let's draw an arrow to show the intended action
      let start_point = utils::initial_map_drawing_position(
        &TileSize(constants::TILE_SIZE, constants::TILE_SIZE),
        &start,
        0.,
      )
      .truncate();
      let end_point = utils::initial_map_drawing_position(
        &TileSize(constants::TILE_SIZE, constants::TILE_SIZE),
        &end,
        0.,
      )
      .truncate();
      // We create an arrow by finding the angle of the action vector, and the drawing to smaller lines
      // with slightly offset angles from the end of the vector.
      let hyp = end_point - start_point;
      if hyp.x == 0. && hyp.y == 0. {
        return;
      }
      let angle = hyp.angle_between(Vec2::X).abs();
      let upper_angle = angle + 0.4;
      let lower_angle = angle - 0.4;
      let mut upper_vec =
        Vec2::new(1., upper_angle.tan()).normalize() * (constants::TILE_SIZE - 2.);
      let mut lower_vec =
        Vec2::new(1., lower_angle.tan()).normalize() * (constants::TILE_SIZE - 2.);
      // TODO: surely I could simplify this with better math
      if hyp.x < 0. && hyp.y >= 0. {
        upper_vec = upper_vec * -1.;
        lower_vec = lower_vec * -1.;
      } else if hyp.y < 0. && hyp.x > 0. {
        upper_vec.y = upper_vec.y * -1.;
        lower_vec.y = lower_vec.y * -1.;
      } else if hyp.y < 0. && hyp.x < 0. {
        upper_vec.x = upper_vec.x * -1.;
        lower_vec.x = lower_vec.x * -1.;
      } else if hyp.y < 0. && hyp.x == 0. {
        lower_vec = lower_vec * -1.;
      } else if hyp.x == 0. && hyp.y > 0. {
        upper_vec = upper_vec * -1.;
      }
      let upper_ch_end = end_point - upper_vec;
      let lower_ch_end = end_point - lower_vec;
      let arrow_line = shapes::Line(start_point, end_point);
      let upper_chevron = shapes::Line(end_point, upper_ch_end);
      let lower_chevron = shapes::Line(end_point, lower_ch_end);
      let mut transform: Transform = Default::default();
      transform.translation.z = constants::MAP_INDICATOR_Z_LEVEL;
      // The arrow indicators are their own entities, rather than being attached to players,
      // because they have some duplicate components with the player's sprites.
      commands
        .spawn_bundle(
          GeometryBuilder::new()
            .add(&arrow_line)
            .add(&upper_chevron)
            .add(&lower_chevron)
            .build(
              DrawMode::Stroke(StrokeMode::new(
                if is_moving {
                  constants::MOVE_INDICATION_ARROW_COLOR
                } else {
                  constants::ATTACK_INDICATION_ARROW_COLOR
                },
                3.,
              )),
              transform,
            ),
        )
        .insert(ActionIndicationMarker)
        .insert(start.clone());
    });
}
pub fn draw_action_arrows ( mut commands : Commands , pending : Query < ( & TilePos , & EntityPendingAction ) , ( Changed < EntityPendingAction > , With < PlayerStatus > ) , > , active_turn : Query < & TurnDisplayer > , ) { // Don't want to draw arrows while a turn is being animated if ! active_turn . is_empty ( ) { return ; } pending . iter ( ) . filter_map ( | ( center , action ) | match ( action . is_ready , action . action . to_owned ( ) ) { ( true , EntityAction :: Move ( ( a , b ) ) ) => Some ( ( true , a , b ) ) , ( true , EntityAction :: Attack ( PendingAttack { enemy_position : target , .. } ) , ) => Some ( ( false , center . to_owned ( ) , target ) ) , _ => None , } , ) . for_each ( | ( is_moving , start , end ) | { // a new pending action has been added, but the turn is not yet animating // so, let's draw an arrow to show the intended action let start_point = utils :: initial_map_drawing_position ( & TileSize ( constants :: TILE_SIZE , constants :: TILE_SIZE ) , & start , 0. , ) . truncate ( ) ; let end_point = utils :: initial_map_drawing_position ( & TileSize ( constants :: TILE_SIZE , constants :: TILE_SIZE ) , & end , 0. , ) . truncate ( ) ; // We create an arrow by finding the angle of the action vector, and the drawing to smaller lines // with slightly offset angles from the end of the vector. let hyp = end_point - start_point ; if hyp . x == 0. && hyp . y == 0. { return ; } let angle = hyp . angle_between ( Vec2 :: X ) . abs ( ) ; let upper_angle = angle + 0.4 ; let lower_angle = angle - 0.4 ; let mut upper_vec = Vec2 :: new ( 1. , upper_angle . tan ( ) ) . normalize ( ) * ( constants :: TILE_SIZE - 2. ) ; let mut lower_vec = Vec2 :: new ( 1. , lower_angle . tan ( ) ) . normalize ( ) * ( constants :: TILE_SIZE - 2. ) ; // TODO: surely I could simplify this with better math if hyp . x < 0. && hyp . y >= 0. { upper_vec = upper_vec * - 1. ; lower_vec = lower_vec * - 1. ; } else if hyp . y < 0. && hyp . x > 0. { upper_vec . y = upper_vec . y * - 1. ; lower_vec . y = lower_vec . y * - 1. ; } else if hyp . y < 0. && hyp . x < 0. { upper_vec . x = upper_vec . x * - 1. ; lower_vec . x = lower_vec . x * - 1. ; } else if hyp . y < 0. && hyp . x == 0. { lower_vec = lower_vec * - 1. ; } else if hyp . x == 0. && hyp . y > 0. { upper_vec = upper_vec * - 1. ; } let upper_ch_end = end_point - upper_vec ; let lower_ch_end = end_point - lower_vec ; let arrow_line = shapes :: Line ( start_point , end_point ) ; let upper_chevron = shapes :: Line ( end_point , upper_ch_end ) ; let lower_chevron = shapes :: Line ( end_point , lower_ch_end ) ; let mut transform : Transform = Default :: default ( ) ; transform . translation . z = constants :: MAP_INDICATOR_Z_LEVEL ; // The arrow indicators are their own entities, rather than being attached to players, // because they have some duplicate components with the player's sprites. commands . spawn_bundle ( GeometryBuilder :: new ( ) . add ( & arrow_line ) . add ( & upper_chevron ) . add ( & lower_chevron ) . build ( DrawMode :: Stroke ( StrokeMode :: new ( if is_moving { constants :: MOVE_INDICATION_ARROW_COLOR } else { constants :: ATTACK_INDICATION_ARROW_COLOR } , 3. , ) ) , transform , ) , ) . insert ( ActionIndicationMarker ) . insert ( start . clone ( ) ) ; } ) ; }
Inserts action arrows for pending player actions.
Inserts action arrows for pending player actions .
commands
Commands
pending
Query<
    (&TilePos, &EntityPendingAction),
    (Changed<EntityPendingAction>, With<PlayerStatus>),
  >
active_turn
Query<&TurnDisplayer>
commands
Commands
pending
Query<
    (&TilePos, &EntityPendingAction),
    (Changed<EntityPendingAction>, With<PlayerStatus>),
  >
active_turn
Query<&TurnDisplayer>