| @@ -1,3 +1,6 @@ | |||||
| x -> needed | |||||
| o -> optional | |||||
| ___________________________________________________________ | ___________________________________________________________ | ||||
| WorldPersistence________________________________________ \ | WorldPersistence________________________________________ \ | ||||
| Planet_______________________________________________ \ \ | Planet_______________________________________________ \ \ | ||||
| @@ -19,7 +22,7 @@ Player______________ \ \ \ \ \ \ \ \ \ \ \ \ \ | |||||
| | Player | x | | | | | | | | | | | | x | | | Player | x | | | | | | | | | | | | x | | ||||
| | Ship | | x | x | x | x | | | | | | | | x | | | Ship | | x | x | x | x | | | | | | | | x | | ||||
| | Fleet | | | | | | x | x | | | | | | x | | | Fleet | | | | | | x | x | | | | | | x | | ||||
| | Asteroid | | x | x | | | | | x | x | x | x | | x | | |||||
| | Planet | | x | x | | | | | x | x | x | | x | x | | |||||
| | Asteroid | | o | x | | | | | x | x | x | x | | x | | |||||
| | Planet | | o | x | | | | | x | x | x | | x | x | | |||||
| | MeetingPoint | | | x | | | | | | | x | | | x | | | MeetingPoint | | | x | | | | | | | x | | | x | | ||||
| +--------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+ | +--------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+ | ||||
| @@ -1,6 +1,6 @@ | |||||
| use glc::vector::Vector4f; | use glc::vector::Vector4f; | ||||
| use space_crush_common::{ | use space_crush_common::{ | ||||
| components::{Position, Ship, ShipObstacle}, | |||||
| components::{Player, PlayerOwned, Position, Ship, ShipObstacle}, | |||||
| continue_if_none, | continue_if_none, | ||||
| }; | }; | ||||
| use specs::{prelude::*, ReadStorage, System, World, WriteExpect}; | use specs::{prelude::*, ReadStorage, System, World, WriteExpect}; | ||||
| @@ -14,6 +14,8 @@ pub struct Ships; | |||||
| pub struct ShipsData<'a> { | pub struct ShipsData<'a> { | ||||
| geometry: WriteExpect<'a, Geometry>, | geometry: WriteExpect<'a, Geometry>, | ||||
| positions: ReadStorage<'a, Position>, | positions: ReadStorage<'a, Position>, | ||||
| player_owned: ReadStorage<'a, PlayerOwned>, | |||||
| players: ReadStorage<'a, Player>, | |||||
| ships: ReadStorage<'a, Ship>, | ships: ReadStorage<'a, Ship>, | ||||
| } | } | ||||
| @@ -24,18 +26,24 @@ impl<'a> System<'a> for Ships { | |||||
| let ShipsData { | let ShipsData { | ||||
| mut geometry, | mut geometry, | ||||
| positions, | positions, | ||||
| player_owned, | |||||
| players, | |||||
| ships, | ships, | ||||
| } = data; | } = data; | ||||
| gl::enable(gl::BLEND); | gl::enable(gl::BLEND); | ||||
| gl::blend_func(gl::SRC_ALPHA, gl::ONE); | gl::blend_func(gl::SRC_ALPHA, gl::ONE); | ||||
| for (position, ship) in (&positions, &ships).join() { | |||||
| for (position, player_owned, ship) in (&positions, &player_owned, &ships).join() { | |||||
| let ship_pos = position.get(); | let ship_pos = position.get(); | ||||
| let type_ = ship.type_(); | |||||
| let player_id = player_owned.owner(); | |||||
| let player = continue_if_none!(players.get(player_id)); | |||||
| let ship_data = player.ship_data(type_); | |||||
| geometry.render_lines( | geometry.render_lines( | ||||
| Vector4f::new(0.0, 0.0, 1.0, 0.2), | Vector4f::new(0.0, 0.0, 1.0, 0.2), | ||||
| &[*ship_pos, ship_pos + ship.dir() * ship.speed()], | |||||
| &[*ship_pos, ship_pos + ship.dir() * ship_data.speed], | |||||
| ); | ); | ||||
| geometry.render_lines( | geometry.render_lines( | ||||
| Vector4f::new(1.0, 0.0, 0.0, 0.2), | Vector4f::new(1.0, 0.0, 0.0, 0.2), | ||||
| @@ -19,7 +19,7 @@ pub struct AsteroidBuilder { | |||||
| } | } | ||||
| impl AsteroidBuilder { | impl AsteroidBuilder { | ||||
| pub fn build(self, world: &mut World) -> Result<Entity, Error> { | |||||
| pub fn build(&self, world: &mut World) -> Result<Entity, Error> { | |||||
| let type_ = self.type_.ok_or(Error::MissingValue("type"))?; | let type_ = self.type_.ok_or(Error::MissingValue("type"))?; | ||||
| let position = self.position.ok_or(Error::MissingValue("position"))?; | let position = self.position.ok_or(Error::MissingValue("position"))?; | ||||
| let size = self.size.ok_or(Error::MissingValue("size"))?; | let size = self.size.ok_or(Error::MissingValue("size"))?; | ||||
| @@ -13,7 +13,7 @@ pub struct FleetBuilder { | |||||
| } | } | ||||
| impl FleetBuilder { | impl FleetBuilder { | ||||
| pub fn build(self, world: &mut World) -> Result<Entity, Error> { | |||||
| pub fn build(&self, world: &mut World) -> Result<Entity, Error> { | |||||
| let owner = self.owner.ok_or(Error::MissingValue("owner"))?; | let owner = self.owner.ok_or(Error::MissingValue("owner"))?; | ||||
| let meeting_point_owned = MeetingPointOwned::new(owner); | let meeting_point_owned = MeetingPointOwned::new(owner); | ||||
| @@ -18,7 +18,7 @@ pub struct PlanetBuilder { | |||||
| } | } | ||||
| impl PlanetBuilder { | impl PlanetBuilder { | ||||
| pub fn build(self, world: &mut World) -> Result<Entity, Error> { | |||||
| pub fn build(&self, world: &mut World) -> Result<Entity, Error> { | |||||
| let position = self.position.ok_or(Error::MissingValue("position"))?; | let position = self.position.ok_or(Error::MissingValue("position"))?; | ||||
| let size = self.size.ok_or(Error::MissingValue("size"))?; | let size = self.size.ok_or(Error::MissingValue("size"))?; | ||||
| let (orbit_min, orbit_max) = self.orbit.ok_or(Error::MissingValue("orbit"))?; | let (orbit_min, orbit_max) = self.orbit.ok_or(Error::MissingValue("orbit"))?; | ||||
| @@ -3,22 +3,26 @@ use specs::{saveload::MarkedBuilder, Builder, Entity, World, WorldExt}; | |||||
| use glc::vector::Vector3f; | use glc::vector::Vector3f; | ||||
| use crate::{ | use crate::{ | ||||
| components::Player, | |||||
| components::{Player, Race}, | |||||
| misc::{Persistence, WorldPersistence}, | misc::{Persistence, WorldPersistence}, | ||||
| }; | }; | ||||
| use super::Error; | use super::Error; | ||||
| #[derive(Default, Clone)] | |||||
| #[derive(Clone)] | |||||
| pub struct PlayerBuilder { | pub struct PlayerBuilder { | ||||
| index: usize, | |||||
| race: Race, | |||||
| color: Option<Vector3f>, | color: Option<Vector3f>, | ||||
| } | } | ||||
| impl PlayerBuilder { | impl PlayerBuilder { | ||||
| pub fn build(self, world: &mut World) -> Result<Entity, Error> { | |||||
| let color = self.color.ok_or(Error::MissingValue("color"))?; | |||||
| pub fn build(&mut self, world: &mut World) -> Result<Entity, Error> { | |||||
| let index = self.index; | |||||
| let race = self.race; | |||||
| let color = self.color.take().ok_or(Error::MissingValue("color"))?; | |||||
| let player = Player::new(color); | |||||
| let player = Player::new(index, race, color); | |||||
| let entity = world | let entity = world | ||||
| .create_entity() | .create_entity() | ||||
| @@ -26,6 +30,8 @@ impl PlayerBuilder { | |||||
| .with(player) | .with(player) | ||||
| .build(); | .build(); | ||||
| self.index += 1; | |||||
| Ok(entity) | Ok(entity) | ||||
| } | } | ||||
| @@ -35,3 +41,13 @@ impl PlayerBuilder { | |||||
| self | self | ||||
| } | } | ||||
| } | } | ||||
| impl Default for PlayerBuilder { | |||||
| fn default() -> Self { | |||||
| Self { | |||||
| index: 0, | |||||
| race: Race::Fighter, | |||||
| color: None, | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -19,18 +19,17 @@ pub struct ShipBuilder { | |||||
| } | } | ||||
| impl ShipBuilder { | impl ShipBuilder { | ||||
| pub fn build(self, world: &mut World) -> Result<Entity, Error> { | |||||
| pub fn build(&self, world: &mut World) -> Result<Entity, Error> { | |||||
| let player = self.player.ok_or(Error::MissingValue("player"))?; | let player = self.player.ok_or(Error::MissingValue("player"))?; | ||||
| let fleet = self.fleet.ok_or(Error::MissingValue("fleet"))?; | let fleet = self.fleet.ok_or(Error::MissingValue("fleet"))?; | ||||
| let position = self.position.ok_or(Error::MissingValue("position"))?; | let position = self.position.ok_or(Error::MissingValue("position"))?; | ||||
| let type_ = self.type_.ok_or(Error::MissingValue("type"))?; | let type_ = self.type_.ok_or(Error::MissingValue("type"))?; | ||||
| let direction = self.direction; | let direction = self.direction; | ||||
| let speed = 100.0; | |||||
| let player_owned = PlayerOwned::new(player); | let player_owned = PlayerOwned::new(player); | ||||
| let fleet_owned = FleetOwned::new(fleet); | let fleet_owned = FleetOwned::new(fleet); | ||||
| let position = Position::new(position); | let position = Position::new(position); | ||||
| let ship = Ship::new(type_, direction, speed); | |||||
| let ship = Ship::new(type_, direction); | |||||
| let entity = world | let entity = world | ||||
| .create_entity() | .create_entity() | ||||
| @@ -13,7 +13,7 @@ pub use fleet::{Fleet, FleetOwned}; | |||||
| pub use meeting_point::{MeetingPoint, MeetingPointOwned}; | pub use meeting_point::{MeetingPoint, MeetingPointOwned}; | ||||
| pub use obstacle::Obstacle; | pub use obstacle::Obstacle; | ||||
| pub use planet::Planet; | pub use planet::Planet; | ||||
| pub use player::{Player, PlayerOwned}; | |||||
| pub use player::{Player, PlayerOwned, Race}; | |||||
| pub use position::Position; | pub use position::Position; | ||||
| pub use shape::Shape; | pub use shape::Shape; | ||||
| pub use ship::{Count as ShipCount, Obstacle as ShipObstacle, Ship, Type as ShipType}; | |||||
| pub use ship::{Ship, ShipCount, ShipData, ShipObstacle, ShipType, ShipsData}; | |||||
| @@ -6,12 +6,27 @@ use specs::{ | |||||
| Component, Entity, HashMapStorage, | Component, Entity, HashMapStorage, | ||||
| }; | }; | ||||
| use crate::builder::PlayerBuilder; | |||||
| use crate::{ | |||||
| builder::PlayerBuilder, | |||||
| components::{ShipData, ShipType, ShipsData}, | |||||
| constants::{SHIPS_DATA_FIGHTER, SHIPS_DATA_RESEARCHER, SHIPS_DATA_TRADER}, | |||||
| }; | |||||
| #[derive(Clone, Debug, Default, Serialize, Deserialize)] | |||||
| #[derive(Clone, Debug, Serialize, Deserialize)] | |||||
| pub struct Player { | pub struct Player { | ||||
| index: usize, | index: usize, | ||||
| race: Race, | |||||
| color: Vector3f, | color: Vector3f, | ||||
| #[serde(skip)] | |||||
| ships_data: ShipsData, | |||||
| } | |||||
| #[derive(Copy, Clone, Debug, Serialize, Deserialize)] | |||||
| pub enum Race { | |||||
| Fighter, | |||||
| Trader, | |||||
| Researcher, | |||||
| } | } | ||||
| #[derive(Copy, Clone, Debug)] | #[derive(Copy, Clone, Debug)] | ||||
| @@ -41,14 +56,25 @@ impl Player { | |||||
| pub fn color(&self) -> &Vector3f { | pub fn color(&self) -> &Vector3f { | ||||
| &self.color | &self.color | ||||
| } | } | ||||
| #[inline] | |||||
| pub fn ship_data(&self, type_: ShipType) -> &ShipData { | |||||
| &self.ships_data[type_] | |||||
| } | |||||
| } | } | ||||
| impl Player { | impl Player { | ||||
| #[inline] | #[inline] | ||||
| pub(crate) fn new(color: Vector3f) -> Self { | |||||
| pub(crate) fn new(index: usize, race: Race, color: Vector3f) -> Self { | |||||
| Self { | Self { | ||||
| index: next_index(), | |||||
| index, | |||||
| race, | |||||
| color, | color, | ||||
| ships_data: match race { | |||||
| Race::Fighter => SHIPS_DATA_FIGHTER, | |||||
| Race::Trader => SHIPS_DATA_TRADER, | |||||
| Race::Researcher => SHIPS_DATA_RESEARCHER, | |||||
| }, | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -100,11 +126,3 @@ where | |||||
| Ok(PlayerOwned { owner }) | Ok(PlayerOwned { owner }) | ||||
| } | } | ||||
| } | } | ||||
| fn next_index() -> usize { | |||||
| use std::sync::atomic::{AtomicUsize, Ordering}; | |||||
| static NEXT_INDEX: AtomicUsize = AtomicUsize::new(0); | |||||
| NEXT_INDEX.fetch_add(1, Ordering::Relaxed) | |||||
| } | |||||
| @@ -9,12 +9,11 @@ use crate::{builder::ShipBuilder, misc::FlaggedStorage}; | |||||
| #[derive(Clone, Debug, Serialize, Deserialize)] | #[derive(Clone, Debug, Serialize, Deserialize)] | ||||
| pub struct Ship { | pub struct Ship { | ||||
| type_: Type, | |||||
| type_: ShipType, | |||||
| dir: Vector2f, | dir: Vector2f, | ||||
| speed: f32, | |||||
| #[serde(skip)] | #[serde(skip)] | ||||
| obstacle: Obstacle, | |||||
| obstacle: ShipObstacle, | |||||
| #[serde(skip)] | #[serde(skip)] | ||||
| target_pos: Vector2f, | target_pos: Vector2f, | ||||
| @@ -24,21 +23,33 @@ pub struct Ship { | |||||
| } | } | ||||
| #[derive(Copy, Clone, Debug, PartialEq, Eq)] | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||||
| pub enum Obstacle { | |||||
| pub enum ShipObstacle { | |||||
| Known(Entity), | Known(Entity), | ||||
| Search, | Search, | ||||
| Done, | Done, | ||||
| } | } | ||||
| #[derive(Copy, Clone, Debug, Default)] | #[derive(Copy, Clone, Debug, Default)] | ||||
| pub struct Count { | |||||
| pub struct ShipCount { | |||||
| pub fighter: usize, | pub fighter: usize, | ||||
| pub bomber: usize, | pub bomber: usize, | ||||
| pub transporter: usize, | pub transporter: usize, | ||||
| } | } | ||||
| #[derive(Clone, Default, Debug)] | |||||
| pub struct ShipsData { | |||||
| pub fighter: ShipData, | |||||
| pub bomber: ShipData, | |||||
| pub transporter: ShipData, | |||||
| } | |||||
| #[derive(Clone, Default, Debug)] | |||||
| pub struct ShipData { | |||||
| pub speed: f32, | |||||
| } | |||||
| #[derive(Copy, Clone, Debug, Serialize, Deserialize)] | #[derive(Copy, Clone, Debug, Serialize, Deserialize)] | ||||
| pub enum Type { | |||||
| pub enum ShipType { | |||||
| Fighter, | Fighter, | ||||
| Bomber, | Bomber, | ||||
| Transporter, | Transporter, | ||||
| @@ -53,7 +64,7 @@ impl Ship { | |||||
| } | } | ||||
| #[inline] | #[inline] | ||||
| pub fn type_(&self) -> Type { | |||||
| pub fn type_(&self) -> ShipType { | |||||
| self.type_ | self.type_ | ||||
| } | } | ||||
| @@ -62,11 +73,6 @@ impl Ship { | |||||
| &self.dir | &self.dir | ||||
| } | } | ||||
| #[inline] | |||||
| pub fn speed(&self) -> f32 { | |||||
| self.speed | |||||
| } | |||||
| #[inline] | #[inline] | ||||
| pub fn target_pos(&self) -> &Vector2f { | pub fn target_pos(&self) -> &Vector2f { | ||||
| &self.target_pos | &self.target_pos | ||||
| @@ -78,18 +84,17 @@ impl Ship { | |||||
| } | } | ||||
| #[inline] | #[inline] | ||||
| pub fn obstacle(&self) -> Obstacle { | |||||
| pub fn obstacle(&self) -> ShipObstacle { | |||||
| self.obstacle | self.obstacle | ||||
| } | } | ||||
| } | } | ||||
| impl Ship { | impl Ship { | ||||
| #[inline] | #[inline] | ||||
| pub(crate) fn new(type_: Type, dir: Vector2f, speed: f32) -> Self { | |||||
| pub(crate) fn new(type_: ShipType, dir: Vector2f) -> Self { | |||||
| Self { | Self { | ||||
| type_, | type_, | ||||
| dir, | dir, | ||||
| speed, | |||||
| obstacle: Default::default(), | obstacle: Default::default(), | ||||
| target_pos: Default::default(), | target_pos: Default::default(), | ||||
| target_dir: Default::default(), | target_dir: Default::default(), | ||||
| @@ -108,7 +113,7 @@ impl Ship { | |||||
| } | } | ||||
| #[inline] | #[inline] | ||||
| pub(crate) fn obstacle_mut(&mut self) -> &mut Obstacle { | |||||
| pub(crate) fn obstacle_mut(&mut self) -> &mut ShipObstacle { | |||||
| &mut self.obstacle | &mut self.obstacle | ||||
| } | } | ||||
| } | } | ||||
| @@ -119,7 +124,7 @@ impl Component for Ship { | |||||
| /* Obstacle */ | /* Obstacle */ | ||||
| impl Default for Obstacle { | |||||
| impl Default for ShipObstacle { | |||||
| fn default() -> Self { | fn default() -> Self { | ||||
| Self::Search | Self::Search | ||||
| } | } | ||||
| @@ -127,7 +132,7 @@ impl Default for Obstacle { | |||||
| /* Count */ | /* Count */ | ||||
| impl Count { | |||||
| impl ShipCount { | |||||
| pub fn all() -> Self { | pub fn all() -> Self { | ||||
| Self { | Self { | ||||
| fighter: usize::MAX, | fighter: usize::MAX, | ||||
| @@ -163,7 +168,7 @@ impl Count { | |||||
| } | } | ||||
| } | } | ||||
| impl Index<usize> for Count { | |||||
| impl Index<usize> for ShipCount { | |||||
| type Output = usize; | type Output = usize; | ||||
| fn index(&self, index: usize) -> &Self::Output { | fn index(&self, index: usize) -> &Self::Output { | ||||
| @@ -176,7 +181,7 @@ impl Index<usize> for Count { | |||||
| } | } | ||||
| } | } | ||||
| impl IndexMut<usize> for Count { | |||||
| impl IndexMut<usize> for ShipCount { | |||||
| fn index_mut(&mut self, index: usize) -> &mut Self::Output { | fn index_mut(&mut self, index: usize) -> &mut Self::Output { | ||||
| match index { | match index { | ||||
| 0 => &mut self.fighter, | 0 => &mut self.fighter, | ||||
| @@ -187,30 +192,30 @@ impl IndexMut<usize> for Count { | |||||
| } | } | ||||
| } | } | ||||
| impl Index<Type> for Count { | |||||
| impl Index<ShipType> for ShipCount { | |||||
| type Output = usize; | type Output = usize; | ||||
| fn index(&self, index: Type) -> &Self::Output { | |||||
| fn index(&self, index: ShipType) -> &Self::Output { | |||||
| match index { | match index { | ||||
| Type::Fighter => &self.fighter, | |||||
| Type::Bomber => &self.bomber, | |||||
| Type::Transporter => &self.transporter, | |||||
| ShipType::Fighter => &self.fighter, | |||||
| ShipType::Bomber => &self.bomber, | |||||
| ShipType::Transporter => &self.transporter, | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| impl IndexMut<Type> for Count { | |||||
| fn index_mut(&mut self, index: Type) -> &mut Self::Output { | |||||
| impl IndexMut<ShipType> for ShipCount { | |||||
| fn index_mut(&mut self, index: ShipType) -> &mut Self::Output { | |||||
| match index { | match index { | ||||
| Type::Fighter => &mut self.fighter, | |||||
| Type::Bomber => &mut self.bomber, | |||||
| Type::Transporter => &mut self.transporter, | |||||
| ShipType::Fighter => &mut self.fighter, | |||||
| ShipType::Bomber => &mut self.bomber, | |||||
| ShipType::Transporter => &mut self.transporter, | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| impl Mul<f32> for Count { | |||||
| type Output = Count; | |||||
| impl Mul<f32> for ShipCount { | |||||
| type Output = ShipCount; | |||||
| #[allow(unused_assignments)] | #[allow(unused_assignments)] | ||||
| fn mul(self, rhs: f32) -> Self::Output { | fn mul(self, rhs: f32) -> Self::Output { | ||||
| @@ -238,10 +243,37 @@ impl Mul<f32> for Count { | |||||
| actual += 1; | actual += 1; | ||||
| } | } | ||||
| Count { | |||||
| ShipCount { | |||||
| fighter, | fighter, | ||||
| bomber, | bomber, | ||||
| transporter, | transporter, | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* ShipsData */ | |||||
| impl Index<usize> for ShipsData { | |||||
| type Output = ShipData; | |||||
| fn index(&self, index: usize) -> &Self::Output { | |||||
| match index { | |||||
| 0 => &self.fighter, | |||||
| 1 => &self.bomber, | |||||
| 2 => &self.transporter, | |||||
| x => panic!("Invalid ships data index: {}", x), | |||||
| } | |||||
| } | |||||
| } | |||||
| impl Index<ShipType> for ShipsData { | |||||
| type Output = ShipData; | |||||
| fn index(&self, index: ShipType) -> &Self::Output { | |||||
| match index { | |||||
| ShipType::Fighter => &self.fighter, | |||||
| ShipType::Bomber => &self.bomber, | |||||
| ShipType::Transporter => &self.transporter, | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,5 +1,7 @@ | |||||
| use glc::{matrix::Angle, vector::Vector2f}; | use glc::{matrix::Angle, vector::Vector2f}; | ||||
| use crate::components::{ShipData, ShipsData}; | |||||
| /// Distance to orbit before ship is handled as "in orbit" in % | /// Distance to orbit before ship is handled as "in orbit" in % | ||||
| pub const SHIP_ORBIT_DISTANCE_MAX: f32 = 1.10; | pub const SHIP_ORBIT_DISTANCE_MAX: f32 = 1.10; | ||||
| @@ -13,3 +15,21 @@ pub const SHIP_ORBIT_ANGLE_DELTA_RND: Angle<f32> = Angle::Deg(5000.0); | |||||
| pub const SHIP_ORBIT_AGILITY: Angle<f32> = Angle::Deg(90.0); | pub const SHIP_ORBIT_AGILITY: Angle<f32> = Angle::Deg(90.0); | ||||
| pub const VECTOR_2F_POS_X: Vector2f = Vector2f::new(1.0, 0.0); | pub const VECTOR_2F_POS_X: Vector2f = Vector2f::new(1.0, 0.0); | ||||
| pub const SHIPS_DATA_FIGHTER: ShipsData = ShipsData { | |||||
| fighter: ShipData { speed: 120.0 }, | |||||
| bomber: ShipData { speed: 80.0 }, | |||||
| transporter: ShipData { speed: 100.0 }, | |||||
| }; | |||||
| pub const SHIPS_DATA_TRADER: ShipsData = ShipsData { | |||||
| fighter: ShipData { speed: 100.0 }, | |||||
| bomber: ShipData { speed: 70.0 }, | |||||
| transporter: ShipData { speed: 120.0 }, | |||||
| }; | |||||
| pub const SHIPS_DATA_RESEARCHER: ShipsData = ShipsData { | |||||
| fighter: ShipData { speed: 90.0 }, | |||||
| bomber: ShipData { speed: 60.0 }, | |||||
| transporter: ShipData { speed: 100.0 }, | |||||
| }; | |||||
| @@ -3,7 +3,7 @@ use specs::{Dispatcher as Inner, DispatcherBuilder, World, WorldExt}; | |||||
| use crate::{ | use crate::{ | ||||
| components::Player, | components::Player, | ||||
| resources::Global, | resources::Global, | ||||
| systems::{FleetControl, FleetOwnedUpdate, Movement, Process, Ships}, | |||||
| systems::{FleetControl, FleetOwnedUpdate, Process, ShipMovement, Ships}, | |||||
| Error, | Error, | ||||
| }; | }; | ||||
| @@ -19,7 +19,7 @@ impl<'a, 'b> Dispatcher<'a, 'b> { | |||||
| let mut dispatcher = DispatcherBuilder::new() | let mut dispatcher = DispatcherBuilder::new() | ||||
| .with(Process::default(), "process", &[]) | .with(Process::default(), "process", &[]) | ||||
| .with(Movement::default(), "movement", &[]) | |||||
| .with(ShipMovement::default(), "ship_movement", &[]) | |||||
| .with(Ships::new(world), "ships", &[]) | .with(Ships::new(world), "ships", &[]) | ||||
| .with(FleetControl::new(world)?, "fleet_control", &[]) | .with(FleetControl::new(world)?, "fleet_control", &[]) | ||||
| .with(FleetOwnedUpdate::new(world), "fleet_owned_update", &[]) | .with(FleetOwnedUpdate::new(world), "fleet_owned_update", &[]) | ||||
| @@ -1,11 +1,11 @@ | |||||
| mod fleet_control; | mod fleet_control; | ||||
| mod fleet_owned_update; | mod fleet_owned_update; | ||||
| mod movement; | |||||
| mod process; | mod process; | ||||
| mod ship_movement; | |||||
| mod ships; | mod ships; | ||||
| pub use fleet_control::{FleetControl, FleetControlEvent}; | pub use fleet_control::{FleetControl, FleetControlEvent}; | ||||
| pub use fleet_owned_update::FleetOwnedUpdate; | pub use fleet_owned_update::FleetOwnedUpdate; | ||||
| pub use movement::Movement; | |||||
| pub use process::Process; | pub use process::Process; | ||||
| pub use ship_movement::ShipMovement; | |||||
| pub use ships::Ships; | pub use ships::Ships; | ||||
| @@ -1,39 +0,0 @@ | |||||
| #![allow(dead_code)] | |||||
| use specs::{prelude::*, ParJoin, Read, ReadStorage, System, WriteStorage}; | |||||
| use crate::{ | |||||
| components::{Position, Ship}, | |||||
| resources::Global, | |||||
| }; | |||||
| #[derive(Default)] | |||||
| pub struct Movement; | |||||
| #[derive(SystemData)] | |||||
| pub struct MovementData<'a> { | |||||
| positions: WriteStorage<'a, Position>, | |||||
| ships: ReadStorage<'a, Ship>, | |||||
| global: Read<'a, Global>, | |||||
| } | |||||
| impl<'a> System<'a> for Movement { | |||||
| type SystemData = MovementData<'a>; | |||||
| fn run(&mut self, data: Self::SystemData) { | |||||
| let MovementData { | |||||
| mut positions, | |||||
| ships, | |||||
| global, | |||||
| } = data; | |||||
| (&mut positions, &ships) | |||||
| .par_join() | |||||
| .for_each(|(position, ship)| { | |||||
| let delta = global.delta * global.world_speed; | |||||
| let position = position.get_mut(); | |||||
| *position += ship.dir() * ship.speed() * delta; | |||||
| }); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,48 @@ | |||||
| #![allow(dead_code)] | |||||
| use specs::{prelude::*, ParJoin, Read, ReadStorage, System, WriteStorage}; | |||||
| use crate::{ | |||||
| components::{Player, PlayerOwned, Position, Ship}, | |||||
| resources::Global, | |||||
| return_if_none, | |||||
| }; | |||||
| #[derive(Default)] | |||||
| pub struct ShipMovement; | |||||
| #[derive(SystemData)] | |||||
| pub struct ShipMovementData<'a> { | |||||
| positions: WriteStorage<'a, Position>, | |||||
| ships: ReadStorage<'a, Ship>, | |||||
| player_owned: ReadStorage<'a, PlayerOwned>, | |||||
| players: ReadStorage<'a, Player>, | |||||
| global: Read<'a, Global>, | |||||
| } | |||||
| impl<'a> System<'a> for ShipMovement { | |||||
| type SystemData = ShipMovementData<'a>; | |||||
| fn run(&mut self, data: Self::SystemData) { | |||||
| let ShipMovementData { | |||||
| mut positions, | |||||
| ships, | |||||
| player_owned, | |||||
| players, | |||||
| global, | |||||
| } = data; | |||||
| (&mut positions, &player_owned, &ships).par_join().for_each( | |||||
| |(position, player_owned, ship)| { | |||||
| let delta = global.delta * global.world_speed; | |||||
| let position = position.get_mut(); | |||||
| let type_ = ship.type_(); | |||||
| let player_id = player_owned.owner(); | |||||
| let player = return_if_none!(players.get(player_id)); | |||||
| let ship_data = player.ship_data(type_); | |||||
| *position += ship.dir() * ship_data.speed * delta; | |||||
| }, | |||||
| ); | |||||
| } | |||||
| } | |||||