|
- use glc::{
- matrix::Matrix4f,
- misc::{BindGuard, Bindable},
- shader::{Program, Type, Uniform},
- texture::Texture,
- vector::Vector4f,
- };
- use space_crush_common::{
- components::{Player, PlayerOwned, Position, Ship, ShipType, Velocity},
- misc::LogResult,
- };
- use specs::{prelude::*, ReadExpect, ReadStorage, System, World};
-
- use crate::{
- constants::{
- PLAYER_COLOR_DEFAULT, SHIP_SIZE, UNIFORM_BUFFER_INDEX_CAMERA, UNIFORM_BUFFER_INDEX_UNIFORM,
- },
- misc::WorldHelper,
- resources::Geometry,
- Error,
- };
-
- pub struct Ships {
- program: Program,
- texture_bomber: Texture,
- texture_fighter: Texture,
- texture_transporter: Texture,
- location_model: gl::GLint,
- location_glow_color: gl::GLint,
- }
-
- impl Ships {
- pub fn new(world: &World) -> Result<Self, Error> {
- let program = world.load_program(vec![
- (Type::Vertex, "resources/shader/ship/vert.glsl"),
- (Type::Fragment, "resources/shader/ship/frag.glsl"),
- ])?;
-
- program.uniform_block_binding("Camera", UNIFORM_BUFFER_INDEX_CAMERA)?;
- program.uniform_block_binding("Global", UNIFORM_BUFFER_INDEX_UNIFORM)?;
-
- let location_model = program.uniform_location("uModel")?;
- let location_glow_color = program.uniform_location("uGlowColor")?;
-
- program.bind();
- program.uniform("uTexture", Uniform::Texture(0))?;
- program.unbind();
-
- 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")?;
-
- Ok(Self {
- program,
- texture_bomber,
- texture_fighter,
- texture_transporter,
- location_model,
- location_glow_color,
- })
- }
- }
-
- #[derive(SystemData)]
- pub struct ShipsData<'a> {
- geometry: ReadExpect<'a, Geometry>,
- position: ReadStorage<'a, Position>,
- velocity: ReadStorage<'a, Velocity>,
- ship: ReadStorage<'a, Ship>,
- owned: ReadStorage<'a, PlayerOwned>,
- player: ReadStorage<'a, Player>,
- }
-
- impl<'a> System<'a> for Ships {
- type SystemData = ShipsData<'a>;
-
- fn run(&mut self, data: Self::SystemData) {
- let ShipsData {
- geometry,
- position,
- velocity,
- ship,
- owned,
- player,
- } = data;
-
- gl::enable(gl::BLEND);
- gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
-
- let _guard = BindGuard::new(&self.program);
-
- for (p, v, ship, owned) in (&position, &velocity, &ship, owned.maybe()).join() {
- let _guard = match ship.type_ {
- ShipType::Fighter => BindGuard::new(&self.texture_fighter),
- ShipType::Bomber => BindGuard::new(&self.texture_bomber),
- ShipType::Transporter => BindGuard::new(&self.texture_transporter),
- };
-
- let c = match owned.and_then(|owned| player.get(owned.owner)) {
- Some(pv) => &pv.color,
- 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 s = SHIP_SIZE;
-
- let m = Matrix4f::new(
- Vector4f::new(-s * d_y, s * d_x, 0.0, 0.0),
- Vector4f::new(-s * d_x, -s * d_y, 0.0, 0.0),
- Vector4f::new(0.0, 0.0, s, 0.0),
- Vector4f::new(p_x, p_y, 0.0, 1.0),
- );
-
- self.program
- .uniform(self.location_glow_color, Uniform::Vector4f(&c))
- .error("Error while updating glow color");
- self.program
- .uniform(self.location_model, Uniform::Matrix4f(&m))
- .error("Error while updating model matrix");
-
- geometry.render_quad();
- }
-
- gl::disable(gl::BLEND);
- }
- }
|