diff --git a/assets b/assets index 74ddbde..607aea5 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 74ddbde9e1cec1418c17844bc7336324ece88d15 +Subproject commit 607aea5630a0c1ccadacd1cf207394b5dc86147e diff --git a/content/effects.toml b/content/effects.toml index 19f9d23..c00b9d1 100644 --- a/content/effects.toml +++ b/content/effects.toml @@ -6,6 +6,8 @@ size = 8.0 size_rng = 1.6 angle_rng = 360 velocity_scale_parent = 1.0 +fade = 0.2 +fade_rng = 0.1 [effect."large explosion"] @@ -16,6 +18,8 @@ size = 25.0 size_rng = 5.0 angle_rng = 360 velocity_scale_parent = 1.0 +fade = 0.2 +fade_rng = 0.1 [effect."huge explosion"] @@ -26,6 +30,46 @@ size = 50.0 size_rng = 10.0 angle_rng = 360 velocity_scale_parent = 1.0 +fade = 0.2 +fade_rng = 0.1 + + +[effect."blue spark"] +sprite = "particle::spark::blue" +lifetime = 0.5 +lifetime_rng = 0.5 +inherit_velocity = "parent" +size = 4.0 +size_rng = 2.0 +angle_rng = 360 +angvel_rng = 0.0 +velocity_scale_parent = 1.0 +fade = 0.2 +fade_rng = 0.1 + +[effect."yellow spark"] +sprite = "particle::spark::yellow" +lifetime = "inherit" +inherit_velocity = "parent" +size = 4.0 +size_rng = 2.0 +angle_rng = 360 +angvel_rng = 0.0 +velocity_scale_parent = 1.0 +fade = 0.2 +fade_rng = 0.1 + +[effect."red spark"] +sprite = "particle::spark::red" +lifetime = "inherit" +inherit_velocity = "parent" +size = 4.0 +size_rng = 1.0 +angle_rng = 360 +angvel_rng = 0.0 +velocity_scale_parent = 1.0 +fade = 0.2 +fade_rng = 0.1 # Every effect has a parent, some effects have a target @@ -53,6 +97,8 @@ velocity_scale_target_rng = 1.0 direction_rng = 1.0 # Random variation of travel direction, in degrees, applied to velocity vector (/2 each side?) +fade = 0.2 +fade_rng = 0.1 # TODO: # effect probabilities & variants diff --git a/content/ship.toml b/content/ship.toml index 995a263..164bca1 100644 --- a/content/ship.toml +++ b/content/ship.toml @@ -17,6 +17,15 @@ engines = [{ x = 0.0, y = -1.05, size = 50.0 }] guns = [{ x = 0.0, y = 1 }, { x = 0.1, y = 0.80 }, { x = -0.1, y = 0.80 }] +# Show these once we've been reduced to this much hull +damage.hull = 190 +# Spawn this effect once every n seconds, on average +damage.effects = [ + { effect = "blue spark", frequency = 3 }, + { effect = "yellow spark", frequency = 1 }, +] + + # Length of death sequence, in seconds collapse.length = 5.0 diff --git a/content/sprite.toml b/content/sprite.toml index 59fe634..89bd607 100644 --- a/content/sprite.toml +++ b/content/sprite.toml @@ -139,3 +139,39 @@ frames = [ "particle/explosion-huge/09.png", "particle/explosion-huge/10.png", ] + + +[sprite."particle::spark::blue"] +timing.duration = 0.3 +#timing.rng = 0.2 # each frame will be independently sped up/slowed by this factor +#timing.uniform_rng = 0.2 # one factor for all frames +repeat = "reverse" +frames = [ + "particle/spark-blue/01.png", + "particle/spark-blue/02.png", + "particle/spark-blue/03.png", + "particle/spark-blue/04.png", + "particle/spark-blue/05.png", +] + +[sprite."particle::spark::yellow"] +timing.duration = 0.3 +timing.rng = 0.2 +repeat = "once" +frames = [ + "particle/spark-yellow/01.png", + "particle/spark-yellow/02.png", + "particle/spark-yellow/03.png", + "particle/spark-yellow/04.png", + "particle/spark-yellow/05.png", +] + +[sprite."particle::spark::red"] +timing.duration = 0.3 +timing.rng = 0.2 +repeat = "once" +frames = [ + "particle/spark-red/01.png", + "particle/spark-red/02.png", + "particle/spark-red/03.png", +] diff --git a/crates/content/src/part/effect.rs b/crates/content/src/part/effect.rs index 6c550d2..7f67d39 100644 --- a/crates/content/src/part/effect.rs +++ b/crates/content/src/part/effect.rs @@ -29,6 +29,8 @@ pub(crate) mod syntax { pub velocity_scale_target: Option, pub velocity_scale_target_rng: Option, pub direction_rng: Option, + pub fade: Option, + pub fade_rng: Option, } #[derive(Debug, Deserialize)] @@ -56,7 +58,7 @@ pub(crate) mod syntax { TextOrFloat::Text(s) => { if s == "inherit" { let sprite = content.get_sprite(sprite); - sprite.fps * sprite.frames.len() as f32 + sprite.frame_duration * sprite.frames.len() as f32 } else { bail!("bad effect lifetime, must be float or \"inherit\"",) } @@ -74,14 +76,16 @@ pub(crate) mod syntax { lifetime, lifetime_rng: self.lifetime_rng.unwrap_or(0.0), angle: Deg(self.angle.unwrap_or(0.0) / 2.0).into(), - angle_rng: Deg(self.angle_rng.unwrap_or(0.0) / 2.0).into(), + angle_rng: self.angle_rng.unwrap_or(0.0) / 2.0, angvel: Deg(self.angvel.unwrap_or(0.0)).into(), - angvel_rng: Deg(self.angle_rng.unwrap_or(0.0)).into(), + angvel_rng: self.angvel_rng.unwrap_or(0.0), velocity_scale_parent: self.velocity_scale_parent.unwrap_or(0.0), velocity_scale_parent_rng: self.velocity_scale_parent_rng.unwrap_or(0.0), velocity_scale_target: self.velocity_scale_target.unwrap_or(0.0), velocity_scale_target_rng: self.velocity_scale_target_rng.unwrap_or(0.0), - direction_rng: Deg(self.direction_rng.unwrap_or(0.0) / 2.0).into(), + direction_rng: self.direction_rng.unwrap_or(0.0) / 2.0, + fade: self.fade.unwrap_or(0.0), + fade_rng: self.fade_rng.unwrap_or(0.0), }); return Ok(handle); @@ -141,13 +145,13 @@ pub struct Effect { pub angle: Rad, /// Random angle variation - pub angle_rng: Rad, + pub angle_rng: f32, /// How fast this particle spins pub angvel: Rad, /// Random angvel variation - pub angvel_rng: Rad, + pub angvel_rng: f32, /// The amount of this particle's parent's velocity to inherit pub velocity_scale_parent: f32, @@ -163,7 +167,13 @@ pub struct Effect { pub velocity_scale_target_rng: f32, /// Travel direction random variation - pub direction_rng: Rad, + pub direction_rng: f32, + + /// Fade this effect out over this many seconds as it ends + pub fade: f32, + + /// Random fade ariation + pub fade_rng: f32, } impl crate::Build for Effect { diff --git a/crates/content/src/part/ship.rs b/crates/content/src/part/ship.rs index 9d49fd0..cdd931d 100644 --- a/crates/content/src/part/ship.rs +++ b/crates/content/src/part/ship.rs @@ -26,6 +26,7 @@ pub(crate) mod syntax { pub linear_drag: f32, pub space: outfitspace::syntax::OutfitSpace, pub collapse: Option, + pub damage: Option, } #[derive(Debug, Deserialize)] @@ -41,6 +42,19 @@ pub(crate) mod syntax { pub y: f32, } + #[derive(Debug, Deserialize)] + pub struct Damage { + pub hull: f32, + pub effects: Vec, + } + + #[derive(Debug, Deserialize)] + pub struct DamageEffectSpawner { + pub effect: EffectReference, + pub frequency: f32, + pub pos: Option<[f32; 2]>, + } + // TODO: // plural or not? document! #[derive(Debug, Deserialize)] @@ -118,6 +132,9 @@ pub struct Ship { /// Ship collapse sequence pub collapse: ShipCollapse, + + /// Damaged ship effects + pub damage: ShipDamage, } /// Collision shape for this ship @@ -161,7 +178,31 @@ pub struct ShipCollapse { pub events: Vec, } -/// A scripted event during a ship collapse sequence +/// Parameters for damaged ship effects +#[derive(Debug, Clone)] +pub struct ShipDamage { + /// Show damaged ship effects if hull is below this value + pub hull: f32, + + /// Effects to create during collapse + pub effects: Vec, +} + +/// An effect shown when a ship is damaged +#[derive(Debug, Clone)] +pub struct DamageEffectSpawner { + /// The effect to create + pub effect: EffectHandle, + + /// How often to create this effect + pub frequency: f32, + + /// Where to create is effect. + /// Position is random if None. + pub pos: Option>, +} + +/// An effect shown during a ship collapse sequence #[derive(Debug, Clone)] pub struct CollapseEffectSpawner { /// The effect to create @@ -170,7 +211,7 @@ pub struct CollapseEffectSpawner { /// How many effects to create pub count: f32, - /// Where to create these effects. + /// Where to create this effect. /// Position is random if None. pub pos: Option>, } @@ -213,65 +254,101 @@ impl crate::Build for Ship { let size = ship.size; let aspect = ct.get_sprite(handle).aspect; - let collapse = if let Some(c) = ship.collapse { - let mut effects = Vec::new(); - for e in c.effects { - effects.push(CollapseEffectSpawner { - effect: e - .effect - .to_handle(build_context, ct) - .with_context(|| format!("while loading ship `{}`", ship_name))?, - count: e.count, - pos: e.pos.map(|p| Point2 { - x: p[0] * (size / 2.0) * aspect, - y: p[1] * size / 2.0, - }), - }); - } + let collapse = { + if let Some(c) = ship.collapse { + let mut effects = Vec::new(); + for e in c.effects { + effects.push(CollapseEffectSpawner { + effect: e + .effect + .to_handle(build_context, ct) + .with_context(|| format!("while loading ship `{}`", ship_name))?, + count: e.count, + pos: e.pos.map(|p| Point2 { + x: p[0] * (size / 2.0) * aspect, + y: p[1] * size / 2.0, + }), + }); + } - let mut events = Vec::new(); - for e in c.event { - match e { - syntax::CollapseEvent::Effect(e) => { - let mut effects = Vec::new(); - for g in e.effects { - effects.push(CollapseEffectSpawner { - effect: g.effect.to_handle(build_context, ct).with_context( - || format!("while loading ship `{}`", ship_name), - )?, - count: g.count, - pos: g.pos.map(|p| Point2 { - x: p[0] * (size / 2.0) * aspect, - y: p[1] * size / 2.0, - }), - }) + let mut events = Vec::new(); + for e in c.event { + match e { + syntax::CollapseEvent::Effect(e) => { + let mut effects = Vec::new(); + for g in e.effects { + effects.push(CollapseEffectSpawner { + effect: g + .effect + .to_handle(build_context, ct) + .with_context(|| { + format!("while loading ship `{}`", ship_name) + })?, + count: g.count, + pos: g.pos.map(|p| Point2 { + x: p[0] * (size / 2.0) * aspect, + y: p[1] * size / 2.0, + }), + }) + } + + events.push(CollapseEvent::Effect(EffectCollapseEvent { + time: e.time, + effects, + })) } - - events.push(CollapseEvent::Effect(EffectCollapseEvent { - time: e.time, - effects, - })) } } - } - ShipCollapse { - length: c.length, - effects, - events, + ShipCollapse { + length: c.length, + effects, + events, + } + } else { + // Default collapse sequence + ShipCollapse { + length: 0.0, + effects: vec![], + events: vec![], + } } - } else { - // Default collapse sequence - ShipCollapse { - length: 0.0, - effects: vec![], - events: vec![], + }; + + let damage = { + if let Some(c) = ship.damage { + let mut effects = Vec::new(); + for e in c.effects { + effects.push(DamageEffectSpawner { + effect: e + .effect + .to_handle(build_context, ct) + .with_context(|| format!("while loading ship `{}`", ship_name))?, + frequency: e.frequency, + pos: e.pos.map(|p| Point2 { + x: p[0] * (size / 2.0) * aspect, + y: p[1] * size / 2.0, + }), + }); + } + + ShipDamage { + hull: c.hull, + effects: effects, + } + } else { + // Default damage effects + ShipDamage { + hull: 0.0, + effects: vec![], + } } }; ct.ships.push(Self { aspect, collapse, + damage, name: ship_name, sprite: handle, mass: ship.mass, diff --git a/crates/render/shaders/particle.wgsl b/crates/render/shaders/particle.wgsl index 7b8c677..9164209 100644 --- a/crates/render/shaders/particle.wgsl +++ b/crates/render/shaders/particle.wgsl @@ -8,7 +8,8 @@ struct InstanceInput { @location(6) size: f32, @location(7) created: f32, @location(8) expires: f32, - @location(9) sprite_index: u32, + @location(9) fade: f32, + @location(10) sprite_index: u32, }; struct VertexInput { @@ -19,10 +20,11 @@ struct VertexInput { struct VertexOutput { @builtin(position) position: vec4, @location(0) tween: f32, - @location(1) texture_index_a: u32, - @location(2) texture_coords_a: vec2, - @location(3) texture_index_b: u32, - @location(4) texture_coords_b: vec2, + @location(1) fade: f32, + @location(2) texture_index_a: u32, + @location(3) texture_coords_a: vec2, + @location(4) texture_index_b: u32, + @location(5) texture_coords_b: vec2, } @@ -84,6 +86,11 @@ fn vertex_main( out.position = vec4(pos, 0.0, 1.0); + if instance.expires - global_data.current_time.x <= instance.fade { + out.fade = (instance.expires - global_data.current_time.x) / instance.fade; + } else { + out.fade = 1.0; + } // Compute texture coordinates let frame = animate(instance.sprite_index, age, 0.0); @@ -131,5 +138,5 @@ fn fragment_main(in: VertexOutput) -> @location(0) vec4 { 0.0 ).rgba, in.tween - ); + ) * vec4(1.0, 1.0, 1.0, in.fade); } \ No newline at end of file diff --git a/crates/render/src/gpustate.rs b/crates/render/src/gpustate.rs index f169600..8aa6639 100644 --- a/crates/render/src/gpustate.rs +++ b/crates/render/src/gpustate.rs @@ -586,6 +586,7 @@ impl GPUState { sprite_index: i.sprite.get_index(), created: state.current_time, expires: state.current_time + i.lifetime, + fade: i.fade, }]), ); self.vertex_buffers.particle_array_head += 1; diff --git a/crates/render/src/sprite.rs b/crates/render/src/sprite.rs index 4465323..8fd98c4 100644 --- a/crates/render/src/sprite.rs +++ b/crates/render/src/sprite.rs @@ -1,5 +1,6 @@ use crate::content; -use cgmath::{Deg, Point2, Point3, Rad, Vector2}; +use cgmath::{Deg, Matrix2, Point2, Point3, Rad, Vector2}; +use rand::Rng; /// Instructions to create a new particle pub struct ParticleBuilder { @@ -24,6 +25,65 @@ pub struct ParticleBuilder { /// The size of this particle, /// given as height in world units. pub size: f32, + + /// Fade this particle out over this many seconds as it expires + pub fade: f32, +} + +impl ParticleBuilder { + /// Create a ParticleBuilder from an Effect + pub fn from_content( + effect: &content::Effect, + pos: Point2, + parent_angle: Rad, + parent_velocity: Vector2, + target_velocity: Vector2, + ) -> Self { + let mut rng = rand::thread_rng(); + + let velocity = { + let a = + rng.gen_range(-effect.velocity_scale_parent_rng..=effect.velocity_scale_parent_rng); + let b = + rng.gen_range(-effect.velocity_scale_target_rng..=effect.velocity_scale_target_rng); + + let velocity = ((effect.velocity_scale_parent + a) * parent_velocity) + + ((effect.velocity_scale_target + b) * target_velocity); + + Matrix2::from_angle(Rad( + rng.gen_range(-effect.direction_rng..=effect.direction_rng) + )) * velocity + }; + + // Rad has odd behavior when its angle is zero, so we need extra checks here + let angvel = if effect.angvel_rng == 0.0 { + effect.angvel + } else { + Rad(effect.angvel.0 + rng.gen_range(-effect.angvel_rng..=effect.angvel_rng)) + }; + let angle = if effect.angle_rng == 0.0 { + parent_angle + effect.angle + } else { + parent_angle + effect.angle + Rad(rng.gen_range(-effect.angle_rng..=effect.angle_rng)) + }; + + ParticleBuilder { + sprite: effect.sprite, + pos, + velocity, + + angle, + angvel, + + lifetime: 0f32 + .max(effect.lifetime + rng.gen_range(-effect.lifetime_rng..=effect.lifetime_rng)), + + // Make sure size isn't negative. This check should be on EVERY rng! + size: 0f32.max(effect.size + rng.gen_range(-effect.size_rng..=effect.size_rng)), + + fade: 0f32.max(effect.fade + rng.gen_range(-effect.fade_rng..=effect.fade_rng)), + } + } } /// The location of a UI element, in one of a few diff --git a/crates/render/src/vertexbuffer/types.rs b/crates/render/src/vertexbuffer/types.rs index 41dc1e2..ddf2982 100644 --- a/crates/render/src/vertexbuffer/types.rs +++ b/crates/render/src/vertexbuffer/types.rs @@ -206,6 +206,9 @@ pub struct ParticleInstance { /// Time is kept by a variable in the global uniform. pub expires: f32, + /// Fade this particle out over this many seconds as it expires + pub fade: f32, + /// What sprite to use for this particle pub sprite_index: u32, } @@ -258,10 +261,16 @@ impl BufferObject for ParticleInstance { shader_location: 8, format: wgpu::VertexFormat::Float32, }, - // Sprite + // Fade wgpu::VertexAttribute { offset: mem::size_of::<[f32; 9]>() as wgpu::BufferAddress, shader_location: 9, + format: wgpu::VertexFormat::Float32, + }, + // Sprite + wgpu::VertexAttribute { + offset: mem::size_of::<[f32; 10]>() as wgpu::BufferAddress, + shader_location: 10, format: wgpu::VertexFormat::Uint32, }, ], diff --git a/crates/world/src/objects/ship.rs b/crates/world/src/objects/ship.rs index ba572a6..3e8bce8 100644 --- a/crates/world/src/objects/ship.rs +++ b/crates/world/src/objects/ship.rs @@ -98,51 +98,21 @@ impl ShipCollapseSequence { } else { self.random_in_ship(ship_content, collider) }; - - // Position, adjusted for ship rotation let pos = ship_pos - + Matrix2::from_angle(-ship_ang - Rad::from(Deg(90.0))) * pos; + + (Matrix2::from_angle(-ship_ang - Rad::from(Deg(90.0))) * pos); - let velocity = { - let a = self.rng.gen_range( - -effect.velocity_scale_parent_rng - ..=effect.velocity_scale_parent_rng, - ); + let velocity = rigid_body.velocity_at_point(&point![pos.x, pos.y]); - let velocity = (effect.velocity_scale_parent + a) - * rigid_body.velocity_at_point(&point![pos.x, pos.y]); - - Matrix2::from_angle(Rad(self.rng.gen_range( - -effect.direction_rng.0..=effect.direction_rng.0, - ))) * Vector2 { + particles.push(ParticleBuilder::from_content( + effect, + pos, + Rad::zero(), + Vector2 { x: velocity.x, y: velocity.y, - } - }; - - particles.push(ParticleBuilder { - sprite: effect.sprite, - pos, - velocity, - - angle: effect.angle - + Rad(self - .rng - .gen_range(-effect.angle_rng.0..=effect.angle_rng.0)), - - angvel: Rad(effect.angvel.0 - + self - .rng - .gen_range(-effect.angvel_rng.0..=effect.angvel_rng.0)), - - lifetime: effect.lifetime - + self - .rng - .gen_range(-effect.lifetime_rng..=effect.lifetime_rng), - - size: effect.size - + self.rng.gen_range(-effect.size_rng..=effect.size_rng), - }); + }, + Vector2::zero(), + )) } } } @@ -188,6 +158,7 @@ impl ShipCollapseSequence { angvel: Rad::zero(), lifetime: effect.lifetime, size: effect.size, + fade: 0.0, }); } } @@ -236,21 +207,68 @@ impl ShipWorldObject { &mut self, ct: &content::Content, particles: &mut Vec, - r: &mut RigidBody, - c: &mut Collider, + rigid_body: &mut RigidBody, + collider: &mut Collider, t: f32, ) { if self.ship.is_dead() { return self .collapse_sequence - .step(&self.ship, ct, particles, r, c, t); + .step(&self.ship, ct, particles, rigid_body, collider, t); + } + + let ship_content = ct.get_ship(self.ship.handle); + let ship_pos = util::rigidbody_position(&rigid_body); + let ship_rot = util::rigidbody_rotation(rigid_body); + let ship_ang = ship_rot.angle(Vector2 { x: 1.0, y: 0.0 }); + let mut rng = rand::thread_rng(); + + if self.ship.hull <= ship_content.damage.hull { + for e in &ship_content.damage.effects { + if rng.gen_range(0.0..=1.0) <= t / e.frequency { + let effect = ct.get_effect(e.effect); + let ship_content = ct.get_ship(self.ship.handle); + + let pos = if let Some(pos) = e.pos { + pos.to_vec() + } else { + // Pick a random point inside this ship's collider + let mut y = 0.0; + 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) + * ship_content.size * ship_content.sprite.aspect + / 2.0; + a = collider.shape().contains_local_point(&point![x, y]); + } + Vector2 { x, y } + }; + + let pos = + ship_pos + (Matrix2::from_angle(-ship_ang - Rad::from(Deg(90.0))) * pos); + + let velocity = rigid_body.velocity_at_point(&point![pos.x, pos.y]); + + particles.push(ParticleBuilder::from_content( + effect, + pos, + Rad::zero(), + Vector2 { + x: velocity.x, + y: velocity.y, + }, + Vector2::zero(), + )) + } + } } - let ship_rot = util::rigidbody_rotation(r); let engine_force = ship_rot * t; if self.controls.thrust { - r.apply_impulse( + rigid_body.apply_impulse( vector![engine_force.x, engine_force.y] * self.ship.outfits.stat_sum().engine_thrust, true, @@ -258,11 +276,13 @@ impl ShipWorldObject { } if self.controls.right { - r.apply_torque_impulse(self.ship.outfits.stat_sum().steer_power * -100.0 * t, true); + rigid_body + .apply_torque_impulse(self.ship.outfits.stat_sum().steer_power * -100.0 * t, true); } if self.controls.left { - r.apply_torque_impulse(self.ship.outfits.stat_sum().steer_power * 100.0 * t, true); + rigid_body + .apply_torque_impulse(self.ship.outfits.stat_sum().steer_power * 100.0 * t, true); } for i in self.ship.outfits.iter_guns() { diff --git a/crates/world/src/world.rs b/crates/world/src/world.rs index a20fd01..3eece65 100644 --- a/crates/world/src/world.rs +++ b/crates/world/src/world.rs @@ -1,4 +1,4 @@ -use cgmath::{Deg, EuclideanSpace, InnerSpace, Matrix2, Point2, Rad, Vector2}; +use cgmath::{Deg, EuclideanSpace, InnerSpace, Matrix2, Point2, Rad, Vector2, Zero}; use crossbeam::channel::Receiver; use nalgebra::{point, vector}; use rand::Rng; @@ -80,9 +80,9 @@ impl<'a> World { let pos = ship_pos + (Matrix2::from_angle(-ship_ang) * point.pos.to_vec()); - let spread: Rad = Deg(rng.gen_range( - -(projectile.content.angle_rng.0 / 2.0)..=projectile.content.angle_rng.0 / 2.0, - )) + let spread: Rad = Deg( + rng.gen_range(-projectile.content.angle_rng.0..=projectile.content.angle_rng.0) + ) .into(); let vel = ship_vel @@ -117,11 +117,7 @@ impl<'a> World { self.projectiles.insert( collider.clone(), - ProjectileWorldObject { - projectile, - rigid_body, - collider, - }, + ProjectileWorldObject::new(projectile, rigid_body, collider), ); } } @@ -133,7 +129,6 @@ impl<'a> World { projectile_h: ColliderHandle, ship_h: ColliderHandle, ) { - let mut rng = rand::thread_rng(); let projectile = self.projectiles.get(&projectile_h); let ship = self.ships.get_mut(&ship_h); if projectile.is_none() || ship.is_none() { @@ -173,40 +168,22 @@ impl<'a> World { match &projectile.projectile.content.impact_effect { None => {} Some(x) => { - let x = ct.get_effect(*x); + let effect = ct.get_effect(*x); + let (_, sr) = self.get_ship_body(s).unwrap(); + let parent_velocity = util::rigidbody_velocity(pr); + let target_velocity = + sr.velocity_at_point(&nalgebra::Point2::new(pos.x, pos.y)); - let velocity = { - let (_, sr) = self.get_ship_body(s).unwrap(); - let target_velocity = - sr.velocity_at_point(&nalgebra::Point2::new(pos.x, pos.y)); - let a = rng - .gen_range(-x.velocity_scale_parent_rng..=x.velocity_scale_parent_rng); - let b = rng - .gen_range(-x.velocity_scale_target_rng..=x.velocity_scale_target_rng); - - let velocity = ((x.velocity_scale_parent + a) - * util::rigidbody_velocity(pr)) - + ((x.velocity_scale_target + b) - * Vector2 { - x: target_velocity.x, - y: target_velocity.y, - }); - - Matrix2::from_angle(Rad( - rng.gen_range(-x.direction_rng.0..=x.direction_rng.0) - )) * velocity - }; - - particles.push(ParticleBuilder { - sprite: x.sprite, - pos: Point2 { x: pos.x, y: pos.y }, - velocity, - angle: Rad::from(-angle) - + Rad(rng.gen_range(-x.angle_rng.0..=x.angle_rng.0)), - angvel: Rad(x.angvel.0 + rng.gen_range(-x.angvel_rng.0..=x.angvel_rng.0)), - lifetime: x.lifetime + rng.gen_range(-x.lifetime_rng..=x.lifetime_rng), - size: x.size + rng.gen_range(-x.size_rng..=x.size_rng), - }); + particles.push(ParticleBuilder::from_content( + effect, + pos, + Rad::from(-angle), + parent_velocity, + Vector2 { + x: target_velocity.x, + y: target_velocity.y, + }, + )); } }; @@ -352,21 +329,15 @@ impl<'a> World { let velocity = (x.velocity_scale_parent + a) * vel; velocity - //Matrix2::from_angle(Rad( - // rng.gen_range(-x.direction_rng.0..=x.direction_rng.0) - //)) * velocity }; - particles.push(ParticleBuilder { - sprite: x.sprite, - pos: Point2 { x: pos.x, y: pos.y }, + particles.push(ParticleBuilder::from_content( + x, + pos, + Rad::from(-angle), velocity, - angle: Rad::from(-angle) - + x.angle + Rad(rng.gen_range(-x.angle_rng.0..=x.angle_rng.0)), - angvel: Rad(x.angvel.0 + rng.gen_range(-x.angvel_rng.0..=x.angvel_rng.0)), - lifetime: x.lifetime + rng.gen_range(-x.lifetime_rng..=x.lifetime_rng), - size: x.size + rng.gen_range(-x.size_rng..=x.size_rng), - }); + Vector2::zero(), + )); } }; }