diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..32b156b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "auto_ops"] + path = auto_ops + url = https://github.com/carbotaniuman/auto_ops.git diff --git a/Cargo.lock b/Cargo.lock index 9e87709..36742c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,6 +83,10 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9ff149ed9780025acfdb36862d35b28856bb693ceb451259a7164442f22fdc3" +[[package]] +name = "auto_ops" +version = "0.1.0" + [[package]] name = "autocfg" version = "1.0.1" @@ -548,6 +552,7 @@ dependencies = [ name = "glc" version = "0.1.0" dependencies = [ + "auto_ops", "gl", "imagefmt", "serde", diff --git a/Cargo.toml b/Cargo.toml index 1733848..3bab33e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ default-members = [ ] [patch.crates-io] +auto_ops = { path = "./auto_ops" } gl = { path = "./gl" } glc = { path = "./glc" } space-crush-app = { path = "./space-crush-app" } diff --git a/auto_ops b/auto_ops new file mode 160000 index 0000000..59ebf01 --- /dev/null +++ b/auto_ops @@ -0,0 +1 @@ +Subproject commit 59ebf01379d09c0707d257c20efb21a3b1dc877b diff --git a/glc/Cargo.toml b/glc/Cargo.toml index 3029d71..b42b4e4 100644 --- a/glc/Cargo.toml +++ b/glc/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" default = [ ] [dependencies] +auto_ops = "0.1" gl = { version = "0.1", features = [ "generate_global" ] } imagefmt = "4.0" serde = { version = "1.0", optional = true, features = [ "derive" ] } diff --git a/glc/src/angle.rs b/glc/src/angle.rs index ddb83b3..42b81a9 100644 --- a/glc/src/angle.rs +++ b/glc/src/angle.rs @@ -1,7 +1,7 @@ use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; use std::f64::consts::PI; -use std::ops::{Add, Div, Mul, Neg, Sub}; +use auto_ops::impl_op_ex; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -47,99 +47,59 @@ where Self::Rad(value) => Self::Rad(value.abs()), } } -} - -impl Angle -where - T: Float, -{ - pub fn sin(self) -> T { - T::sin(self.into_rad().into_inner()) - } - - pub fn cos(self) -> T { - T::cos(self.into_rad().into_inner()) - } - /// Normalizes the angle to (-pi, pi] / (-180.0, 180.0] - pub fn normalize(self) -> Self { - match self { - Self::Deg(value) => Self::Deg(normalize(value, T::new(-180.0), T::new(180.0))), - Self::Rad(value) => Self::Rad(normalize(value, T::new(-PI), T::new(PI))), - } - } -} - -impl Neg for Angle -where - T: Neg + Numeric, -{ - type Output = Angle; - - fn neg(self) -> Self::Output { + fn _neg(self) -> Self { match self { Self::Deg(value) => Self::Deg(-value), Self::Rad(value) => Self::Rad(-value), } } -} -impl Add for Angle -where - T: Add + Numeric, -{ - type Output = Angle; - - fn add(self, v: Self) -> Self::Output { + fn _add(self, other: &Self) -> Self { match self { - Self::Deg(value) => Self::Deg(value + v.into_deg().into_inner()), - Self::Rad(value) => Self::Rad(value + v.into_rad().into_inner()), + Self::Deg(value) => Self::Deg(value + other.into_deg().into_inner()), + Self::Rad(value) => Self::Rad(value * other.into_rad().into_inner()), } } -} - -impl Sub for Angle -where - T: Sub + Numeric, -{ - type Output = Angle; - fn sub(self, v: Self) -> Self::Output { + fn _mul(self, other: T) -> Self { match self { - Self::Deg(value) => Self::Deg(value - v.into_deg().into_inner()), - Self::Rad(value) => Self::Rad(value - v.into_rad().into_inner()), + Self::Deg(value) => Self::Deg(value * other), + Self::Rad(value) => Self::Rad(value * other), } } } -impl Mul for Angle +impl Angle where - T: Mul + Numeric, + T: Float, { - type Output = Angle; - - fn mul(self, factor: T) -> Self::Output { - match self { - Self::Deg(value) => Self::Deg(value * factor), - Self::Rad(value) => Self::Rad(value * factor), - } + pub fn sin(self) -> T { + T::sin(self.into_rad().into_inner()) } -} -impl Div for Angle -where - T: Div + Numeric, -{ - type Output = Angle; + pub fn cos(self) -> T { + T::cos(self.into_rad().into_inner()) + } - fn div(self, factor: T) -> Self::Output { + /// Normalizes the angle to (-pi, pi] / (-180.0, 180.0] + pub fn normalize(self) -> Self { match self { - Self::Deg(value) => Self::Deg(value / factor), - Self::Rad(value) => Self::Rad(value / factor), + Self::Deg(value) => Self::Deg(normalize(value, T::new(-180.0), T::new(180.0))), + Self::Rad(value) => Self::Rad(normalize(value, T::new(-PI), T::new(PI))), } } } +impl_op_ex!(*|a: &f32, b: &Angle| -> Angle { b._mul(*a) }); +impl_op_ex!(- |a: &Angle| -> Angle { a._neg() }); +impl_op_ex!(+ |a: &Angle, b: &Angle| -> Angle { a._add(b) }); +impl_op_ex!(- |a: &Angle, b: &Angle| -> Angle { a._add(&b._neg()) }); +impl_op_ex!(* |a: &Angle, b: &T| -> Angle { a._mul(*b) }); +impl_op_ex!(/ |a: &Angle, b: &T| -> Angle { a._mul(T::one() / *b) }); +impl_op_ex!(+= |a: &mut Angle, b: &Angle| { *a = a._add(b); }); +impl_op_ex!(-= |a: &mut Angle, b: &Angle| { *a = a._add(&b._neg()); }); + impl PartialEq> for Angle where T: Numeric + PartialEq, diff --git a/glc/src/matrix.rs b/glc/src/matrix.rs index 7eff894..79bfc99 100644 --- a/glc/src/matrix.rs +++ b/glc/src/matrix.rs @@ -3,8 +3,9 @@ use std::borrow::Borrow; use std::convert::{AsMut, AsRef}; use std::fmt::{Debug, Formatter, Result as FmtResult}; -use std::ops::{Deref, DerefMut, Mul}; +use std::ops::{Deref, DerefMut}; +use auto_ops::impl_op_ex; #[cfg(feature = "serde")] use serde::{ de::{Deserializer, Error, MapAccess, SeqAccess, Visitor}, @@ -356,17 +357,9 @@ where } } -impl Mul for Matrix3 -where - T: Float, - M: Borrow>, -{ - type Output = Self; - - fn mul(self, rhs: M) -> Self::Output { - self.multiply(rhs.borrow()) - } -} +impl_op_ex!(* |a: &Matrix3, b: &Matrix3| -> Matrix3 { a.multiply(b) }); +impl_op_ex!(* |a: &Matrix3, b: &Vector2| -> Vector2 { a.transform(*b) }); +impl_op_ex!(*= |a: &mut Vector2, b: &Matrix3| { *a = b.transform(*a); }); /* Matrix4 */ @@ -638,35 +631,8 @@ where } } -macro_rules! impl_mul_mat4 { - ($input:ty, $output:ty, $func:ident) => { - impl Mul<$input> for Matrix4 - where - T: Float, - { - type Output = $output; - - fn mul(self, rhs: $input) -> Self::Output { - self.$func(rhs) - } - } - - impl Mul<$input> for &Matrix4 - where - T: Float, - { - type Output = $output; - - fn mul(self, rhs: $input) -> Self::Output { - self.$func(rhs) - } - } - }; -} - -impl_mul_mat4!(Matrix4, Matrix4, multiply); -impl_mul_mat4!(&Matrix4, Matrix4, multiply); -impl_mul_mat4!(Vector4, Vector4, transform); +impl_op_ex!(* |a: &Matrix4, b: &Matrix4| -> Matrix4 { a.multiply(b) }); +impl_op_ex!(* |a: &Matrix4, b: &Vector4| -> Vector4 { a.transform(*b) }); #[cfg(test)] mod tests { diff --git a/glc/src/vector.rs b/glc/src/vector.rs index 5733bb4..e1024c6 100644 --- a/glc/src/vector.rs +++ b/glc/src/vector.rs @@ -2,8 +2,9 @@ use std::convert::{AsMut, AsRef}; use std::fmt::{Debug, Formatter, Result as FmtResult}; -use std::ops::{Add, Deref, DerefMut, Mul, Neg, Sub}; +use std::ops::{Deref, DerefMut}; +use auto_ops::impl_op_ex; #[cfg(feature = "serde")] use serde::{ de::{Deserialize, Deserializer, Error}, @@ -296,74 +297,15 @@ where } } -impl Neg for Vector2 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn neg(self) -> Self::Output { - Self { - x: -self.x, - y: -self.y, - } - } -} - -impl Add for Vector2 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn add(mut self, other: Self) -> Self::Output { - self.x = self.x + other.x; - self.y = self.y + other.y; - - self - } -} - -impl Sub for Vector2 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn sub(mut self, other: Self) -> Self::Output { - self.x = self.x - other.x; - self.y = self.y - other.y; - - self - } -} - -impl Mul for Vector2 -where - T: Numeric, -{ - type Output = T; - - #[inline] - fn mul(self, rhs: Self) -> Self::Output { - self.scalar(&rhs) - } -} - -impl Mul for Vector2 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn mul(self, rhs: T) -> Self::Output { - self.multiply(rhs) - } -} +impl_op_ex!(*|a: &f32, b: &Vector2f| -> Vector2f { b.multiply(*a) }); +impl_op_ex!(- |a: &Vector2| -> Vector2 { Vector2 { x: -a.x, y: -a.y } }); +impl_op_ex!(+ |a: &Vector2, b: &Vector2| -> Vector2 { Vector2 { x: a.x + b.x, y: a.y + b.y } }); +impl_op_ex!(- |a: &Vector2, b: &Vector2| -> Vector2 { Vector2 { x: a.x - b.x, y: a.y - b.y } }); +impl_op_ex!(* |a: &Vector2, b: &Vector2| -> T { a.scalar(b) }); +impl_op_ex!(* |a: &Vector2, b: &T| -> Vector2 { a.multiply(*b) }); +impl_op_ex!(/ |a: &Vector2, b: &T| -> Vector2 { a.multiply(T::one() / *b) }); +impl_op_ex!(+= |a: &mut Vector2, b: &Vector2| { a.x = a.x + b.x; a.y = a.y + b.y; }); +impl_op_ex!(-= |a: &mut Vector2, b: &Vector2| { a.x = a.x - b.x; a.y = a.y - b.y; }); impl From> for Vector2 where @@ -445,6 +387,16 @@ where y: self.y, } } + + #[inline] + pub fn into_vec4(self) -> Vector4 { + Vector4 { + x: self.x, + y: self.y, + z: self.z, + w: T::one(), + } + } } impl Vector3 @@ -461,77 +413,15 @@ where } } -impl Neg for Vector3 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn neg(self) -> Self::Output { - Self { - x: -self.x, - y: -self.y, - z: -self.z, - } - } -} - -impl Add for Vector3 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn add(mut self, other: Self) -> Self::Output { - self.x = self.x + other.x; - self.y = self.y + other.y; - self.z = self.z + other.z; - - self - } -} - -impl Sub for Vector3 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn sub(mut self, other: Self) -> Self::Output { - self.x = self.x - other.x; - self.y = self.y - other.y; - self.z = self.z - other.z; - - self - } -} - -impl Mul for Vector3 -where - T: Numeric, -{ - type Output = T; - - #[inline] - fn mul(self, rhs: Self) -> Self::Output { - self.scalar(&rhs) - } -} - -impl Mul for Vector3 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn mul(self, rhs: T) -> Self::Output { - self.multiply(rhs) - } -} +impl_op_ex!(*|a: &f32, b: &Vector3f| -> Vector3f { b.multiply(*a) }); +impl_op_ex!(- |a: &Vector3| -> Vector3 { Vector3 { x: -a.x, y: -a.y, z: -a.z } }); +impl_op_ex!(+ |a: &Vector3, b: &Vector3| -> Vector3 { Vector3 { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z } }); +impl_op_ex!(- |a: &Vector3, b: &Vector3| -> Vector3 { Vector3 { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z } }); +impl_op_ex!(* |a: &Vector3, b: &Vector3| -> T { a.scalar(b) }); +impl_op_ex!(* |a: &Vector3, b: &T| -> Vector3 { a.multiply(*b) }); +impl_op_ex!(/ |a: &Vector3, b: &T| -> Vector3 { a.multiply(T::one() / *b) }); +impl_op_ex!(+= |a: &mut Vector3, b: &Vector3| { a.x = a.x + b.x; a.y = a.y + b.y; a.z = a.z + b.z; }); +impl_op_ex!(-= |a: &mut Vector3, b: &Vector3| { a.x = a.x - b.x; a.y = a.y - b.y; a.z = a.z - b.z; }); impl From> for Vector3 where @@ -665,52 +555,15 @@ where } } -impl Add for Vector4 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn add(self, other: Self) -> Self::Output { - (self.into_vec3() + other.into_vec3(), T::one()).into() - } -} - -impl Sub for Vector4 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn sub(self, other: Self) -> Self::Output { - (self.into_vec3() - other.into_vec3(), T::one()).into() - } -} - -impl Mul for Vector4 -where - T: Numeric, -{ - type Output = T; - - fn mul(self, rhs: Self) -> Self::Output { - self.scalar(&rhs) - } -} - -impl Mul for Vector4 -where - T: Numeric, -{ - type Output = Self; - - #[inline] - fn mul(self, rhs: T) -> Self::Output { - self.multiply(rhs) - } -} +impl_op_ex!(*|a: &f32, b: &Vector4f| -> Vector4f { b.multiply(*a) }); +impl_op_ex!(- |a: &Vector4| -> Vector4 { Vector4 { x: -a.x, y: -a.y, z: -a.z, w: a.w } }); +impl_op_ex!(+ |a: &Vector4, b: &Vector4| -> Vector4 { (a.into_vec3() + b.into_vec3()).into_vec4() }); +impl_op_ex!(- |a: &Vector4, b: &Vector4| -> Vector4 { (a.into_vec3() - b.into_vec3()).into_vec4() }); +impl_op_ex!(* |a: &Vector4, b: &Vector4| -> T { a.scalar(b) }); +impl_op_ex!(* |a: &Vector4, b: &T| -> Vector4 { a.multiply(*b) }); +impl_op_ex!(/ |a: &Vector4, b: &T| -> Vector4 { a.multiply(T::one() / *b) }); +impl_op_ex!(+= |a: &mut Vector4, b: &Vector4| { *a = (a.into_vec3() + b.into_vec3()).into_vec4(); }); +impl_op_ex!(-= |a: &mut Vector4, b: &Vector4| { *a = (a.into_vec3() - b.into_vec3()).into_vec4(); }); impl From> for Vector4 where diff --git a/space-crush-app/src/debug/fleets.rs b/space-crush-app/src/debug/fleets.rs index ca6a96e..3d8a6fc 100644 --- a/space-crush-app/src/debug/fleets.rs +++ b/space-crush-app/src/debug/fleets.rs @@ -65,7 +65,7 @@ impl<'a> System<'a> for Fleets { 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!(orbit.fleets().get(player.index())); let fleet_id = continue_if_none!(fleet_id); let fleet = continue_if_none!(fleets.get(*fleet_id)); @@ -73,15 +73,15 @@ impl<'a> System<'a> for Fleets { 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), + &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), + &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), + &create_circle(position.pos(), SHIP_ORBIT_DISTANCE_MAX * orbit.max()), ); gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); @@ -91,11 +91,13 @@ impl<'a> System<'a> for Fleets { 0, format!( "F:{}\nB:{}\nT:{}", - fleet.count.fighter, fleet.count.bomber, fleet.count.transporter + fleet.count().fighter, + fleet.count().bomber, + fleet.count().transporter ), ) .panic("Unable to update text") - .render_offset(&camera.world_to_window(position.pos)); + .render_offset(&camera.world_to_window(*position.pos())); } gl::blend_equation(gl::FUNC_ADD); @@ -103,7 +105,7 @@ impl<'a> System<'a> for Fleets { } } -fn create_circle(p: Vector2f, r: f32) -> Vec { +fn create_circle(p: &Vector2f, r: f32) -> Vec { let mut points = Vec::new(); for i in 0..=180 { diff --git a/space-crush-app/src/debug/ships.rs b/space-crush-app/src/debug/ships.rs index c1146fa..8a78881 100644 --- a/space-crush-app/src/debug/ships.rs +++ b/space-crush-app/src/debug/ships.rs @@ -33,25 +33,28 @@ impl<'a> System<'a> for Ships { gl::blend_func(gl::SRC_ALPHA, gl::ONE); for (position, velocity, ship) in (&positions, &velocities, &ships).join() { - let ship_pos = position.pos; + let ship_pos = position.pos(); geometry.render_lines( Vector4f::new(0.0, 0.0, 1.0, 0.2), - &[ship_pos, ship_pos + velocity.dir * velocity.speed], + &[*ship_pos, ship_pos + velocity.dir() * velocity.speed()], ); geometry.render_lines( Vector4f::new(1.0, 0.0, 0.0, 0.2), - &[ship_pos, ship_pos + ship.target_dir * 100.0], + &[*ship_pos, ship_pos + ship.target_dir() * 100.0], ); geometry.render_lines( Vector4f::new(1.0, 1.0, 1.0, 0.2), - &[ship_pos, ship.target_pos], + &[*ship_pos, *ship.target_pos()], ); - if let ShipObstacle::Known(obstacle) = ship.obstacle { - let obstacle_pos = continue_if_none!(positions.get(obstacle)).pos; + if let ShipObstacle::Known(obstacle) = ship.obstacle() { + let obstacle_pos = continue_if_none!(positions.get(obstacle)).pos(); - geometry.render_lines(Vector4f::new(0.0, 1.0, 0.0, 0.2), &[ship_pos, obstacle_pos]); + geometry.render_lines( + Vector4f::new(0.0, 1.0, 0.0, 0.2), + &[*ship_pos, *obstacle_pos], + ); } } diff --git a/space-crush-app/src/main.rs b/space-crush-app/src/main.rs index 12e793b..7b93d10 100644 --- a/space-crush-app/src/main.rs +++ b/space-crush-app/src/main.rs @@ -57,11 +57,10 @@ fn create_world(world: &mut World, player_id: Entity) { matrix::Angle, vector::{Vector2f, Vector4f}, }; - use smallvec::smallvec; use space_crush_common::{ components::{ Asteroid, AsteroidType, Fleet, FleetOwned, Obstacle, Orbit, OrbitOwned, Planet, Player, - PlayerOwned, Position, Shape, Ship, ShipType, Velocity, + PlayerOwned, Position, Ship, ShipType, Velocity, }, misc::{PersistWorld, Persistence}, }; @@ -71,13 +70,7 @@ fn create_world(world: &mut World, player_id: Entity) { world .system_data::>() - .insert( - player_id, - Player { - index: 0, - color: Vector4f::new(0.0, 0.5, 1.0, 0.1), - }, - ) + .insert(player_id, Player::new(Vector4f::new(0.0, 0.5, 1.0, 0.1))) .unwrap(); let planets = (0..3) @@ -88,16 +81,9 @@ fn create_world(world: &mut World, player_id: Entity) { world .create_entity() .marked::<::Marker>() - .with(PlayerOwned { owner: player_id }) - .with(Position { - pos: Vector2f::new(x, y), - shape: Shape::Circle(250.0), - }) - .with(Orbit { - min: 325.0, - max: 425.0, - fleets: smallvec![], - }) + .with(PlayerOwned::new(player_id)) + .with(Position::circle(Vector2f::new(x, y), 250.0)) + .with(Orbit::new(325.0, 425.0)) .with(Obstacle {}) .with(Planet {}) .build() @@ -114,31 +100,22 @@ fn create_world(world: &mut World, player_id: Entity) { world .create_entity() .marked::<::Marker>() - .with(Position { - pos: Vector2f::new(x, y), - shape: Shape::Circle(100.0), - }) - .with(Orbit { - min: 125.0, - max: 175.0, - fleets: smallvec![], - }) + .with(Position::circle(Vector2f::new(x, y), 100.0)) + .with(Orbit::new(125.0, 175.0)) .with(Obstacle {}) - .with(Asteroid { - type_: match i_x * i_y { - -1 => AsteroidType::Metal, - 1 => AsteroidType::Crystal, - _ => unreachable!(), - }, - }) + .with(Asteroid::new(match i_x * i_y { + -1 => AsteroidType::Metal, + 1 => AsteroidType::Crystal, + _ => unreachable!(), + })) .build(); } let fleet_id = world .create_entity() .marked::<::Marker>() - .with(PlayerOwned { owner: player_id }) - .with(OrbitOwned { owner: planets[1] }) + .with(PlayerOwned::new(player_id)) + .with(OrbitOwned::new(planets[1])) .with(Fleet::default()) .build(); @@ -152,28 +129,19 @@ fn create_world(world: &mut World, player_id: Entity) { world .create_entity() .marked::<::Marker>() - .with(PlayerOwned { owner: player_id }) - .with(FleetOwned { owner: fleet_id }) - .with(Position { - pos: Vector2f::new(x, y), - shape: Shape::Dot, - }) - .with(Velocity { - dir: Vector2f::new(random::() - 0.5, random::() - 0.5).normalize(), - speed: 100.0, - }) - .with(Ship { - type_: match i % 3 { - 0 => ShipType::Fighter, - 1 => ShipType::Bomber, - 2 => ShipType::Transporter, - _ => unreachable!(), - }, - agility: Angle::Deg(360.0), - target_pos: Default::default(), - target_dir: Default::default(), - obstacle: Default::default(), - }) + .with(PlayerOwned::new(player_id)) + .with(FleetOwned::new(fleet_id)) + .with(Position::dot(Vector2f::new(x, y))) + .with(Velocity::new( + Vector2f::new(random::() - 0.5, random::() - 0.5).normalize(), + 100.0, + )) + .with(Ship::new(match i % 3 { + 0 => ShipType::Fighter, + 1 => ShipType::Bomber, + 2 => ShipType::Transporter, + _ => unreachable!(), + })) .build(); } } diff --git a/space-crush-app/src/render/asteroids.rs b/space-crush-app/src/render/asteroids.rs index bcf7184..ac2c3e6 100644 --- a/space-crush-app/src/render/asteroids.rs +++ b/space-crush-app/src/render/asteroids.rs @@ -86,17 +86,17 @@ impl<'a> System<'a> for Asteroids { let _guard = BindGuard::new(&self.program); for (position, asteroid, owned) in (&position, &asteroid, owned.maybe()).join() { - let p_x = position.pos.x; - let p_y = position.pos.y; - let s = position.shape.circle().unwrap_or(ASTEROID_SIZE); + let p_x = position.pos().x; + let p_y = position.pos().y; + let s = position.shape().circle().unwrap_or(ASTEROID_SIZE); - let _guard = match asteroid.type_ { + let _guard = match asteroid.type_() { AsteroidType::Metal => BindGuard::new(&self.texture_metal), AsteroidType::Crystal => BindGuard::new(&self.texture_crystal), }; - let c = match owned.and_then(|owned| player.get(owned.owner)) { - Some(pv) => &pv.color, + let c = match owned.and_then(|owned| player.get(owned.owner())) { + Some(pv) => pv.color(), None => &PLAYER_COLOR_DEFAULT, }; diff --git a/space-crush-app/src/render/fleet_select.rs b/space-crush-app/src/render/fleet_select.rs index c882b31..a27d3d1 100644 --- a/space-crush-app/src/render/fleet_select.rs +++ b/space-crush-app/src/render/fleet_select.rs @@ -194,12 +194,12 @@ impl FleetSelect { let pos = d.camera.view_to_world(d.input_state.mouse_pos); let selection = d.game_state.selection.take(); for (position, orbit) in (&d.positions, &d.orbits).join() { - let r = orbit.max * orbit.max; - if (position.pos - pos).length_sqr() <= r { + 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 fleet_id = continue_if_none!(orbit.fleets.get(player_index)); + let player_index = 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 { @@ -225,7 +225,7 @@ impl FleetSelect { self.mouse_pos = d.input_state.mouse_pos; self.select_mode = SelectMode::Init(timeout); self.values_changed_once = false; - self.set_count(selection.count, &fleet.count); + self.set_count(selection.count, &fleet.count()); break; } @@ -282,12 +282,12 @@ impl FleetSelect { /* calculate values */ let selection = selection!(&d); let orbit_owned = orbit_owned!(&d, selection.fleet); - let position = position!(&d, orbit_owned.owner); + let position = position!(&d, orbit_owned.owner()); let fleet = fleet!(&d, selection.fleet); - self.marker = d.camera.view_to_world(self.mouse_pos) - position.pos; + self.marker = d.camera.view_to_world(self.mouse_pos) - position.pos(); self.zoom = d.camera.view().axis_x.as_vec3().length(); - self.shape_size = position.shape.radius(); + self.shape_size = position.shape().radius(); self.ring0 = self.shape_size + FLEET_SELECT_OFFSET / self.zoom; self.ring1 = self.ring0 + FLEET_SELECT_WIDTH / self.zoom; @@ -314,10 +314,10 @@ impl FleetSelect { x @ 0..=2 => { let mut count = selection.count; count[x] = usize::MAX; - self.set_count(count, &fleet.count); + self.set_count(count, fleet.count()); self.values[x] = 1.0; - self.update_values(&fleet.count); + self.update_values(fleet.count()); } _ => { self.count = ShipCount::all(); @@ -332,14 +332,14 @@ impl FleetSelect { match sector { x @ 0..=2 => { let mut count = selection.count; - count[x] = (fleet.count[x] as f32 * value).round() as usize; - self.set_count(count, &fleet.count); + count[x] = (fleet.count()[x] as f32 * value).round() as usize; + self.set_count(count, fleet.count()); self.values[x] = value; - self.update_values(&fleet.count); + self.update_values(fleet.count()); } _ => { - self.count = fleet.count * value; + self.count = *fleet.count() * value; self.values = value.into(); } } @@ -348,10 +348,10 @@ impl FleetSelect { x @ 0..=2 => { let mut count = selection.count; count[x] = 0; - self.set_count(count, &fleet.count); + self.set_count(count, fleet.count()); self.values[x] = 0.0; - self.update_values(&fleet.count); + self.update_values(fleet.count()); } _ => { self.count = Default::default(); @@ -361,7 +361,7 @@ impl FleetSelect { } /* update texts */ - let c = self.count.merge(&fleet.count); + let c = self.count.merge(fleet.count()); let _guard = self.cache.begin_update(); self.text_total .update(0, c.total().to_string()) @@ -436,13 +436,13 @@ impl FleetSelect { /* extract system data */ let selection = selection!(&d); let orbit_owned = orbit_owned!(&d, selection.fleet); - let position = position!(&d, orbit_owned.owner); + let position = position!(&d, orbit_owned.owner()); /* calculate shared values */ let size = self.ring1 + 50.0; let rings = Vector2f::new(self.ring0 / size, self.ring1 / size); - let px = position.pos.x; - let py = position.pos.y; + let px = position.pos().x; + let py = position.pos().y; let m = Matrix4f::new( Vector4f::new(size, 0.0, 0.0, 0.0), Vector4f::new(0.0, size, 0.0, 0.0), @@ -485,20 +485,20 @@ impl FleetSelect { if is_simple { self.text_total .color(Vector4f::new(1.0, 1.0, 1.0, alpha)) - .render_offset(&self.text_pos(self.marker, position.pos, d)); + .render_offset(&self.text_pos(self.marker, *position.pos(), d)); } else { self.text_total .color(Vector4f::new(1.0, 1.0, 1.0, alpha)) - .render_offset(&self.text_pos((0.0, 1.0), position.pos, d)); + .render_offset(&self.text_pos((0.0, 1.0), *position.pos(), d)); self.text_fighter .color(Vector4f::new(1.0, 1.0, 1.0, alpha)) - .render_offset(&self.text_pos((1.0, 0.0), position.pos, d)); + .render_offset(&self.text_pos((1.0, 0.0), *position.pos(), d)); self.text_bomber .color(Vector4f::new(1.0, 1.0, 1.0, alpha)) - .render_offset(&self.text_pos((0.0, -1.0), position.pos, d)); + .render_offset(&self.text_pos((0.0, -1.0), *position.pos(), d)); self.text_transporter .color(Vector4f::new(1.0, 1.0, 1.0, alpha)) - .render_offset(&self.text_pos((-1.0, 0.0), position.pos, d)); + .render_offset(&self.text_pos((-1.0, 0.0), *position.pos(), d)); } } diff --git a/space-crush-app/src/render/planets.rs b/space-crush-app/src/render/planets.rs index 876c4f5..3c5cf8b 100644 --- a/space-crush-app/src/render/planets.rs +++ b/space-crush-app/src/render/planets.rs @@ -84,12 +84,12 @@ impl<'a> System<'a> for Planets { let _guard = BindGuard::new(&self.texture); for (p, _, owned) in (&position, &planet, owned.maybe()).join() { - let p_x = p.pos.x; - let p_y = p.pos.y; - let s = p.shape.circle().unwrap_or(PLANET_SIZE); + let p_x = p.pos().x; + let p_y = p.pos().y; + let s = p.shape().circle().unwrap_or(PLANET_SIZE); - let c = match owned.and_then(|owned| player.get(owned.owner)) { - Some(pv) => &pv.color, + let c = match owned.and_then(|owned| player.get(owned.owner())) { + Some(pv) => &pv.color(), None => &PLAYER_COLOR_DEFAULT, }; diff --git a/space-crush-app/src/render/ships.rs b/space-crush-app/src/render/ships.rs index ce04b96..6a04100 100644 --- a/space-crush-app/src/render/ships.rs +++ b/space-crush-app/src/render/ships.rs @@ -90,21 +90,21 @@ impl<'a> System<'a> for Ships { let _guard = BindGuard::new(&self.program); for (p, v, ship, owned) in (&position, &velocity, &ship, owned.maybe()).join() { - let _guard = match ship.type_ { + let _guard = match ship.type_() { ShipType::Fighter => BindGuard::new(&self.texture_fighter), ShipType::Bomber => BindGuard::new(&self.texture_bomber), ShipType::Transporter => BindGuard::new(&self.texture_transporter), }; - let c = match owned.and_then(|owned| player.get(owned.owner)) { - Some(pv) => &pv.color, + let c = match owned.and_then(|owned| player.get(owned.owner())) { + Some(pv) => pv.color(), None => &PLAYER_COLOR_DEFAULT, }; - let p_x = p.pos.x; - let p_y = p.pos.y; - let d_x = v.dir.x; - let d_y = v.dir.y; + let p_x = p.pos().x; + let p_y = p.pos().y; + let d_x = v.dir().x; + let d_y = v.dir().y; let s = SHIP_SIZE; let m = Matrix4f::new( diff --git a/space-crush-app/src/systems/fleet_control.rs b/space-crush-app/src/systems/fleet_control.rs index eac6df4..f9254f3 100644 --- a/space-crush-app/src/systems/fleet_control.rs +++ b/space-crush-app/src/systems/fleet_control.rs @@ -69,11 +69,11 @@ impl<'a> System<'a> for FleetControl { 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 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!(orbit.fleets().get(player.index())); let fleet_id = *continue_if_none!(fleet_id); self.target_fleet = Some(fleet_id); @@ -82,23 +82,24 @@ impl<'a> System<'a> for FleetControl { } } } + #[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_ { + for (ship, fleet_owned, _) in (&ships, &mut fleet_owned, fleet.owned()).join() { + match ship.type_() { ShipType::Fighter if selection.count.fighter > 0 => { - fleet_owned.owner = target_fleet; + // TODO fleet_owned.set_owner(target_fleet); selection.count.fighter -= 1; } ShipType::Bomber if selection.count.bomber > 0 => { - fleet_owned.owner = target_fleet; + // TODO fleet_owned.set_owner(target_fleet); selection.count.bomber -= 1; } ShipType::Transporter if selection.count.transporter > 0 => { - fleet_owned.owner = target_fleet; + // TODO fleet_owned.set_owner(target_fleet); selection.count.transporter -= 1; } _ => (), diff --git a/space-crush-common/src/components/asteroid.rs b/space-crush-common/src/components/asteroid.rs index f0191a2..a588a5e 100644 --- a/space-crush-common/src/components/asteroid.rs +++ b/space-crush-common/src/components/asteroid.rs @@ -3,15 +3,27 @@ use specs::{Component, HashMapStorage}; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Asteroid { - pub type_: Type, + type_: Type, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub enum Type { Metal, Crystal, } +impl Asteroid { + #[inline] + pub fn new(type_: Type) -> Self { + Self { type_ } + } + + #[inline] + pub fn type_(&self) -> Type { + self.type_ + } +} + impl Component for Asteroid { type Storage = HashMapStorage; } diff --git a/space-crush-common/src/components/fleet.rs b/space-crush-common/src/components/fleet.rs index 4b11b3d..e168f98 100644 --- a/space-crush-common/src/components/fleet.rs +++ b/space-crush-common/src/components/fleet.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use serde::{Deserialize, Serialize}; use specs::{ error::NoError, @@ -10,13 +12,13 @@ use crate::{components::ShipCount, misc::FlaggedStorage}; #[derive(Default, Debug, Clone)] pub struct Fleet { - pub owned: BitSet, - pub count: ShipCount, + owned: BitSet, + count: ShipCount, } #[derive(Copy, Clone, Debug)] pub struct Owned { - pub owner: Entity, + owner: Entity, } #[derive(Serialize, Deserialize)] @@ -24,10 +26,46 @@ pub struct OwnedData { pub owner: M, } +impl Fleet { + #[inline] + pub fn owned(&self) -> &BitSet { + &self.owned + } + + #[inline] + pub(crate) fn owned_mut(&mut self) -> &mut BitSet { + &mut self.owned + } + + #[inline] + pub fn count(&self) -> &ShipCount { + &self.count + } + + #[inline] + pub(crate) fn count_mut(&mut self) -> &mut ShipCount { + &mut self.count + } +} + impl Component for Fleet { type Storage = HashMapStorage; } +impl Owned { + pub fn new(owner: Entity) -> Self { + Self { owner } + } + + pub fn owner(&self) -> Entity { + self.owner + } + + pub(crate) fn set_owner(&mut self, owner: Entity) { + self.owner = owner; + } +} + impl Component for Owned { type Storage = FlaggedStorage>; } diff --git a/space-crush-common/src/components/orbit.rs b/space-crush-common/src/components/orbit.rs index f909c78..bd23338 100644 --- a/space-crush-common/src/components/orbit.rs +++ b/space-crush-common/src/components/orbit.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use smallvec::smallvec; use smallvec::SmallVec; use specs::{ error::NoError, @@ -10,9 +11,9 @@ use crate::misc::FlaggedStorage; #[derive(Clone, Debug, Default)] pub struct Orbit { - pub min: f32, - pub max: f32, - pub fleets: SmallVec<[Option; 8]>, + min: f32, + max: f32, + fleets: Fleets, } #[derive(Serialize, Deserialize)] @@ -24,7 +25,7 @@ pub struct OrbitData { #[derive(Copy, Clone, Debug)] pub struct Owned { - pub owner: Entity, + owner: Entity, } #[derive(Serialize, Deserialize)] @@ -32,6 +33,39 @@ pub struct OwnedData { pub owner: M, } +type Fleets = SmallVec<[Option; 8]>; + +impl Orbit { + #[inline] + pub fn new(min: f32, max: f32) -> Self { + Self { + min, + max, + fleets: smallvec![], + } + } + + #[inline] + pub fn min(&self) -> f32 { + self.min + } + + #[inline] + pub fn max(&self) -> f32 { + self.max + } + + #[inline] + pub fn fleets(&self) -> &Fleets { + &self.fleets + } + + #[inline] + pub(crate) fn fleets_mut(&mut self) -> &mut Fleets { + &mut self.fleets + } +} + impl Component for Orbit { type Storage = HashMapStorage; } @@ -71,6 +105,16 @@ where } } +impl Owned { + pub fn new(owner: Entity) -> Self { + Self { owner } + } + + pub fn owner(&self) -> Entity { + self.owner + } +} + impl Component for Owned { type Storage = FlaggedStorage>; } diff --git a/space-crush-common/src/components/player.rs b/space-crush-common/src/components/player.rs index a9a6d19..ece7eb6 100644 --- a/space-crush-common/src/components/player.rs +++ b/space-crush-common/src/components/player.rs @@ -8,13 +8,13 @@ use specs::{ #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct Player { - pub index: usize, - pub color: Vector4f, + index: usize, + color: Vector4f, } #[derive(Copy, Clone, Debug)] pub struct Owned { - pub owner: Entity, + owner: Entity, } #[derive(Serialize, Deserialize)] @@ -22,10 +22,40 @@ pub struct OwnedData { pub owner: M, } +impl Player { + #[inline] + pub fn new(color: Vector4f) -> Self { + Self { + index: next_index(), + color, + } + } + + #[inline] + pub fn index(&self) -> usize { + self.index + } + + #[inline] + pub fn color(&self) -> &Vector4f { + &self.color + } +} + impl Component for Player { type Storage = HashMapStorage; } +impl Owned { + pub fn new(owner: Entity) -> Self { + Self { owner } + } + + pub fn owner(&self) -> Entity { + self.owner + } +} + impl Component for Owned { type Storage = HashMapStorage; } @@ -55,3 +85,11 @@ where Ok(Owned { 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) +} diff --git a/space-crush-common/src/components/position.rs b/space-crush-common/src/components/position.rs index 8543562..4e822ba 100644 --- a/space-crush-common/src/components/position.rs +++ b/space-crush-common/src/components/position.rs @@ -4,8 +4,8 @@ use specs::{Component, VecStorage}; #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct Position { - pub pos: Vector2f, - pub shape: Shape, + pos: Vector2f, + shape: Shape, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -14,6 +14,34 @@ pub enum Shape { Circle(f32), } +impl Position { + pub fn dot(pos: Vector2f) -> Self { + Self { + pos, + shape: Shape::Dot, + } + } + + pub fn circle(pos: Vector2f, radius: f32) -> Self { + Self { + pos, + shape: Shape::Circle(radius), + } + } + + pub fn pos(&self) -> &Vector2f { + &self.pos + } + + pub fn shape(&self) -> &Shape { + &self.shape + } + + pub(crate) fn pos_mut(&mut self) -> &mut Vector2f { + &mut self.pos + } +} + impl Component for Position { type Storage = VecStorage; } diff --git a/space-crush-common/src/components/ship.rs b/space-crush-common/src/components/ship.rs index 21c9e94..94af0d7 100644 --- a/space-crush-common/src/components/ship.rs +++ b/space-crush-common/src/components/ship.rs @@ -1,18 +1,22 @@ use std::cmp::min; use std::ops::{Index, IndexMut, Mul}; -use glc::{matrix::Angle, vector::Vector2f}; +use glc::vector::Vector2f; use serde::{Deserialize, Serialize}; use specs::{Component, Entity, VecStorage}; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Ship { - pub type_: Type, - pub agility: Angle, - pub target_pos: Vector2f, - pub target_dir: Vector2f, + type_: Type, + + #[serde(skip)] + obstacle: Obstacle, + #[serde(skip)] - pub obstacle: Obstacle, + target_pos: Vector2f, + + #[serde(skip)] + target_dir: Vector2f, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -36,6 +40,49 @@ pub enum Type { Transporter, } +impl Ship { + #[inline] + pub fn new(type_: Type) -> Self { + Self { + type_, + obstacle: Default::default(), + target_pos: Default::default(), + target_dir: Default::default(), + } + } + + #[inline] + pub fn type_(&self) -> Type { + self.type_ + } + + #[inline] + pub fn target_pos(&self) -> &Vector2f { + &self.target_pos + } + + #[inline] + pub fn target_dir(&self) -> &Vector2f { + &self.target_dir + } + + #[inline] + pub(crate) fn set_target(&mut self, pos: Vector2f, dir: Vector2f) { + self.target_pos = pos; + self.target_dir = dir; + } + + #[inline] + pub fn obstacle(&self) -> Obstacle { + self.obstacle + } + + #[inline] + pub(crate) fn set_obstacle(&mut self, value: Obstacle) { + self.obstacle = value; + } +} + impl Component for Ship { type Storage = VecStorage; } diff --git a/space-crush-common/src/components/velocity.rs b/space-crush-common/src/components/velocity.rs index 1f6f97a..34cbadd 100644 --- a/space-crush-common/src/components/velocity.rs +++ b/space-crush-common/src/components/velocity.rs @@ -4,8 +4,26 @@ use specs::{Component, VecStorage}; #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct Velocity { - pub dir: Vector2f, - pub speed: f32, + dir: Vector2f, + speed: f32, +} + +impl Velocity { + pub fn new(dir: Vector2f, speed: f32) -> Self { + Self { dir, speed } + } + + pub fn dir(&self) -> &Vector2f { + &self.dir + } + + pub fn dir_mut(&mut self) -> &mut Vector2f { + &mut self.dir + } + + pub fn speed(&self) -> f32 { + self.speed + } } impl Component for Velocity { diff --git a/space-crush-common/src/systems/fleet_owned_update.rs b/space-crush-common/src/systems/fleet_owned_update.rs index 4cf24bf..db64491 100644 --- a/space-crush-common/src/systems/fleet_owned_update.rs +++ b/space-crush-common/src/systems/fleet_owned_update.rs @@ -71,18 +71,24 @@ impl<'a> System<'a> for FleetOwnedUpdate { for event in events { match event { ComponentEvent::Inserted(id, fleet_owned) => { - self.fleet_ids.add(fleet_owned.owner.id()); + self.fleet_ids.add(fleet_owned.owner().id()); self.fleet_owned_ids.add(*id); } ComponentEvent::Modified(id, fleet_owned) => { - self.fleet_ids.add(fleet_owned.owner.id()); + self.fleet_ids.add(fleet_owned.owner().id()); self.fleet_owned_ids.add(*id); - *self.old_fleet_ids.entry(*id).or_insert(fleet_owned.owner) = fleet_owned.owner; + *self + .old_fleet_ids + .entry(*id) + .or_insert_with(|| fleet_owned.owner()) = fleet_owned.owner(); } ComponentEvent::Removed(id, fleet_owned) => { - self.fleet_ids.add(fleet_owned.owner.id()); + self.fleet_ids.add(fleet_owned.owner().id()); self.fleet_owned_ids.add(*id); - *self.old_fleet_ids.entry(*id).or_insert(fleet_owned.owner) = fleet_owned.owner; + *self + .old_fleet_ids + .entry(*id) + .or_insert_with(|| fleet_owned.owner()) = fleet_owned.owner(); } } } @@ -92,18 +98,24 @@ impl<'a> System<'a> for FleetOwnedUpdate { let data = (&entities, &ships, &fleet_owned, &self.fleet_owned_ids); for (ship_id, ship, fleet_owned, _) in data.join() { - let new_match = fleet_id == fleet_owned.owner; + let new_match = fleet_id == fleet_owned.owner(); let old_match = match self.old_fleet_ids.get(&ship_id.id()) { Some(old_fleet_id) => fleet_id == *old_fleet_id, None => false, }; 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); + let count = fleet_info.count_mut(); + let count = &mut count[ship.type_()]; + *count = count.saturating_sub(1); + + fleet_info.owned_mut().remove(ship_id.id()); } else if !old_match && new_match { - fleet_info.owned.add(ship_id.id()); - fleet_info.count[ship.type_] += 1; + let count = fleet_info.count_mut(); + let count = &mut count[ship.type_()]; + *count += 1; + + fleet_info.owned_mut().add(ship_id.id()); } } } diff --git a/space-crush-common/src/systems/movement.rs b/space-crush-common/src/systems/movement.rs index a22a986..5f8a8fe 100644 --- a/space-crush-common/src/systems/movement.rs +++ b/space-crush-common/src/systems/movement.rs @@ -32,7 +32,7 @@ impl<'a> System<'a> for Movement { .for_each(|(position, velocity)| { let delta = global.delta * global.world_speed; - position.pos = position.pos + velocity.dir * velocity.speed * delta; + *position.pos_mut() += velocity.dir() * velocity.speed() * delta; }); } } diff --git a/space-crush-common/src/systems/orbit_owned_update.rs b/space-crush-common/src/systems/orbit_owned_update.rs index ed8ce6a..8bd075b 100644 --- a/space-crush-common/src/systems/orbit_owned_update.rs +++ b/space-crush-common/src/systems/orbit_owned_update.rs @@ -74,18 +74,24 @@ impl<'a> System<'a> for OrbitOwnedUpdate { for event in events { match event { ComponentEvent::Inserted(id, orbit_owned) => { - self.orbit_ids.add(orbit_owned.owner.id()); + self.orbit_ids.add(orbit_owned.owner().id()); self.orbit_owned_ids.add(*id); } ComponentEvent::Modified(id, orbit_owned) => { - self.orbit_ids.add(orbit_owned.owner.id()); + self.orbit_ids.add(orbit_owned.owner().id()); self.orbit_owned_ids.add(*id); - *self.old_orbit_ids.entry(*id).or_insert(orbit_owned.owner) = orbit_owned.owner; + *self + .old_orbit_ids + .entry(*id) + .or_insert_with(|| orbit_owned.owner()) = orbit_owned.owner(); } ComponentEvent::Removed(id, orbit_owned) => { - self.orbit_ids.add(orbit_owned.owner.id()); + self.orbit_ids.add(orbit_owned.owner().id()); self.orbit_owned_ids.add(*id); - *self.old_orbit_ids.entry(*id).or_insert(orbit_owned.owner) = orbit_owned.owner; + *self + .old_orbit_ids + .entry(*id) + .or_insert_with(|| orbit_owned.owner()) = orbit_owned.owner(); } } } @@ -100,20 +106,22 @@ impl<'a> System<'a> for OrbitOwnedUpdate { ); for (fleet_id, orbit_owned, player_owned, _) in data.join() { - let new_match = orbit_id == orbit_owned.owner; + let new_match = orbit_id == orbit_owned.owner(); let old_match = match self.old_orbit_ids.get(&fleet_id.id()) { Some(old_orbit_id) => orbit_id == *old_orbit_id, None => false, }; - let player_id = player_owned.owner.id() as usize; + let player_id = player_owned.owner().id() as usize; if old_match && !new_match { - if let Some(fleet) = orbit.fleets.get_mut(player_id) { + if let Some(fleet) = orbit.fleets_mut().get_mut(player_id) { *fleet = None; } } else if !old_match && new_match { - orbit.fleets.resize_with(player_id + 1, Default::default); - orbit.fleets[player_id] = Some(fleet_id); + orbit + .fleets_mut() + .resize_with(player_id + 1, Default::default); + orbit.fleets_mut()[player_id] = Some(fleet_id); } } } diff --git a/space-crush-common/src/systems/ships.rs b/space-crush-common/src/systems/ships.rs index 555f240..3f36d62 100644 --- a/space-crush-common/src/systems/ships.rs +++ b/space-crush-common/src/systems/ships.rs @@ -139,24 +139,27 @@ impl Processor<'_> { position: &Position, fleet_owned: &FleetOwned, ) { - let fleet_id = fleet_owned.owner; + let fleet_id = fleet_owned.owner(); let orbit_owned = return_if_none!(self.orbit_owned.get(fleet_id)); - let orbit_id = orbit_owned.owner; + let orbit_id = orbit_owned.owner(); let orbit = return_if_none!(self.orbits.get(orbit_id)); - let orbit_pos = return_if_none!(self.positions.get(orbit_id)).pos; - let ship_pos = position.pos; - let target_pos = ship.target_pos; - let target_dir = ship.target_dir; + let orbit_pos = return_if_none!(self.positions.get(orbit_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 = ship_pos - orbit_pos; - let mut ship_to_target = target_pos - position.pos; + let mut ship_to_target = target_pos - ship_pos; let r_ship = orbit_to_ship.length_sqr(); let r_target = orbit_to_target.length_sqr(); - let target_in_orbit = (r_target <= sqr(orbit.max)) && (r_target >= sqr(orbit.min)); - let ship_in_orbit = r_ship < sqr(SHIP_ORBIT_DISTANCE_MAX * orbit.max); + let orbit_min = orbit.min(); + let orbit_max = orbit.max(); + + let target_in_orbit = (r_target <= sqr(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(id); let has_target = target_dir.length_sqr() != 0.0; @@ -164,9 +167,9 @@ impl Processor<'_> { /* 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 && orbit.max > 0.0 { + let target_pos = 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 ship_dir_vec3 = velocity.dir().into_vec3(); let dir = if orbit_to_ship_vec3.cross(&ship_dir_vec3).z > 0.0 { 1.0 @@ -174,34 +177,35 @@ impl Processor<'_> { -1.0 }; - let add = SHIP_ORBIT_ANGLE_DELTA_MIN + SHIP_ORBIT_ANGLE_DELTA_RND * random(); - let angle = orbit_to_ship.angle2(&VECTOR_2F_POS_X); - let angle = angle + add * dir / orbit.max; - let radius = orbit.min + (orbit.max - orbit.min) * random::(); + let orbit_min = orbit.min(); + let orbit_max = orbit.max(); + + let add = SHIP_ORBIT_ANGLE_DELTA_MIN + SHIP_ORBIT_ANGLE_DELTA_RND * random::(); + let angle = orbit_to_ship.angle2(&VECTOR_2F_POS_X) + add * dir / orbit_max; + let radius = orbit_min + (orbit_max - orbit_min) * random::(); Vector2f::new( orbit_pos.x + radius * angle.cos(), orbit_pos.y + radius * angle.sin(), ) } else { - ship.obstacle = ShipObstacle::Search; + ship.set_obstacle(ShipObstacle::Search); - orbit_pos + *orbit_pos }; - ship.target_pos = target_pos; - ship.target_dir = (target_pos - ship_pos).normalize(); + ship.set_target(target_pos, (target_pos - ship_pos).normalize()); ship_to_target = target_pos - ship_pos; } /* check if obstacle is still valid */ if ship_in_orbit { - ship.obstacle = ShipObstacle::Done; - } else if let ShipObstacle::Known(obstacle) = ship.obstacle { + ship.set_obstacle(ShipObstacle::Done); + } else if let ShipObstacle::Known(obstacle) = ship.obstacle() { if let Some(position) = self.positions.get(obstacle) { let obstacle_orbit = self.orbits.get(obstacle).unwrap(); - let obstacle_pos = position.pos; + let obstacle_pos = position.pos(); let ship_to_obstacle = obstacle_pos - ship_pos; let obstacle_angle = ship_to_target @@ -210,22 +214,22 @@ impl Processor<'_> { .into_inner() .abs(); - let orbit_sqr = obstacle_orbit.max * obstacle_orbit.max; + let orbit_sqr = obstacle_orbit.max() * obstacle_orbit.max(); if (obstacle_angle > 90.0 && ship_to_obstacle.length_sqr() > orbit_sqr) || obstacle_angle > 170.0 { - ship.obstacle = ShipObstacle::Search; + ship.set_obstacle(ShipObstacle::Search); } } else { - ship.obstacle = ShipObstacle::Search; + ship.set_obstacle(ShipObstacle::Search); } } /* find obstacle */ - if !ship_in_orbit && ship.obstacle == ShipObstacle::Search { + if !ship_in_orbit && ship.obstacle() == ShipObstacle::Search { let mut dist_sqr = f32::MAX; for (e, position, _) in (self.entities, self.positions, self.obstacles).join() { - let obstacle_pos = position.pos; + let obstacle_pos = position.pos(); let ship_to_obstacle = obstacle_pos - ship_pos; if ship_to_target * ship_to_obstacle < 0.0 { @@ -235,31 +239,32 @@ impl Processor<'_> { let len_sqr = ship_to_obstacle.length_sqr(); if len_sqr < dist_sqr { dist_sqr = len_sqr; - ship.obstacle = ShipObstacle::Known(e); + ship.set_obstacle(ShipObstacle::Known(e)); } } - if let ShipObstacle::Known(e) = ship.obstacle { - if e == fleet_owned.owner { - ship.obstacle = ShipObstacle::Done; + if let ShipObstacle::Known(e) = ship.obstacle() { + if e == fleet_owned.owner() { + ship.set_obstacle(ShipObstacle::Done); } } } /* check the obstacle */ let mut expected_dir = ship_to_target; - if let ShipObstacle::Known(obstacle) = ship.obstacle { + if let ShipObstacle::Known(obstacle) = ship.obstacle() { let obstacle_pos = self.positions.get(obstacle).unwrap(); let obstacle_orbit = self.orbits.get(obstacle).unwrap(); - let ship_to_obstacle = obstacle_pos.pos - ship_pos; + let ship_to_obstacle = obstacle_pos.pos() - ship_pos; + + let orbit_min = obstacle_orbit.min(); + let orbit_max = obstacle_orbit.max(); let orbit = ship_to_obstacle.length(); - if orbit < obstacle_orbit.max { - let orbit_min = obstacle_orbit.min; - let orbit_max = obstacle_orbit.max; + if orbit < orbit_max { let mut tangent = Vector2f::new(-ship_to_obstacle.y, ship_to_obstacle.x); - let radius = obstacle_pos.shape.radius(); + let radius = obstacle_pos.shape().radius(); let mut adjust_low = linear_step(orbit_min, radius, orbit); let adjust_high = 1.0 - linear_step(orbit_max, orbit_min, orbit); @@ -277,17 +282,13 @@ impl Processor<'_> { } /* update ship direction */ - let angle = expected_dir.angle2(&velocity.dir); + let angle = expected_dir.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 agility = SHIP_ORBIT_AGILITY; let rot_speed = agility * linear_step(0.0, 45.0, angle.abs().into_deg().into_inner()); - velocity.dir = Matrix3f::rotate(rot_speed * -dir * self.delta).transform(velocity.dir); + *velocity.dir_mut() *= Matrix3f::rotate(rot_speed * -dir * self.delta); } } }