From 5815bb9f9fa4451abe67e793c1dbdfa93ddfc5d9 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 14 Jan 2024 11:50:19 -0800 Subject: [PATCH] Minor fixes --- crates/system/src/data/ship/ship.rs | 51 ++++++-------------- crates/system/src/phys/controller/point.rs | 13 +++-- crates/system/src/phys/objects/collapse.rs | 38 ++++++++------- crates/system/src/phys/objects/ship.rs | 11 +++-- crates/system/src/phys/systemsim/steputil.rs | 2 +- crates/util/src/lib.rs | 2 +- 6 files changed, 54 insertions(+), 63 deletions(-) diff --git a/crates/system/src/data/ship/ship.rs b/crates/system/src/data/ship/ship.rs index 7ba23bf..3d28e55 100644 --- a/crates/system/src/data/ship/ship.rs +++ b/crates/system/src/data/ship/ship.rs @@ -38,13 +38,7 @@ pub enum ShipState { }, /// This ship has been destroyed, and is playing its collapse sequence. - Collapsing { - /// Total collapse sequence length, in seconds - total: f32, - - /// How many seconds of the collapse sequence we've played - elapsed: f32, - }, + Collapsing, /// This ship is landed on a planet Landed { @@ -84,18 +78,6 @@ impl ShipState { _ => None, } } - - /// If this ship is collapsing, return total collapse time and remaining collapse time. - /// Otherwise, return None - pub fn collapse_state(&self) -> Option<(f32, f32)> { - match self { - Self::Collapsing { - total, - elapsed: remaining, - } => Some((*total, *remaining)), - _ => None, - } - } } /// Represents all attributes of a single ship @@ -257,6 +239,18 @@ impl ShipData { } }; } + + /// Called when collapse sequence is finished. + /// Will panic if we're not collapsing + pub fn finish_collapse(&mut self) { + match self.state { + ShipState::Collapsing => self.state = ShipState::Dead, + _ => { + unreachable!("Called `finish_collapse` on a ship that isn't collapsing!") + } + }; + } + /// Add an outfit to this ship pub fn add_outfit(&mut self, o: &Outfit) -> super::OutfitAddResult { let r = self.outfits.add(o); @@ -292,7 +286,7 @@ impl ShipData { } /// Hit this ship with the given amount of damage - pub(crate) fn apply_damage(&mut self, ct: &Content, mut d: f32) { + pub(crate) fn apply_damage(&mut self, mut d: f32) { match self.state { ShipState::Flying { .. } => {} _ => { @@ -311,10 +305,7 @@ impl ShipData { if self.hull <= 0.0 { // This ship has been destroyed, update state - self.state = ShipState::Collapsing { - total: ct.get_ship(self.ct_handle).collapse.length, - elapsed: 0.0, - } + self.state = ShipState::Collapsing } } @@ -360,17 +351,7 @@ impl ShipData { } } - ShipState::Collapsing { - ref mut elapsed, - total, - } => { - *elapsed += t; - if *elapsed >= total { - self.state = ShipState::Dead - } - } - - ShipState::Dead => {} + ShipState::Collapsing {} | ShipState::Dead => {} } } } diff --git a/crates/system/src/phys/controller/point.rs b/crates/system/src/phys/controller/point.rs index a9e8724..c447915 100644 --- a/crates/system/src/phys/controller/point.rs +++ b/crates/system/src/phys/controller/point.rs @@ -1,5 +1,6 @@ use galactica_content::Relationship; -use nalgebra::{Rotation2, Vector2}; +use galactica_util::clockwise_angle; +use nalgebra::Vector2; use rapier2d::{dynamics::RigidBodySet, geometry::ColliderHandle}; use std::collections::HashMap; @@ -73,12 +74,14 @@ impl ShipControllerStruct for PointShipController { } } - let angle = (closest_enemy_position - my_position).angle(&Vector2::new(1.0, 0.0)); - let angle_delta = my_rotation.angle_to(&Rotation2::new(angle).into()); + let angle = clockwise_angle( + &(my_rotation * Vector2::new(1.0, 0.0)), + &(closest_enemy_position - my_position), + ); - if angle_delta < 0.0 && my_angvel > -0.3 { + if angle < 0.0 && my_angvel > -0.3 { controls.right = true; - } else if angle_delta > 0.0 && my_angvel < 0.3 { + } else if angle > 0.0 && my_angvel < 0.3 { controls.left = true; } diff --git a/crates/system/src/phys/objects/collapse.rs b/crates/system/src/phys/objects/collapse.rs index c8fdd82..5ff9750 100644 --- a/crates/system/src/phys/objects/collapse.rs +++ b/crates/system/src/phys/objects/collapse.rs @@ -10,27 +10,35 @@ use crate::data::ShipData; pub(super) struct ShipCollapseSequence { rng: ThreadRng, - /// The elapsed collapse duration when step() - /// was last called - last_call: f32, + /// The total length of this collapse sequence + total_length: f32, + + /// How many seconds we've spent playing this sequence + elapsed: f32, } impl ShipCollapseSequence { - pub(super) fn new() -> Self { + pub(super) fn new(total_length: f32) -> Self { Self { rng: rand::thread_rng(), - last_call: 0.0, + total_length, + elapsed: 0.0, } } + /// Has this collapse sequence fully played out? + pub fn is_done(&self) -> bool { + self.elapsed >= self.total_length + } + /// Pick a random points inside a ship's collider fn random_in_ship(&mut self, ship: &Ship, collider: &Collider) -> Vector2 { let mut y = 0.0; let mut x = 0.0; let mut a = false; while !a { - y = self.rng.gen_range(-1.0..=1.0) * ship.size / 2.0; - x = self.rng.gen_range(-1.0..=1.0) * ship.size * ship.sprite.aspect / 2.0; + x = self.rng.gen_range(-1.0..=1.0) * ship.size / 2.0; + y = self.rng.gen_range(-1.0..=1.0) * ship.size * ship.sprite.aspect / 2.0; a = collider.shape().contains_local_point(&Point2::new(x, y)); } Vector2::new(x, y) @@ -48,12 +56,8 @@ impl ShipCollapseSequence { let ship_pos = rigid_body.translation(); let ship_rot = rigid_body.rotation(); - let (total, elapsed) = ship_data.get_state().collapse_state().unwrap(); - // How much time has passed since step() was last called - let delta = elapsed - self.last_call; - // The fraction of this collapse sequence that has been played - let frac_done = elapsed / total; + let frac_done = self.elapsed / self.total_length; // TODO: slight random offset for event particles @@ -61,8 +65,8 @@ impl ShipCollapseSequence { for event in &ship_content.collapse.events { match event { CollapseEvent::Effect(event) => { - if (event.time > self.last_call && event.time <= elapsed) - || (event.time == 0.0 && self.last_call == 0.0) + if (event.time > self.elapsed && event.time <= self.elapsed + res.t) + || (event.time == 0.0 && self.elapsed == 0.0) // ^^ Don't miss events scheduled at the very start of the sequence! { for spawner in &event.effects { @@ -110,9 +114,7 @@ impl ShipCollapseSequence { return y; }; - // Notice that we don't use res.t here, since ship state is updated earlier - // ( through self.data.step() ) - let p_add = (delta / total) * pdf(frac_done) * spawner.count; + let p_add = (res.t / self.total_length) * pdf(frac_done) * spawner.count; if self.rng.gen_range(0.0..=1.0) <= p_add { let pos = if let Some(pos) = spawner.pos { @@ -138,6 +140,6 @@ impl ShipCollapseSequence { } } - self.last_call = elapsed; + self.elapsed += res.t; } } diff --git a/crates/system/src/phys/objects/ship.rs b/crates/system/src/phys/objects/ship.rs index 67099a2..0c83f9e 100644 --- a/crates/system/src/phys/objects/ship.rs +++ b/crates/system/src/phys/objects/ship.rs @@ -70,12 +70,13 @@ impl PhysSimShip { rigid_body: RigidBodyHandle, collider: ColliderHandle, ) -> Self { + let ship_ct = ct.get_ship(handle); PhysSimShip { rigid_body, collider, data: ShipData::new(ct, handle, faction, personality), controls: ShipControls::new(), - collapse_sequence: Some(ShipCollapseSequence::new()), + collapse_sequence: Some(ShipCollapseSequence::new(ship_ct.collapse.length)), } } @@ -94,6 +95,10 @@ impl PhysSimShip { let mut seq = self.collapse_sequence.take().unwrap(); seq.step(res, &self.data, rigid_body, collider); self.collapse_sequence = Some(seq); + + if self.collapse_sequence.as_ref().unwrap().is_done() { + self.data.finish_collapse(); + } } ShipState::Flying { .. } => { self.step_physics(res, rigid_body, collider); @@ -167,8 +172,8 @@ impl PhysSimShip { let mut x = 0.0; let mut a = false; while !a { - y = rng.gen_range(-1.0..=1.0) * ship_content.size / 2.0; - x = rng.gen_range(-1.0..=1.0) + x = rng.gen_range(-1.0..=1.0) * ship_content.size / 2.0; + y = rng.gen_range(-1.0..=1.0) * ship_content.size * ship_content.sprite.aspect / 2.0; a = collider.shape().contains_local_point(&point![x, y]); diff --git a/crates/system/src/phys/systemsim/steputil.rs b/crates/system/src/phys/systemsim/steputil.rs index ec6cb6d..1a22c28 100644 --- a/crates/system/src/phys/systemsim/steputil.rs +++ b/crates/system/src/phys/systemsim/steputil.rs @@ -162,7 +162,7 @@ impl PhysSim { let destory_projectile = match r { Relationship::Hostile => match ship.data.get_state() { ShipState::Flying { .. } => { - ship.data.apply_damage(res.ct, projectile.content.damage); + ship.data.apply_damage(projectile.content.damage); true } ShipState::Collapsing { .. } => true, diff --git a/crates/util/src/lib.rs b/crates/util/src/lib.rs index 87480ad..525ee53 100644 --- a/crates/util/src/lib.rs +++ b/crates/util/src/lib.rs @@ -13,7 +13,7 @@ pub fn to_radians(degrees: f32) -> f32 { } /// Compute the clockwise angle between two vectors -/// Returns a value in [0, 2pi] +/// Returns a value in [-pi, pi] pub fn clockwise_angle(a: &Vector2, b: &Vector2) -> f32 { (a.x * b.y - b.x * a.y).atan2(a.dot(&b)) }