@@ -0,0 +1,3 @@ | |||||
[submodule "auto_ops"] | |||||
path = auto_ops | |||||
url = https://github.com/carbotaniuman/auto_ops.git |
@@ -83,6 +83,10 @@ version = "0.3.6" | |||||
source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
checksum = "c9ff149ed9780025acfdb36862d35b28856bb693ceb451259a7164442f22fdc3" | checksum = "c9ff149ed9780025acfdb36862d35b28856bb693ceb451259a7164442f22fdc3" | ||||
[[package]] | |||||
name = "auto_ops" | |||||
version = "0.1.0" | |||||
[[package]] | [[package]] | ||||
name = "autocfg" | name = "autocfg" | ||||
version = "1.0.1" | version = "1.0.1" | ||||
@@ -548,6 +552,7 @@ dependencies = [ | |||||
name = "glc" | name = "glc" | ||||
version = "0.1.0" | version = "0.1.0" | ||||
dependencies = [ | dependencies = [ | ||||
"auto_ops", | |||||
"gl", | "gl", | ||||
"imagefmt", | "imagefmt", | ||||
"serde", | "serde", | ||||
@@ -11,6 +11,7 @@ default-members = [ | |||||
] | ] | ||||
[patch.crates-io] | [patch.crates-io] | ||||
auto_ops = { path = "./auto_ops" } | |||||
gl = { path = "./gl" } | gl = { path = "./gl" } | ||||
glc = { path = "./glc" } | glc = { path = "./glc" } | ||||
space-crush-app = { path = "./space-crush-app" } | space-crush-app = { path = "./space-crush-app" } | ||||
@@ -0,0 +1 @@ | |||||
Subproject commit 59ebf01379d09c0707d257c20efb21a3b1dc877b |
@@ -8,6 +8,7 @@ edition = "2018" | |||||
default = [ ] | default = [ ] | ||||
[dependencies] | [dependencies] | ||||
auto_ops = "0.1" | |||||
gl = { version = "0.1", features = [ "generate_global" ] } | gl = { version = "0.1", features = [ "generate_global" ] } | ||||
imagefmt = "4.0" | imagefmt = "4.0" | ||||
serde = { version = "1.0", optional = true, features = [ "derive" ] } | serde = { version = "1.0", optional = true, features = [ "derive" ] } | ||||
@@ -1,7 +1,7 @@ | |||||
use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; | use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; | ||||
use std::f64::consts::PI; | use std::f64::consts::PI; | ||||
use std::ops::{Add, Div, Mul, Neg, Sub}; | |||||
use auto_ops::impl_op_ex; | |||||
#[cfg(feature = "serde")] | #[cfg(feature = "serde")] | ||||
use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||
@@ -47,99 +47,59 @@ where | |||||
Self::Rad(value) => Self::Rad(value.abs()), | Self::Rad(value) => Self::Rad(value.abs()), | ||||
} | } | ||||
} | } | ||||
} | |||||
impl<T> Angle<T> | |||||
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<T> Neg for Angle<T> | |||||
where | |||||
T: Neg + Numeric, | |||||
{ | |||||
type Output = Angle<T>; | |||||
fn neg(self) -> Self::Output { | |||||
fn _neg(self) -> Self { | |||||
match self { | match self { | ||||
Self::Deg(value) => Self::Deg(-value), | Self::Deg(value) => Self::Deg(-value), | ||||
Self::Rad(value) => Self::Rad(-value), | Self::Rad(value) => Self::Rad(-value), | ||||
} | } | ||||
} | } | ||||
} | |||||
impl<T> Add for Angle<T> | |||||
where | |||||
T: Add<T, Output = T> + Numeric, | |||||
{ | |||||
type Output = Angle<T>; | |||||
fn add(self, v: Self) -> Self::Output { | |||||
fn _add(self, other: &Self) -> Self { | |||||
match 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<T> Sub for Angle<T> | |||||
where | |||||
T: Sub<T, Output = T> + Numeric, | |||||
{ | |||||
type Output = Angle<T>; | |||||
fn sub(self, v: Self) -> Self::Output { | |||||
fn _mul(self, other: T) -> Self { | |||||
match 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<T> Mul<T> for Angle<T> | |||||
impl<T> Angle<T> | |||||
where | where | ||||
T: Mul<T, Output = T> + Numeric, | |||||
T: Float, | |||||
{ | { | ||||
type Output = Angle<T>; | |||||
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<T> Div<T> for Angle<T> | |||||
where | |||||
T: Div<T, Output = T> + Numeric, | |||||
{ | |||||
type Output = Angle<T>; | |||||
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 { | 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<f32>| -> Angle<f32> { b._mul(*a) }); | |||||
impl_op_ex!(- <T: Numeric> |a: &Angle<T>| -> Angle<T> { a._neg() }); | |||||
impl_op_ex!(+ <T: Numeric> |a: &Angle<T>, b: &Angle<T>| -> Angle<T> { a._add(b) }); | |||||
impl_op_ex!(- <T: Numeric> |a: &Angle<T>, b: &Angle<T>| -> Angle<T> { a._add(&b._neg()) }); | |||||
impl_op_ex!(* <T: Numeric> |a: &Angle<T>, b: &T| -> Angle<T> { a._mul(*b) }); | |||||
impl_op_ex!(/ <T: Numeric> |a: &Angle<T>, b: &T| -> Angle<T> { a._mul(T::one() / *b) }); | |||||
impl_op_ex!(+= <T: Numeric> |a: &mut Angle<T>, b: &Angle<T>| { *a = a._add(b); }); | |||||
impl_op_ex!(-= <T: Numeric> |a: &mut Angle<T>, b: &Angle<T>| { *a = a._add(&b._neg()); }); | |||||
impl<T, S> PartialEq<Angle<S>> for Angle<T> | impl<T, S> PartialEq<Angle<S>> for Angle<T> | ||||
where | where | ||||
T: Numeric + PartialEq<S>, | T: Numeric + PartialEq<S>, | ||||
@@ -3,8 +3,9 @@ | |||||
use std::borrow::Borrow; | use std::borrow::Borrow; | ||||
use std::convert::{AsMut, AsRef}; | use std::convert::{AsMut, AsRef}; | ||||
use std::fmt::{Debug, Formatter, Result as FmtResult}; | 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")] | #[cfg(feature = "serde")] | ||||
use serde::{ | use serde::{ | ||||
de::{Deserializer, Error, MapAccess, SeqAccess, Visitor}, | de::{Deserializer, Error, MapAccess, SeqAccess, Visitor}, | ||||
@@ -356,17 +357,9 @@ where | |||||
} | } | ||||
} | } | ||||
impl<T, M> Mul<M> for Matrix3<T> | |||||
where | |||||
T: Float, | |||||
M: Borrow<Matrix3<T>>, | |||||
{ | |||||
type Output = Self; | |||||
fn mul(self, rhs: M) -> Self::Output { | |||||
self.multiply(rhs.borrow()) | |||||
} | |||||
} | |||||
impl_op_ex!(* <T: Float> |a: &Matrix3<T>, b: &Matrix3<T>| -> Matrix3<T> { a.multiply(b) }); | |||||
impl_op_ex!(* <T: Float> |a: &Matrix3<T>, b: &Vector2<T>| -> Vector2<T> { a.transform(*b) }); | |||||
impl_op_ex!(*= <T: Float> |a: &mut Vector2<T>, b: &Matrix3<T>| { *a = b.transform(*a); }); | |||||
/* Matrix4 */ | /* Matrix4 */ | ||||
@@ -638,35 +631,8 @@ where | |||||
} | } | ||||
} | } | ||||
macro_rules! impl_mul_mat4 { | |||||
($input:ty, $output:ty, $func:ident) => { | |||||
impl<T> Mul<$input> for Matrix4<T> | |||||
where | |||||
T: Float, | |||||
{ | |||||
type Output = $output; | |||||
fn mul(self, rhs: $input) -> Self::Output { | |||||
self.$func(rhs) | |||||
} | |||||
} | |||||
impl<T> Mul<$input> for &Matrix4<T> | |||||
where | |||||
T: Float, | |||||
{ | |||||
type Output = $output; | |||||
fn mul(self, rhs: $input) -> Self::Output { | |||||
self.$func(rhs) | |||||
} | |||||
} | |||||
}; | |||||
} | |||||
impl_mul_mat4!(Matrix4<T>, Matrix4<T>, multiply); | |||||
impl_mul_mat4!(&Matrix4<T>, Matrix4<T>, multiply); | |||||
impl_mul_mat4!(Vector4<T>, Vector4<T>, transform); | |||||
impl_op_ex!(* <T: Float> |a: &Matrix4<T>, b: &Matrix4<T>| -> Matrix4<T> { a.multiply(b) }); | |||||
impl_op_ex!(* <T: Float> |a: &Matrix4<T>, b: &Vector4<T>| -> Vector4<T> { a.transform(*b) }); | |||||
#[cfg(test)] | #[cfg(test)] | ||||
mod tests { | mod tests { | ||||
@@ -2,8 +2,9 @@ | |||||
use std::convert::{AsMut, AsRef}; | use std::convert::{AsMut, AsRef}; | ||||
use std::fmt::{Debug, Formatter, Result as FmtResult}; | 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")] | #[cfg(feature = "serde")] | ||||
use serde::{ | use serde::{ | ||||
de::{Deserialize, Deserializer, Error}, | de::{Deserialize, Deserializer, Error}, | ||||
@@ -296,74 +297,15 @@ where | |||||
} | } | ||||
} | } | ||||
impl<T> Neg for Vector2<T> | |||||
where | |||||
T: Numeric, | |||||
{ | |||||
type Output = Self; | |||||
#[inline] | |||||
fn neg(self) -> Self::Output { | |||||
Self { | |||||
x: -self.x, | |||||
y: -self.y, | |||||
} | |||||
} | |||||
} | |||||
impl<T> Add for Vector2<T> | |||||
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<T> Sub for Vector2<T> | |||||
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<T> Mul for Vector2<T> | |||||
where | |||||
T: Numeric, | |||||
{ | |||||
type Output = T; | |||||
#[inline] | |||||
fn mul(self, rhs: Self) -> Self::Output { | |||||
self.scalar(&rhs) | |||||
} | |||||
} | |||||
impl<T> Mul<T> for Vector2<T> | |||||
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!(- <T: Numeric> |a: &Vector2<T>| -> Vector2<T> { Vector2 { x: -a.x, y: -a.y } }); | |||||
impl_op_ex!(+ <T: Numeric> |a: &Vector2<T>, b: &Vector2<T>| -> Vector2<T> { Vector2 { x: a.x + b.x, y: a.y + b.y } }); | |||||
impl_op_ex!(- <T: Numeric> |a: &Vector2<T>, b: &Vector2<T>| -> Vector2<T> { Vector2 { x: a.x - b.x, y: a.y - b.y } }); | |||||
impl_op_ex!(* <T: Numeric> |a: &Vector2<T>, b: &Vector2<T>| -> T { a.scalar(b) }); | |||||
impl_op_ex!(* <T: Numeric> |a: &Vector2<T>, b: &T| -> Vector2<T> { a.multiply(*b) }); | |||||
impl_op_ex!(/ <T: Numeric> |a: &Vector2<T>, b: &T| -> Vector2<T> { a.multiply(T::one() / *b) }); | |||||
impl_op_ex!(+= <T: Numeric> |a: &mut Vector2<T>, b: &Vector2<T>| { a.x = a.x + b.x; a.y = a.y + b.y; }); | |||||
impl_op_ex!(-= <T: Numeric> |a: &mut Vector2<T>, b: &Vector2<T>| { a.x = a.x - b.x; a.y = a.y - b.y; }); | |||||
impl<T> From<Vector3<T>> for Vector2<T> | impl<T> From<Vector3<T>> for Vector2<T> | ||||
where | where | ||||
@@ -445,6 +387,16 @@ where | |||||
y: self.y, | y: self.y, | ||||
} | } | ||||
} | } | ||||
#[inline] | |||||
pub fn into_vec4(self) -> Vector4<T> { | |||||
Vector4 { | |||||
x: self.x, | |||||
y: self.y, | |||||
z: self.z, | |||||
w: T::one(), | |||||
} | |||||
} | |||||
} | } | ||||
impl<T> Vector3<T> | impl<T> Vector3<T> | ||||
@@ -461,77 +413,15 @@ where | |||||
} | } | ||||
} | } | ||||
impl<T> Neg for Vector3<T> | |||||
where | |||||
T: Numeric, | |||||
{ | |||||
type Output = Self; | |||||
#[inline] | |||||
fn neg(self) -> Self::Output { | |||||
Self { | |||||
x: -self.x, | |||||
y: -self.y, | |||||
z: -self.z, | |||||
} | |||||
} | |||||
} | |||||
impl<T> Add for Vector3<T> | |||||
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<T> Sub for Vector3<T> | |||||
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<T> Mul for Vector3<T> | |||||
where | |||||
T: Numeric, | |||||
{ | |||||
type Output = T; | |||||
#[inline] | |||||
fn mul(self, rhs: Self) -> Self::Output { | |||||
self.scalar(&rhs) | |||||
} | |||||
} | |||||
impl<T> Mul<T> for Vector3<T> | |||||
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!(- <T: Numeric> |a: &Vector3<T>| -> Vector3<T> { Vector3 { x: -a.x, y: -a.y, z: -a.z } }); | |||||
impl_op_ex!(+ <T: Numeric> |a: &Vector3<T>, b: &Vector3<T>| -> Vector3<T> { Vector3 { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z } }); | |||||
impl_op_ex!(- <T: Numeric> |a: &Vector3<T>, b: &Vector3<T>| -> Vector3<T> { Vector3 { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z } }); | |||||
impl_op_ex!(* <T: Numeric> |a: &Vector3<T>, b: &Vector3<T>| -> T { a.scalar(b) }); | |||||
impl_op_ex!(* <T: Numeric> |a: &Vector3<T>, b: &T| -> Vector3<T> { a.multiply(*b) }); | |||||
impl_op_ex!(/ <T: Numeric> |a: &Vector3<T>, b: &T| -> Vector3<T> { a.multiply(T::one() / *b) }); | |||||
impl_op_ex!(+= <T: Numeric> |a: &mut Vector3<T>, b: &Vector3<T>| { a.x = a.x + b.x; a.y = a.y + b.y; a.z = a.z + b.z; }); | |||||
impl_op_ex!(-= <T: Numeric> |a: &mut Vector3<T>, b: &Vector3<T>| { a.x = a.x - b.x; a.y = a.y - b.y; a.z = a.z - b.z; }); | |||||
impl<T> From<Vector2<T>> for Vector3<T> | impl<T> From<Vector2<T>> for Vector3<T> | ||||
where | where | ||||
@@ -665,52 +555,15 @@ where | |||||
} | } | ||||
} | } | ||||
impl<T> Add for Vector4<T> | |||||
where | |||||
T: Numeric, | |||||
{ | |||||
type Output = Self; | |||||
#[inline] | |||||
fn add(self, other: Self) -> Self::Output { | |||||
(self.into_vec3() + other.into_vec3(), T::one()).into() | |||||
} | |||||
} | |||||
impl<T> Sub for Vector4<T> | |||||
where | |||||
T: Numeric, | |||||
{ | |||||
type Output = Self; | |||||
#[inline] | |||||
fn sub(self, other: Self) -> Self::Output { | |||||
(self.into_vec3() - other.into_vec3(), T::one()).into() | |||||
} | |||||
} | |||||
impl<T> Mul for Vector4<T> | |||||
where | |||||
T: Numeric, | |||||
{ | |||||
type Output = T; | |||||
fn mul(self, rhs: Self) -> Self::Output { | |||||
self.scalar(&rhs) | |||||
} | |||||
} | |||||
impl<T> Mul<T> for Vector4<T> | |||||
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!(- <T: Numeric> |a: &Vector4<T>| -> Vector4<T> { Vector4 { x: -a.x, y: -a.y, z: -a.z, w: a.w } }); | |||||
impl_op_ex!(+ <T: Numeric> |a: &Vector4<T>, b: &Vector4<T>| -> Vector4<T> { (a.into_vec3() + b.into_vec3()).into_vec4() }); | |||||
impl_op_ex!(- <T: Numeric> |a: &Vector4<T>, b: &Vector4<T>| -> Vector4<T> { (a.into_vec3() - b.into_vec3()).into_vec4() }); | |||||
impl_op_ex!(* <T: Numeric> |a: &Vector4<T>, b: &Vector4<T>| -> T { a.scalar(b) }); | |||||
impl_op_ex!(* <T: Numeric> |a: &Vector4<T>, b: &T| -> Vector4<T> { a.multiply(*b) }); | |||||
impl_op_ex!(/ <T: Numeric> |a: &Vector4<T>, b: &T| -> Vector4<T> { a.multiply(T::one() / *b) }); | |||||
impl_op_ex!(+= <T: Numeric> |a: &mut Vector4<T>, b: &Vector4<T>| { *a = (a.into_vec3() + b.into_vec3()).into_vec4(); }); | |||||
impl_op_ex!(-= <T: Numeric> |a: &mut Vector4<T>, b: &Vector4<T>| { *a = (a.into_vec3() - b.into_vec3()).into_vec4(); }); | |||||
impl<T> From<Vector2<T>> for Vector4<T> | impl<T> From<Vector2<T>> for Vector4<T> | ||||
where | where | ||||
@@ -65,7 +65,7 @@ impl<'a> System<'a> for Fleets { | |||||
gl::enable(gl::BLEND); | gl::enable(gl::BLEND); | ||||
for (position, orbit) in (&positions, &orbits).join() { | 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_id = continue_if_none!(fleet_id); | ||||
let fleet = continue_if_none!(fleets.get(*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); | gl::blend_equation(gl::FUNC_ADD); | ||||
geometry.render_lines( | geometry.render_lines( | ||||
Vector4f::new(0.5, 0.5, 0.5, 0.05), | 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( | geometry.render_lines( | ||||
Vector4f::new(0.5, 0.5, 0.5, 0.05), | 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( | geometry.render_lines( | ||||
Vector4f::new(0.5, 0.5, 0.5, 0.05), | 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); | gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); | ||||
@@ -91,11 +91,13 @@ impl<'a> System<'a> for Fleets { | |||||
0, | 0, | ||||
format!( | format!( | ||||
"F:{}\nB:{}\nT:{}", | "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") | .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); | gl::blend_equation(gl::FUNC_ADD); | ||||
@@ -103,7 +105,7 @@ impl<'a> System<'a> for Fleets { | |||||
} | } | ||||
} | } | ||||
fn create_circle(p: Vector2f, r: f32) -> Vec<Vector2f> { | |||||
fn create_circle(p: &Vector2f, r: f32) -> Vec<Vector2f> { | |||||
let mut points = Vec::new(); | let mut points = Vec::new(); | ||||
for i in 0..=180 { | for i in 0..=180 { | ||||
@@ -33,25 +33,28 @@ impl<'a> System<'a> for Ships { | |||||
gl::blend_func(gl::SRC_ALPHA, gl::ONE); | gl::blend_func(gl::SRC_ALPHA, gl::ONE); | ||||
for (position, velocity, ship) in (&positions, &velocities, &ships).join() { | for (position, velocity, ship) in (&positions, &velocities, &ships).join() { | ||||
let ship_pos = position.pos; | |||||
let ship_pos = position.pos(); | |||||
geometry.render_lines( | geometry.render_lines( | ||||
Vector4f::new(0.0, 0.0, 1.0, 0.2), | Vector4f::new(0.0, 0.0, 1.0, 0.2), | ||||
&[ship_pos, ship_pos + velocity.dir * velocity.speed], | |||||
&[*ship_pos, ship_pos + velocity.dir() * velocity.speed()], | |||||
); | ); | ||||
geometry.render_lines( | geometry.render_lines( | ||||
Vector4f::new(1.0, 0.0, 0.0, 0.2), | Vector4f::new(1.0, 0.0, 0.0, 0.2), | ||||
&[ship_pos, ship_pos + ship.target_dir * 100.0], | |||||
&[*ship_pos, ship_pos + ship.target_dir() * 100.0], | |||||
); | ); | ||||
geometry.render_lines( | geometry.render_lines( | ||||
Vector4f::new(1.0, 1.0, 1.0, 0.2), | 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], | |||||
); | |||||
} | } | ||||
} | } | ||||
@@ -57,11 +57,10 @@ fn create_world(world: &mut World, player_id: Entity) { | |||||
matrix::Angle, | matrix::Angle, | ||||
vector::{Vector2f, Vector4f}, | vector::{Vector2f, Vector4f}, | ||||
}; | }; | ||||
use smallvec::smallvec; | |||||
use space_crush_common::{ | use space_crush_common::{ | ||||
components::{ | components::{ | ||||
Asteroid, AsteroidType, Fleet, FleetOwned, Obstacle, Orbit, OrbitOwned, Planet, Player, | Asteroid, AsteroidType, Fleet, FleetOwned, Obstacle, Orbit, OrbitOwned, Planet, Player, | ||||
PlayerOwned, Position, Shape, Ship, ShipType, Velocity, | |||||
PlayerOwned, Position, Ship, ShipType, Velocity, | |||||
}, | }, | ||||
misc::{PersistWorld, Persistence}, | misc::{PersistWorld, Persistence}, | ||||
}; | }; | ||||
@@ -71,13 +70,7 @@ fn create_world(world: &mut World, player_id: Entity) { | |||||
world | world | ||||
.system_data::<WriteStorage<Player>>() | .system_data::<WriteStorage<Player>>() | ||||
.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(); | .unwrap(); | ||||
let planets = (0..3) | let planets = (0..3) | ||||
@@ -88,16 +81,9 @@ fn create_world(world: &mut World, player_id: Entity) { | |||||
world | world | ||||
.create_entity() | .create_entity() | ||||
.marked::<<PersistWorld as Persistence>::Marker>() | .marked::<<PersistWorld as Persistence>::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(Obstacle {}) | ||||
.with(Planet {}) | .with(Planet {}) | ||||
.build() | .build() | ||||
@@ -114,31 +100,22 @@ fn create_world(world: &mut World, player_id: Entity) { | |||||
world | world | ||||
.create_entity() | .create_entity() | ||||
.marked::<<PersistWorld as Persistence>::Marker>() | .marked::<<PersistWorld as Persistence>::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(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(); | .build(); | ||||
} | } | ||||
let fleet_id = world | let fleet_id = world | ||||
.create_entity() | .create_entity() | ||||
.marked::<<PersistWorld as Persistence>::Marker>() | .marked::<<PersistWorld as Persistence>::Marker>() | ||||
.with(PlayerOwned { owner: player_id }) | |||||
.with(OrbitOwned { owner: planets[1] }) | |||||
.with(PlayerOwned::new(player_id)) | |||||
.with(OrbitOwned::new(planets[1])) | |||||
.with(Fleet::default()) | .with(Fleet::default()) | ||||
.build(); | .build(); | ||||
@@ -152,28 +129,19 @@ fn create_world(world: &mut World, player_id: Entity) { | |||||
world | world | ||||
.create_entity() | .create_entity() | ||||
.marked::<<PersistWorld as Persistence>::Marker>() | .marked::<<PersistWorld as Persistence>::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::<f32>() - 0.5, random::<f32>() - 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::<f32>() - 0.5, random::<f32>() - 0.5).normalize(), | |||||
100.0, | |||||
)) | |||||
.with(Ship::new(match i % 3 { | |||||
0 => ShipType::Fighter, | |||||
1 => ShipType::Bomber, | |||||
2 => ShipType::Transporter, | |||||
_ => unreachable!(), | |||||
})) | |||||
.build(); | .build(); | ||||
} | } | ||||
} | } |
@@ -86,17 +86,17 @@ impl<'a> System<'a> for Asteroids { | |||||
let _guard = BindGuard::new(&self.program); | let _guard = BindGuard::new(&self.program); | ||||
for (position, asteroid, owned) in (&position, &asteroid, owned.maybe()).join() { | 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::Metal => BindGuard::new(&self.texture_metal), | ||||
AsteroidType::Crystal => BindGuard::new(&self.texture_crystal), | 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, | None => &PLAYER_COLOR_DEFAULT, | ||||
}; | }; | ||||
@@ -194,12 +194,12 @@ impl FleetSelect { | |||||
let pos = d.camera.view_to_world(d.input_state.mouse_pos); | 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.take(); | ||||
for (position, orbit) in (&d.positions, &d.orbits).join() { | 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_id = d.game_state.player_id; | ||||
let player = player!(&d, 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); | let fleet_id = *continue_if_none!(fleet_id); | ||||
d.game_state.selection = match selection { | d.game_state.selection = match selection { | ||||
@@ -225,7 +225,7 @@ impl FleetSelect { | |||||
self.mouse_pos = d.input_state.mouse_pos; | self.mouse_pos = d.input_state.mouse_pos; | ||||
self.select_mode = SelectMode::Init(timeout); | self.select_mode = SelectMode::Init(timeout); | ||||
self.values_changed_once = false; | self.values_changed_once = false; | ||||
self.set_count(selection.count, &fleet.count); | |||||
self.set_count(selection.count, &fleet.count()); | |||||
break; | break; | ||||
} | } | ||||
@@ -282,12 +282,12 @@ impl FleetSelect { | |||||
/* calculate values */ | /* calculate values */ | ||||
let selection = selection!(&d); | let selection = selection!(&d); | ||||
let orbit_owned = orbit_owned!(&d, selection.fleet); | 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); | 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.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.ring0 = self.shape_size + FLEET_SELECT_OFFSET / self.zoom; | ||||
self.ring1 = self.ring0 + FLEET_SELECT_WIDTH / self.zoom; | self.ring1 = self.ring0 + FLEET_SELECT_WIDTH / self.zoom; | ||||
@@ -314,10 +314,10 @@ impl FleetSelect { | |||||
x @ 0..=2 => { | x @ 0..=2 => { | ||||
let mut count = selection.count; | let mut count = selection.count; | ||||
count[x] = usize::MAX; | count[x] = usize::MAX; | ||||
self.set_count(count, &fleet.count); | |||||
self.set_count(count, fleet.count()); | |||||
self.values[x] = 1.0; | self.values[x] = 1.0; | ||||
self.update_values(&fleet.count); | |||||
self.update_values(fleet.count()); | |||||
} | } | ||||
_ => { | _ => { | ||||
self.count = ShipCount::all(); | self.count = ShipCount::all(); | ||||
@@ -332,14 +332,14 @@ impl FleetSelect { | |||||
match sector { | match sector { | ||||
x @ 0..=2 => { | x @ 0..=2 => { | ||||
let mut count = selection.count; | 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.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(); | self.values = value.into(); | ||||
} | } | ||||
} | } | ||||
@@ -348,10 +348,10 @@ impl FleetSelect { | |||||
x @ 0..=2 => { | x @ 0..=2 => { | ||||
let mut count = selection.count; | let mut count = selection.count; | ||||
count[x] = 0; | count[x] = 0; | ||||
self.set_count(count, &fleet.count); | |||||
self.set_count(count, fleet.count()); | |||||
self.values[x] = 0.0; | self.values[x] = 0.0; | ||||
self.update_values(&fleet.count); | |||||
self.update_values(fleet.count()); | |||||
} | } | ||||
_ => { | _ => { | ||||
self.count = Default::default(); | self.count = Default::default(); | ||||
@@ -361,7 +361,7 @@ impl FleetSelect { | |||||
} | } | ||||
/* update texts */ | /* update texts */ | ||||
let c = self.count.merge(&fleet.count); | |||||
let c = self.count.merge(fleet.count()); | |||||
let _guard = self.cache.begin_update(); | let _guard = self.cache.begin_update(); | ||||
self.text_total | self.text_total | ||||
.update(0, c.total().to_string()) | .update(0, c.total().to_string()) | ||||
@@ -436,13 +436,13 @@ impl FleetSelect { | |||||
/* extract system data */ | /* extract system data */ | ||||
let selection = selection!(&d); | let selection = selection!(&d); | ||||
let orbit_owned = orbit_owned!(&d, selection.fleet); | 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 */ | /* calculate shared values */ | ||||
let size = self.ring1 + 50.0; | let size = self.ring1 + 50.0; | ||||
let rings = Vector2f::new(self.ring0 / size, self.ring1 / size); | 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( | let m = Matrix4f::new( | ||||
Vector4f::new(size, 0.0, 0.0, 0.0), | Vector4f::new(size, 0.0, 0.0, 0.0), | ||||
Vector4f::new(0.0, size, 0.0, 0.0), | Vector4f::new(0.0, size, 0.0, 0.0), | ||||
@@ -485,20 +485,20 @@ impl FleetSelect { | |||||
if is_simple { | if is_simple { | ||||
self.text_total | self.text_total | ||||
.color(Vector4f::new(1.0, 1.0, 1.0, alpha)) | .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 { | } else { | ||||
self.text_total | self.text_total | ||||
.color(Vector4f::new(1.0, 1.0, 1.0, alpha)) | .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 | self.text_fighter | ||||
.color(Vector4f::new(1.0, 1.0, 1.0, alpha)) | .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 | self.text_bomber | ||||
.color(Vector4f::new(1.0, 1.0, 1.0, alpha)) | .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 | self.text_transporter | ||||
.color(Vector4f::new(1.0, 1.0, 1.0, alpha)) | .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)); | |||||
} | } | ||||
} | } | ||||
@@ -84,12 +84,12 @@ impl<'a> System<'a> for Planets { | |||||
let _guard = BindGuard::new(&self.texture); | let _guard = BindGuard::new(&self.texture); | ||||
for (p, _, owned) in (&position, &planet, owned.maybe()).join() { | 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, | None => &PLAYER_COLOR_DEFAULT, | ||||
}; | }; | ||||
@@ -90,21 +90,21 @@ impl<'a> System<'a> for Ships { | |||||
let _guard = BindGuard::new(&self.program); | let _guard = BindGuard::new(&self.program); | ||||
for (p, v, ship, owned) in (&position, &velocity, &ship, owned.maybe()).join() { | 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::Fighter => BindGuard::new(&self.texture_fighter), | ||||
ShipType::Bomber => BindGuard::new(&self.texture_bomber), | ShipType::Bomber => BindGuard::new(&self.texture_bomber), | ||||
ShipType::Transporter => BindGuard::new(&self.texture_transporter), | 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, | 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 s = SHIP_SIZE; | ||||
let m = Matrix4f::new( | let m = Matrix4f::new( | ||||
@@ -69,11 +69,11 @@ impl<'a> System<'a> for FleetControl { | |||||
MouseEvent::ButtonDown(button) if button == &config.input.fleet_move_button => { | MouseEvent::ButtonDown(button) if button == &config.input.fleet_move_button => { | ||||
let pos = camera.view_to_world(input_state.mouse_pos); | let pos = camera.view_to_world(input_state.mouse_pos); | ||||
for (position, orbit) in (&positions, &orbits).join() { | 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_id = game_state.player_id; | ||||
let player = continue_if_none!(players.get(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); | let fleet_id = *continue_if_none!(fleet_id); | ||||
self.target_fleet = Some(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 => { | MouseEvent::ButtonUp(button) if button == &config.input.fleet_move_button => { | ||||
let selection = game_state.selection.take(); | let selection = game_state.selection.take(); | ||||
let target_fleet = continue_if_none!(self.target_fleet.take()); | let target_fleet = continue_if_none!(self.target_fleet.take()); | ||||
let mut selection = continue_if_none!(selection); | let mut selection = continue_if_none!(selection); | ||||
let fleet = continue_if_none!(fleets.get(selection.fleet)); | 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 => { | ShipType::Fighter if selection.count.fighter > 0 => { | ||||
fleet_owned.owner = target_fleet; | |||||
// TODO fleet_owned.set_owner(target_fleet); | |||||
selection.count.fighter -= 1; | selection.count.fighter -= 1; | ||||
} | } | ||||
ShipType::Bomber if selection.count.bomber > 0 => { | ShipType::Bomber if selection.count.bomber > 0 => { | ||||
fleet_owned.owner = target_fleet; | |||||
// TODO fleet_owned.set_owner(target_fleet); | |||||
selection.count.bomber -= 1; | selection.count.bomber -= 1; | ||||
} | } | ||||
ShipType::Transporter if selection.count.transporter > 0 => { | ShipType::Transporter if selection.count.transporter > 0 => { | ||||
fleet_owned.owner = target_fleet; | |||||
// TODO fleet_owned.set_owner(target_fleet); | |||||
selection.count.transporter -= 1; | selection.count.transporter -= 1; | ||||
} | } | ||||
_ => (), | _ => (), | ||||
@@ -3,15 +3,27 @@ use specs::{Component, HashMapStorage}; | |||||
#[derive(Clone, Debug, Serialize, Deserialize)] | #[derive(Clone, Debug, Serialize, Deserialize)] | ||||
pub struct Asteroid { | pub struct Asteroid { | ||||
pub type_: Type, | |||||
type_: Type, | |||||
} | } | ||||
#[derive(Clone, Debug, Serialize, Deserialize)] | |||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)] | |||||
pub enum Type { | pub enum Type { | ||||
Metal, | Metal, | ||||
Crystal, | Crystal, | ||||
} | } | ||||
impl Asteroid { | |||||
#[inline] | |||||
pub fn new(type_: Type) -> Self { | |||||
Self { type_ } | |||||
} | |||||
#[inline] | |||||
pub fn type_(&self) -> Type { | |||||
self.type_ | |||||
} | |||||
} | |||||
impl Component for Asteroid { | impl Component for Asteroid { | ||||
type Storage = HashMapStorage<Self>; | type Storage = HashMapStorage<Self>; | ||||
} | } |
@@ -1,3 +1,5 @@ | |||||
#![allow(dead_code)] | |||||
use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||
use specs::{ | use specs::{ | ||||
error::NoError, | error::NoError, | ||||
@@ -10,13 +12,13 @@ use crate::{components::ShipCount, misc::FlaggedStorage}; | |||||
#[derive(Default, Debug, Clone)] | #[derive(Default, Debug, Clone)] | ||||
pub struct Fleet { | pub struct Fleet { | ||||
pub owned: BitSet, | |||||
pub count: ShipCount, | |||||
owned: BitSet, | |||||
count: ShipCount, | |||||
} | } | ||||
#[derive(Copy, Clone, Debug)] | #[derive(Copy, Clone, Debug)] | ||||
pub struct Owned { | pub struct Owned { | ||||
pub owner: Entity, | |||||
owner: Entity, | |||||
} | } | ||||
#[derive(Serialize, Deserialize)] | #[derive(Serialize, Deserialize)] | ||||
@@ -24,10 +26,46 @@ pub struct OwnedData<M> { | |||||
pub owner: M, | 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 { | impl Component for Fleet { | ||||
type Storage = HashMapStorage<Self>; | type Storage = HashMapStorage<Self>; | ||||
} | } | ||||
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 { | impl Component for Owned { | ||||
type Storage = FlaggedStorage<Self, VecStorage<Self>>; | type Storage = FlaggedStorage<Self, VecStorage<Self>>; | ||||
} | } | ||||
@@ -1,4 +1,5 @@ | |||||
use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||
use smallvec::smallvec; | |||||
use smallvec::SmallVec; | use smallvec::SmallVec; | ||||
use specs::{ | use specs::{ | ||||
error::NoError, | error::NoError, | ||||
@@ -10,9 +11,9 @@ use crate::misc::FlaggedStorage; | |||||
#[derive(Clone, Debug, Default)] | #[derive(Clone, Debug, Default)] | ||||
pub struct Orbit { | pub struct Orbit { | ||||
pub min: f32, | |||||
pub max: f32, | |||||
pub fleets: SmallVec<[Option<Entity>; 8]>, | |||||
min: f32, | |||||
max: f32, | |||||
fleets: Fleets, | |||||
} | } | ||||
#[derive(Serialize, Deserialize)] | #[derive(Serialize, Deserialize)] | ||||
@@ -24,7 +25,7 @@ pub struct OrbitData<M> { | |||||
#[derive(Copy, Clone, Debug)] | #[derive(Copy, Clone, Debug)] | ||||
pub struct Owned { | pub struct Owned { | ||||
pub owner: Entity, | |||||
owner: Entity, | |||||
} | } | ||||
#[derive(Serialize, Deserialize)] | #[derive(Serialize, Deserialize)] | ||||
@@ -32,6 +33,39 @@ pub struct OwnedData<M> { | |||||
pub owner: M, | pub owner: M, | ||||
} | } | ||||
type Fleets = SmallVec<[Option<Entity>; 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 { | impl Component for Orbit { | ||||
type Storage = HashMapStorage<Self>; | type Storage = HashMapStorage<Self>; | ||||
} | } | ||||
@@ -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 { | impl Component for Owned { | ||||
type Storage = FlaggedStorage<Self, HashMapStorage<Self>>; | type Storage = FlaggedStorage<Self, HashMapStorage<Self>>; | ||||
} | } | ||||
@@ -8,13 +8,13 @@ use specs::{ | |||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)] | #[derive(Clone, Debug, Default, Serialize, Deserialize)] | ||||
pub struct Player { | pub struct Player { | ||||
pub index: usize, | |||||
pub color: Vector4f, | |||||
index: usize, | |||||
color: Vector4f, | |||||
} | } | ||||
#[derive(Copy, Clone, Debug)] | #[derive(Copy, Clone, Debug)] | ||||
pub struct Owned { | pub struct Owned { | ||||
pub owner: Entity, | |||||
owner: Entity, | |||||
} | } | ||||
#[derive(Serialize, Deserialize)] | #[derive(Serialize, Deserialize)] | ||||
@@ -22,10 +22,40 @@ pub struct OwnedData<M> { | |||||
pub owner: M, | 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 { | impl Component for Player { | ||||
type Storage = HashMapStorage<Self>; | type Storage = HashMapStorage<Self>; | ||||
} | } | ||||
impl Owned { | |||||
pub fn new(owner: Entity) -> Self { | |||||
Self { owner } | |||||
} | |||||
pub fn owner(&self) -> Entity { | |||||
self.owner | |||||
} | |||||
} | |||||
impl Component for Owned { | impl Component for Owned { | ||||
type Storage = HashMapStorage<Self>; | type Storage = HashMapStorage<Self>; | ||||
} | } | ||||
@@ -55,3 +85,11 @@ where | |||||
Ok(Owned { owner }) | 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) | |||||
} |
@@ -4,8 +4,8 @@ use specs::{Component, VecStorage}; | |||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)] | #[derive(Clone, Debug, Default, Serialize, Deserialize)] | ||||
pub struct Position { | pub struct Position { | ||||
pub pos: Vector2f, | |||||
pub shape: Shape, | |||||
pos: Vector2f, | |||||
shape: Shape, | |||||
} | } | ||||
#[derive(Clone, Debug, Serialize, Deserialize)] | #[derive(Clone, Debug, Serialize, Deserialize)] | ||||
@@ -14,6 +14,34 @@ pub enum Shape { | |||||
Circle(f32), | 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 { | impl Component for Position { | ||||
type Storage = VecStorage<Self>; | type Storage = VecStorage<Self>; | ||||
} | } | ||||
@@ -1,18 +1,22 @@ | |||||
use std::cmp::min; | use std::cmp::min; | ||||
use std::ops::{Index, IndexMut, Mul}; | use std::ops::{Index, IndexMut, Mul}; | ||||
use glc::{matrix::Angle, vector::Vector2f}; | |||||
use glc::vector::Vector2f; | |||||
use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||
use specs::{Component, Entity, VecStorage}; | use specs::{Component, Entity, VecStorage}; | ||||
#[derive(Clone, Debug, Serialize, Deserialize)] | #[derive(Clone, Debug, Serialize, Deserialize)] | ||||
pub struct Ship { | pub struct Ship { | ||||
pub type_: Type, | |||||
pub agility: Angle<f32>, | |||||
pub target_pos: Vector2f, | |||||
pub target_dir: Vector2f, | |||||
type_: Type, | |||||
#[serde(skip)] | |||||
obstacle: Obstacle, | |||||
#[serde(skip)] | #[serde(skip)] | ||||
pub obstacle: Obstacle, | |||||
target_pos: Vector2f, | |||||
#[serde(skip)] | |||||
target_dir: Vector2f, | |||||
} | } | ||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)] | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||||
@@ -36,6 +40,49 @@ pub enum Type { | |||||
Transporter, | 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 { | impl Component for Ship { | ||||
type Storage = VecStorage<Self>; | type Storage = VecStorage<Self>; | ||||
} | } | ||||
@@ -4,8 +4,26 @@ use specs::{Component, VecStorage}; | |||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)] | #[derive(Clone, Debug, Default, Serialize, Deserialize)] | ||||
pub struct Velocity { | 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 { | impl Component for Velocity { | ||||
@@ -71,18 +71,24 @@ impl<'a> System<'a> for FleetOwnedUpdate { | |||||
for event in events { | for event in events { | ||||
match event { | match event { | ||||
ComponentEvent::Inserted(id, fleet_owned) => { | 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); | self.fleet_owned_ids.add(*id); | ||||
} | } | ||||
ComponentEvent::Modified(id, fleet_owned) => { | 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.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) => { | 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.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); | let data = (&entities, &ships, &fleet_owned, &self.fleet_owned_ids); | ||||
for (ship_id, ship, fleet_owned, _) in data.join() { | 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()) { | let old_match = match self.old_fleet_ids.get(&ship_id.id()) { | ||||
Some(old_fleet_id) => fleet_id == *old_fleet_id, | Some(old_fleet_id) => fleet_id == *old_fleet_id, | ||||
None => false, | None => false, | ||||
}; | }; | ||||
if old_match && !new_match { | 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 { | } 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()); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -32,7 +32,7 @@ impl<'a> System<'a> for Movement { | |||||
.for_each(|(position, velocity)| { | .for_each(|(position, velocity)| { | ||||
let delta = global.delta * global.world_speed; | let delta = global.delta * global.world_speed; | ||||
position.pos = position.pos + velocity.dir * velocity.speed * delta; | |||||
*position.pos_mut() += velocity.dir() * velocity.speed() * delta; | |||||
}); | }); | ||||
} | } | ||||
} | } |
@@ -74,18 +74,24 @@ impl<'a> System<'a> for OrbitOwnedUpdate { | |||||
for event in events { | for event in events { | ||||
match event { | match event { | ||||
ComponentEvent::Inserted(id, orbit_owned) => { | 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); | self.orbit_owned_ids.add(*id); | ||||
} | } | ||||
ComponentEvent::Modified(id, orbit_owned) => { | 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.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) => { | 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.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() { | 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()) { | let old_match = match self.old_orbit_ids.get(&fleet_id.id()) { | ||||
Some(old_orbit_id) => orbit_id == *old_orbit_id, | Some(old_orbit_id) => orbit_id == *old_orbit_id, | ||||
None => false, | 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 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; | *fleet = None; | ||||
} | } | ||||
} else if !old_match && new_match { | } 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); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -139,24 +139,27 @@ impl Processor<'_> { | |||||
position: &Position, | position: &Position, | ||||
fleet_owned: &FleetOwned, | 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_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 = 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_target = target_pos - orbit_pos; | ||||
let orbit_to_ship = ship_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_ship = orbit_to_ship.length_sqr(); | ||||
let r_target = orbit_to_target.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 need_update = self.need_update.contains(id); | ||||
let has_target = target_dir.length_sqr() != 0.0; | let has_target = target_dir.length_sqr() != 0.0; | ||||
@@ -164,9 +167,9 @@ impl Processor<'_> { | |||||
/* check and update target posistion */ | /* check and update target posistion */ | ||||
if need_update || !has_target || passed_target || ship_in_orbit != target_in_orbit { | 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 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 { | let dir = if orbit_to_ship_vec3.cross(&ship_dir_vec3).z > 0.0 { | ||||
1.0 | 1.0 | ||||
@@ -174,34 +177,35 @@ impl Processor<'_> { | |||||
-1.0 | -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::<f32>(); | |||||
let orbit_min = orbit.min(); | |||||
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 radius = orbit_min + (orbit_max - orbit_min) * random::<f32>(); | |||||
Vector2f::new( | Vector2f::new( | ||||
orbit_pos.x + radius * angle.cos(), | orbit_pos.x + radius * angle.cos(), | ||||
orbit_pos.y + radius * angle.sin(), | orbit_pos.y + radius * angle.sin(), | ||||
) | ) | ||||
} else { | } 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; | ship_to_target = target_pos - ship_pos; | ||||
} | } | ||||
/* check if obstacle is still valid */ | /* check if obstacle is still valid */ | ||||
if ship_in_orbit { | 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) { | if let Some(position) = self.positions.get(obstacle) { | ||||
let obstacle_orbit = self.orbits.get(obstacle).unwrap(); | 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 ship_to_obstacle = obstacle_pos - ship_pos; | ||||
let obstacle_angle = ship_to_target | let obstacle_angle = ship_to_target | ||||
@@ -210,22 +214,22 @@ impl Processor<'_> { | |||||
.into_inner() | .into_inner() | ||||
.abs(); | .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) | if (obstacle_angle > 90.0 && ship_to_obstacle.length_sqr() > orbit_sqr) | ||||
|| obstacle_angle > 170.0 | || obstacle_angle > 170.0 | ||||
{ | { | ||||
ship.obstacle = ShipObstacle::Search; | |||||
ship.set_obstacle(ShipObstacle::Search); | |||||
} | } | ||||
} else { | } else { | ||||
ship.obstacle = ShipObstacle::Search; | |||||
ship.set_obstacle(ShipObstacle::Search); | |||||
} | } | ||||
} | } | ||||
/* find obstacle */ | /* find obstacle */ | ||||
if !ship_in_orbit && ship.obstacle == ShipObstacle::Search { | |||||
if !ship_in_orbit && ship.obstacle() == ShipObstacle::Search { | |||||
let mut dist_sqr = f32::MAX; | let mut dist_sqr = f32::MAX; | ||||
for (e, position, _) in (self.entities, self.positions, self.obstacles).join() { | 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; | let ship_to_obstacle = obstacle_pos - ship_pos; | ||||
if ship_to_target * ship_to_obstacle < 0.0 { | if ship_to_target * ship_to_obstacle < 0.0 { | ||||
@@ -235,31 +239,32 @@ impl Processor<'_> { | |||||
let len_sqr = ship_to_obstacle.length_sqr(); | let len_sqr = ship_to_obstacle.length_sqr(); | ||||
if len_sqr < dist_sqr { | if len_sqr < dist_sqr { | ||||
dist_sqr = len_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 */ | /* check the obstacle */ | ||||
let mut expected_dir = ship_to_target; | 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_pos = self.positions.get(obstacle).unwrap(); | ||||
let obstacle_orbit = self.orbits.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(); | 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 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 mut adjust_low = linear_step(orbit_min, radius, orbit); | ||||
let adjust_high = 1.0 - linear_step(orbit_max, orbit_min, orbit); | let adjust_high = 1.0 - linear_step(orbit_max, orbit_min, orbit); | ||||
@@ -277,17 +282,13 @@ impl Processor<'_> { | |||||
} | } | ||||
/* update ship direction */ | /* update ship direction */ | ||||
let angle = expected_dir.angle2(&velocity.dir); | |||||
let angle = expected_dir.angle2(&velocity.dir()); | |||||
if angle.into_inner().abs() > 0.0001 { | if angle.into_inner().abs() > 0.0001 { | ||||
let dir = angle.into_inner() / angle.abs().into_inner(); | 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()); | 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); | |||||
} | } | ||||
} | } | ||||
} | } |