From 200e9cc4a25dd6161ace40c6a222bac2810ea104 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 2 Oct 2017 20:40:59 +0200 Subject: [PATCH] ParticleSpawner::step cleanup and rotation fix (#6486) * Particles: Move spawner code to a separate fucntion --- src/particles.cpp | 182 ++++++++++++++++++---------------------------- src/particles.h | 10 ++- 2 files changed, 76 insertions(+), 116 deletions(-) diff --git a/src/particles.cpp b/src/particles.cpp index 0caa4f796..69bc31358 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -290,6 +290,59 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr, ParticleSpawner::~ParticleSpawner() {} +void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius, + bool is_attached, const v3f &attached_pos, float attached_yaw) +{ + v3f ppos = m_player->getPosition() / BS; + v3f pos = random_v3f(m_minpos, m_maxpos); + + // Need to apply this first or the following check + // will be wrong for attached spawners + if (is_attached) { + pos.rotateXZBy(attached_yaw); + pos += attached_pos; + } + + if (pos.getDistanceFrom(ppos) > radius) + return; + + v3f vel = random_v3f(m_minvel, m_maxvel); + v3f acc = random_v3f(m_minacc, m_maxacc); + + if (is_attached) { + // Apply attachment yaw + vel.rotateXZBy(attached_yaw); + acc.rotateXZBy(attached_yaw); + } + + float exptime = rand() / (float)RAND_MAX + * (m_maxexptime - m_minexptime) + + m_minexptime; + float size = rand() / (float)RAND_MAX + * (m_maxsize - m_minsize) + + m_minsize; + + m_particlemanager->addParticle(new Particle( + m_gamedef, + m_smgr, + m_player, + env, + pos, + vel, + acc, + exptime, + size, + m_collisiondetection, + m_collision_removal, + m_vertical, + m_texture, + v2f(0.0, 0.0), + v2f(1.0, 1.0), + m_animation, + m_glow + )); +} + void ParticleSpawner::step(float dtime, ClientEnvironment* env) { m_time += dtime; @@ -311,130 +364,33 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) } } - if (m_spawntime != 0) // Spawner exists for a predefined timespan - { - for(std::vector::iterator i = m_spawntimes.begin(); - i != m_spawntimes.end();) - { - if ((*i) <= m_time && m_amount > 0) - { + if (m_spawntime != 0) { + // Spawner exists for a predefined timespan + for (std::vector::iterator i = m_spawntimes.begin(); + i != m_spawntimes.end();) { + if ((*i) <= m_time && m_amount > 0) { m_amount--; // Pretend to, but don't actually spawn a particle if it is // attached to an unloaded object or distant from player. - if (!unloaded) { - v3f ppos = m_player->getPosition() / BS; - v3f pos = random_v3f(m_minpos, m_maxpos); - - // Need to apply this first or the following check - // will be wrong for attached spawners - if (is_attached) - pos += attached_pos; - - if (pos.getDistanceFrom(ppos) <= radius) { - v3f vel = random_v3f(m_minvel, m_maxvel); - v3f acc = random_v3f(m_minacc, m_maxacc); - - if (is_attached) { - // Apply attachment yaw and position - pos.rotateXZBy(attached_yaw); - vel.rotateXZBy(attached_yaw); - acc.rotateXZBy(attached_yaw); - } - - float exptime = rand()/(float)RAND_MAX - *(m_maxexptime-m_minexptime) - +m_minexptime; - float size = rand()/(float)RAND_MAX - *(m_maxsize-m_minsize) - +m_minsize; - - Particle* toadd = new Particle( - m_gamedef, - m_smgr, - m_player, - env, - pos, - vel, - acc, - exptime, - size, - m_collisiondetection, - m_collision_removal, - m_vertical, - m_texture, - v2f(0.0, 0.0), - v2f(1.0, 1.0), - m_animation, - m_glow); - m_particlemanager->addParticle(toadd); - } - } + if (!unloaded) + spawnParticle(env, radius, is_attached, attached_pos, attached_yaw); + i = m_spawntimes.erase(i); - } - else - { + } else { ++i; } } - } - else // Spawner exists for an infinity timespan, spawn on a per-second base - { + } else { + // Spawner exists for an infinity timespan, spawn on a per-second base + // Skip this step if attached to an unloaded object if (unloaded) return; - for (int i = 0; i <= m_amount; i++) - { - if (rand()/(float)RAND_MAX < dtime) - { - // Do not spawn particle if distant from player - v3f ppos = m_player->getPosition() / BS; - v3f pos = random_v3f(m_minpos, m_maxpos); - - // Need to apply this first or the following check - // will be wrong for attached spawners - if (is_attached) - pos += attached_pos; - - if (pos.getDistanceFrom(ppos) <= radius) { - v3f vel = random_v3f(m_minvel, m_maxvel); - v3f acc = random_v3f(m_minacc, m_maxacc); - - if (is_attached) { - // Apply attachment yaw and position - pos.rotateXZBy(attached_yaw); - vel.rotateXZBy(attached_yaw); - acc.rotateXZBy(attached_yaw); - } - - float exptime = rand()/(float)RAND_MAX - *(m_maxexptime-m_minexptime) - +m_minexptime; - float size = rand()/(float)RAND_MAX - *(m_maxsize-m_minsize) - +m_minsize; - - Particle* toadd = new Particle( - m_gamedef, - m_smgr, - m_player, - env, - pos, - vel, - acc, - exptime, - size, - m_collisiondetection, - m_collision_removal, - m_vertical, - m_texture, - v2f(0.0, 0.0), - v2f(1.0, 1.0), - m_animation, - m_glow); - m_particlemanager->addParticle(toadd); - } - } + + for (int i = 0; i <= m_amount; i++) { + if (rand() / (float)RAND_MAX < dtime) + spawnParticle(env, radius, is_attached, attached_pos, attached_yaw); } } } diff --git a/src/particles.h b/src/particles.h index eaec1f0fa..cb16d1c07 100644 --- a/src/particles.h +++ b/src/particles.h @@ -117,7 +117,7 @@ private: class ParticleSpawner { - public: +public: ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr, LocalPlayer *player, @@ -144,8 +144,12 @@ class ParticleSpawner bool get_expired () { return (m_amount <= 0) && m_spawntime != 0; } - private: - ParticleManager* m_particlemanager; +private: + void spawnParticle(ClientEnvironment *env, float radius, + bool is_attached, const v3f &attached_pos, + float attached_yaw); + + ParticleManager *m_particlemanager; float m_time; IGameDef *m_gamedef; scene::ISceneManager *m_smgr; -- 2.25.1