diff --git a/crates/constants/src/lib.rs b/crates/constants/src/lib.rs index 81ef2cb..8275266 100644 --- a/crates/constants/src/lib.rs +++ b/crates/constants/src/lib.rs @@ -1,14 +1,24 @@ +#![warn(missing_docs)] + +//! Compile-time parameters + +/// Minimum zoom level pub const ZOOM_MIN: f32 = 200.0; +/// Maximum zoom level pub const ZOOM_MAX: f32 = 2000.0; /// Z-axis range for starfield stars /// This does not affect scale. pub const STARFIELD_Z_MIN: f32 = 100.0; +/// Z-axis range for starfield stars +/// This does not affect scale. pub const STARFIELD_Z_MAX: f32 = 200.0; /// Size range for starfield stars, in game units. /// This is scaled for zoom, but NOT for distance. pub const STARFIELD_SIZE_MIN: f32 = 0.2; +/// Size range for starfield stars, in game units. +/// This is scaled for zoom, but NOT for distance. pub const STARFIELD_SIZE_MAX: f32 = 1.8; /// Size of a square starfield tile, in game units. @@ -34,9 +44,8 @@ pub const CONTENT_ROOT: &'static str = "./content"; /// Root directory of game textures pub const TEXTURE_ROOT: &'static str = "./assets/render"; -// We can draw at most this many sprites on the screen. -// TODO: compile-time option or config file +/// We can draw at most this many sprites on the screen. pub const SPRITE_INSTANCE_LIMIT: u64 = 500; -// Must be small enough to fit in an i32 +/// Must be small enough to fit in an i32 pub const STARFIELD_INSTANCE_LIMIT: u64 = STARFIELD_COUNT * 24; diff --git a/crates/physics/src/lib.rs b/crates/physics/src/lib.rs index dd72dac..444a780 100644 --- a/crates/physics/src/lib.rs +++ b/crates/physics/src/lib.rs @@ -1,3 +1,9 @@ +#![warn(missing_docs)] + +//! This module keeps track of all objects and interactions in the game: +//! Ships, projectiles, collisions, etc. +//! TODO: Rename & re-organize + pub mod objects; mod physics; pub mod util; @@ -7,5 +13,6 @@ pub use physics::Physics; use rapier2d::{dynamics::RigidBodyHandle, geometry::ColliderHandle}; +/// A lightweight handle for a specific ship in a physics system #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct ShipHandle(pub RigidBodyHandle, ColliderHandle); diff --git a/crates/physics/src/objects/outfits.rs b/crates/physics/src/objects/outfits.rs index e2a34c3..592b9ee 100644 --- a/crates/physics/src/objects/outfits.rs +++ b/crates/physics/src/objects/outfits.rs @@ -5,12 +5,18 @@ use galactica_render::ObjectSubSprite; /// Represents a gun attached to a specific ship at a certain gunpoint. #[derive(Debug)] pub struct ShipGun { + /// The kind of gun this is pub kind: content::Gun, + + /// How many seconds we must wait before this gun can fire pub cooldown: f32, + + /// Index of the gunpoint this gun is attached to pub point: usize, } impl ShipGun { + /// Make a new shipgun pub fn new(kind: content::Gun, point: usize) -> Self { Self { kind: kind, @@ -63,11 +69,15 @@ impl OutfitStatSum { /// Represents all the outfits attached to a ship. /// Keeps track of the sum of their stats, so it mustn't be re-computed every frame. +/// TODO: rename (outfitset?) +/// TODO: ctrl-f outfitset in comments #[derive(Debug)] pub struct ShipOutfits { + /// The total sum of the stats this set of outfits provides + /// TODO: this shouldn't be pub pub stats: OutfitStatSum, - pub total_space: content::OutfitSpace, + //pub total_space: content::OutfitSpace, available_space: content::OutfitSpace, outfits: Vec, guns: Vec, @@ -80,13 +90,14 @@ pub struct ShipOutfits { } impl<'a> ShipOutfits { + /// Make a new outfit array pub fn new(content: &content::Ship) -> Self { Self { stats: OutfitStatSum::new(), outfits: Vec::new(), guns: Vec::new(), available_space: content.space.clone(), - total_space: content.space.clone(), + //total_space: content.space.clone(), enginepoints: content.engines.clone(), gunpoints: content.guns.clone(), engine_flare_sprites: vec![], @@ -153,10 +164,12 @@ impl<'a> ShipOutfits { return true; } + /// Iterate over all guns in this outfitset pub fn iter_guns(&mut self) -> impl Iterator { self.guns.iter_mut() } + /// Iterate over all guns and the gunpoints they're attached to pub fn iter_guns_points(&mut self) -> impl Iterator { self.guns .iter_mut() @@ -164,6 +177,7 @@ impl<'a> ShipOutfits { .map(|(a, b)| (b, a)) } + /// Update engine flare sprites pub fn update_engine_flares(&mut self) { // TODO: better way to pick flare texture self.engine_flare_sprites.clear(); @@ -189,6 +203,7 @@ impl<'a> ShipOutfits { .collect(); } + /// Get the sprites we should show if this ship is firing its engines pub fn get_engine_flares(&self) -> Vec { return self.engine_flare_sprites.clone(); } diff --git a/crates/physics/src/objects/projectile.rs b/crates/physics/src/objects/projectile.rs index 6515429..8a6162d 100644 --- a/crates/physics/src/objects/projectile.rs +++ b/crates/physics/src/objects/projectile.rs @@ -8,50 +8,81 @@ use crate::util; use galactica_content as content; use galactica_render::ObjectSprite; +/// A helper struct that contains parameters for a projectile +/// TODO: decouple data from physics pub struct ProjectileBuilder { + /// TODO pub rigid_body: RigidBodyBuilder, + + /// TODO pub collider: ColliderBuilder, + + /// TODO pub sprite_texture: content::TextureHandle, + + /// TODO pub lifetime: f32, + + /// TODO pub size: f32, + + /// TODO pub damage: f32, + + /// TODO pub faction: content::FactionHandle, } -impl ProjectileBuilder { - pub fn build(self, r: RigidBodyHandle, c: ColliderHandle) -> Projectile { - Projectile { - rigid_body: r, - collider: c, - sprite_texture: self.sprite_texture, - lifetime: self.lifetime, - size: self.size, - damage: self.damage, - faction: self.faction, - } - } -} - +/// A single projectile in the world #[derive(Debug)] pub struct Projectile { + /// TODO pub rigid_body: RigidBodyHandle, + + /// TODO pub collider: ColliderHandle, + + /// TODO pub sprite_texture: content::TextureHandle, + + /// TODO pub lifetime: f32, + + /// TODOd pub size: f32, + + /// TODO pub damage: f32, + + /// TODO pub faction: content::FactionHandle, } impl Projectile { + /// Make a new projectile + pub fn new(b: ProjectileBuilder, r: RigidBodyHandle, c: ColliderHandle) -> Self { + Projectile { + rigid_body: r, + collider: c, + sprite_texture: b.sprite_texture, + lifetime: b.lifetime, + size: b.size, + damage: b.damage, + faction: b.faction, + } + } + + /// Update this projectile's state after `t` seconds pub fn tick(&mut self, t: f32) { self.lifetime -= t; } + /// Is this projectile expired? pub fn is_expired(&self) -> bool { return self.lifetime < 0.0; } + /// Get this projectiles' sprite pub fn get_sprite(&self, r: &RigidBody) -> ObjectSprite { let pos = util::rigidbody_position(r); let rot = util::rigidbody_rotation(r); diff --git a/crates/physics/src/objects/ship.rs b/crates/physics/src/objects/ship.rs index 1ca7c6a..c507041 100644 --- a/crates/physics/src/objects/ship.rs +++ b/crates/physics/src/objects/ship.rs @@ -35,10 +35,19 @@ impl ShipControls { } } +/// A ship instance in the physics system +/// TODO: Decouple ship data from physics pub struct Ship { + /// TODO pub physics_handle: ShipHandle, + + /// TODO pub faction: FactionHandle, + + /// TODO pub hull: f32, + + /// TODO pub controls: ShipControls, outfits: ShipOutfits, @@ -47,6 +56,7 @@ pub struct Ship { } impl Ship { + /// Make a new ship pub fn new( c: &content::Ship, outfits: ShipOutfits, @@ -64,6 +74,7 @@ impl Ship { } } + /// Fire this ship's guns. Called every frame, if this ship is firing. pub fn fire_guns(&mut self, r: &RigidBody) -> Vec { let mut rng = rand::thread_rng(); let mut out = Vec::new(); @@ -154,6 +165,7 @@ impl Ship { return ShipTickResult { projectiles: p }; } + /// Get this ship's sprite pub fn get_sprite(&self, r: &RigidBody) -> ObjectSprite { let ship_pos = util::rigidbody_position(r); let ship_rot = util::rigidbody_rotation(r); diff --git a/crates/physics/src/physics.rs b/crates/physics/src/physics.rs index 851b347..e13391c 100644 --- a/crates/physics/src/physics.rs +++ b/crates/physics/src/physics.rs @@ -8,7 +8,12 @@ use rapier2d::{ }; use std::{collections::HashMap, f32::consts::PI}; -use crate::{objects, objects::ShipOutfits, wrapper::Wrapper, ShipHandle}; +use crate::{ + objects, + objects::{Projectile, ShipOutfits}, + wrapper::Wrapper, + ShipHandle, +}; use galactica_content as content; use galactica_render::ObjectSprite; @@ -59,13 +64,14 @@ impl Physics { r, &mut self.wrapper.rigid_body_set, ); - self.projectiles.insert(c, pb.build(r, c)); + self.projectiles.insert(c, Projectile::new(pb, r, c)); return c; } } // Public methods impl Physics { + /// Create a new physics system pub fn new() -> Self { let (collision_send, collision_queue) = crossbeam::channel::unbounded(); let (contact_force_send, _) = crossbeam::channel::unbounded(); @@ -79,6 +85,8 @@ impl Physics { } } + /// Add a ship to this physics system + /// TODO: decouple from Ship::new() pub fn add_ship( &mut self, ct: &content::Ship, @@ -114,6 +122,7 @@ impl Physics { return h; } + /// Step this physics system by `t` seconds pub fn step(&mut self, t: f32, ct: &content::Content) { // Run ship updates let mut res = Vec::new(); @@ -183,19 +192,23 @@ impl Physics { } } + /// Get a rigid body from a handle pub fn get_rigid_body(&self, r: RigidBodyHandle) -> &RigidBody { &self.wrapper.rigid_body_set[r] } + /// Get a ship from a handle pub fn get_ship_mut(&mut self, s: &ShipHandle) -> Option<&mut objects::Ship> { self.ships.get_mut(&s.1) } + /// Get a ship and its rigidbody from a handle pub fn get_ship_body(&self, s: &ShipHandle) -> Option<(&objects::Ship, &RigidBody)> { // TODO: handle dead handles Some((self.ships.get(&s.1)?, self.wrapper.rigid_body_set.get(s.0)?)) } + /// Iterate over all ships in this physics system pub fn iter_ship_body(&self) -> impl Iterator + '_ { self.ships.values().map(|x| { ( @@ -205,12 +218,14 @@ impl Physics { }) } + /// Iterate over all ship sprites in this physics system pub fn get_ship_sprites(&self) -> impl Iterator + '_ { self.ships .values() .map(|x| x.get_sprite(&self.wrapper.rigid_body_set[x.physics_handle.0])) } + /// Iterate over all projectile sprites in this physics system pub fn get_projectile_sprites(&self) -> impl Iterator + '_ { self.projectiles .values() diff --git a/crates/physics/src/util.rs b/crates/physics/src/util.rs index 2c2ed4a..6674fb4 100644 --- a/crates/physics/src/util.rs +++ b/crates/physics/src/util.rs @@ -1,7 +1,12 @@ +//! Conversion utilities + use cgmath::{Point2, Vector2}; use nalgebra; use rapier2d::dynamics::RigidBody; +// TODO: Migrate to nalgebra fully, remove these converters + +/// Convert a rigidbody position to a position in game coordinates pub fn rigidbody_position(r: &RigidBody) -> cgmath::Point2 { Point2 { x: r.translation()[0], @@ -9,6 +14,7 @@ pub fn rigidbody_position(r: &RigidBody) -> cgmath::Point2 { } } +/// Convert a rigidbody rotation to a rotation in game coordinates pub fn rigidbody_rotation(r: &RigidBody) -> Vector2 { Vector2 { x: r.rotation().re, @@ -16,6 +22,7 @@ pub fn rigidbody_rotation(r: &RigidBody) -> Vector2 { } } +/// Convert a rigidbody velocity to a velocity in game coordinates pub fn rigidbody_velocity(r: &RigidBody) -> cgmath::Vector2 { let v = r.velocity_at_point(&nalgebra::Point2::new( r.translation()[0], diff --git a/crates/shipbehavior/src/behavior/dummy.rs b/crates/shipbehavior/src/behavior/dummy.rs index 59db192..d9b22f4 100644 --- a/crates/shipbehavior/src/behavior/dummy.rs +++ b/crates/shipbehavior/src/behavior/dummy.rs @@ -2,11 +2,14 @@ use crate::ShipBehavior; use galactica_content as content; use galactica_physics::{Physics, ShipHandle}; +/// Dummy ship behavior. +/// Does nothing. pub struct Dummy { _handle: ShipHandle, } impl Dummy { + /// Create a new ship controller pub fn new(handle: ShipHandle) -> Box { Box::new(Self { _handle: handle }) } diff --git a/crates/shipbehavior/src/behavior/mod.rs b/crates/shipbehavior/src/behavior/mod.rs index 96cf301..fc95c58 100644 --- a/crates/shipbehavior/src/behavior/mod.rs +++ b/crates/shipbehavior/src/behavior/mod.rs @@ -1,3 +1,5 @@ +//! Various implementations of [`crate::ShipBehavior`] + mod dummy; mod player; mod point; diff --git a/crates/shipbehavior/src/behavior/player.rs b/crates/shipbehavior/src/behavior/player.rs index b015349..269f0c3 100644 --- a/crates/shipbehavior/src/behavior/player.rs +++ b/crates/shipbehavior/src/behavior/player.rs @@ -2,6 +2,8 @@ use crate::ShipBehavior; use galactica_content as content; use galactica_physics::{Physics, ShipHandle}; +/// Player ship behavior. +/// Controls a ship using controller input pub struct Player { handle: ShipHandle, key_left: bool, @@ -11,6 +13,7 @@ pub struct Player { } impl Player { + /// Make a new ship controller pub fn new(handle: ShipHandle) -> Box { Box::new(Self { handle, diff --git a/crates/shipbehavior/src/behavior/point.rs b/crates/shipbehavior/src/behavior/point.rs index 31f58df..0f01373 100644 --- a/crates/shipbehavior/src/behavior/point.rs +++ b/crates/shipbehavior/src/behavior/point.rs @@ -4,11 +4,14 @@ use crate::ShipBehavior; use galactica_content as content; use galactica_physics::{util, Physics, ShipHandle}; +/// "Point" ship behavior. +/// Point and shoot towards the nearest enemy. pub struct Point { handle: ShipHandle, } impl Point { + /// Create a new ship controller pub fn new(handle: ShipHandle) -> Box { Box::new(Self { handle }) } diff --git a/crates/shipbehavior/src/lib.rs b/crates/shipbehavior/src/lib.rs index 8c1de42..b1520ad 100644 --- a/crates/shipbehavior/src/lib.rs +++ b/crates/shipbehavior/src/lib.rs @@ -1,12 +1,21 @@ +#![warn(missing_docs)] + +//! Computer-controlled ship behaviors + pub mod behavior; use galactica_content as content; use galactica_physics::{Physics, ShipHandle}; +/// Main behavior trait. Any struct that implements this +/// may be used to control a ship. pub trait ShipBehavior where Self: Send, { + /// Update a ship's controls based on world state fn update_controls(&mut self, physics: &mut Physics, content: &content::Content); + + /// Get the ship this behavior is attached to fn get_handle(&self) -> ShipHandle; }