Smoother particle emission for moving objects

This commit is contained in:
Joshua Barretto 2021-03-21 23:25:55 +00:00
parent 0372e89fb8
commit 7b736640f5
2 changed files with 73 additions and 27 deletions

View File

@ -8,7 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added ### Added
- New Skills for Climbing: Climbing Speed and Climbing Cost - New Skills for Climbing: Climbing Speed and Climbing Cost
- Pickaxes (can be used to collect gems and mine weak rock)
### Changed ### Changed

View File

@ -10,7 +10,7 @@ use common::{
assets::{AssetExt, DotVoxAsset}, assets::{AssetExt, DotVoxAsset},
comp::{ comp::{
self, aura, beam, buff, item::Reagent, object, BeamSegment, Body, CharacterState, Ori, Pos, self, aura, beam, buff, item::Reagent, object, BeamSegment, Body, CharacterState, Ori, Pos,
Shockwave, Shockwave, Vel,
}, },
figure::Segment, figure::Segment,
outcome::Outcome, outcome::Outcome,
@ -212,19 +212,25 @@ impl ParticleMgr {
"ParticleMgr::maintain_body_particles" "ParticleMgr::maintain_body_particles"
); );
let ecs = scene_data.state.ecs(); let ecs = scene_data.state.ecs();
for (body, pos) in (&ecs.read_storage::<Body>(), &ecs.read_storage::<Pos>()).join() { for (body, pos, vel) in (
&ecs.read_storage::<Body>(),
&ecs.read_storage::<Pos>(),
ecs.read_storage::<Vel>().maybe(),
)
.join()
{
match body { match body {
Body::Object(object::Body::CampfireLit) => { Body::Object(object::Body::CampfireLit) => {
self.maintain_campfirelit_particles(scene_data, pos) self.maintain_campfirelit_particles(scene_data, pos, vel)
}, },
Body::Object(object::Body::BoltFire) => { Body::Object(object::Body::BoltFire) => {
self.maintain_boltfire_particles(scene_data, pos) self.maintain_boltfire_particles(scene_data, pos, vel)
}, },
Body::Object(object::Body::BoltFireBig) => { Body::Object(object::Body::BoltFireBig) => {
self.maintain_boltfirebig_particles(scene_data, pos) self.maintain_boltfirebig_particles(scene_data, pos, vel)
}, },
Body::Object(object::Body::BoltNature) => { Body::Object(object::Body::BoltNature) => {
self.maintain_boltnature_particles(scene_data, pos) self.maintain_boltnature_particles(scene_data, pos, vel)
}, },
Body::Object( Body::Object(
object::Body::Bomb object::Body::Bomb
@ -234,21 +240,28 @@ impl ParticleMgr {
| object::Body::FireworkRed | object::Body::FireworkRed
| object::Body::FireworkWhite | object::Body::FireworkWhite
| object::Body::FireworkYellow, | object::Body::FireworkYellow,
) => self.maintain_bomb_particles(scene_data, pos), ) => self.maintain_bomb_particles(scene_data, pos, vel),
_ => {}, _ => {},
} }
} }
} }
fn maintain_campfirelit_particles(&mut self, scene_data: &SceneData, pos: &Pos) { fn maintain_campfirelit_particles(
&mut self,
scene_data: &SceneData,
pos: &Pos,
vel: Option<&Vel>,
) {
span!( span!(
_guard, _guard,
"campfirelit_particles", "campfirelit_particles",
"ParticleMgr::maintain_campfirelit_particles" "ParticleMgr::maintain_campfirelit_particles"
); );
let time = scene_data.state.get_time(); let time = scene_data.state.get_time();
let dt = scene_data.state.get_delta_time();
let mut rng = thread_rng();
for _ in 0..self.scheduler.heartbeats(Duration::from_millis(10)) { for _ in 0..self.scheduler.heartbeats(Duration::from_millis(50)) {
self.particles.push(Particle::new( self.particles.push(Particle::new(
Duration::from_millis(250), Duration::from_millis(250),
time, time,
@ -260,22 +273,30 @@ impl ParticleMgr {
Duration::from_secs(10), Duration::from_secs(10),
time, time,
ParticleMode::CampfireSmoke, ParticleMode::CampfireSmoke,
pos.0.map(|e| e + thread_rng().gen_range(-0.25..0.25)), pos.0.map(|e| e + thread_rng().gen_range(-0.25..0.25))
+ vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
)); ));
} }
} }
fn maintain_boltfire_particles(&mut self, scene_data: &SceneData, pos: &Pos) { fn maintain_boltfire_particles(
&mut self,
scene_data: &SceneData,
pos: &Pos,
vel: Option<&Vel>,
) {
span!( span!(
_guard, _guard,
"boltfire_particles", "boltfire_particles",
"ParticleMgr::maintain_boltfire_particles" "ParticleMgr::maintain_boltfire_particles"
); );
let time = scene_data.state.get_time(); let time = scene_data.state.get_time();
let dt = scene_data.state.get_delta_time();
let mut rng = thread_rng();
for _ in 0..self.scheduler.heartbeats(Duration::from_millis(10)) { for _ in 0..self.scheduler.heartbeats(Duration::from_millis(4)) {
self.particles.push(Particle::new( self.particles.push(Particle::new(
Duration::from_millis(250), Duration::from_millis(500),
time, time,
ParticleMode::CampfireFire, ParticleMode::CampfireFire,
pos.0, pos.0,
@ -284,28 +305,37 @@ impl ParticleMgr {
Duration::from_secs(1), Duration::from_secs(1),
time, time,
ParticleMode::CampfireSmoke, ParticleMode::CampfireSmoke,
pos.0, pos.0.map(|e| e + rng.gen_range(-0.25..0.25))
+ vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
)); ));
} }
} }
fn maintain_boltfirebig_particles(&mut self, scene_data: &SceneData, pos: &Pos) { fn maintain_boltfirebig_particles(
&mut self,
scene_data: &SceneData,
pos: &Pos,
vel: Option<&Vel>,
) {
span!( span!(
_guard, _guard,
"boltfirebig_particles", "boltfirebig_particles",
"ParticleMgr::maintain_boltfirebig_particles" "ParticleMgr::maintain_boltfirebig_particles"
); );
let time = scene_data.state.get_time(); let time = scene_data.state.get_time();
let dt = scene_data.state.get_delta_time();
let mut rng = thread_rng();
// fire // fire
self.particles.resize_with( self.particles.resize_with(
self.particles.len() + usize::from(self.scheduler.heartbeats(Duration::from_millis(3))), self.particles.len() + usize::from(self.scheduler.heartbeats(Duration::from_millis(2))),
|| { || {
Particle::new( Particle::new(
Duration::from_millis(250), Duration::from_millis(500),
time, time,
ParticleMode::CampfireFire, ParticleMode::CampfireFire,
pos.0, pos.0.map(|e| e + rng.gen_range(-0.25..0.25))
+ vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
) )
}, },
); );
@ -318,36 +348,47 @@ impl ParticleMgr {
Duration::from_secs(2), Duration::from_secs(2),
time, time,
ParticleMode::CampfireSmoke, ParticleMode::CampfireSmoke,
pos.0, pos.0.map(|e| e + rng.gen_range(-0.25..0.25))
+ vel.map_or(Vec3::zero(), |v| -v.0 * dt),
) )
}, },
); );
} }
fn maintain_boltnature_particles(&mut self, scene_data: &SceneData, pos: &Pos) { fn maintain_boltnature_particles(
&mut self,
scene_data: &SceneData,
pos: &Pos,
vel: Option<&Vel>,
) {
let time = scene_data.state.get_time(); let time = scene_data.state.get_time();
let dt = scene_data.state.get_delta_time();
let mut rng = thread_rng();
// nature // nature
self.particles.resize_with( self.particles.resize_with(
self.particles.len() + usize::from(self.scheduler.heartbeats(Duration::from_millis(3))), self.particles.len() + usize::from(self.scheduler.heartbeats(Duration::from_millis(2))),
|| { || {
Particle::new( Particle::new(
Duration::from_millis(250), Duration::from_millis(500),
time, time,
ParticleMode::CampfireSmoke, ParticleMode::CampfireSmoke,
pos.0, pos.0.map(|e| e + rng.gen_range(-0.25..0.25))
+ vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
) )
}, },
); );
} }
fn maintain_bomb_particles(&mut self, scene_data: &SceneData, pos: &Pos) { fn maintain_bomb_particles(&mut self, scene_data: &SceneData, pos: &Pos, vel: Option<&Vel>) {
span!( span!(
_guard, _guard,
"bomb_particles", "bomb_particles",
"ParticleMgr::maintain_bomb_particles" "ParticleMgr::maintain_bomb_particles"
); );
let time = scene_data.state.get_time(); let time = scene_data.state.get_time();
let dt = scene_data.state.get_delta_time();
let mut rng = thread_rng();
for _ in 0..self.scheduler.heartbeats(Duration::from_millis(10)) { for _ in 0..self.scheduler.heartbeats(Duration::from_millis(10)) {
// sparks // sparks
@ -363,7 +404,7 @@ impl ParticleMgr {
Duration::from_secs(2), Duration::from_secs(2),
time, time,
ParticleMode::CampfireSmoke, ParticleMode::CampfireSmoke,
pos.0, pos.0 + vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
)); ));
} }
} }
@ -377,9 +418,12 @@ impl ParticleMgr {
let state = scene_data.state; let state = scene_data.state;
let ecs = state.ecs(); let ecs = state.ecs();
let time = state.get_time(); let time = state.get_time();
let dt = scene_data.state.get_delta_time();
let mut rng = thread_rng();
for (pos, character_state) in ( for (pos, vel, character_state) in (
&ecs.read_storage::<Pos>(), &ecs.read_storage::<Pos>(),
ecs.read_storage::<Vel>().maybe(),
&ecs.read_storage::<CharacterState>(), &ecs.read_storage::<CharacterState>(),
) )
.join() .join()
@ -393,7 +437,7 @@ impl ParticleMgr {
Duration::from_secs(15), Duration::from_secs(15),
time, time,
ParticleMode::CampfireSmoke, ParticleMode::CampfireSmoke,
pos.0, pos.0 + vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
) )
}, },
); );