171 lines
3.4 KiB
Rust
Raw Normal View History

use std::collections::HashMap;
use anyhow::{bail, Result};
2023-12-27 19:51:58 -08:00
use cgmath::Point2;
use nalgebra::{point, Point};
2023-12-30 16:57:03 -08:00
use crate::{handle::TextureHandle, Content};
2023-12-27 19:51:58 -08:00
2023-12-30 16:57:03 -08:00
pub(crate) mod syntax {
2023-12-27 19:51:58 -08:00
use serde::Deserialize;
// Raw serde syntax structs.
// These are never seen by code outside this crate.
#[derive(Debug, Deserialize)]
pub struct Ship {
2023-12-30 11:25:51 -08:00
pub sprite_texture: String,
2023-12-27 19:51:58 -08:00
pub size: f32,
pub engines: Vec<Engine>,
pub guns: Vec<Gun>,
pub hull: f32,
2023-12-30 11:07:20 -08:00
pub mass: f32,
pub collision: Collision,
}
#[derive(Debug, Deserialize)]
pub struct Collision {
pub points: Vec<[f32; 2]>,
pub indices: Vec<[u32; 2]>,
2023-12-27 19:51:58 -08:00
}
#[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.
2023-12-29 15:46:09 -08:00
/// Represents a ship chassis.
2023-12-27 19:51:58 -08:00
#[derive(Debug, Clone)]
pub struct Ship {
2023-12-29 15:46:09 -08:00
/// This ship's name
2023-12-27 19:51:58 -08:00
pub name: String,
2023-12-29 15:46:09 -08:00
/// This ship's sprite
2023-12-30 11:25:51 -08:00
pub sprite_texture: TextureHandle,
2023-12-29 15:46:09 -08:00
/// The size of this ship.
/// Measured as unrotated height,
/// in terms of game units.
2023-12-27 19:51:58 -08:00
pub size: f32,
2023-12-29 15:46:09 -08:00
2023-12-30 11:07:20 -08:00
/// The mass of this ship
pub mass: f32,
2023-12-29 15:46:09 -08:00
/// Engine points on this ship.
/// This is where engine flares are drawn.
2023-12-28 17:04:41 -08:00
pub engines: Vec<EnginePoint>,
2023-12-29 15:46:09 -08:00
/// Gun points on this ship.
/// A gun outfit can be mounted on each.
2023-12-28 17:04:41 -08:00
pub guns: Vec<GunPoint>,
2023-12-29 15:46:09 -08:00
/// This ship's hull strength
pub hull: f32,
/// Collision shape for this ship
pub collision: Collision,
/// Remove later
pub aspect: f32,
}
/// Collision shape for this ship
#[derive(Debug, Clone)]
pub struct Collision {
pub points: Vec<Point<f32, 2>>,
pub indices: Vec<[u32; 2]>,
2023-12-27 19:51:58 -08:00
}
2023-12-29 15:46:09 -08:00
/// An engine point on a ship.
/// This is where flares are drawn.
2023-12-27 19:51:58 -08:00
#[derive(Debug, Clone)]
2023-12-28 17:04:41 -08:00
pub struct EnginePoint {
2023-12-29 15:46:09 -08:00
/// This engine point's position, in game units,
/// relative to the ship's center.
2023-12-27 19:51:58 -08:00
pub pos: Point2<f32>,
2023-12-29 15:46:09 -08:00
/// The size of the flare that should be drawn
/// at this point, measured as height in game units.
2023-12-27 19:51:58 -08:00
pub size: f32,
}
2023-12-29 15:46:09 -08:00
/// A gun point on a ship.
2023-12-27 19:51:58 -08:00
#[derive(Debug, Clone)]
2023-12-28 17:04:41 -08:00
pub struct GunPoint {
2023-12-29 15:46:09 -08:00
/// This gun point's position, in game units,
/// relative to the ship's center.
2023-12-27 19:51:58 -08:00
pub pos: Point2<f32>,
}
2023-12-30 16:57:03 -08:00
impl crate::Build for Ship {
type InputSyntax = HashMap<String, syntax::Ship>;
fn build(ship: Self::InputSyntax, ct: &mut Content) -> Result<()> {
2023-12-27 20:13:39 -08:00
for (ship_name, ship) in ship {
2023-12-30 11:25:51 -08:00
let th = match ct.texture_index.get(&ship.sprite_texture) {
None => bail!(
"In ship `{}`: texture `{}` doesn't exist",
ship_name,
2023-12-30 11:25:51 -08:00
ship.sprite_texture
),
Some(t) => *t,
};
2023-12-30 11:07:20 -08:00
let size = ship.size;
let aspect = th.aspect;
ct.ships.push(Self {
aspect,
2023-12-30 11:07:20 -08:00
name: ship_name,
2023-12-30 11:25:51 -08:00
sprite_texture: th,
2023-12-30 11:07:20 -08:00
mass: ship.mass,
2023-12-28 20:19:33 -08:00
size,
hull: ship.hull,
2023-12-27 19:51:58 -08:00
engines: ship
.engines
.iter()
2023-12-28 17:04:41 -08:00
.map(|e| EnginePoint {
2023-12-28 20:19:33 -08:00
pos: Point2 {
x: e.x * size * aspect / 2.0,
y: e.y * size / 2.0,
2023-12-28 20:19:33 -08:00
},
2023-12-27 19:51:58 -08:00
size: e.size,
})
.collect(),
guns: ship
.guns
.iter()
2023-12-28 17:04:41 -08:00
.map(|e| GunPoint {
2023-12-28 20:19:33 -08:00
pos: Point2 {
x: e.x * size * aspect / 2.0,
y: e.y * size / 2.0,
2023-12-28 20:19:33 -08:00
},
2023-12-27 19:51:58 -08:00
})
.collect(),
collision: Collision {
2023-12-30 16:57:03 -08:00
indices: ship.collision.indices,
points: ship
.collision
.points
.iter()
.map(|x| point![x[0] * (size / 2.0) * aspect, x[1] * size / 2.0])
.collect(),
},
2023-12-27 19:51:58 -08:00
});
}
return Ok(());
2023-12-27 19:51:58 -08:00
}
}