use std::collections::HashMap; use anyhow::{bail, Result}; use cgmath::Point2; use nalgebra::{point, Point}; use crate::{handle::TextureHandle, Content}; use super::OutfitSpace; pub(crate) mod syntax { use super::super::shared; use serde::Deserialize; // Raw serde syntax structs. // These are never seen by code outside this crate. #[derive(Debug, Deserialize)] pub struct Ship { pub sprite_texture: String, pub size: f32, pub engines: Vec, pub guns: Vec, pub hull: f32, pub mass: f32, pub collision: Collision, pub angular_drag: f32, pub linear_drag: f32, pub space: shared::syntax::OutfitSpace, } #[derive(Debug, Deserialize)] pub struct Collision { pub points: Vec<[f32; 2]>, pub indices: Vec<[u32; 2]>, } #[derive(Debug, Deserialize)] pub struct Engine { pub x: f32, pub y: f32, pub size: f32, } #[derive(Debug, Deserialize)] pub struct Gun { pub x: f32, pub y: f32, } } // Processed data structs. // These are exported. /// Represents a ship chassis. #[derive(Debug, Clone)] pub struct Ship { /// This ship's name pub name: String, /// This ship's sprite pub sprite_texture: TextureHandle, /// The size of this ship. /// Measured as unrotated height, /// in terms of game units. pub size: f32, /// The mass of this ship pub mass: f32, /// Engine points on this ship. /// This is where engine flares are drawn. pub engines: Vec, /// Gun points on this ship. /// A gun outfit can be mounted on each. pub guns: Vec, /// This ship's hull strength pub hull: f32, /// Collision shape for this ship pub collision: Collision, /// Remove later pub aspect: f32, /// Reduction in angular velocity over time pub angular_drag: f32, /// Reduction in velocity over time pub linear_drag: f32, /// Outfit space in this ship pub space: OutfitSpace, } /// Collision shape for this ship #[derive(Debug, Clone)] pub struct Collision { pub points: Vec>, pub indices: Vec<[u32; 2]>, } /// An engine point on a ship. /// This is where flares are drawn. #[derive(Debug, Clone)] pub struct EnginePoint { /// This engine point's position, in game units, /// relative to the ship's center. pub pos: Point2, /// The size of the flare that should be drawn /// at this point, measured as height in game units. pub size: f32, } /// A gun point on a ship. #[derive(Debug, Clone)] pub struct GunPoint { /// This gun point's position, in game units, /// relative to the ship's center. pub pos: Point2, } impl crate::Build for Ship { type InputSyntax = HashMap; fn build(ship: Self::InputSyntax, ct: &mut Content) -> Result<()> { for (ship_name, ship) in ship { let th = match ct.texture_index.get(&ship.sprite_texture) { None => bail!( "In ship `{}`: texture `{}` doesn't exist", ship_name, ship.sprite_texture ), Some(t) => *t, }; let size = ship.size; let aspect = th.aspect; ct.ships.push(Self { aspect, name: ship_name, sprite_texture: th, mass: ship.mass, space: OutfitSpace::from(ship.space), angular_drag: ship.angular_drag, linear_drag: ship.linear_drag, size, hull: ship.hull, engines: ship .engines .iter() .map(|e| EnginePoint { pos: Point2 { x: e.x * size * aspect / 2.0, y: e.y * size / 2.0, }, size: e.size, }) .collect(), guns: ship .guns .iter() .map(|e| GunPoint { pos: Point2 { x: e.x * size * aspect / 2.0, y: e.y * size / 2.0, }, }) .collect(), collision: Collision { indices: ship.collision.indices, points: ship .collision .points .iter() .map(|x| point![x[0] * (size / 2.0) * aspect, x[1] * size / 2.0]) .collect(), }, }); } return Ok(()); } }