Browse Source

Implemented ship data depending on ship type and player race

master
Bergmann89 3 years ago
parent
commit
a1c55d712b
15 changed files with 211 additions and 106 deletions
  1. +5
    -2
      overview
  2. +11
    -3
      space-crush-app/src/debug/ships.rs
  3. +1
    -1
      space-crush-common/src/builder/asteroid.rs
  4. +1
    -1
      space-crush-common/src/builder/fleet.rs
  5. +1
    -1
      space-crush-common/src/builder/planet.rs
  6. +21
    -5
      space-crush-common/src/builder/player.rs
  7. +2
    -3
      space-crush-common/src/builder/ship.rs
  8. +2
    -2
      space-crush-common/src/components/mod.rs
  9. +30
    -12
      space-crush-common/src/components/player.rs
  10. +65
    -33
      space-crush-common/src/components/ship.rs
  11. +20
    -0
      space-crush-common/src/constants.rs
  12. +2
    -2
      space-crush-common/src/dispatcher.rs
  13. +2
    -2
      space-crush-common/src/systems/mod.rs
  14. +0
    -39
      space-crush-common/src/systems/movement.rs
  15. +48
    -0
      space-crush-common/src/systems/ship_movement.rs

+ 5
- 2
overview View File

@@ -1,3 +1,6 @@
x -> needed
o -> optional

___________________________________________________________
WorldPersistence________________________________________ \
Planet_______________________________________________ \ \
@@ -19,7 +22,7 @@ Player______________ \ \ \ \ \ \ \ \ \ \ \ \ \
| 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 |
| Asteroid | | o | x | | | | | x | x | x | x | | x |
| Planet | | o | x | | | | | x | x | x | | x | x |
| MeetingPoint | | | x | | | | | | | x | | | x |
+--------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+

+ 11
- 3
space-crush-app/src/debug/ships.rs View File

@@ -1,6 +1,6 @@
use glc::vector::Vector4f;
use space_crush_common::{
components::{Position, Ship, ShipObstacle},
components::{Player, PlayerOwned, Position, Ship, ShipObstacle},
continue_if_none,
};
use specs::{prelude::*, ReadStorage, System, World, WriteExpect};
@@ -14,6 +14,8 @@ pub struct Ships;
pub struct ShipsData<'a> {
geometry: WriteExpect<'a, Geometry>,
positions: ReadStorage<'a, Position>,
player_owned: ReadStorage<'a, PlayerOwned>,
players: ReadStorage<'a, Player>,
ships: ReadStorage<'a, Ship>,
}

@@ -24,18 +26,24 @@ impl<'a> System<'a> for Ships {
let ShipsData {
mut geometry,
positions,
player_owned,
players,
ships,
} = data;

gl::enable(gl::BLEND);
gl::blend_func(gl::SRC_ALPHA, gl::ONE);

for (position, ship) in (&positions, &ships).join() {
for (position, player_owned, ship) in (&positions, &player_owned, &ships).join() {
let ship_pos = position.get();
let type_ = ship.type_();
let player_id = player_owned.owner();
let player = continue_if_none!(players.get(player_id));
let ship_data = player.ship_data(type_);

geometry.render_lines(
Vector4f::new(0.0, 0.0, 1.0, 0.2),
&[*ship_pos, ship_pos + ship.dir() * ship.speed()],
&[*ship_pos, ship_pos + ship.dir() * ship_data.speed],
);
geometry.render_lines(
Vector4f::new(1.0, 0.0, 0.0, 0.2),


+ 1
- 1
space-crush-common/src/builder/asteroid.rs View File

@@ -19,7 +19,7 @@ pub struct AsteroidBuilder {
}

impl AsteroidBuilder {
pub fn build(self, world: &mut World) -> Result<Entity, Error> {
pub fn build(&self, world: &mut World) -> Result<Entity, Error> {
let type_ = self.type_.ok_or(Error::MissingValue("type"))?;
let position = self.position.ok_or(Error::MissingValue("position"))?;
let size = self.size.ok_or(Error::MissingValue("size"))?;


+ 1
- 1
space-crush-common/src/builder/fleet.rs View File

@@ -13,7 +13,7 @@ pub struct FleetBuilder {
}

impl FleetBuilder {
pub fn build(self, world: &mut World) -> Result<Entity, Error> {
pub fn build(&self, world: &mut World) -> Result<Entity, Error> {
let owner = self.owner.ok_or(Error::MissingValue("owner"))?;

let meeting_point_owned = MeetingPointOwned::new(owner);


+ 1
- 1
space-crush-common/src/builder/planet.rs View File

@@ -18,7 +18,7 @@ pub struct PlanetBuilder {
}

impl PlanetBuilder {
pub fn build(self, world: &mut World) -> Result<Entity, Error> {
pub fn build(&self, world: &mut World) -> Result<Entity, Error> {
let position = self.position.ok_or(Error::MissingValue("position"))?;
let size = self.size.ok_or(Error::MissingValue("size"))?;
let (orbit_min, orbit_max) = self.orbit.ok_or(Error::MissingValue("orbit"))?;


+ 21
- 5
space-crush-common/src/builder/player.rs View File

@@ -3,22 +3,26 @@ use specs::{saveload::MarkedBuilder, Builder, Entity, World, WorldExt};
use glc::vector::Vector3f;

use crate::{
components::Player,
components::{Player, Race},
misc::{Persistence, WorldPersistence},
};

use super::Error;

#[derive(Default, Clone)]
#[derive(Clone)]
pub struct PlayerBuilder {
index: usize,
race: Race,
color: Option<Vector3f>,
}

impl PlayerBuilder {
pub fn build(self, world: &mut World) -> Result<Entity, Error> {
let color = self.color.ok_or(Error::MissingValue("color"))?;
pub fn build(&mut self, world: &mut World) -> Result<Entity, Error> {
let index = self.index;
let race = self.race;
let color = self.color.take().ok_or(Error::MissingValue("color"))?;

let player = Player::new(color);
let player = Player::new(index, race, color);

let entity = world
.create_entity()
@@ -26,6 +30,8 @@ impl PlayerBuilder {
.with(player)
.build();

self.index += 1;

Ok(entity)
}

@@ -35,3 +41,13 @@ impl PlayerBuilder {
self
}
}

impl Default for PlayerBuilder {
fn default() -> Self {
Self {
index: 0,
race: Race::Fighter,
color: None,
}
}
}

+ 2
- 3
space-crush-common/src/builder/ship.rs View File

@@ -19,18 +19,17 @@ pub struct ShipBuilder {
}

impl ShipBuilder {
pub fn build(self, world: &mut World) -> Result<Entity, Error> {
pub fn build(&self, world: &mut World) -> Result<Entity, Error> {
let player = self.player.ok_or(Error::MissingValue("player"))?;
let fleet = self.fleet.ok_or(Error::MissingValue("fleet"))?;
let position = self.position.ok_or(Error::MissingValue("position"))?;
let type_ = self.type_.ok_or(Error::MissingValue("type"))?;
let direction = self.direction;
let speed = 100.0;

let player_owned = PlayerOwned::new(player);
let fleet_owned = FleetOwned::new(fleet);
let position = Position::new(position);
let ship = Ship::new(type_, direction, speed);
let ship = Ship::new(type_, direction);

let entity = world
.create_entity()


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

@@ -13,7 +13,7 @@ pub use fleet::{Fleet, FleetOwned};
pub use meeting_point::{MeetingPoint, MeetingPointOwned};
pub use obstacle::Obstacle;
pub use planet::Planet;
pub use player::{Player, PlayerOwned};
pub use player::{Player, PlayerOwned, Race};
pub use position::Position;
pub use shape::Shape;
pub use ship::{Count as ShipCount, Obstacle as ShipObstacle, Ship, Type as ShipType};
pub use ship::{Ship, ShipCount, ShipData, ShipObstacle, ShipType, ShipsData};

+ 30
- 12
space-crush-common/src/components/player.rs View File

@@ -6,12 +6,27 @@ use specs::{
Component, Entity, HashMapStorage,
};

use crate::builder::PlayerBuilder;
use crate::{
builder::PlayerBuilder,
components::{ShipData, ShipType, ShipsData},
constants::{SHIPS_DATA_FIGHTER, SHIPS_DATA_RESEARCHER, SHIPS_DATA_TRADER},
};

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Player {
index: usize,
race: Race,
color: Vector3f,

#[serde(skip)]
ships_data: ShipsData,
}

#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub enum Race {
Fighter,
Trader,
Researcher,
}

#[derive(Copy, Clone, Debug)]
@@ -41,14 +56,25 @@ impl Player {
pub fn color(&self) -> &Vector3f {
&self.color
}

#[inline]
pub fn ship_data(&self, type_: ShipType) -> &ShipData {
&self.ships_data[type_]
}
}

impl Player {
#[inline]
pub(crate) fn new(color: Vector3f) -> Self {
pub(crate) fn new(index: usize, race: Race, color: Vector3f) -> Self {
Self {
index: next_index(),
index,
race,
color,
ships_data: match race {
Race::Fighter => SHIPS_DATA_FIGHTER,
Race::Trader => SHIPS_DATA_TRADER,
Race::Researcher => SHIPS_DATA_RESEARCHER,
},
}
}
}
@@ -100,11 +126,3 @@ where
Ok(PlayerOwned { 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)
}

+ 65
- 33
space-crush-common/src/components/ship.rs View File

@@ -9,12 +9,11 @@ use crate::{builder::ShipBuilder, misc::FlaggedStorage};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Ship {
type_: Type,
type_: ShipType,
dir: Vector2f,
speed: f32,

#[serde(skip)]
obstacle: Obstacle,
obstacle: ShipObstacle,

#[serde(skip)]
target_pos: Vector2f,
@@ -24,21 +23,33 @@ pub struct Ship {
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Obstacle {
pub enum ShipObstacle {
Known(Entity),
Search,
Done,
}

#[derive(Copy, Clone, Debug, Default)]
pub struct Count {
pub struct ShipCount {
pub fighter: usize,
pub bomber: usize,
pub transporter: usize,
}

#[derive(Clone, Default, Debug)]
pub struct ShipsData {
pub fighter: ShipData,
pub bomber: ShipData,
pub transporter: ShipData,
}

#[derive(Clone, Default, Debug)]
pub struct ShipData {
pub speed: f32,
}

#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub enum Type {
pub enum ShipType {
Fighter,
Bomber,
Transporter,
@@ -53,7 +64,7 @@ impl Ship {
}

#[inline]
pub fn type_(&self) -> Type {
pub fn type_(&self) -> ShipType {
self.type_
}

@@ -62,11 +73,6 @@ impl Ship {
&self.dir
}

#[inline]
pub fn speed(&self) -> f32 {
self.speed
}

#[inline]
pub fn target_pos(&self) -> &Vector2f {
&self.target_pos
@@ -78,18 +84,17 @@ impl Ship {
}

#[inline]
pub fn obstacle(&self) -> Obstacle {
pub fn obstacle(&self) -> ShipObstacle {
self.obstacle
}
}

impl Ship {
#[inline]
pub(crate) fn new(type_: Type, dir: Vector2f, speed: f32) -> Self {
pub(crate) fn new(type_: ShipType, dir: Vector2f) -> Self {
Self {
type_,
dir,
speed,
obstacle: Default::default(),
target_pos: Default::default(),
target_dir: Default::default(),
@@ -108,7 +113,7 @@ impl Ship {
}

#[inline]
pub(crate) fn obstacle_mut(&mut self) -> &mut Obstacle {
pub(crate) fn obstacle_mut(&mut self) -> &mut ShipObstacle {
&mut self.obstacle
}
}
@@ -119,7 +124,7 @@ impl Component for Ship {

/* Obstacle */

impl Default for Obstacle {
impl Default for ShipObstacle {
fn default() -> Self {
Self::Search
}
@@ -127,7 +132,7 @@ impl Default for Obstacle {

/* Count */

impl Count {
impl ShipCount {
pub fn all() -> Self {
Self {
fighter: usize::MAX,
@@ -163,7 +168,7 @@ impl Count {
}
}

impl Index<usize> for Count {
impl Index<usize> for ShipCount {
type Output = usize;

fn index(&self, index: usize) -> &Self::Output {
@@ -176,7 +181,7 @@ impl Index<usize> for Count {
}
}

impl IndexMut<usize> for Count {
impl IndexMut<usize> for ShipCount {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match index {
0 => &mut self.fighter,
@@ -187,30 +192,30 @@ impl IndexMut<usize> for Count {
}
}

impl Index<Type> for Count {
impl Index<ShipType> for ShipCount {
type Output = usize;

fn index(&self, index: Type) -> &Self::Output {
fn index(&self, index: ShipType) -> &Self::Output {
match index {
Type::Fighter => &self.fighter,
Type::Bomber => &self.bomber,
Type::Transporter => &self.transporter,
ShipType::Fighter => &self.fighter,
ShipType::Bomber => &self.bomber,
ShipType::Transporter => &self.transporter,
}
}
}

impl IndexMut<Type> for Count {
fn index_mut(&mut self, index: Type) -> &mut Self::Output {
impl IndexMut<ShipType> for ShipCount {
fn index_mut(&mut self, index: ShipType) -> &mut Self::Output {
match index {
Type::Fighter => &mut self.fighter,
Type::Bomber => &mut self.bomber,
Type::Transporter => &mut self.transporter,
ShipType::Fighter => &mut self.fighter,
ShipType::Bomber => &mut self.bomber,
ShipType::Transporter => &mut self.transporter,
}
}
}

impl Mul<f32> for Count {
type Output = Count;
impl Mul<f32> for ShipCount {
type Output = ShipCount;

#[allow(unused_assignments)]
fn mul(self, rhs: f32) -> Self::Output {
@@ -238,10 +243,37 @@ impl Mul<f32> for Count {
actual += 1;
}

Count {
ShipCount {
fighter,
bomber,
transporter,
}
}
}

/* ShipsData */

impl Index<usize> for ShipsData {
type Output = ShipData;

fn index(&self, index: usize) -> &Self::Output {
match index {
0 => &self.fighter,
1 => &self.bomber,
2 => &self.transporter,
x => panic!("Invalid ships data index: {}", x),
}
}
}

impl Index<ShipType> for ShipsData {
type Output = ShipData;

fn index(&self, index: ShipType) -> &Self::Output {
match index {
ShipType::Fighter => &self.fighter,
ShipType::Bomber => &self.bomber,
ShipType::Transporter => &self.transporter,
}
}
}

+ 20
- 0
space-crush-common/src/constants.rs View File

@@ -1,5 +1,7 @@
use glc::{matrix::Angle, vector::Vector2f};

use crate::components::{ShipData, ShipsData};

/// Distance to orbit before ship is handled as "in orbit" in %
pub const SHIP_ORBIT_DISTANCE_MAX: f32 = 1.10;

@@ -13,3 +15,21 @@ pub const SHIP_ORBIT_ANGLE_DELTA_RND: Angle<f32> = Angle::Deg(5000.0);
pub const SHIP_ORBIT_AGILITY: Angle<f32> = Angle::Deg(90.0);

pub const VECTOR_2F_POS_X: Vector2f = Vector2f::new(1.0, 0.0);

pub const SHIPS_DATA_FIGHTER: ShipsData = ShipsData {
fighter: ShipData { speed: 120.0 },
bomber: ShipData { speed: 80.0 },
transporter: ShipData { speed: 100.0 },
};

pub const SHIPS_DATA_TRADER: ShipsData = ShipsData {
fighter: ShipData { speed: 100.0 },
bomber: ShipData { speed: 70.0 },
transporter: ShipData { speed: 120.0 },
};

pub const SHIPS_DATA_RESEARCHER: ShipsData = ShipsData {
fighter: ShipData { speed: 90.0 },
bomber: ShipData { speed: 60.0 },
transporter: ShipData { speed: 100.0 },
};

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

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

@@ -19,7 +19,7 @@ impl<'a, 'b> Dispatcher<'a, 'b> {

let mut dispatcher = DispatcherBuilder::new()
.with(Process::default(), "process", &[])
.with(Movement::default(), "movement", &[])
.with(ShipMovement::default(), "ship_movement", &[])
.with(Ships::new(world), "ships", &[])
.with(FleetControl::new(world)?, "fleet_control", &[])
.with(FleetOwnedUpdate::new(world), "fleet_owned_update", &[])


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

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

pub use fleet_control::{FleetControl, FleetControlEvent};
pub use fleet_owned_update::FleetOwnedUpdate;
pub use movement::Movement;
pub use process::Process;
pub use ship_movement::ShipMovement;
pub use ships::Ships;

+ 0
- 39
space-crush-common/src/systems/movement.rs View File

@@ -1,39 +0,0 @@
#![allow(dead_code)]

use specs::{prelude::*, ParJoin, Read, ReadStorage, System, WriteStorage};

use crate::{
components::{Position, Ship},
resources::Global,
};

#[derive(Default)]
pub struct Movement;

#[derive(SystemData)]
pub struct MovementData<'a> {
positions: WriteStorage<'a, Position>,
ships: ReadStorage<'a, Ship>,
global: Read<'a, Global>,
}

impl<'a> System<'a> for Movement {
type SystemData = MovementData<'a>;

fn run(&mut self, data: Self::SystemData) {
let MovementData {
mut positions,
ships,
global,
} = data;

(&mut positions, &ships)
.par_join()
.for_each(|(position, ship)| {
let delta = global.delta * global.world_speed;
let position = position.get_mut();

*position += ship.dir() * ship.speed() * delta;
});
}
}

+ 48
- 0
space-crush-common/src/systems/ship_movement.rs View File

@@ -0,0 +1,48 @@
#![allow(dead_code)]

use specs::{prelude::*, ParJoin, Read, ReadStorage, System, WriteStorage};

use crate::{
components::{Player, PlayerOwned, Position, Ship},
resources::Global,
return_if_none,
};

#[derive(Default)]
pub struct ShipMovement;

#[derive(SystemData)]
pub struct ShipMovementData<'a> {
positions: WriteStorage<'a, Position>,
ships: ReadStorage<'a, Ship>,
player_owned: ReadStorage<'a, PlayerOwned>,
players: ReadStorage<'a, Player>,
global: Read<'a, Global>,
}

impl<'a> System<'a> for ShipMovement {
type SystemData = ShipMovementData<'a>;

fn run(&mut self, data: Self::SystemData) {
let ShipMovementData {
mut positions,
ships,
player_owned,
players,
global,
} = data;

(&mut positions, &player_owned, &ships).par_join().for_each(
|(position, player_owned, ship)| {
let delta = global.delta * global.world_speed;
let position = position.get_mut();
let type_ = ship.type_();
let player_id = player_owned.owner();
let player = return_if_none!(players.get(player_id));
let ship_data = player.ship_data(type_);

*position += ship.dir() * ship_data.speed * delta;
},
);
}
}

Loading…
Cancel
Save