|
- use glc::{
- math::linear_step,
- matrix::Matrix3f,
- vector::{Vector2f, Vector3f},
- };
- use rand::random;
- use specs::{prelude::*, ParJoin, Read, ReadStorage, System, WriteStorage};
-
- use crate::{
- components::{FleetOrbiting, FleetOwned, MeetingPoint, Position, Ship, ShipOrbiting},
- constants::{SHIP_DATA_IN_ORBIT, SHIP_ORBIT_ANGLE_DELTA_MIN, SHIP_ORBIT_ANGLE_DELTA_RND},
- misc::StorageHelperMut,
- resources::Global,
- };
-
- #[derive(Default)]
- pub struct ShipsOrbiting;
-
- #[derive(SystemData)]
- pub struct ShipsData<'a> {
- global: Read<'a, Global>,
- positions: ReadStorage<'a, Position>,
- fleet_owned: ReadStorage<'a, FleetOwned>,
- ships: WriteStorage<'a, Ship>,
- ships_orbiting: WriteStorage<'a, ShipOrbiting>,
- fleets_orbiting: ReadStorage<'a, FleetOrbiting>,
- meeting_points: ReadStorage<'a, MeetingPoint>,
- }
-
- struct Processor<'a> {
- delta: f32,
- positions: &'a ReadStorage<'a, Position>,
- meeting_points: &'a ReadStorage<'a, MeetingPoint>,
- fleets_orbiting: &'a ReadStorage<'a, FleetOrbiting>,
- }
-
- impl<'a> System<'a> for ShipsOrbiting {
- type SystemData = ShipsData<'a>;
-
- fn run(&mut self, data: Self::SystemData) {
- let ShipsData {
- global,
- positions,
- fleet_owned,
- mut ships,
- mut ships_orbiting,
- fleets_orbiting,
- meeting_points,
- } = data;
-
- /* update ships */
- let processor = Processor {
- delta: global.delta * global.world_speed,
- positions: &positions,
- fleets_orbiting: &fleets_orbiting,
- meeting_points: &meeting_points,
- };
-
- ships.set_event_emission(false);
-
- let data = (&positions, &fleet_owned, &mut ships, &mut ships_orbiting);
-
- data.par_join()
- .for_each(|(position, fleet_owned, ship, ship_orbiting)| {
- processor.progress_ship(position, fleet_owned, ship, ship_orbiting);
- });
-
- ships.set_event_emission(true);
- }
- }
-
- impl Processor<'_> {
- fn progress_ship(
- &self,
- position: &Position,
- fleet_owned: &FleetOwned,
- ship: &mut Ship,
- ship_orbiting: &mut ShipOrbiting,
- ) {
- let fleet_id = fleet_owned.owner();
- let fleet_orbiting = self.fleets_orbiting.get(fleet_id).unwrap();
- let meeting_point_id = fleet_orbiting.meeting_point();
- let meeting_point = self.meeting_points.get(meeting_point_id).unwrap();
- let meeting_point_pos = self.positions.get(meeting_point_id).unwrap().get();
- let ship_pos = position.get();
- let target_pos = *ship_orbiting.target_pos();
- let target_dir = ship_orbiting.target_dir();
-
- let meeting_point_to_ship = ship_pos - meeting_point_pos;
- let mut ship_to_target = target_pos - ship_pos;
-
- let has_target = target_dir.length_sqr() != 0.0;
- let passed_target = target_dir * ship_to_target <= 0.0;
-
- /* check and update target posistion */
- if !has_target || passed_target {
- let meeting_point_to_ship_vec3 =
- Vector3f::new(meeting_point_to_ship.x, meeting_point_to_ship.y, 0.0);
- let ship_dir_vec3 = ship.dir().into_vec3();
-
- let dir = if meeting_point_to_ship_vec3.cross(&ship_dir_vec3).z > 0.0 {
- 1.0
- } else {
- -1.0
- };
-
- let meeting_point_min = meeting_point.min();
- let meeting_point_max = meeting_point.max();
-
- const VECTOR2F_POS_X: Vector2f = Vector2f::new(1.0, 0.0);
-
- let add = SHIP_ORBIT_ANGLE_DELTA_MIN + SHIP_ORBIT_ANGLE_DELTA_RND * random::<f32>();
- let angle =
- meeting_point_to_ship.angle2(&VECTOR2F_POS_X) + (add * dir / meeting_point_max);
- let radius =
- meeting_point_min + (meeting_point_max - meeting_point_min) * random::<f32>();
-
- let target_pos = Vector2f::new(
- meeting_point_pos.x + radius * angle.cos(),
- meeting_point_pos.y + radius * angle.sin(),
- );
- ship_to_target = target_pos - ship_pos;
- let target_dir = ship_to_target.normalize();
-
- ship_orbiting.set_target(target_pos, target_dir);
- }
-
- /* update ship direction */
- let angle = ship_to_target.angle2(ship.dir());
- if angle.into_inner().abs() > 0.0001 {
- let dir = angle.into_inner() / angle.abs().into_inner();
- let agility = SHIP_DATA_IN_ORBIT.agility;
- let rot_speed = agility * linear_step(0.0, 45.0, angle.abs().into_deg().into_inner());
-
- *ship.dir_mut() *= Matrix3f::rotate(rot_speed * -dir * self.delta);
- }
- }
- }
|