Browse Source

Added system to handle fleet control events

master
Bergmann89 3 years ago
parent
commit
574b769235
20 changed files with 412 additions and 207 deletions
  1. +1
    -1
      glc/src/angle.rs
  2. +6
    -42
      space-crush-app/src/debug/fleets.rs
  3. +2
    -0
      space-crush-app/src/debug/mod.rs
  4. +65
    -0
      space-crush-app/src/debug/orbits.rs
  5. +7
    -3
      space-crush-app/src/lib.rs
  6. +10
    -14
      space-crush-app/src/main.rs
  7. +94
    -0
      space-crush-app/src/render/fleet_move.rs
  8. +6
    -15
      space-crush-app/src/render/fleet_select.rs
  9. +2
    -0
      space-crush-app/src/render/mod.rs
  10. +29
    -5
      space-crush-app/src/resources/game_state.rs
  11. +0
    -116
      space-crush-app/src/systems/fleet_control.rs
  12. +0
    -2
      space-crush-app/src/systems/mod.rs
  13. +16
    -0
      space-crush-common/src/components/orbit.rs
  14. +4
    -0
      space-crush-common/src/components/ship.rs
  15. +5
    -3
      space-crush-common/src/dispatcher.rs
  16. +146
    -0
      space-crush-common/src/systems/fleet_control.rs
  17. +10
    -5
      space-crush-common/src/systems/fleet_owned_update.rs
  18. +2
    -0
      space-crush-common/src/systems/mod.rs
  19. +6
    -0
      space-crush-common/src/systems/orbit_owned_update.rs
  20. +1
    -1
      space-crush-common/src/systems/ships.rs

+ 1
- 1
glc/src/angle.rs View File

@@ -58,7 +58,7 @@ where
fn _add(self, other: &Self) -> Self {
match self {
Self::Deg(value) => Self::Deg(value + other.into_deg().into_inner()),
Self::Rad(value) => Self::Rad(value * other.into_rad().into_inner()),
Self::Rad(value) => Self::Rad(value + other.into_rad().into_inner()),
}
}



+ 6
- 42
space-crush-app/src/debug/fleets.rs View File

@@ -1,16 +1,13 @@
use glc::vector::{Angle, Vector2f, Vector4f};
use space_crush_common::{
components::{Fleet, Orbit, Player, Position},
constants::SHIP_ORBIT_DISTANCE_MAX,
components::{Fleet, Orbit, Position},
continue_if_none,
misc::LogResult,
return_if_none,
};
use specs::{prelude::*, ReadExpect, ReadStorage, System, World, WriteExpect};
use specs::{prelude::*, ReadExpect, ReadStorage, System, World};

use crate::{
misc::{HorizontalAlign, Text, TextManager, VerticalAlign},
resources::{Camera, GameState, Geometry},
resources::{Camera, GameState},
Error,
};

@@ -21,10 +18,8 @@ pub struct Fleets {
#[derive(SystemData)]
pub struct FleetData<'a> {
game_state: ReadExpect<'a, GameState>,
geometry: WriteExpect<'a, Geometry>,
camera: ReadExpect<'a, Camera>,
positions: ReadStorage<'a, Position>,
players: ReadStorage<'a, Player>,
orbits: ReadStorage<'a, Orbit>,
fleets: ReadStorage<'a, Fleet>,
}
@@ -52,37 +47,19 @@ impl<'a> System<'a> for Fleets {
fn run(&mut self, data: Self::SystemData) {
let FleetData {
game_state,
mut geometry,
camera,
positions,
players,
orbits,
fleets,
} = data;

let player = return_if_none!(players.get(game_state.player_id));
let player_index = game_state.player_index();

gl::enable(gl::BLEND);

for (position, orbit) in (&positions, &orbits).join() {
let fleet_id = continue_if_none!(orbit.fleets().get(player.index()));
let fleet_id = continue_if_none!(fleet_id);
let fleet = continue_if_none!(fleets.get(*fleet_id));

gl::blend_func(gl::SRC_ALPHA, gl::ONE);
gl::blend_equation(gl::FUNC_ADD);
geometry.render_lines(
Vector4f::new(0.5, 0.5, 0.5, 0.05),
&create_circle(position.pos(), orbit.min()),
);
geometry.render_lines(
Vector4f::new(0.5, 0.5, 0.5, 0.05),
&create_circle(position.pos(), orbit.max()),
);
geometry.render_lines(
Vector4f::new(0.5, 0.5, 0.5, 0.05),
&create_circle(position.pos(), SHIP_ORBIT_DISTANCE_MAX * orbit.max()),
);
let fleet_id = continue_if_none!(orbit.fleet(player_index));
let fleet = continue_if_none!(fleets.get(fleet_id));

gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
gl::blend_equation(gl::FUNC_SUBTRACT);
@@ -104,16 +81,3 @@ impl<'a> System<'a> for Fleets {
gl::disable(gl::BLEND);
}
}

fn create_circle(p: &Vector2f, r: f32) -> Vec<Vector2f> {
let mut points = Vec::new();

for i in 0..=180 {
points.push(Vector2f::new(
p.x + r * Angle::Deg(i as f32 * 2.0).cos(),
p.y + r * Angle::Deg(i as f32 * 2.0).sin(),
));
}

points
}

+ 2
- 0
space-crush-app/src/debug/mod.rs View File

@@ -1,7 +1,9 @@
mod fleets;
mod orbits;
mod ships;
mod summary;

pub use fleets::Fleets;
pub use orbits::Orbits;
pub use ships::Ships;
pub use summary::Summary;

+ 65
- 0
space-crush-app/src/debug/orbits.rs View File

@@ -0,0 +1,65 @@
use glc::vector::{Angle, Vector2f, Vector4f};
use space_crush_common::{
components::{Orbit, Position},
constants::SHIP_ORBIT_DISTANCE_MAX,
};
use specs::{prelude::*, ReadStorage, System, World, WriteExpect};

use crate::resources::Geometry;

#[derive(Default)]
pub struct Orbits {}

#[derive(SystemData)]
pub struct OrbitsData<'a> {
geometry: WriteExpect<'a, Geometry>,
positions: ReadStorage<'a, Position>,
orbits: ReadStorage<'a, Orbit>,
}

impl<'a> System<'a> for Orbits {
type SystemData = OrbitsData<'a>;

fn run(&mut self, data: Self::SystemData) {
let OrbitsData {
mut geometry,
positions,
orbits,
} = data;

gl::enable(gl::BLEND);

for (position, orbit) in (&positions, &orbits).join() {
gl::blend_func(gl::SRC_ALPHA, gl::ONE);
gl::blend_equation(gl::FUNC_ADD);
geometry.render_lines(
Vector4f::new(0.5, 0.5, 0.5, 0.05),
&create_circle(position.pos(), orbit.min()),
);
geometry.render_lines(
Vector4f::new(0.5, 0.5, 0.5, 0.05),
&create_circle(position.pos(), orbit.max()),
);
geometry.render_lines(
Vector4f::new(0.5, 0.5, 0.5, 0.05),
&create_circle(position.pos(), SHIP_ORBIT_DISTANCE_MAX * orbit.max()),
);
}

gl::blend_equation(gl::FUNC_ADD);
gl::disable(gl::BLEND);
}
}

fn create_circle(p: &Vector2f, r: f32) -> Vec<Vector2f> {
let mut points = Vec::new();

for i in 0..=180 {
points.push(Vector2f::new(
p.x + r * Angle::Deg(i as f32 * 2.0).cos(),
p.y + r * Angle::Deg(i as f32 * 2.0).sin(),
));
}

points
}

+ 7
- 3
space-crush-app/src/lib.rs View File

@@ -11,9 +11,11 @@ use specs::{Dispatcher, DispatcherBuilder, Entity, World};

pub use error::Error;

use debug::{Fleets as DebugFleets, Ships as DebugShips, Summary as DebugSummary};
use debug::{
Fleets as DebugFleets, Orbits as DebugOrbits, Ships as DebugShips, Summary as DebugSummary,
};
use misc::{Events, TextManager, Window};
use render::{Asteroids, FleetSelect, Init, Planets, Ships};
use render::{Asteroids, FleetMove, FleetSelect, Init, Planets, Ships};
use resources::{Camera, Config, GameState, Geometry, InputState, Uniform};
use systems::InputStateUpdate;

@@ -34,7 +36,7 @@ impl<'a, 'b> App<'a, 'b> {
let uniform = Uniform::new()?;
let geometry = Geometry::new(world)?;
let input_state = InputState::default();
let game_state = GameState::new(player_id);
let game_state = GameState::new(world, player_id);

camera.update(Matrix4f::scale(0.25))?;

@@ -54,7 +56,9 @@ impl<'a, 'b> App<'a, 'b> {
.with_thread_local(Asteroids::new(world)?)
.with_thread_local(Ships::new(world)?)
.with_thread_local(FleetSelect::new(world, &text_manager)?)
.with_thread_local(FleetMove::new(world)?)
.with_thread_local(DebugShips::default())
.with_thread_local(DebugOrbits::default())
.with_thread_local(DebugFleets::new(&text_manager)?)
.with_thread_local(DebugSummary::new(&text_manager)?)
.build();


+ 10
- 14
space-crush-app/src/main.rs View File

@@ -1,7 +1,9 @@
use glc::vector::Vector4f;
use log::{error, info};
use rand::random;
use space_crush_app::{App, Error};
use space_crush_common::{
components::Player,
misc::{init_logger, Vfs},
Dispatcher,
};
@@ -33,9 +35,11 @@ fn run(vfs: Vfs) -> Result<(), Error> {
let mut world = World::new();
world.insert(vfs);

let player1 = world.create_entity().build();

let mut common = Dispatcher::new(&mut world);
let mut common = Dispatcher::new(&mut world)?;
let player1 = world
.create_entity()
.with(Player::new(Vector4f::new(0.0, 0.5, 1.0, 0.1)))
.build();
let mut app = App::new(&mut world, player1)?;

create_world(&mut world, player1);
@@ -53,26 +57,18 @@ fn run(vfs: Vfs) -> Result<(), Error> {
}

fn create_world(world: &mut World, player_id: Entity) {
use glc::{
matrix::Angle,
vector::{Vector2f, Vector4f},
};
use glc::{matrix::Angle, vector::Vector2f};
use space_crush_common::{
components::{
Asteroid, AsteroidType, Fleet, FleetOwned, Obstacle, Orbit, OrbitOwned, Planet, Player,
Asteroid, AsteroidType, Fleet, FleetOwned, Obstacle, Orbit, OrbitOwned, Planet,
PlayerOwned, Position, Ship, ShipType, Velocity,
},
misc::{PersistWorld, Persistence},
};
use specs::{saveload::MarkedBuilder, WriteStorage};
use specs::saveload::MarkedBuilder;

PersistWorld::setup(world);

world
.system_data::<WriteStorage<Player>>()
.insert(player_id, Player::new(Vector4f::new(0.0, 0.5, 1.0, 0.1)))
.unwrap();

let planets = (0..3)
.map(|i| {
let x = 2000.0 * (i as f32 - 1.0);


+ 94
- 0
space-crush-app/src/render/fleet_move.rs View File

@@ -0,0 +1,94 @@
use shrev::{EventChannel, ReaderId};
use space_crush_common::{
components::{Orbit, Position},
continue_if_none,
misc::WorldHelper,
systems::FleetControlEvent,
};
use specs::{prelude::*, Entities, Entity, ReadStorage, System, World};

use crate::{
misc::MouseEvent,
resources::{Camera, Config, GameState, InputState, Selection},
Error,
};

pub struct FleetMove {
mouse_event_id: ReaderId<MouseEvent>,
target_orbit: Option<Entity>,
}

#[derive(SystemData)]
pub struct FleetMoveData<'a> {
game_state: WriteExpect<'a, GameState>,
fleet_control: WriteExpect<'a, EventChannel<FleetControlEvent>>,
mouse_events: ReadExpect<'a, EventChannel<MouseEvent>>,
input_state: ReadExpect<'a, InputState>,
camera: ReadExpect<'a, Camera>,
config: ReadExpect<'a, Config>,

entities: Entities<'a>,
positions: ReadStorage<'a, Position>,
orbits: ReadStorage<'a, Orbit>,
}

impl FleetMove {
pub fn new(world: &mut World) -> Result<Self, Error> {
let mouse_event_id = world.register_event_reader::<MouseEvent>()?;
let target_orbit = None;

Ok(Self {
mouse_event_id,
target_orbit,
})
}
}

impl<'a> System<'a> for FleetMove {
type SystemData = FleetMoveData<'a>;

fn run(&mut self, data: Self::SystemData) {
let FleetMoveData {
mut game_state,
mut fleet_control,
mouse_events,
input_state,
camera,
config,
entities,
positions,
orbits,
} = 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, orbit) in (&entities, &positions, &orbits).join() {
let r = orbit.max() * orbit.max();
if (position.pos() - pos).length_sqr() <= r {
self.target_orbit = Some(id);

break;
}
}
}
MouseEvent::ButtonUp(button) if button == &config.input.fleet_move_button => {
let selection = game_state.selection_mut().take();
let selection = continue_if_none!(selection);
let Selection { fleet, count } = selection;
let target = continue_if_none!(self.target_orbit);
let player = game_state.player_id();
let event = FleetControlEvent::move_(player, target, fleet, count);

fleet_control.single_write(event);
}
MouseEvent::Move(_, _) => {
self.target_orbit = None;
}
_ => (),
}
}
}
}

+ 6
- 15
space-crush-app/src/render/fleet_select.rs View File

@@ -10,7 +10,7 @@ use glc::{
};
use shrev::{EventChannel, ReaderId};
use space_crush_common::{
components::{Fleet, Orbit, OrbitOwned, Player, Position, ShipCount},
components::{Fleet, Orbit, OrbitOwned, Position, ShipCount},
constants::VECTOR_2F_POS_X,
continue_if_none,
misc::{LogResult, WorldHelper as _},
@@ -82,23 +82,16 @@ pub struct FleetSelectData<'a> {

orbit_owned: ReadStorage<'a, OrbitOwned>,
positions: ReadStorage<'a, Position>,
players: ReadStorage<'a, Player>,
orbits: ReadStorage<'a, Orbit>,
fleets: ReadStorage<'a, Fleet>,
}

macro_rules! selection {
(&$data:expr) => {
return_if_none!(&$data.game_state.selection)
return_if_none!($data.game_state.selection())
};
(&mut $data:expr) => {
return_if_none!(&mut $data.game_state.selection)
};
}

macro_rules! player {
(&$data:expr, $id:expr) => {
return_if_none!($data.players.get($id))
return_if_none!($data.game_state.selection_mut())
};
}

@@ -192,17 +185,15 @@ impl FleetSelect {
match event {
MouseEvent::ButtonDown(button) if button == &d.config.input.fleet_select_button => {
let pos = d.camera.view_to_world(d.input_state.mouse_pos);
let selection = d.game_state.selection.take();
let selection = d.game_state.selection_mut().take();
for (position, orbit) in (&d.positions, &d.orbits).join() {
let r = orbit.max() * orbit.max();
if (position.pos() - pos).length_sqr() <= r {
let player_id = d.game_state.player_id;
let player = player!(&d, player_id);
let player_index = player.index();
let player_index = d.game_state.player_index();
let fleet_id = continue_if_none!(orbit.fleets().get(player_index));
let fleet_id = *continue_if_none!(fleet_id);

d.game_state.selection = match selection {
*d.game_state.selection_mut() = match selection {
Some(s) if s.fleet == fleet_id => {
self.is_new_selection = false;



+ 2
- 0
space-crush-app/src/render/mod.rs View File

@@ -1,10 +1,12 @@
mod asteroids;
mod fleet_move;
mod fleet_select;
mod init;
mod planets;
mod ships;

pub use asteroids::Asteroids;
pub use fleet_move::FleetMove;
pub use fleet_select::FleetSelect;
pub use init::Init;
pub use planets::Planets;


+ 29
- 5
space-crush-app/src/resources/game_state.rs View File

@@ -1,11 +1,12 @@
#![allow(dead_code)]

use space_crush_common::components::ShipCount;
use specs::Entity;
use space_crush_common::components::{Player, ShipCount};
use specs::{Entity, ReadStorage, World};

pub struct GameState {
pub player_id: Entity,
pub selection: Option<Selection>,
player_id: Entity,
player_index: usize,
selection: Option<Selection>,
}

pub struct Selection {
@@ -14,10 +15,33 @@ pub struct Selection {
}

impl GameState {
pub fn new(player_id: Entity) -> Self {
pub fn new(world: &mut World, player_id: Entity) -> Self {
let player_index = world
.system_data::<ReadStorage<Player>>()
.get(player_id)
.unwrap()
.index();

Self {
player_id,
player_index,
selection: None,
}
}

pub fn player_id(&self) -> Entity {
self.player_id
}

pub fn player_index(&self) -> usize {
self.player_index
}

pub fn selection(&self) -> &Option<Selection> {
&self.selection
}

pub(crate) fn selection_mut(&mut self) -> &mut Option<Selection> {
&mut self.selection
}
}

+ 0
- 116
space-crush-app/src/systems/fleet_control.rs View File

@@ -1,116 +0,0 @@
use shrev::{EventChannel, ReaderId};
use space_crush_common::{
components::{Fleet, FleetOwned, Orbit, Player, Position, Ship, ShipType},
continue_if_none,
misc::WorldHelper,
};
use specs::{prelude::*, Entity, ReadStorage, System, World, WriteStorage};

use crate::{
misc::MouseEvent,
resources::{Camera, Config, GameState, InputState},
Error,
};

pub struct FleetControl {
mouse_event_id: ReaderId<MouseEvent>,
target_fleet: Option<Entity>,
}

#[derive(SystemData)]
pub struct FleetControlData<'a> {
game_state: WriteExpect<'a, GameState>,
mouse_events: ReadExpect<'a, EventChannel<MouseEvent>>,
input_state: ReadExpect<'a, InputState>,
camera: ReadExpect<'a, Camera>,
config: ReadExpect<'a, Config>,

ships: ReadStorage<'a, Ship>,
fleet_owned: WriteStorage<'a, FleetOwned>,
positions: ReadStorage<'a, Position>,
players: ReadStorage<'a, Player>,
orbits: ReadStorage<'a, Orbit>,
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 game_state,
mouse_events,
input_state,
camera,
config,
ships,
mut fleet_owned,
positions,
players,
orbits,
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 (position, orbit) in (&positions, &orbits).join() {
let r = orbit.max() * orbit.max();
if (position.pos() - pos).length_sqr() <= r {
let player_id = game_state.player_id;
let player = continue_if_none!(players.get(player_id));
let fleet_id = continue_if_none!(orbit.fleets().get(player.index()));
let fleet_id = *continue_if_none!(fleet_id);

self.target_fleet = Some(fleet_id);

break;
}
}
}
#[allow(unused_variables)] // TODO
MouseEvent::ButtonUp(button) if button == &config.input.fleet_move_button => {
let selection = game_state.selection.take();
let target_fleet = continue_if_none!(self.target_fleet.take());
let mut selection = continue_if_none!(selection);
let fleet = continue_if_none!(fleets.get(selection.fleet));
for (ship, fleet_owned, _) in (&ships, &mut fleet_owned, fleet.owned()).join() {
match ship.type_() {
ShipType::Fighter if selection.count.fighter > 0 => {
// TODO fleet_owned.set_owner(target_fleet);
selection.count.fighter -= 1;
}
ShipType::Bomber if selection.count.bomber > 0 => {
// TODO fleet_owned.set_owner(target_fleet);
selection.count.bomber -= 1;
}
ShipType::Transporter if selection.count.transporter > 0 => {
// TODO fleet_owned.set_owner(target_fleet);
selection.count.transporter -= 1;
}
_ => (),
}
}
}
MouseEvent::Move(_, _) => {
self.target_fleet = None;
}
_ => (),
}
}
}
}

+ 0
- 2
space-crush-app/src/systems/mod.rs View File

@@ -1,5 +1,3 @@
mod fleet_control;
mod input_state_update;

pub use fleet_control::FleetControl;
pub use input_state_update::InputStateUpdate;

+ 16
- 0
space-crush-common/src/components/orbit.rs View File

@@ -64,6 +64,18 @@ impl Orbit {
pub(crate) fn fleets_mut(&mut self) -> &mut Fleets {
&mut self.fleets
}

#[inline]
pub fn fleet(&self, index: usize) -> Option<Entity> {
self.fleets.get(index).cloned().flatten()
}

#[inline]
pub(crate) fn fleet_mut(&mut self, index: usize) -> &mut Option<Entity> {
self.fleets.resize_with(index + 1, Default::default);

&mut self.fleets[index]
}
}

impl Component for Orbit {
@@ -113,6 +125,10 @@ impl Owned {
pub fn owner(&self) -> Entity {
self.owner
}

pub(crate) fn set_owner(&mut self, value: Entity) {
self.owner = value;
}
}

impl Component for Owned {


+ 4
- 0
space-crush-common/src/components/ship.rs View File

@@ -123,6 +123,10 @@ impl Count {
transporter: min(self.transporter, other.transporter),
}
}

pub fn is_all(&self) -> bool {
self.fighter == usize::MAX && self.bomber == usize::MAX && self.transporter == usize::MAX
}
}

impl Index<usize> for Count {


+ 5
- 3
space-crush-common/src/dispatcher.rs View File

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

pub struct Dispatcher<'a, 'b> {
@@ -11,7 +12,7 @@ pub struct Dispatcher<'a, 'b> {
}

impl<'a, 'b> Dispatcher<'a, 'b> {
pub fn new(world: &mut World) -> Self {
pub fn new(world: &mut World) -> Result<Self, Error> {
world.insert(Global::default());

world.register::<Player>();
@@ -20,12 +21,13 @@ impl<'a, 'b> Dispatcher<'a, 'b> {
.with(Process::default(), "process", &[])
.with(Movement::default(), "movement", &[])
.with(Ships::new(world), "ships", &[])
.with(FleetControl::new(world)?, "fleet_control", &[])
.with(FleetOwnedUpdate::new(world), "fleet_owned_update", &[])
.with(OrbitOwnedUpdate::new(world), "orbit_owned_update", &[])
.build();
dispatcher.setup(world);

Self { dispatcher }
Ok(Self { dispatcher })
}

pub fn process(&mut self, world: &World) {


+ 146
- 0
space-crush-common/src/systems/fleet_control.rs View File

@@ -0,0 +1,146 @@
use shrev::{EventChannel, ReaderId};
use specs::{
prelude::*, saveload::MarkedBuilder, Entities, Entity, LazyUpdate, ReadExpect, ReadStorage,
System, World, WriteStorage,
};

use crate::{
components::{
Fleet, FleetOwned, Orbit, OrbitOwned, Player, PlayerOwned, Ship, ShipCount, ShipType,
},
continue_if_none,
misc::{LogResult, PersistWorld, Persistence, WorldHelper},
Error,
};

pub struct FleetControl {
fleet_control_event_id: ReaderId<FleetControlEvent>,
}

#[derive(Debug)]
pub enum FleetControlEvent {
Move(MoveArgs),
}

#[derive(Debug)]
pub struct MoveArgs {
player: Entity,
target: Entity,
fleet: Entity,
count: ShipCount,
}

#[derive(SystemData)]
pub struct FleetControlData<'a> {
lazy: Read<'a, LazyUpdate>,
entities: Entities<'a>,
fleet_control_events: ReadExpect<'a, EventChannel<FleetControlEvent>>,
player_owned: WriteStorage<'a, PlayerOwned>,
orbit_owned: WriteStorage<'a, OrbitOwned>,
fleet_owned: WriteStorage<'a, FleetOwned>,
orbits: WriteStorage<'a, Orbit>,
fleets: WriteStorage<'a, Fleet>,
players: ReadStorage<'a, Player>,
ships: ReadStorage<'a, Ship>,
}

impl FleetControl {
pub fn new(world: &mut World) -> Result<Self, Error> {
world.insert(EventChannel::<FleetControlEvent>::default());

let fleet_control_event_id = world.register_event_reader::<FleetControlEvent>()?;

Ok(Self {
fleet_control_event_id,
})
}
}

impl<'a> System<'a> for FleetControl {
type SystemData = FleetControlData<'a>;

fn run(&mut self, data: Self::SystemData) {
let FleetControlData {
lazy,
entities,
fleet_control_events,
mut player_owned,
mut orbit_owned,
mut fleet_owned,
mut orbits,
mut fleets,
players,
ships,
} = data;

let events = fleet_control_events.read(&mut self.fleet_control_event_id);
for event in events {
match event {
FleetControlEvent::Move(args) if args.count.is_all() => {
let orbit_owned = continue_if_none!(orbit_owned.get_mut(args.fleet));
orbit_owned.set_owner(args.target);
}
FleetControlEvent::Move(args) => {
let target_orbit = continue_if_none!(orbits.get_mut(args.target));
let player = continue_if_none!(players.get(args.player));
let mut count = args.count;

let target_fleet = match target_orbit.fleet_mut(player.index()) {
Some(fleet) => *fleet,
f @ None => {
let fleet = lazy
.create_entity(&entities)
.marked::<<PersistWorld as Persistence>::Marker>()
.build();

player_owned
.insert(fleet, PlayerOwned::new(args.player))
.error("Unable to insert component: PlayerOwned");
orbit_owned
.insert(fleet, OrbitOwned::new(args.target))
.error("Unable to insert component: OrbitOwned");
fleets
.insert(fleet, Fleet::default())
.error("Unable to insert component: Fleet");

*f = Some(fleet);

fleet
}
};

let source_fleet = continue_if_none!(fleets.get(args.fleet));
let data = (&mut fleet_owned, &ships, source_fleet.owned());
for (fleet_owned, ship, _) in data.join() {
match ship.type_() {
ShipType::Fighter if count.fighter > 0 => {
count.fighter -= 1;
fleet_owned.set_owner(target_fleet);
}
ShipType::Bomber if count.bomber > 0 => {
count.bomber -= 1;
fleet_owned.set_owner(target_fleet);
}
ShipType::Transporter if count.transporter > 0 => {
count.transporter -= 1;
fleet_owned.set_owner(target_fleet);
}
_ => (),
}
}
}
}
}
}
}

impl FleetControlEvent {
pub fn move_(player: Entity, target: Entity, fleet: Entity, count: ShipCount) -> Self {
Self::Move(MoveArgs {
player,
target,
fleet,
count,
})
}
}

+ 10
- 5
space-crush-common/src/systems/fleet_owned_update.rs View File

@@ -93,8 +93,13 @@ impl<'a> System<'a> for FleetOwnedUpdate {
}
}

/* find new fleet ids */
for (fleet_owned, _) in (&fleet_owned, &self.fleet_owned_ids).join() {
self.fleet_ids.add(fleet_owned.owner().id());
}

/* update fleets */
for (fleet_id, fleet_info, _) in (&entities, &mut fleets, &self.fleet_ids).join() {
for (fleet_id, fleet, _) in (&entities, &mut fleets, &self.fleet_ids).join() {
let data = (&entities, &ships, &fleet_owned, &self.fleet_owned_ids);

for (ship_id, ship, fleet_owned, _) in data.join() {
@@ -105,17 +110,17 @@ impl<'a> System<'a> for FleetOwnedUpdate {
};

if old_match && !new_match {
let count = fleet_info.count_mut();
let count = fleet.count_mut();
let count = &mut count[ship.type_()];
*count = count.saturating_sub(1);

fleet_info.owned_mut().remove(ship_id.id());
fleet.owned_mut().remove(ship_id.id());
} else if !old_match && new_match {
let count = fleet_info.count_mut();
let count = fleet.count_mut();
let count = &mut count[ship.type_()];
*count += 1;

fleet_info.owned_mut().add(ship_id.id());
fleet.owned_mut().add(ship_id.id());
}
}
}


+ 2
- 0
space-crush-common/src/systems/mod.rs View File

@@ -1,9 +1,11 @@
mod fleet_control;
mod fleet_owned_update;
mod movement;
mod orbit_owned_update;
mod process;
mod ships;

pub use fleet_control::{FleetControl, FleetControlEvent};
pub use fleet_owned_update::FleetOwnedUpdate;
pub use movement::Movement;
pub use orbit_owned_update::OrbitOwnedUpdate;


+ 6
- 0
space-crush-common/src/systems/orbit_owned_update.rs View File

@@ -96,6 +96,11 @@ impl<'a> System<'a> for OrbitOwnedUpdate {
}
}

/* find new orbit ids */
for (orbit_owned, _) in (&orbit_owned, &self.orbit_owned_ids).join() {
self.orbit_ids.add(orbit_owned.owner().id());
}

/* update orbits */
for (orbit_id, orbit, _) in (&entities, &mut orbits, &self.orbit_ids).join() {
let data = (
@@ -121,6 +126,7 @@ impl<'a> System<'a> for OrbitOwnedUpdate {
orbit
.fleets_mut()
.resize_with(player_id + 1, Default::default);
// TODO: merge fleets if player already have a fleet on this orbit
orbit.fleets_mut()[player_id] = Some(fleet_id);
}
}


+ 1
- 1
space-crush-common/src/systems/ships.rs View File

@@ -181,7 +181,7 @@ impl Processor<'_> {
let orbit_max = orbit.max();

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

Vector2f::new(


Loading…
Cancel
Save