@@ -1510,6 +1510,7 @@ dependencies = [ | |||||
"glc", | "glc", | ||||
"glutin", | "glutin", | ||||
"glyph_brush", | "glyph_brush", | ||||
"lazy_static", | |||||
"log", | "log", | ||||
"log4rs", | "log4rs", | ||||
"ordered-float 2.0.1", | "ordered-float 2.0.1", | ||||
@@ -9,6 +9,7 @@ gl = { version = "0.1", features = [ "use_log_crate" ] } | |||||
glc = "0.1" | glc = "0.1" | ||||
glutin = { version = "0.25", features = [ "serde" ] } | glutin = { version = "0.25", features = [ "serde" ] } | ||||
glyph_brush = "0.7" | glyph_brush = "0.7" | ||||
lazy_static = "1.4" | |||||
log = { version = "0.4", features = [ "max_level_trace", "release_max_level_warn" ] } | log = { version = "0.4", features = [ "max_level_trace", "release_max_level_warn" ] } | ||||
log4rs = "0.13" | log4rs = "0.13" | ||||
ordered-float = "2.0" | ordered-float = "2.0" | ||||
@@ -4,6 +4,7 @@ | |||||
#pragma include ../misc/glow.glsl | #pragma include ../misc/glow.glsl | ||||
#pragma include ../misc/global.glsl | #pragma include ../misc/global.glsl | ||||
const float GLOW_ALPHA = 0.20; | |||||
const GlowArgs GLOW_ARGS = { | const GlowArgs GLOW_ARGS = { | ||||
/* step0 */ 0.100, | /* step0 */ 0.100, | ||||
/* step1 */ 1.900, | /* step1 */ 1.900, | ||||
@@ -21,7 +22,7 @@ out vec4 outColor; | |||||
void main() { | void main() { | ||||
float alpha = glow(GLOW_ARGS, fragmentData.texCoords - vec2(0.5), uGlobal.time); | float alpha = glow(GLOW_ARGS, fragmentData.texCoords - vec2(0.5), uGlobal.time); | ||||
vec4 glow = vec4(uGlowColor.rgb, uGlowColor.a * alpha); | |||||
vec4 glow = vec4(uGlowColor.rgb, uGlowColor.a * alpha * GLOW_ALPHA); | |||||
vec4 tex = texture(uTexture, fragmentData.texCoords); | vec4 tex = texture(uTexture, fragmentData.texCoords); | ||||
outColor = tex * tex.a + glow * (1.0 - tex.a); | outColor = tex * tex.a + glow * (1.0 - tex.a); | ||||
@@ -13,6 +13,13 @@ | |||||
}, | }, | ||||
null, | null, | ||||
{}, | {}, | ||||
null, | |||||
{ | |||||
"owner": [ | |||||
4 | |||||
] | |||||
}, | |||||
null, | |||||
null | null | ||||
] | ] | ||||
}, | }, | ||||
@@ -38,7 +45,14 @@ | |||||
null, | null, | ||||
{ | { | ||||
"type_": "Fighter" | "type_": "Fighter" | ||||
} | |||||
}, | |||||
{ | |||||
"owner": [ | |||||
4 | |||||
] | |||||
}, | |||||
null, | |||||
null | |||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
@@ -63,7 +77,14 @@ | |||||
null, | null, | ||||
{ | { | ||||
"type_": "Bomber" | "type_": "Bomber" | ||||
} | |||||
}, | |||||
{ | |||||
"owner": [ | |||||
4 | |||||
] | |||||
}, | |||||
null, | |||||
null | |||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
@@ -88,6 +109,34 @@ | |||||
null, | null, | ||||
{ | { | ||||
"type_": "Transporter" | "type_": "Transporter" | ||||
}, | |||||
{ | |||||
"owner": [ | |||||
4 | |||||
] | |||||
}, | |||||
null, | |||||
null | |||||
] | |||||
}, | |||||
{ | |||||
"marker": [ | |||||
4 | |||||
], | |||||
"components": [ | |||||
null, | |||||
null, | |||||
null, | |||||
null, | |||||
null, | |||||
{}, | |||||
{ | |||||
"color": [ | |||||
0.0, | |||||
0.5, | |||||
1.0, | |||||
0.1 | |||||
] | |||||
} | } | ||||
] | ] | ||||
} | } | ||||
@@ -0,0 +1,3 @@ | |||||
mod player_visual; | |||||
pub use player_visual::PlayerVisual; |
@@ -0,0 +1,12 @@ | |||||
use glc::vector::Vector4f; | |||||
use serde::{Deserialize, Serialize}; | |||||
use specs::{Component, HashMapStorage}; | |||||
#[derive(Clone, Debug, Serialize, Deserialize)] | |||||
pub struct PlayerVisual { | |||||
pub color: Vector4f, | |||||
} | |||||
impl Component for PlayerVisual { | |||||
type Storage = HashMapStorage<Self>; | |||||
} |
@@ -1,2 +1,9 @@ | |||||
use glc::vector::Vector4f; | |||||
use lazy_static::lazy_static; | |||||
pub const UNIFORM_BUFFER_INDEX_CAMERA: gl::GLuint = 0; | pub const UNIFORM_BUFFER_INDEX_CAMERA: gl::GLuint = 0; | ||||
pub const UNIFORM_BUFFER_INDEX_UNIFORM: gl::GLuint = 1; | pub const UNIFORM_BUFFER_INDEX_UNIFORM: gl::GLuint = 1; | ||||
lazy_static! { | |||||
pub static ref PLAYER_COLOR_DEFAULT: Vector4f = Vector4f::new(1.0, 1.0, 1.0, 0.1); | |||||
} |
@@ -1,9 +1,10 @@ | |||||
mod constants; | |||||
mod error; | |||||
mod misc; | |||||
mod render; | |||||
mod resources; | |||||
mod systems; | |||||
pub mod components; | |||||
pub mod constants; | |||||
pub mod error; | |||||
pub mod misc; | |||||
pub mod render; | |||||
pub mod resources; | |||||
pub mod systems; | |||||
use specs::{Dispatcher, DispatcherBuilder, World}; | use specs::{Dispatcher, DispatcherBuilder, World}; | ||||
@@ -50,16 +50,26 @@ fn run(vfs: Vfs) -> Result<(), Error> { | |||||
} | } | ||||
fn create_world(world: &mut World) { | fn create_world(world: &mut World) { | ||||
use glc::vector::Vector2f; | |||||
use glc::vector::{Vector2f, Vector4f}; | |||||
use space_crush_app::{components::PlayerVisual, misc::PersistWorld}; | |||||
use space_crush_common::{ | use space_crush_common::{ | ||||
components::{Planet, Position, Ship, ShipType, Velocity}, | |||||
misc::{PersistWorld, Persistence}, | |||||
components::{Owned, Planet, Player, Position, Ship, ShipType, Velocity}, | |||||
misc::Persistence, | |||||
}; | }; | ||||
use specs::{saveload::MarkedBuilder, Builder}; | use specs::{saveload::MarkedBuilder, Builder}; | ||||
let player1 = world | |||||
.create_entity() | |||||
.with(Player {}) | |||||
.with(PlayerVisual { | |||||
color: Vector4f::new(0.0, 0.5, 1.0, 0.1), | |||||
}) | |||||
.build(); | |||||
world | world | ||||
.create_entity() | .create_entity() | ||||
.marked::<<PersistWorld as Persistence>::Marker>() | .marked::<<PersistWorld as Persistence>::Marker>() | ||||
.with(Owned { owner: player1 }) | |||||
.with(Position { | .with(Position { | ||||
pos: Vector2f::default(), | pos: Vector2f::default(), | ||||
size: 500.0, | size: 500.0, | ||||
@@ -74,9 +84,10 @@ fn create_world(world: &mut World) { | |||||
world | world | ||||
.create_entity() | .create_entity() | ||||
.marked::<<PersistWorld as Persistence>::Marker>() | .marked::<<PersistWorld as Persistence>::Marker>() | ||||
.with(Owned { owner: player1 }) | |||||
.with(Position { | .with(Position { | ||||
pos: Vector2f::new(250.0 * x, 250.0 * y), | pos: Vector2f::new(250.0 * x, 250.0 * y), | ||||
size: 100.0, | |||||
size: 30.0, | |||||
}) | }) | ||||
.with(Velocity { | .with(Velocity { | ||||
dir: Vector2f::new(i as f32 - 1.0, 1.0).normalize(), | dir: Vector2f::new(i as f32 - 1.0, 1.0).normalize(), | ||||
@@ -96,7 +107,8 @@ fn create_world(world: &mut World) { | |||||
fn load_world(world: &mut World, path: &str) -> Result<bool, Error> { | fn load_world(world: &mut World, path: &str) -> Result<bool, Error> { | ||||
use serde_json::de::{Deserializer, IoRead}; | use serde_json::de::{Deserializer, IoRead}; | ||||
use space_crush_common::misc::{PersistWorld, Persistence, WorldHelper}; | |||||
use space_crush_app::misc::PersistWorld; | |||||
use space_crush_common::misc::{Persistence, WorldHelper}; | |||||
PersistWorld::setup(world); | PersistWorld::setup(world); | ||||
@@ -116,7 +128,8 @@ fn load_world(world: &mut World, path: &str) -> Result<bool, Error> { | |||||
fn save_world(world: &mut World, path: &str) -> Result<(), Error> { | fn save_world(world: &mut World, path: &str) -> Result<(), Error> { | ||||
use serde_json::Serializer; | use serde_json::Serializer; | ||||
use space_crush_common::misc::{PersistWorld, WorldHelper}; | |||||
use space_crush_app::misc::PersistWorld; | |||||
use space_crush_common::misc::WorldHelper; | |||||
let vfs = world.resource::<Vfs>()?; | let vfs = world.resource::<Vfs>()?; | ||||
let mut file = vfs.join(path)?.create_file()?; | let mut file = vfs.join(path)?.create_file()?; | ||||
@@ -6,4 +6,4 @@ mod world; | |||||
pub use events::{Events, KeyboardEvent, MouseButton, MouseEvent, VirtualKeyCode, WindowEvent}; | pub use events::{Events, KeyboardEvent, MouseButton, MouseEvent, VirtualKeyCode, WindowEvent}; | ||||
pub use text::{Text, TextCache, TextManager}; | pub use text::{Text, TextCache, TextManager}; | ||||
pub use window::Window; | pub use window::Window; | ||||
pub use world::WorldHelper; | |||||
pub use world::{PersistWorld, WorldHelper}; |
@@ -5,10 +5,33 @@ use glc::{ | |||||
shader::{Program, Shader, Type}, | shader::{Program, Shader, Type}, | ||||
texture::{Data, FilterMag, FilterMin, Target, Texture, Wrap}, | texture::{Data, FilterMag, FilterMin, Target, Texture, Wrap}, | ||||
}; | }; | ||||
use space_crush_common::misc::Vfs; | |||||
use specs::World; | |||||
use space_crush_common::{ | |||||
components::{Owned, Planet, Player, Position, Ship, Velocity}, | |||||
misc::{Persistence, Vfs}, | |||||
}; | |||||
use specs::{saveload::SimpleMarker, World}; | |||||
use crate::{components::PlayerVisual, Error}; | |||||
/* PersistWorld */ | |||||
pub struct PersistWorld; | |||||
pub struct PersistWorldMarker; | |||||
impl Persistence for PersistWorld { | |||||
type Marker = SimpleMarker<PersistWorldMarker>; | |||||
type Components = ( | |||||
Position, | |||||
Velocity, | |||||
Planet, | |||||
Ship, | |||||
Owned, | |||||
Player, | |||||
PlayerVisual, | |||||
); | |||||
} | |||||
use crate::Error; | |||||
/* WorldHelper */ | |||||
pub trait WorldHelper { | pub trait WorldHelper { | ||||
fn load_program<I>(&self, iter: I) -> Result<Program, Error> | fn load_program<I>(&self, iter: I) -> Result<Program, Error> | ||||
@@ -1,16 +1,17 @@ | |||||
use glc::{ | use glc::{ | ||||
matrix::Matrix4f, | matrix::Matrix4f, | ||||
misc::Bindable, | |||||
misc::{BindGuard, Bindable}, | |||||
shader::{Program, Type, Uniform}, | shader::{Program, Type, Uniform}, | ||||
texture::Texture, | texture::Texture, | ||||
vector::Vector4f, | vector::Vector4f, | ||||
}; | }; | ||||
use log::error; | use log::error; | ||||
use space_crush_common::components::{Planet, Position}; | |||||
use space_crush_common::components::{Owned, Planet, Position}; | |||||
use specs::{prelude::*, ReadExpect, ReadStorage, System, World}; | use specs::{prelude::*, ReadExpect, ReadStorage, System, World}; | ||||
use crate::{ | use crate::{ | ||||
constants::{UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM}, | |||||
components::PlayerVisual, | |||||
constants::{PLAYER_COLOR_DEFAULT, UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM}, | |||||
misc::WorldHelper, | misc::WorldHelper, | ||||
resources::Geometry, | resources::Geometry, | ||||
Error, | Error, | ||||
@@ -19,7 +20,8 @@ use crate::{ | |||||
pub struct Planets { | pub struct Planets { | ||||
program: Program, | program: Program, | ||||
texture: Texture, | texture: Texture, | ||||
model_location: gl::GLint, | |||||
location_model: gl::GLint, | |||||
location_glow_color: gl::GLint, | |||||
} | } | ||||
impl Planets { | impl Planets { | ||||
@@ -32,13 +34,11 @@ impl Planets { | |||||
program.uniform_block_binding("Camera", UNIFORM_BUFFER_INDEX_CAMERA)?; | program.uniform_block_binding("Camera", UNIFORM_BUFFER_INDEX_CAMERA)?; | ||||
program.uniform_block_binding("Global", UNIFORM_BUFFER_INDEX_UNIFORM)?; | program.uniform_block_binding("Global", UNIFORM_BUFFER_INDEX_UNIFORM)?; | ||||
let glow_color = Vector4f::new(1.0, 1.0, 1.0, 0.1); | |||||
let glow_color = Uniform::Vector4f(&glow_color); | |||||
let model_location = program.uniform_location("uModel")?; | |||||
let location_model = program.uniform_location("uModel")?; | |||||
let location_glow_color = program.uniform_location("uGlowColor")?; | |||||
program.bind(); | program.bind(); | ||||
program.uniform("uTexture", Uniform::Texture(0))?; | program.uniform("uTexture", Uniform::Texture(0))?; | ||||
program.uniform("uGlowColor", glow_color)?; | |||||
program.unbind(); | program.unbind(); | ||||
let texture = world.load_texture("resources/textures/planet01.png")?; | let texture = world.load_texture("resources/textures/planet01.png")?; | ||||
@@ -46,7 +46,8 @@ impl Planets { | |||||
Ok(Self { | Ok(Self { | ||||
program, | program, | ||||
texture, | texture, | ||||
model_location, | |||||
location_model, | |||||
location_glow_color, | |||||
}) | }) | ||||
} | } | ||||
} | } | ||||
@@ -56,6 +57,8 @@ pub struct PlanetsData<'a> { | |||||
geometry: ReadExpect<'a, Geometry>, | geometry: ReadExpect<'a, Geometry>, | ||||
position: ReadStorage<'a, Position>, | position: ReadStorage<'a, Position>, | ||||
planet: ReadStorage<'a, Planet>, | planet: ReadStorage<'a, Planet>, | ||||
owned: ReadStorage<'a, Owned>, | |||||
player_visual: ReadStorage<'a, PlayerVisual>, | |||||
} | } | ||||
impl<'a> System<'a> for Planets { | impl<'a> System<'a> for Planets { | ||||
@@ -66,29 +69,43 @@ impl<'a> System<'a> for Planets { | |||||
geometry, | geometry, | ||||
position, | position, | ||||
planet, | planet, | ||||
owned, | |||||
player_visual, | |||||
} = data; | } = data; | ||||
gl::enable(gl::BLEND); | gl::enable(gl::BLEND); | ||||
gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); | gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); | ||||
self.texture.bind(); | |||||
self.program.bind(); | |||||
let _guard = BindGuard::new(&self.program); | |||||
let _guard = BindGuard::new(&self.texture); | |||||
for (p, _) in (&position, &planet).join() { | |||||
let x = p.pos.x; | |||||
let y = p.pos.y; | |||||
for (p, _, owned) in (&position, &planet, owned.maybe()).join() { | |||||
let p_x = p.pos.x; | |||||
let p_y = p.pos.y; | |||||
let s = p.size; | let s = p.size; | ||||
let c = match owned.and_then(|owned| player_visual.get(owned.owner)) { | |||||
Some(pv) => &pv.color, | |||||
None => &*PLAYER_COLOR_DEFAULT, | |||||
}; | |||||
let m = Matrix4f::new( | let m = Matrix4f::new( | ||||
Vector4f::new(s, 0.0, 0.0, 0.0), | Vector4f::new(s, 0.0, 0.0, 0.0), | ||||
Vector4f::new(0.0, s, 0.0, 0.0), | Vector4f::new(0.0, s, 0.0, 0.0), | ||||
Vector4f::new(0.0, 0.0, s, 0.0), | Vector4f::new(0.0, 0.0, s, 0.0), | ||||
Vector4f::new(x, y, 0.0, 1.0), | |||||
Vector4f::new(p_x, p_y, 0.0, 1.0), | |||||
); | ); | ||||
if let Err(err) = self | if let Err(err) = self | ||||
.program | .program | ||||
.uniform(self.model_location, Uniform::Matrix4f(&m)) | |||||
.uniform(self.location_glow_color, Uniform::Vector4f(&c)) | |||||
{ | |||||
error!("Error while updating glow color: {}", err); | |||||
} | |||||
if let Err(err) = self | |||||
.program | |||||
.uniform(self.location_model, Uniform::Matrix4f(&m)) | |||||
{ | { | ||||
error!("Error while updating model matrix: {}", err); | error!("Error while updating model matrix: {}", err); | ||||
} | } | ||||
@@ -96,9 +113,6 @@ impl<'a> System<'a> for Planets { | |||||
geometry.render_quad(); | geometry.render_quad(); | ||||
} | } | ||||
self.program.unbind(); | |||||
self.texture.unbind(); | |||||
gl::disable(gl::BLEND); | gl::disable(gl::BLEND); | ||||
} | } | ||||
} | } |
@@ -6,11 +6,12 @@ use glc::{ | |||||
vector::Vector4f, | vector::Vector4f, | ||||
}; | }; | ||||
use log::error; | use log::error; | ||||
use space_crush_common::components::{Position, Ship, ShipType, Velocity}; | |||||
use space_crush_common::components::{Owned, Position, Ship, ShipType, Velocity}; | |||||
use specs::{prelude::*, ReadExpect, ReadStorage, System, World}; | use specs::{prelude::*, ReadExpect, ReadStorage, System, World}; | ||||
use crate::{ | use crate::{ | ||||
constants::{UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM}, | |||||
components::PlayerVisual, | |||||
constants::{PLAYER_COLOR_DEFAULT, UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM}, | |||||
misc::WorldHelper, | misc::WorldHelper, | ||||
resources::Geometry, | resources::Geometry, | ||||
Error, | Error, | ||||
@@ -18,10 +19,11 @@ use crate::{ | |||||
pub struct Ships { | pub struct Ships { | ||||
program: Program, | program: Program, | ||||
texture_fighter: Texture, | |||||
texture_bomber: Texture, | texture_bomber: Texture, | ||||
texture_fighter: Texture, | |||||
texture_transporter: Texture, | texture_transporter: Texture, | ||||
model_location: gl::GLint, | |||||
location_model: gl::GLint, | |||||
location_glow_color: gl::GLint, | |||||
} | } | ||||
impl Ships { | impl Ships { | ||||
@@ -34,25 +36,24 @@ impl Ships { | |||||
program.uniform_block_binding("Camera", UNIFORM_BUFFER_INDEX_CAMERA)?; | program.uniform_block_binding("Camera", UNIFORM_BUFFER_INDEX_CAMERA)?; | ||||
program.uniform_block_binding("Global", UNIFORM_BUFFER_INDEX_UNIFORM)?; | program.uniform_block_binding("Global", UNIFORM_BUFFER_INDEX_UNIFORM)?; | ||||
let glow_color = Vector4f::new(1.0, 1.0, 1.0, 0.02); | |||||
let glow_color = Uniform::Vector4f(&glow_color); | |||||
let model_location = program.uniform_location("uModel")?; | |||||
let location_model = program.uniform_location("uModel")?; | |||||
let location_glow_color = program.uniform_location("uGlowColor")?; | |||||
program.bind(); | program.bind(); | ||||
program.uniform("uTexture", Uniform::Texture(0))?; | program.uniform("uTexture", Uniform::Texture(0))?; | ||||
program.uniform("uGlowColor", glow_color)?; | |||||
program.unbind(); | program.unbind(); | ||||
let texture_fighter = world.load_texture("resources/textures/ship_fighter.png")?; | |||||
let texture_bomber = world.load_texture("resources/textures/ship_bomber.png")?; | let texture_bomber = world.load_texture("resources/textures/ship_bomber.png")?; | ||||
let texture_fighter = world.load_texture("resources/textures/ship_fighter.png")?; | |||||
let texture_transporter = world.load_texture("resources/textures/ship_transporter.png")?; | let texture_transporter = world.load_texture("resources/textures/ship_transporter.png")?; | ||||
Ok(Self { | Ok(Self { | ||||
program, | program, | ||||
texture_fighter, | |||||
texture_bomber, | texture_bomber, | ||||
texture_fighter, | |||||
texture_transporter, | texture_transporter, | ||||
model_location, | |||||
location_model, | |||||
location_glow_color, | |||||
}) | }) | ||||
} | } | ||||
} | } | ||||
@@ -63,6 +64,8 @@ pub struct ShipsData<'a> { | |||||
position: ReadStorage<'a, Position>, | position: ReadStorage<'a, Position>, | ||||
velocity: ReadStorage<'a, Velocity>, | velocity: ReadStorage<'a, Velocity>, | ||||
ship: ReadStorage<'a, Ship>, | ship: ReadStorage<'a, Ship>, | ||||
owned: ReadStorage<'a, Owned>, | |||||
player_visual: ReadStorage<'a, PlayerVisual>, | |||||
} | } | ||||
impl<'a> System<'a> for Ships { | impl<'a> System<'a> for Ships { | ||||
@@ -74,6 +77,8 @@ impl<'a> System<'a> for Ships { | |||||
position, | position, | ||||
velocity, | velocity, | ||||
ship, | ship, | ||||
owned, | |||||
player_visual, | |||||
} = data; | } = data; | ||||
gl::enable(gl::BLEND); | gl::enable(gl::BLEND); | ||||
@@ -81,13 +86,18 @@ impl<'a> System<'a> for Ships { | |||||
let _guard = BindGuard::new(&self.program); | let _guard = BindGuard::new(&self.program); | ||||
for (p, v, ship) in (&position, &velocity, &ship).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_visual.get(owned.owner)) { | |||||
Some(pv) => &pv.color, | |||||
None => &*PLAYER_COLOR_DEFAULT, | |||||
}; | |||||
let p_x = p.pos.x; | let p_x = p.pos.x; | ||||
let p_y = p.pos.y; | let p_y = p.pos.y; | ||||
let d_x = v.dir.x; | let d_x = v.dir.x; | ||||
@@ -103,7 +113,14 @@ impl<'a> System<'a> for Ships { | |||||
if let Err(err) = self | if let Err(err) = self | ||||
.program | .program | ||||
.uniform(self.model_location, Uniform::Matrix4f(&m)) | |||||
.uniform(self.location_glow_color, Uniform::Vector4f(&c)) | |||||
{ | |||||
error!("Error while updating glow color: {}", err); | |||||
} | |||||
if let Err(err) = self | |||||
.program | |||||
.uniform(self.location_model, Uniform::Matrix4f(&m)) | |||||
{ | { | ||||
error!("Error while updating model matrix: {}", err); | error!("Error while updating model matrix: {}", err); | ||||
} | } | ||||
@@ -1,9 +1,13 @@ | |||||
mod owned; | |||||
mod planet; | mod planet; | ||||
mod player; | |||||
mod position; | mod position; | ||||
mod ship; | mod ship; | ||||
mod velocity; | mod velocity; | ||||
pub use owned::Owned; | |||||
pub use planet::Planet; | pub use planet::Planet; | ||||
pub use player::Player; | |||||
pub use position::Position; | pub use position::Position; | ||||
pub use ship::{Ship, Type as ShipType}; | pub use ship::{Ship, Type as ShipType}; | ||||
pub use velocity::Velocity; | pub use velocity::Velocity; |
@@ -0,0 +1,46 @@ | |||||
use serde::{Deserialize, Serialize}; | |||||
use specs::{ | |||||
error::NoError, | |||||
saveload::{ConvertSaveload, Marker}, | |||||
Component, Entity, VecStorage, | |||||
}; | |||||
#[derive(Clone, Debug)] | |||||
pub struct Owned { | |||||
pub owner: Entity, | |||||
} | |||||
#[derive(Serialize, Deserialize)] | |||||
pub struct OwnedData<M> { | |||||
pub owner: M, | |||||
} | |||||
impl Component for Owned { | |||||
type Storage = VecStorage<Self>; | |||||
} | |||||
impl<M> ConvertSaveload<M> for Owned | |||||
where | |||||
for<'de> M: Marker + Serialize + Deserialize<'de>, | |||||
{ | |||||
type Data = OwnedData<M>; | |||||
type Error = NoError; | |||||
fn convert_into<F>(&self, mut ids: F) -> Result<Self::Data, Self::Error> | |||||
where | |||||
F: FnMut(Entity) -> Option<M>, | |||||
{ | |||||
let owner = ids(self.owner).unwrap(); | |||||
Ok(OwnedData { owner }) | |||||
} | |||||
fn convert_from<F>(data: Self::Data, mut ids: F) -> Result<Self, Self::Error> | |||||
where | |||||
F: FnMut(M) -> Option<Entity>, | |||||
{ | |||||
let owner = ids(data.owner).unwrap(); | |||||
Ok(Owned { owner }) | |||||
} | |||||
} |
@@ -0,0 +1,9 @@ | |||||
use serde::{Deserialize, Serialize}; | |||||
use specs::{Component, NullStorage}; | |||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)] | |||||
pub struct Player {} | |||||
impl Component for Player { | |||||
type Storage = NullStorage<Self>; | |||||
} |
@@ -1,6 +1,7 @@ | |||||
use specs::{Dispatcher as Inner, DispatcherBuilder, World}; | |||||
use specs::{Dispatcher as Inner, DispatcherBuilder, World, WorldExt}; | |||||
use crate::{ | use crate::{ | ||||
components::Player, | |||||
resources::Global, | resources::Global, | ||||
systems::{Movement, Process}, | systems::{Movement, Process}, | ||||
}; | }; | ||||
@@ -13,6 +14,8 @@ impl<'a, 'b> Dispatcher<'a, 'b> { | |||||
pub fn new(world: &mut World) -> Self { | pub fn new(world: &mut World) -> Self { | ||||
world.insert(Global::default()); | world.insert(Global::default()); | ||||
world.register::<Player>(); | |||||
let mut dispatcher = DispatcherBuilder::new() | let mut dispatcher = DispatcherBuilder::new() | ||||
.with(Process::default(), "process", &[]) | .with(Process::default(), "process", &[]) | ||||
.with(Movement::default(), "movement", &[]) | .with(Movement::default(), "movement", &[]) | ||||
@@ -1,9 +1,7 @@ | |||||
mod log; | mod log; | ||||
mod persistence; | |||||
mod vfs; | mod vfs; | ||||
mod world; | mod world; | ||||
pub use self::log::init as init_logger; | pub use self::log::init as init_logger; | ||||
pub use self::vfs::{Vfs, VfsError}; | pub use self::vfs::{Vfs, VfsError}; | ||||
pub use persistence::PersistWorld; | |||||
pub use world::{Persistence, WorldHelper}; | pub use world::{Persistence, WorldHelper}; |
@@ -1,13 +0,0 @@ | |||||
use specs::saveload::SimpleMarker; | |||||
use crate::components::{Planet, Position, Ship, Velocity}; | |||||
use super::Persistence; | |||||
pub struct PersistWorld; | |||||
pub struct PersistWorldMarker; | |||||
impl Persistence for PersistWorld { | |||||
type Marker = SimpleMarker<PersistWorldMarker>; | |||||
type Components = (Position, Velocity, Planet, Ship); | |||||
} |
@@ -1,14 +1,11 @@ | |||||
use std::any::type_name; | use std::any::type_name; | ||||
use serde::{ | |||||
de::{DeserializeOwned, Deserializer}, | |||||
ser::{Serialize, Serializer}, | |||||
}; | |||||
use serde::{de::Deserializer, ser::Serializer}; | |||||
use shred::{Fetch, FetchMut, Resource}; | use shred::{Fetch, FetchMut, Resource}; | ||||
use shrev::{Event, EventChannel, ReaderId}; | use shrev::{Event, EventChannel, ReaderId}; | ||||
use specs::{ | use specs::{ | ||||
error::NoError, | error::NoError, | ||||
saveload::{DeserializeComponents, Marker, SerializeComponents}, | |||||
saveload::{ConvertSaveload, DeserializeComponents, Marker, SerializeComponents}, | |||||
Component, Entities, ReadStorage, World, WorldExt, Write, WriteStorage, | Component, Entities, ReadStorage, World, WorldExt, Write, WriteStorage, | ||||
}; | }; | ||||
@@ -133,16 +130,31 @@ macro_rules! define_persistence_components { | |||||
where | where | ||||
M: Marker, | M: Marker, | ||||
M::Allocator: Default, | M::Allocator: Default, | ||||
$($T: Component + Serialize + DeserializeOwned + Clone,)+ | |||||
$($T: Component + ConvertSaveload<M, Error = NoError>,)+ | |||||
{ | { | ||||
fn serialize<S>(world: &World, serializer: S) -> Result<(), S::Error> | fn serialize<S>(world: &World, serializer: S) -> Result<(), S::Error> | ||||
where | where | ||||
S: Serializer, | S: Serializer, | ||||
{ | { | ||||
let (entities, marker, $($T,)+) = | |||||
world.system_data::<(Entities, ReadStorage<M>, $(ReadStorage<$T>,)+)>(); | |||||
let ( | |||||
entities, | |||||
mut marker, | |||||
mut allocator, | |||||
$($T,)+ | |||||
) = world.system_data::<( | |||||
Entities, | |||||
WriteStorage<M>, | |||||
Write<M::Allocator>, | |||||
$(ReadStorage<$T>, | |||||
)+)>(); | |||||
SerializeComponents::<NoError, M>::serialize(&($($T,)+), &entities, &marker, serializer)?; | |||||
SerializeComponents::<NoError, M>::serialize_recursive | |||||
(&($($T,)+), | |||||
&entities, | |||||
&mut marker, | |||||
&mut allocator, | |||||
serializer, | |||||
)?; | |||||
Ok(()) | Ok(()) | ||||
} | } | ||||
@@ -151,7 +163,12 @@ macro_rules! define_persistence_components { | |||||
where | where | ||||
D: Deserializer<'de>, | D: Deserializer<'de>, | ||||
{ | { | ||||
let (entities, mut marker, mut allocator, $($T,)+) = world.system_data::<( | |||||
let ( | |||||
entities, | |||||
mut marker, | |||||
mut allocator, | |||||
$($T,)+ | |||||
) = world.system_data::<( | |||||
Entities, | Entities, | ||||
WriteStorage<M>, | WriteStorage<M>, | ||||
Write<M::Allocator>, | Write<M::Allocator>, | ||||