@@ -0,0 +1,25 @@ | |||
___________________________________________________________ | |||
WorldPersistence________________________________________ \ | |||
Planet_______________________________________________ \ \ | |||
Asteroid__________________________________________ \ \ \ | |||
MeetingPoint___________________________________ \ \ \ \ | |||
Obstacle____________________________________ \ \ \ \ \ | |||
Shape____________________________________ \ \ \ \ \ \ | |||
MeetingPointOwned_____________________ \ \ \ \ \ \ \ | |||
Fleet______________________________ \ \ \ \ \ \ \ \ | |||
Ship____________________________ \ \ \ \ \ \ \ \ \ | |||
FleetOwned___________________ \ \ \ \ \ \ \ \ \ \ | |||
Position__________________ \ \ \ \ \ \ \ \ \ \ \ | |||
PlayerOwned____________ \ \ \ \ \ \ \ \ \ \ \ \ | |||
Player______________ \ \ \ \ \ \ \ \ \ \ \ \ \ | |||
\ \ \ \ \ \ \ \ \ \ \ \ \ \ | |||
+--------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+ | |||
| Game Objects | | | | | | | | | | | | | | | |||
+--------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+ | |||
| Player | x | | | | | | | | | | | | x | | |||
| Ship | | x | x | x | x | | | | | | | | x | | |||
| Fleet | | | | | | x | x | | | | | | x | | |||
| Asteroid | | x | x | | | | | x | x | x | x | | x | | |||
| Planet | | x | x | | | | | x | x | x | | x | x | | |||
| MeetingPoint | | | x | | | | | | | x | | | x | | |||
+--------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+ |
@@ -1,6 +1,6 @@ | |||
use glc::vector::Vector4f; | |||
use space_crush_common::{ | |||
components::{Position, Ship, ShipObstacle, Velocity}, | |||
components::{Position, Ship, ShipObstacle}, | |||
continue_if_none, | |||
}; | |||
use specs::{prelude::*, ReadStorage, System, World, WriteExpect}; | |||
@@ -14,7 +14,6 @@ pub struct Ships; | |||
pub struct ShipsData<'a> { | |||
geometry: WriteExpect<'a, Geometry>, | |||
positions: ReadStorage<'a, Position>, | |||
velocities: ReadStorage<'a, Velocity>, | |||
ships: ReadStorage<'a, Ship>, | |||
} | |||
@@ -25,19 +24,18 @@ impl<'a> System<'a> for Ships { | |||
let ShipsData { | |||
mut geometry, | |||
positions, | |||
velocities, | |||
ships, | |||
} = data; | |||
gl::enable(gl::BLEND); | |||
gl::blend_func(gl::SRC_ALPHA, gl::ONE); | |||
for (position, velocity, ship) in (&positions, &velocities, &ships).join() { | |||
for (position, ship) in (&positions, &ships).join() { | |||
let ship_pos = position.get(); | |||
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 + ship.dir() * ship.speed()], | |||
); | |||
geometry.render_lines( | |||
Vector4f::new(1.0, 0.0, 0.0, 0.2), | |||
@@ -12,7 +12,7 @@ use glc::{ | |||
vertex_array::{DataType, VertexArray}, | |||
}; | |||
use space_crush_common::{ | |||
components::{Player, PlayerOwned, Position, Ship, ShipType, Velocity}, | |||
components::{Player, PlayerOwned, Position, Ship, ShipType}, | |||
misc::{ComponentEvent, LogResult, StorageHelper, StorageHelperMut}, | |||
}; | |||
use specs::{ | |||
@@ -55,7 +55,6 @@ pub struct Ships { | |||
#[derive(SystemData)] | |||
pub struct ShipsData<'a> { | |||
positions: ReadStorage<'a, Position>, | |||
velocities: ReadStorage<'a, Velocity>, | |||
players: ReadStorage<'a, Player>, | |||
owned: ReadStorage<'a, PlayerOwned>, | |||
ships: ReadStorage<'a, Ship>, | |||
@@ -217,16 +216,15 @@ impl Ships { | |||
let data = ( | |||
&ids as &dyn BitSetLike, | |||
&d.positions, | |||
&d.velocities, | |||
&d.ships, | |||
d.owned.maybe(), | |||
); | |||
for (id, position, velocity, ship, owned) in data.join() { | |||
for (id, position, ship, owned) in data.join() { | |||
let index = self.id_to_index[id as usize]; | |||
let mut s = &mut buf_ship[index as usize]; | |||
s.pos = *position.get(); | |||
s.dir = *velocity.dir(); | |||
s.dir = *ship.dir(); | |||
if self.need_init.contains(id) { | |||
s.color = match owned.and_then(|owned| d.players.get(owned.owner())) { | |||
@@ -3,7 +3,7 @@ use rand::random; | |||
use specs::{saveload::MarkedBuilder, Builder, Entity, World, WorldExt}; | |||
use crate::{ | |||
components::{FleetOwned, PlayerOwned, Position, Ship, ShipType, Velocity}, | |||
components::{FleetOwned, PlayerOwned, Position, Ship, ShipType}, | |||
misc::{Persistence, WorldPersistence}, | |||
}; | |||
@@ -30,8 +30,7 @@ impl ShipBuilder { | |||
let player_owned = PlayerOwned::new(player); | |||
let fleet_owned = FleetOwned::new(fleet); | |||
let position = Position::new(position); | |||
let velocity = Velocity::new(direction, speed); | |||
let ship = Ship::new(type_); | |||
let ship = Ship::new(type_, direction, speed); | |||
let entity = world | |||
.create_entity() | |||
@@ -39,7 +38,6 @@ impl ShipBuilder { | |||
.with(player_owned) | |||
.with(fleet_owned) | |||
.with(position) | |||
.with(velocity) | |||
.with(ship) | |||
.build(); | |||
@@ -81,13 +81,15 @@ impl Component for Fleet { | |||
/* FleetOwned */ | |||
impl FleetOwned { | |||
pub fn new(owner: Entity) -> Self { | |||
Self { owner } | |||
} | |||
pub fn owner(&self) -> Entity { | |||
self.owner | |||
} | |||
} | |||
impl FleetOwned { | |||
pub(crate) fn new(owner: Entity) -> Self { | |||
Self { owner } | |||
} | |||
pub(crate) fn set_owner(&mut self, owner: Entity) { | |||
self.owner = owner; | |||
@@ -7,7 +7,6 @@ mod player; | |||
mod position; | |||
mod shape; | |||
mod ship; | |||
mod velocity; | |||
pub use asteroid::{Asteroid, Type as AsteroidType}; | |||
pub use fleet::{Fleet, FleetOwned}; | |||
@@ -18,4 +17,3 @@ pub use player::{Player, PlayerOwned}; | |||
pub use position::Position; | |||
pub use shape::Shape; | |||
pub use ship::{Count as ShipCount, Obstacle as ShipObstacle, Ship, Type as ShipType}; | |||
pub use velocity::Velocity; |
@@ -10,6 +10,8 @@ use crate::{builder::ShipBuilder, misc::FlaggedStorage}; | |||
#[derive(Clone, Debug, Serialize, Deserialize)] | |||
pub struct Ship { | |||
type_: Type, | |||
dir: Vector2f, | |||
speed: f32, | |||
#[serde(skip)] | |||
obstacle: Obstacle, | |||
@@ -55,6 +57,16 @@ impl Ship { | |||
self.type_ | |||
} | |||
#[inline] | |||
pub fn dir(&self) -> &Vector2f { | |||
&self.dir | |||
} | |||
#[inline] | |||
pub fn speed(&self) -> f32 { | |||
self.speed | |||
} | |||
#[inline] | |||
pub fn target_pos(&self) -> &Vector2f { | |||
&self.target_pos | |||
@@ -73,9 +85,11 @@ impl Ship { | |||
impl Ship { | |||
#[inline] | |||
pub(crate) fn new(type_: Type) -> Self { | |||
pub(crate) fn new(type_: Type, dir: Vector2f, speed: f32) -> Self { | |||
Self { | |||
type_, | |||
dir, | |||
speed, | |||
obstacle: Default::default(), | |||
target_pos: Default::default(), | |||
target_dir: Default::default(), | |||
@@ -89,8 +103,13 @@ impl Ship { | |||
} | |||
#[inline] | |||
pub(crate) fn set_obstacle(&mut self, value: Obstacle) { | |||
self.obstacle = value; | |||
pub(crate) fn dir_mut(&mut self) -> &mut Vector2f { | |||
&mut self.dir | |||
} | |||
#[inline] | |||
pub(crate) fn obstacle_mut(&mut self) -> &mut Obstacle { | |||
&mut self.obstacle | |||
} | |||
} | |||
@@ -1,35 +0,0 @@ | |||
use glc::vector::Vector2f; | |||
use serde::{Deserialize, Serialize}; | |||
use specs::{Component, VecStorage}; | |||
#[derive(Clone, Debug, Default, Serialize, Deserialize)] | |||
pub struct Velocity { | |||
dir: Vector2f, | |||
speed: f32, | |||
} | |||
/* Velocity */ | |||
impl Velocity { | |||
pub fn dir(&self) -> &Vector2f { | |||
&self.dir | |||
} | |||
pub fn speed(&self) -> f32 { | |||
self.speed | |||
} | |||
} | |||
impl Velocity { | |||
pub(crate) fn new(dir: Vector2f, speed: f32) -> Self { | |||
Self { dir, speed } | |||
} | |||
pub(crate) fn dir_mut(&mut self) -> &mut Vector2f { | |||
&mut self.dir | |||
} | |||
} | |||
impl Component for Velocity { | |||
type Storage = VecStorage<Self>; | |||
} |
@@ -8,7 +8,7 @@ use specs::{saveload::SimpleMarker, World}; | |||
use crate::{ | |||
components::{ | |||
Asteroid, MeetingPoint, MeetingPointOwned, Obstacle, Planet, Player, PlayerOwned, Position, | |||
Ship, Velocity, | |||
Ship, | |||
}, | |||
Error, | |||
}; | |||
@@ -91,7 +91,6 @@ impl Persistence for WorldPersistence { | |||
type Marker = SimpleMarker<PersistWorldMarker>; | |||
type Components = ( | |||
Position, | |||
Velocity, | |||
Player, | |||
PlayerOwned, | |||
MeetingPoint, | |||
@@ -3,7 +3,7 @@ | |||
use specs::{prelude::*, ParJoin, Read, ReadStorage, System, WriteStorage}; | |||
use crate::{ | |||
components::{Position, Velocity}, | |||
components::{Position, Ship}, | |||
resources::Global, | |||
}; | |||
@@ -12,8 +12,8 @@ pub struct Movement; | |||
#[derive(SystemData)] | |||
pub struct MovementData<'a> { | |||
position: WriteStorage<'a, Position>, | |||
velocity: ReadStorage<'a, Velocity>, | |||
positions: WriteStorage<'a, Position>, | |||
ships: ReadStorage<'a, Ship>, | |||
global: Read<'a, Global>, | |||
} | |||
@@ -22,18 +22,18 @@ impl<'a> System<'a> for Movement { | |||
fn run(&mut self, data: Self::SystemData) { | |||
let MovementData { | |||
mut position, | |||
velocity, | |||
mut positions, | |||
ships, | |||
global, | |||
} = data; | |||
(&mut position, &velocity) | |||
(&mut positions, &ships) | |||
.par_join() | |||
.for_each(|(position, velocity)| { | |||
.for_each(|(position, ship)| { | |||
let delta = global.delta * global.world_speed; | |||
let position = position.get_mut(); | |||
*position += velocity.dir() * velocity.speed() * delta; | |||
*position += ship.dir() * ship.speed() * delta; | |||
}); | |||
} | |||
} |
@@ -13,7 +13,6 @@ use specs::{ | |||
use crate::{ | |||
components::{ | |||
FleetOwned, MeetingPoint, MeetingPointOwned, Obstacle, Position, Shape, Ship, ShipObstacle, | |||
Velocity, | |||
}, | |||
constants::{ | |||
SHIP_ORBIT_AGILITY, SHIP_ORBIT_ANGLE_DELTA_MIN, SHIP_ORBIT_ANGLE_DELTA_RND, | |||
@@ -34,7 +33,6 @@ pub struct ShipsData<'a> { | |||
global: Read<'a, Global>, | |||
entities: Entities<'a>, | |||
ships: WriteStorage<'a, Ship>, | |||
velocities: WriteStorage<'a, Velocity>, | |||
fleet_owned: ReadStorage<'a, FleetOwned>, | |||
meeting_point_owned: ReadStorage<'a, MeetingPointOwned>, | |||
positions: ReadStorage<'a, Position>, | |||
@@ -92,7 +90,6 @@ impl<'a> System<'a> for Ships { | |||
global, | |||
entities, | |||
mut ships, | |||
mut velocities, | |||
fleet_owned, | |||
meeting_point_owned, | |||
positions, | |||
@@ -117,17 +114,11 @@ impl<'a> System<'a> for Ships { | |||
ships.set_event_emission(false); | |||
let data = ( | |||
positions.mask(), | |||
&mut ships, | |||
&mut velocities, | |||
&positions, | |||
&fleet_owned, | |||
); | |||
let data = (positions.mask(), &mut ships, &positions, &fleet_owned); | |||
data.par_join() | |||
.for_each(|(id, ship, velocity, position, fleet_owned)| { | |||
processor.progress_ship(id, ship, velocity, position, fleet_owned); | |||
.for_each(|(id, ship, position, fleet_owned)| { | |||
processor.progress_ship(id, ship, position, fleet_owned); | |||
}); | |||
ships.set_event_emission(true); | |||
@@ -139,7 +130,6 @@ impl Processor<'_> { | |||
&self, | |||
id: Index, | |||
ship: &mut Ship, | |||
velocity: &mut Velocity, | |||
position: &Position, | |||
fleet_owned: &FleetOwned, | |||
) { | |||
@@ -179,7 +169,7 @@ impl Processor<'_> { | |||
let target_pos = if ship_in_meeting_point && meeting_point_max > 0.0 { | |||
let meeting_point_to_ship_vec3 = | |||
Vector3f::new(meeting_point_to_ship.x, meeting_point_to_ship.y, 0.0); | |||
let ship_dir_vec3 = velocity.dir().into_vec3(); | |||
let ship_dir_vec3 = ship.dir().into_vec3(); | |||
let dir = if meeting_point_to_ship_vec3.cross(&ship_dir_vec3).z > 0.0 { | |||
1.0 | |||
@@ -201,7 +191,7 @@ impl Processor<'_> { | |||
meeting_point_pos.y + radius * angle.sin(), | |||
) | |||
} else { | |||
ship.set_obstacle(ShipObstacle::Search); | |||
*ship.obstacle_mut() = ShipObstacle::Search; | |||
*meeting_point_pos | |||
}; | |||
@@ -213,7 +203,7 @@ impl Processor<'_> { | |||
/* check if obstacle is still valid */ | |||
if ship_in_meeting_point { | |||
ship.set_obstacle(ShipObstacle::Done); | |||
*ship.obstacle_mut() = ShipObstacle::Done; | |||
} else if let ShipObstacle::Known(obstacle) = ship.obstacle() { | |||
if let Some(position) = self.positions.get(obstacle) { | |||
let obstacle_meeting_point = self.meeting_points.get(obstacle).unwrap(); | |||
@@ -230,10 +220,10 @@ impl Processor<'_> { | |||
if (obstacle_angle > 90.0 && ship_to_obstacle.length_sqr() > meeting_point_sqr) | |||
|| obstacle_angle > 170.0 | |||
{ | |||
ship.set_obstacle(ShipObstacle::Search); | |||
*ship.obstacle_mut() = ShipObstacle::Search; | |||
} | |||
} else { | |||
ship.set_obstacle(ShipObstacle::Search); | |||
*ship.obstacle_mut() = ShipObstacle::Search; | |||
} | |||
} | |||
@@ -251,13 +241,13 @@ impl Processor<'_> { | |||
let len_sqr = ship_to_obstacle.length_sqr(); | |||
if len_sqr < dist_sqr { | |||
dist_sqr = len_sqr; | |||
ship.set_obstacle(ShipObstacle::Known(e)); | |||
*ship.obstacle_mut() = ShipObstacle::Known(e); | |||
} | |||
} | |||
if let ShipObstacle::Known(e) = ship.obstacle() { | |||
if e == fleet_owned.owner() { | |||
ship.set_obstacle(ShipObstacle::Done); | |||
*ship.obstacle_mut() = ShipObstacle::Done; | |||
} | |||
} | |||
} | |||
@@ -296,13 +286,13 @@ impl Processor<'_> { | |||
} | |||
/* update ship direction */ | |||
let angle = expected_dir.angle2(&velocity.dir()); | |||
let angle = expected_dir.angle2(ship.dir()); | |||
if angle.into_inner().abs() > 0.0001 { | |||
let dir = angle.into_inner() / angle.abs().into_inner(); | |||
let agility = SHIP_ORBIT_AGILITY; | |||
let rot_speed = agility * linear_step(0.0, 45.0, angle.abs().into_deg().into_inner()); | |||
*velocity.dir_mut() *= Matrix3f::rotate(rot_speed * -dir * self.delta); | |||
*ship.dir_mut() *= Matrix3f::rotate(rot_speed * -dir * self.delta); | |||
} | |||
} | |||
} |