@@ -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, | |||
} | |||
@@ -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)?) | |||
@@ -79,69 +79,69 @@ fn create_world(world: &mut World, player_id: Entity) { | |||
) | |||
.unwrap(); | |||
world | |||
let planet = world | |||
.create_entity() | |||
.marked::<<PersistWorld as Persistence>::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::<<PersistWorld as Persistence>::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::<<PersistWorld as Persistence>::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::<<PersistWorld as Persistence>::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 { | |||
@@ -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 | |||
} | |||
@@ -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<MouseEvent>, | |||
target_fleet: Option<Entity>, | |||
} | |||
#[derive(SystemData)] | |||
pub struct FleetControlData<'a> { | |||
player_state: WriteExpect<'a, PlayerState>, | |||
mouse_events: ReadExpect<'a, EventChannel<MouseEvent>>, | |||
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<Self, Error> { | |||
let mouse_event_id = world.register_event_reader::<MouseEvent>()?; | |||
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; | |||
} | |||
_ => (), | |||
} | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
@@ -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; |