Pārlūkot izejas kodu

Refactored ship system and fixed small bug in fleet info calculation

master
Bergmann89 pirms 4 gadiem
vecāks
revīzija
0119fdaf0b
5 mainītis faili ar 213 papildinājumiem un 142 dzēšanām
  1. +4
    -4
      space-crush-app/src/systems/fleet_info_update.rs
  2. +2
    -2
      space-crush-common/src/dispatcher.rs
  3. +0
    -134
      space-crush-common/src/systems/fleets.rs
  4. +2
    -2
      space-crush-common/src/systems/mod.rs
  5. +205
    -0
      space-crush-common/src/systems/ships.rs

+ 4
- 4
space-crush-app/src/systems/fleet_info_update.rs Parādīt failu

@@ -142,15 +142,15 @@ impl<'a> System<'a> for FleetInfoUpdate {
None => false,
Some(modified) => match (modified.old_fleet_id, modified.old_player_id) {
(Some(old_fleet_id), Some(old_player_id)) => {
old_fleet_id != fleet_id && old_player_id == player_id
old_fleet_id == fleet_id && old_player_id == player_id
}
(Some(old_fleet_id), None) => {
old_fleet_id != fleet_id && player_owned.owner == player_id
old_fleet_id == fleet_id && player_owned.owner == player_id
}
(None, Some(old_player_id)) => {
fleet_owned.owner != fleet_id && old_player_id == player_id
fleet_owned.owner == fleet_id && old_player_id == player_id
}
(None, None) => false,
(None, None) => unreachable!(),
},
};



+ 2
- 2
space-crush-common/src/dispatcher.rs Parādīt failu

@@ -3,7 +3,7 @@ use specs::{Dispatcher as Inner, DispatcherBuilder, World, WorldExt};
use crate::{
components::Player,
resources::Global,
systems::{Fleets, Movement, Process},
systems::{Movement, Process, Ships},
};

pub struct Dispatcher<'a, 'b> {
@@ -19,7 +19,7 @@ impl<'a, 'b> Dispatcher<'a, 'b> {
let mut dispatcher = DispatcherBuilder::new()
.with(Process::default(), "process", &[])
.with(Movement::default(), "movement", &[])
.with(Fleets::default(), "fleets", &[])
.with(Ships::new(world), "ships", &[])
.build();
dispatcher.setup(world);



+ 0
- 134
space-crush-common/src/systems/fleets.rs Parādīt failu

@@ -1,134 +0,0 @@
use glc::{
math::{linear_step, sqr},
matrix::Matrix3f,
vector::{Vector2f, Vector3f},
};
use rand::random;
use specs::{prelude::*, ParJoin, Read, ReadStorage, System, WriteStorage};

use crate::{
components::{Fleet, FleetOwned, Position, Ship, Velocity},
constants::{
SHIP_ORBIT_AGILITY, SHIP_ORBIT_ANGLE_DELTA_MIN, SHIP_ORBIT_ANGLE_DELTA_RND,
SHIP_ORBIT_DISTANCE_MAX, VECTOR_2F_POS_X,
},
resources::Global,
};

#[derive(Default)]
pub struct Fleets;

#[derive(SystemData)]
pub struct FleetsData<'a> {
ship: WriteStorage<'a, Ship>,
velocity: WriteStorage<'a, Velocity>,
fleet_owned: ReadStorage<'a, FleetOwned>,
position: ReadStorage<'a, Position>,
fleet: ReadStorage<'a, Fleet>,
global: Read<'a, Global>,
}

impl<'a> System<'a> for Fleets {
type SystemData = FleetsData<'a>;

fn run(&mut self, data: Self::SystemData) {
let FleetsData {
mut ship,
mut velocity,
fleet_owned,
position,
fleet,
global,
} = data;

(&mut ship, &mut velocity, &fleet_owned, &position)
.par_join()
.for_each(|(ship, vel, fleet_owned, pos)| {
progress_ship(
&position,
&fleet,
ship,
vel,
fleet_owned.owner,
pos,
global.delta,
)
});
}
}

fn progress_ship<'a>(
positions: &ReadStorage<'a, Position>,
fleets: &ReadStorage<'a, Fleet>,
ship: &mut Ship,
velocity: &mut Velocity,
fleet_id: Entity,
position: &Position,
delta: f32,
) {
let (orbit_pos, orbit_min, orbit_max): (Vector2f, f32, f32) =
match (positions.get(fleet_id), fleets.get(fleet_id)) {
(Some(position), Some(fleet)) => (position.pos, fleet.orbit_min, fleet.orbit_max),
(_, _) => return,
};

let orbit_to_target = ship.target_pos - orbit_pos;
let orbit_to_ship = position.pos - orbit_pos;
let ship_to_target = ship.target_pos - position.pos;

let target_radius = orbit_to_target.length_sqr();
let ship_radius = orbit_to_ship.length_sqr();

let target_in_orbit = (target_radius <= sqr(orbit_max)) && (target_radius >= sqr(orbit_min));
let ship_in_orbit = ship_radius < sqr(SHIP_ORBIT_DISTANCE_MAX * orbit_max);

/* check and update target posistion */
if ship.target_dir.length_sqr() == 0.0
|| ship_in_orbit != target_in_orbit
|| ship.target_dir * ship_to_target <= 0.0
{
if ship_in_orbit && orbit_max > 0.0 {
let orbit_to_ship_vec3 = Vector3f::new(orbit_to_ship.x, orbit_to_ship.y, 0.0);
let ship_dir_vec3 = Vector3f::new(velocity.dir.x, velocity.dir.y, 0.0);

let dir = if orbit_to_ship_vec3.cross(&ship_dir_vec3).z > 0.0 {
1.0
} else {
-1.0
};

let angle = orbit_to_ship.angle2(&VECTOR_2F_POS_X);
let angle = angle
+ (SHIP_ORBIT_ANGLE_DELTA_MIN + SHIP_ORBIT_ANGLE_DELTA_RND * random()) * dir
/ orbit_max;
let radius = orbit_min + (orbit_max - orbit_min) * random::<f32>();

ship.target_pos.x = orbit_pos.x + radius * angle.cos();
ship.target_pos.y = orbit_pos.y + radius * angle.sin();
} else {
ship.target_pos = orbit_pos;
}
ship.target_dir = (ship.target_pos - position.pos).normalize();
}

/* update ship direction */
let angle = ship_to_target.angle2(&velocity.dir);
if angle.into_inner().abs() > 0.0001 {
let dir = angle.into_inner() / angle.abs().into_inner();
let agility = if ship_in_orbit {
SHIP_ORBIT_AGILITY
} else {
ship.agility
};
let rot_speed = agility * linear_step(0.0, 45.0, angle.abs().into_deg().into_inner());

let m = Matrix3f::new(
Vector3f::new(velocity.dir.y, -velocity.dir.x, 0.0),
Vector3f::new(velocity.dir.x, velocity.dir.y, 0.0),
Vector3f::new(0.0, 0.0, 1.0),
);
let m = m * Matrix3f::rotate(rot_speed * -dir * delta);

velocity.dir = Vector2f::new(m.axis_y.x, m.axis_y.y);
}
}

+ 2
- 2
space-crush-common/src/systems/mod.rs Parādīt failu

@@ -1,7 +1,7 @@
mod fleets;
mod movement;
mod process;
mod ships;

pub use fleets::Fleets;
pub use movement::Movement;
pub use process::Process;
pub use ships::Ships;

+ 205
- 0
space-crush-common/src/systems/ships.rs Parādīt failu

@@ -0,0 +1,205 @@
use glc::{
math::{linear_step, sqr},
matrix::Matrix3f,
vector::{Vector2f, Vector3f},
};
use rand::random;
use shrev::ReaderId;
use specs::{
hibitset::BitSet, prelude::*, Entities, ParJoin, Read, ReadStorage, System, WriteStorage,
};

use crate::{
components::{Fleet, FleetOwned, Position, Ship, Velocity},
constants::{
SHIP_ORBIT_AGILITY, SHIP_ORBIT_ANGLE_DELTA_MIN, SHIP_ORBIT_ANGLE_DELTA_RND,
SHIP_ORBIT_DISTANCE_MAX, VECTOR_2F_POS_X,
},
misc::ComponentEvent,
resources::Global,
return_if_none,
};

pub struct Ships {
need_update: BitSet,
fleet_owned_id: ReaderId<ComponentEvent<FleetOwned>>,
}

#[derive(SystemData)]
pub struct ShipsData<'a> {
global: Read<'a, Global>,
entities: Entities<'a>,
ships: WriteStorage<'a, Ship>,
velocities: WriteStorage<'a, Velocity>,
fleet_owned: ReadStorage<'a, FleetOwned>,
positions: ReadStorage<'a, Position>,
fleets: ReadStorage<'a, Fleet>,
}

struct Processor<'a> {
need_update: &'a BitSet,
positions: &'a ReadStorage<'a, Position>,
fleets: &'a ReadStorage<'a, Fleet>,
delta: f32,
}

impl Ships {
pub fn new(world: &mut World) -> Self {
let need_update = BitSet::new();
let fleet_owned_id = unsafe {
WriteStorage::<FleetOwned>::setup(world);

let mut fleet_owned = world.system_data::<WriteStorage<FleetOwned>>();
fleet_owned
.unprotected_storage_mut()
.channel_mut()
.register_reader()
};

Self {
need_update,
fleet_owned_id,
}
}

fn progress_events(&mut self, fleet_owned: &ReadStorage<'_, FleetOwned>) {
self.need_update.clear();
let events = fleet_owned
.unprotected_storage()
.channel()
.read(&mut self.fleet_owned_id);
for event in events {
let id = match event {
ComponentEvent::Inserted(id) => id,
ComponentEvent::Modified(id, _) => id,
ComponentEvent::Removed(id, _) => id,
};

self.need_update.add(*id);
}
}
}

impl<'a> System<'a> for Ships {
type SystemData = ShipsData<'a>;

fn run(&mut self, data: Self::SystemData) {
let ShipsData {
global,
entities,
mut ships,
mut velocities,
fleet_owned,
positions,
fleets,
} = data;

self.progress_events(&fleet_owned);

/* update ships */
let processor = Processor {
need_update: &self.need_update,
positions: &positions,
fleets: &fleets,
delta: global.delta,
};
(
&entities,
&mut ships,
&mut velocities,
&positions,
&fleet_owned,
)
.par_join()
.for_each(|(entity, ship, velocity, position, fleet_owned)| {
processor.progress_ship(entity, ship, velocity, position, fleet_owned);
});
}
}

impl Processor<'_> {
fn progress_ship(
&self,
entity: Entity,
ship: &mut Ship,
velocity: &mut Velocity,
position: &Position,
fleet_owned: &FleetOwned,
) {
let fleet_id = fleet_owned.owner;
let fleet = return_if_none!(self.fleets.get(fleet_id));
let orbit_pos = return_if_none!(self.positions.get(fleet_id)).pos;
let ship_pos = position.pos;
let target_pos = ship.target_pos;
let target_dir = ship.target_dir;

let orbit_to_target = target_pos - orbit_pos;
let orbit_to_ship = position.pos - orbit_pos;
let ship_to_target = target_pos - position.pos;

let r_ship = orbit_to_ship.length_sqr();
let r_target = orbit_to_target.length_sqr();

let orbit_min = fleet.orbit_min;
let orbit_max = fleet.orbit_max;

let target_in_orbit = (r_target <= sqr(fleet.orbit_max)) && (r_target >= sqr(orbit_min));
let ship_in_orbit = r_ship < sqr(SHIP_ORBIT_DISTANCE_MAX * orbit_max);

let need_update = self.need_update.contains(entity.id());
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 need_update || !has_target || passed_target || ship_in_orbit != target_in_orbit {
let target_pos = if ship_in_orbit && fleet.orbit_max > 0.0 {
let orbit_to_ship_vec3 = Vector3f::new(orbit_to_ship.x, orbit_to_ship.y, 0.0);
let ship_dir_vec3 = Vector3f::new(velocity.dir.x, velocity.dir.y, 0.0);

let dir = if orbit_to_ship_vec3.cross(&ship_dir_vec3).z > 0.0 {
1.0
} else {
-1.0
};

let angle = orbit_to_ship.angle2(&VECTOR_2F_POS_X);
let angle = angle
+ (SHIP_ORBIT_ANGLE_DELTA_MIN + SHIP_ORBIT_ANGLE_DELTA_RND * random()) * dir
/ fleet.orbit_max;
let radius =
fleet.orbit_min + (fleet.orbit_max - fleet.orbit_min) * random::<f32>();

Vector2f::new(
orbit_pos.x + radius * angle.cos(),
orbit_pos.y + radius * angle.sin(),
)
} else {
orbit_pos
};

ship.target_pos = target_pos;
ship.target_dir = (target_pos - ship_pos).normalize();
}

/* update ship direction */
let angle = ship_to_target.angle2(&velocity.dir);
if angle.into_inner().abs() > 0.0001 {
let dir = angle.into_inner() / angle.abs().into_inner();
let agility = if ship_in_orbit {
SHIP_ORBIT_AGILITY
} else {
ship.agility
};
let rot_speed = agility * linear_step(0.0, 45.0, angle.abs().into_deg().into_inner());

let m = Matrix3f::new(
Vector3f::new(velocity.dir.y, -velocity.dir.x, 0.0),
Vector3f::new(velocity.dir.x, velocity.dir.y, 0.0),
Vector3f::new(0.0, 0.0, 1.0),
);
let m = m * Matrix3f::rotate(rot_speed * -dir * self.delta);

velocity.dir = Vector2f::new(m.axis_y.x, m.axis_y.y);
}
}
}

Notiek ielāde…
Atcelt
Saglabāt