From 0c9124f4e763fb25a622fb647d98c0490fb2263e Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Thu, 17 Dec 2020 02:33:16 +0100 Subject: [PATCH] Implemented FleetControl system to move ships between planets --- space-crush-app/src/components/fleet_info.rs | 3 +- space-crush-app/src/lib.rs | 3 +- space-crush-app/src/main.rs | 54 ++++----- space-crush-app/src/resources/config.rs | 7 ++ space-crush-app/src/systems/fleet_control.rs | 113 ++++++++++++++++++ .../src/systems/fleet_info_update.rs | 2 + space-crush-app/src/systems/mod.rs | 2 + 7 files changed, 155 insertions(+), 29 deletions(-) create mode 100644 space-crush-app/src/systems/fleet_control.rs diff --git a/space-crush-app/src/components/fleet_info.rs b/space-crush-app/src/components/fleet_info.rs index 60a05cf..af67637 100644 --- a/space-crush-app/src/components/fleet_info.rs +++ b/space-crush-app/src/components/fleet_info.rs @@ -1,8 +1,9 @@ use space_crush_common::components::ShipCount; -use specs::{Component, HashMapStorage}; +use specs::{hibitset::BitSet, Component, HashMapStorage}; #[derive(Default, Debug)] pub struct FleetInfo { + pub owned: BitSet, pub count: ShipCount, } diff --git a/space-crush-app/src/lib.rs b/space-crush-app/src/lib.rs index 4c2039a..5e9d301 100644 --- a/space-crush-app/src/lib.rs +++ b/space-crush-app/src/lib.rs @@ -15,7 +15,7 @@ use debug::{Fleets as DebugFleets, Ships as DebugShips, Summary as DebugSummary} use misc::{Events, TextManager, Window}; use render::{Asteroids, FleetSelect, Init, Planets, Ships}; use resources::{Camera, Config, Geometry, InputState, PlayerState, Uniform}; -use systems::{FleetInfoUpdate, StateUpdate}; +use systems::{FleetControl, FleetInfoUpdate, StateUpdate}; pub struct App<'a, 'b> { is_running: bool, @@ -48,6 +48,7 @@ impl<'a, 'b> App<'a, 'b> { let mut dispatcher = DispatcherBuilder::new() .with(StateUpdate::new(world)?, "state_update", &[]) .with(FleetInfoUpdate::new(world), "fleet_info_update", &[]) + .with(FleetControl::new(world)?, "fleet_control", &[]) .with_thread_local(Init::new(world)?) .with_thread_local(Planets::new(world)?) .with_thread_local(Asteroids::new(world)?) diff --git a/space-crush-app/src/main.rs b/space-crush-app/src/main.rs index b6b1ff7..ef5ea34 100644 --- a/space-crush-app/src/main.rs +++ b/space-crush-app/src/main.rs @@ -79,69 +79,69 @@ fn create_world(world: &mut World, player_id: Entity) { ) .unwrap(); - world + let planet = world .create_entity() .marked::<::Marker>() + .with(PlayerOwned { owner: player_id }) .with(Position { - pos: Vector2f::new(1000.0, -1000.0), - shape: Shape::Circle(100.0), + pos: Vector2f::default(), + shape: Shape::Circle(250.0), }) .with(Fleet { - orbit_min: 125.0, - orbit_max: 175.0, + orbit_min: 325.0, + orbit_max: 425.0, }) .with(FleetInfo::default()) - .with(Asteroid { - type_: AsteroidType::Metal, - }) + .with(Planet {}) .build(); world .create_entity() .marked::<::Marker>() .with(Position { - pos: Vector2f::new(1000.0, 1000.0), - shape: Shape::Circle(100.0), + pos: Vector2f::new(2000.0, 0.0), + shape: Shape::Circle(250.0), }) .with(Fleet { - orbit_min: 125.0, - orbit_max: 175.0, + orbit_min: 325.0, + orbit_max: 425.0, }) .with(FleetInfo::default()) - .with(Asteroid { - type_: AsteroidType::Crystal, - }) + .with(Planet {}) .build(); - let planet = world + world .create_entity() .marked::<::Marker>() - .with(PlayerOwned { owner: player_id }) .with(Position { - pos: Vector2f::default(), - shape: Shape::Circle(250.0), + pos: Vector2f::new(1000.0, -1000.0), + shape: Shape::Circle(100.0), }) .with(Fleet { - orbit_min: 325.0, - orbit_max: 425.0, + orbit_min: 125.0, + orbit_max: 175.0, }) .with(FleetInfo::default()) - .with(Planet {}) + .with(Asteroid { + type_: AsteroidType::Metal, + }) .build(); world .create_entity() .marked::<::Marker>() .with(Position { - pos: Vector2f::new(2000.0, 0.0), - shape: Shape::Circle(250.0), + pos: Vector2f::new(1000.0, 1000.0), + shape: Shape::Circle(100.0), }) .with(Fleet { - orbit_min: 325.0, - orbit_max: 425.0, + orbit_min: 125.0, + orbit_max: 175.0, }) .with(FleetInfo::default()) - .with(Planet {}) + .with(Asteroid { + type_: AsteroidType::Crystal, + }) .build(); for i in 0..30 { diff --git a/space-crush-app/src/resources/config.rs b/space-crush-app/src/resources/config.rs index 2d36075..a4c427e 100644 --- a/space-crush-app/src/resources/config.rs +++ b/space-crush-app/src/resources/config.rs @@ -46,6 +46,8 @@ pub struct Input { pub camera_move_button: MouseButton, #[serde(default = "defaults::fleet_select_button")] pub fleet_select_button: MouseButton, + #[serde(default = "defaults::fleet_move_button")] + pub fleet_move_button: MouseButton, #[serde(default = "defaults::camera_move_speed")] pub camera_move_speed: f32, @@ -95,6 +97,7 @@ impl Default for Input { camera_move_button: defaults::camera_move_button(), fleet_select_button: defaults::fleet_select_button(), + fleet_move_button: defaults::fleet_move_button(), camera_move_speed: defaults::camera_move_speed(), camera_zoom_speed: defaults::camera_zoom_speed(), @@ -145,6 +148,10 @@ mod defaults { MouseButton::Left } + pub fn fleet_move_button() -> MouseButton { + MouseButton::Right + } + pub fn camera_move_speed() -> f32 { 500.0 } diff --git a/space-crush-app/src/systems/fleet_control.rs b/space-crush-app/src/systems/fleet_control.rs new file mode 100644 index 0000000..e6673ab --- /dev/null +++ b/space-crush-app/src/systems/fleet_control.rs @@ -0,0 +1,113 @@ +use shrev::{EventChannel, ReaderId}; +use space_crush_common::{ + components::{Fleet, FleetOwned, Position, Ship, ShipType}, + misc::WorldHelper, + return_if_none, +}; +use specs::{prelude::*, Entities, Entity, ReadStorage, System, World, WriteStorage}; + +use crate::{ + components::FleetInfo, + misc::MouseEvent, + resources::{Camera, Config, InputState, PlayerState}, + Error, +}; + +pub struct FleetControl { + mouse_event_id: ReaderId, + target_fleet: Option, +} + +#[derive(SystemData)] +pub struct FleetControlData<'a> { + player_state: WriteExpect<'a, PlayerState>, + mouse_events: ReadExpect<'a, EventChannel>, + input_state: ReadExpect<'a, InputState>, + camera: ReadExpect<'a, Camera>, + config: ReadExpect<'a, Config>, + + entities: Entities<'a>, + ships: ReadStorage<'a, Ship>, + fleet_owned: WriteStorage<'a, FleetOwned>, + positions: ReadStorage<'a, Position>, + fleet_infos: ReadStorage<'a, FleetInfo>, + fleets: ReadStorage<'a, Fleet>, +} + +impl FleetControl { + pub fn new(world: &mut World) -> Result { + let mouse_event_id = world.register_event_reader::()?; + let target_fleet = None; + + Ok(Self { + mouse_event_id, + target_fleet, + }) + } +} + +impl<'a> System<'a> for FleetControl { + type SystemData = FleetControlData<'a>; + + fn run(&mut self, data: Self::SystemData) { + let FleetControlData { + mut player_state, + mouse_events, + input_state, + camera, + config, + entities, + ships, + mut fleet_owned, + positions, + fleet_infos, + fleets, + } = data; + + let events = mouse_events.read(&mut self.mouse_event_id); + for event in events { + match event { + MouseEvent::ButtonDown(button) if button == &config.input.fleet_move_button => { + let pos = camera.view_to_world(input_state.mouse_pos); + for (id, position, fleet) in (&entities, &positions, &fleets).join() { + let r = fleet.orbit_max * fleet.orbit_max; + if (position.pos - pos).length_sqr() <= r { + self.target_fleet = Some(id); + + break; + } + } + } + MouseEvent::ButtonUp(button) if button == &config.input.fleet_move_button => { + let selection = player_state.selection.take(); + let target_fleet = return_if_none!(self.target_fleet.take()); + let mut selection = return_if_none!(selection); + let fleet_info = return_if_none!(fleet_infos.get(selection.fleet)); + for (ship, fleet_owned, _) in + (&ships, &mut fleet_owned, &fleet_info.owned).join() + { + match &ship.type_ { + ShipType::Fighter if selection.count.fighter > 0 => { + fleet_owned.owner = target_fleet; + selection.count.fighter -= 1; + } + ShipType::Bomber if selection.count.bomber > 0 => { + fleet_owned.owner = target_fleet; + selection.count.bomber -= 1; + } + ShipType::Transporter if selection.count.transporter > 0 => { + fleet_owned.owner = target_fleet; + selection.count.transporter -= 1; + } + _ => (), + } + } + } + MouseEvent::Move(_, _) => { + self.target_fleet = None; + } + _ => (), + } + } + } +} diff --git a/space-crush-app/src/systems/fleet_info_update.rs b/space-crush-app/src/systems/fleet_info_update.rs index 83dc594..c8dae35 100644 --- a/space-crush-app/src/systems/fleet_info_update.rs +++ b/space-crush-app/src/systems/fleet_info_update.rs @@ -155,8 +155,10 @@ impl<'a> System<'a> for FleetInfoUpdate { }; if old_match && !new_match { + fleet_info.owned.remove(ship_id.id()); fleet_info.count[ship.type_] = fleet_info.count[ship.type_].saturating_sub(1); } else if !old_match && new_match { + fleet_info.owned.add(ship_id.id()); fleet_info.count[ship.type_] += 1; } } diff --git a/space-crush-app/src/systems/mod.rs b/space-crush-app/src/systems/mod.rs index fe26e9d..5b989d2 100644 --- a/space-crush-app/src/systems/mod.rs +++ b/space-crush-app/src/systems/mod.rs @@ -1,5 +1,7 @@ +mod fleet_control; mod fleet_info_update; mod state_update; +pub use fleet_control::FleetControl; pub use fleet_info_update::FleetInfoUpdate; pub use state_update::StateUpdate;